From f1ff27e72013b5c89de241d4d3ab11244aa91e15 Mon Sep 17 00:00:00 2001
From: zhengyiming <540361168@qq.com>
Date: 星期三, 12 十一月 2025 17:30:14 +0800
Subject: [PATCH] fix: 四流

---
 src/views/MaterialReview/MaterialReview.vue                        |   70 -
 src/views/Permission/RoleManage.vue                                |   89 +
 src/views/Permission/components/dialogMember.vue                   |  286 +++++++
 src/views/StatisticalReport/RewardStatistics.vue                   |  125 ---
 src/services/api/ElectronSign.ts                                   |   66 +
 src/views/Permission/components/AddOrEditExternalAccountDialog.vue |  210 +++++
 src/views/Reward/RewardApplyTradeCheck.vue                         |   28 
 src/services/api/EnterpriseApplyFile.ts                            |   51 +
 src/views/Reward/RewardGrant.vue                                   |  145 ---
 src/views/Reward/WithdrawalApproval.vue                            |   74 -
 src/services/api/UserRole.ts                                       |   45 +
 src/router/index.ts                                                |  246 ++----
 src/services/api/ParkBountyApply.ts                                |   15 
 src/constants/app.ts                                               |    6 
 src/views/Permission/ExternalAccountManage.vue                     |  223 ++++++
 src/views/MaterialReview/MaterialReReviewList.vue                  |   85 --
 src/hooks/useUser.ts                                               |   25 
 src/services/api/typings.d.ts                                      |  124 +++
 src/constants/regExp.ts                                            |    3 
 src/views/EnterpriseInfo/EnterpriseInfo.vue                        |  104 --
 src/constants/enum.ts                                              |   47 +
 src/views/Permission/components/ResetPasswordDialog.vue            |   71 +
 src/views/Permission/components/dialogAuthorize.vue                |   20 
 src/views/Reward/FinancialApproval.vue                             |   28 
 src/services/api/BaseModuleNew.ts                                  |   27 
 25 files changed, 1,429 insertions(+), 784 deletions(-)

diff --git a/src/constants/app.ts b/src/constants/app.ts
index 22b3f14..6e59a91 100644
--- a/src/constants/app.ts
+++ b/src/constants/app.ts
@@ -1 +1,7 @@
+import { EnumMenuScene } from './module';
+
 export const AppType = import.meta.env.VITE_AppType || 'one';
+
+export const AppLocalConfig = {
+  menuScene: EnumMenuScene.Goverment,
+};
diff --git a/src/constants/enum.ts b/src/constants/enum.ts
index 2c5984b..80a41ea 100644
--- a/src/constants/enum.ts
+++ b/src/constants/enum.ts
@@ -51,3 +51,50 @@
 };
 
 export const TempFolderPath = 'https://parkmanagement.oss-cn-hangzhou.aliyuncs.com/12333/temp';
+
+export enum DepartmentType {
+  /**
+   * 甯傚満閮�
+   */
+  Market = 1,
+  /**
+   * 閿�鍞儴
+   */
+  Sale,
+  /**
+   * 瀹㈡埛閮�
+   */
+  Customer,
+  /**
+   * 鎷涘晢閮�
+   */
+  Merchants,
+}
+
+export const DepartmentTypeText = {
+  [DepartmentType.Market]: '甯傚満閮�',
+  [DepartmentType.Sale]: '閿�鍞儴',
+  [DepartmentType.Customer]: '瀹㈡埛閮�',
+  [DepartmentType.Merchants]: '鎷涘晢閮�',
+};
+
+export enum ExternalSystem {
+  /**
+   * 鍥涙祦鏀垮姟绔�
+   */
+  Goverend = 'goverend-admin-app-client',
+  /**
+   * 姹熶綉鍏变繚杩愯惀绔�
+   */
+  JYB = 'jyb-admin-app-client',
+  /**
+   * 鐏靛伐绯荤粺杩愯惀绔�
+   */
+  flexjob = 'flexjob-admin-app-client',
+}
+
+export const ExternalSystemText = {
+  [ExternalSystem.Goverend]: '鍥涙祦鏀垮姟绔�',
+  [ExternalSystem.JYB]: '姹熶綉鍏变繚杩愯惀绔�',
+  [ExternalSystem.flexjob]: '鐏靛伐绯荤粺杩愯惀绔�',
+};
diff --git a/src/constants/regExp.ts b/src/constants/regExp.ts
index f160fe8..8c4887b 100644
--- a/src/constants/regExp.ts
+++ b/src/constants/regExp.ts
@@ -9,4 +9,7 @@
   static PasswordRegexNoSymbol =
     // eslint-disable-next-line no-useless-escape
     /^(?![\d]+$)(?![a-z]+$)(?![A-Z]+$)[a-zA-Z\d]{6,16}$/;
+  static PasswordRegexOnlyLetterNumber =
+    // eslint-disable-next-line no-useless-escape
+    /^[a-zA-Z0-9]+$/;
 }
diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts
index d0276b5..6a1928c 100644
--- a/src/hooks/useUser.ts
+++ b/src/hooks/useUser.ts
@@ -1,9 +1,10 @@
 import { useUserStore } from '@/store/modules/user';
 import { UserUtils } from '@bole-core/core';
-// import * as userRoleServices from '@/services/api/UserRole';
+import * as userRoleServices from '@/services/api/UserRole';
 import * as userServices from '@/services/api/User';
 import { useQuery, useQueryClient } from '@tanstack/vue-query';
 import { formatRoleName } from '@/utils';
+import { EnumMenuScene } from '@/constants';
 
 export function useIsSystemAdmin() {
   const userStore = useUserStore();
@@ -23,14 +24,18 @@
   };
 }
 
-export function useAllRoleList() {
-  const { data: allRoleList, refetch } = useQuery({
-    queryKey: ['userServices/getAllRoles'],
+type UseAllRoleListOptions = {
+  menuScene?: EnumMenuScene;
+};
+
+export function useAllRoleList(options: UseAllRoleListOptions = {}) {
+  const { menuScene = EnumMenuScene.Goverment } = options;
+  const { data: allRoleList } = useQuery({
+    queryKey: ['userRoleServices/getRoles', menuScene],
     queryFn: async () => {
-      let res = await userServices.getAllRoles({ showLoading: false });
-      return res;
+      let res = await userRoleServices.getRoles({ menuScene }, { showLoading: false });
+      return res.data;
     },
-    placeholderData: () => [] as API.RoleInfo[],
     select(data) {
       return data.map((x) => ({
         ...x,
@@ -40,8 +45,12 @@
     },
   });
 
+  const enableRoleList = computed(() => {
+    return allRoleList.value.filter((x) => x.isEnable);
+  });
+
   return {
     allRoleList,
-    refetch,
+    enableRoleList,
   };
 }
diff --git a/src/router/index.ts b/src/router/index.ts
index 6fb9c51..e2e0658 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -94,46 +94,6 @@
       rootMenu: true,
     },
   },
-  {
-    path: '/EnterpriseInfo',
-    redirect: 'noRedirect',
-    component: Layout,
-    hidden: false,
-    alwaysShow: true,
-    meta: {
-      rank: 10010,
-      title: '浼佷笟淇℃伅',
-      rootMenu: true,
-      icon: 'home',
-    },
-    children: [
-      {
-        path: '/EnterpriseInfoList',
-        name: 'EnterpriseInfoList',
-        hidden: false,
-        alwaysShow: true,
-        component: () => import('@/views/EnterpriseInfo/EnterpriseInfo.vue'),
-        meta: {
-          rank: 10011,
-          title: '浼佷笟淇℃伅',
-          // rootMenu: true,
-          icon: 'home',
-        },
-      },
-      {
-        path: '/EnterpriseInfoDetail/:id',
-        name: 'EnterpriseInfoDetail',
-        hidden: true,
-        component: () => import('@/views/EnterpriseInfo/EnterpriseInfoDetail.vue'),
-        meta: {
-          rank: 10012,
-          title: '浼佷笟淇℃伅璇︽儏',
-          // rootMenu: true,
-          icon: 'home',
-        },
-      },
-    ],
-  },
   // {
   //   path: '/MaterialReview',
   //   redirect: 'noRedirect',
@@ -210,123 +170,95 @@
   //   ],
   // },
 
-  {
-    path: '/Reward',
-    redirect: 'noRedirect',
-    component: Layout,
-    hidden: false,
-    alwaysShow: true,
-    meta: {
-      rank: 10030,
-      title: '骞冲彴濂栧姳',
-      rootMenu: true,
-      icon: 'home',
-    },
-    children: [
-      {
-        path: '/RewardGrant',
-        name: 'RewardGrant',
-        hidden: false,
-        alwaysShow: true,
-        component: () => import('@/views/Reward/RewardGrant.vue'),
-        meta: {
-          rank: 10031,
-          title: '濂栧姳鍙戞斁鐧昏',
-          // rootMenu: true,
-          icon: 'home',
-        },
-      },
-      {
-        path: '/RewardDeclareDetail/:id',
-        name: 'RewardDeclareDetail',
-        hidden: true,
-        component: () => import('@/views/Reward/RewardDeclareDetail.vue'),
-        meta: {
-          rank: 10032,
-          title: '鐢虫姤璇︽儏',
-          rootMenu: false,
-        },
-      },
-      {
-        path: '/RewardGrantRegister/:id',
-        name: 'RewardGrantRegister',
-        hidden: true,
-        component: () => import('@/views/Reward/RewardGrantRegister.vue'),
-        meta: {
-          rank: 10033,
-          title: '濂栧姳閲戠櫥璁�',
-          rootMenu: false,
-        },
-      },
-      {
-        path: '/WithdrawalApproval',
-        name: 'WithdrawalApproval',
-        hidden: false,
-        alwaysShow: true,
-        component: () => import('@/views/Reward/WithdrawalApproval.vue'),
-        meta: {
-          rank: 10040,
-          title: '鎻愮幇瀹℃壒',
-          // rootMenu: true,
-          icon: 'home',
-        },
-      },
-      {
-        path: '/RewardApplyTradeCheck',
-        name: 'RewardApplyTradeCheck',
-        hidden: false,
-        alwaysShow: true,
-        component: () => import('@/views/Reward/RewardApplyTradeCheck.vue'),
-        meta: {
-          rank: 10050,
-          title: '鍑鸿处瀹℃壒',
-          // rootMenu: true,
-          icon: 'home',
-        },
-      },
-      {
-        path: '/FinancialApproval',
-        name: 'FinancialApproval',
-        hidden: false,
-        alwaysShow: true,
-        component: () => import('@/views/Reward/FinancialApproval.vue'),
-        meta: {
-          rank: 10060,
-          title: '璐㈠姟瀹℃壒',
-          // rootMenu: true,
-          icon: 'home',
-        },
-      },
-    ],
-  },
-  {
-    path: '/StatisticalReport',
-    redirect: 'noRedirect',
-    component: Layout,
-    hidden: false,
-    alwaysShow: true,
-    meta: {
-      rank: 10040,
-      title: '缁熻鎶ヨ〃',
-      rootMenu: true,
-      icon: 'home',
-    },
-    children: [
-      {
-        path: '/RewardStatistics',
-        name: 'RewardStatistics',
-        hidden: false,
-        alwaysShow: true,
-        component: () => import('@/views/StatisticalReport/RewardStatistics.vue'),
-        meta: {
-          rank: 10041,
-          title: '濂栧姳閲戠粺璁�',
-          // rootMenu: true,
-          icon: 'home',
-        },
-      },
-    ],
-  },
+  // {
+  //   path: '/Reward',
+  //   redirect: 'noRedirect',
+  //   component: Layout,
+  //   hidden: false,
+  //   alwaysShow: true,
+  //   meta: {
+  //     rank: 10030,
+  //     title: '骞冲彴濂栧姳',
+  //     rootMenu: true,
+  //     icon: 'home',
+  //   },
+  //   children: [
+  //     {
+  //       path: '/RewardGrant',
+  //       name: 'RewardGrant',
+  //       hidden: false,
+  //       alwaysShow: true,
+  //       component: () => import('@/views/Reward/RewardGrant.vue'),
+  //       meta: {
+  //         rank: 10031,
+  //         title: '濂栧姳鍙戞斁鐧昏',
+  //         // rootMenu: true,
+  //         icon: 'home',
+  //       },
+  //     },
+  //     {
+  //       path: '/RewardDeclareDetail/:id',
+  //       name: 'RewardDeclareDetail',
+  //       hidden: true,
+  //       component: () => import('@/views/Reward/RewardDeclareDetail.vue'),
+  //       meta: {
+  //         rank: 10032,
+  //         title: '鐢虫姤璇︽儏',
+  //         rootMenu: false,
+  //       },
+  //     },
+  //     {
+  //       path: '/RewardGrantRegister/:id',
+  //       name: 'RewardGrantRegister',
+  //       hidden: true,
+  //       component: () => import('@/views/Reward/RewardGrantRegister.vue'),
+  //       meta: {
+  //         rank: 10033,
+  //         title: '濂栧姳閲戠櫥璁�',
+  //         rootMenu: false,
+  //       },
+  //     },
+  //     {
+  //       path: '/WithdrawalApproval',
+  //       name: 'WithdrawalApproval',
+  //       hidden: false,
+  //       alwaysShow: true,
+  //       component: () => import('@/views/Reward/WithdrawalApproval.vue'),
+  //       meta: {
+  //         rank: 10040,
+  //         title: '鎻愮幇瀹℃壒',
+  //         // rootMenu: true,
+  //         icon: 'home',
+  //       },
+  //     },
+  //     {
+  //       path: '/RewardApplyTradeCheck',
+  //       name: 'RewardApplyTradeCheck',
+  //       hidden: false,
+  //       alwaysShow: true,
+  //       component: () => import('@/views/Reward/RewardApplyTradeCheck.vue'),
+  //       meta: {
+  //         rank: 10050,
+  //         title: '鍑鸿处瀹℃壒',
+  //         // rootMenu: true,
+  //         icon: 'home',
+  //       },
+  //     },
+  //     {
+  //       path: '/FinancialApproval',
+  //       name: 'FinancialApproval',
+  //       hidden: false,
+  //       alwaysShow: true,
+  //       component: () => import('@/views/Reward/FinancialApproval.vue'),
+  //       meta: {
+  //         rank: 10060,
+  //         title: '璐㈠姟瀹℃壒',
+  //         // rootMenu: true,
+  //         icon: 'home',
+  //       },
+  //     },
+  //   ],
+  // },
   // {
   //   path: '/Syatem',
   //   redirect: 'noRedirect',
diff --git a/src/services/api/BaseModuleNew.ts b/src/services/api/BaseModuleNew.ts
index 7a09141..f07f8c8 100644
--- a/src/services/api/BaseModuleNew.ts
+++ b/src/services/api/BaseModuleNew.ts
@@ -2,6 +2,18 @@
 // @ts-ignore
 import { request } from '@/utils/request';
 
+/** 姝ゅ鍚庣娌℃湁鎻愪緵娉ㄩ噴 POST /api/BaseModuleNew/AddOrEditModuleV2 */
+export async function addOrEditModuleV2(body: API.ModuleDtoV2, options?: API.RequestConfig) {
+  return request<string>('/api/BaseModuleNew/AddOrEditModuleV2', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鏌ヨ鎵�鏈夋ā鍧� GET /api/BaseModuleNew/GetAllModuleList */
 export async function getAllModuleList(
   // 鍙犲姞鐢熸垚鐨凱aram绫诲瀷 (闈瀊ody鍙傛暟swagger榛樿娌℃湁鐢熸垚瀵硅薄)
@@ -17,6 +29,21 @@
   });
 }
 
+/** 姝ゅ鍚庣娌℃湁鎻愪緵娉ㄩ噴 GET /api/BaseModuleNew/GetCurrentUserModuleListV2 */
+export async function getCurrentUserModuleListV2(
+  body: API.ModuleDtoV2,
+  options?: API.RequestConfig
+) {
+  return request<number>('/api/BaseModuleNew/GetCurrentUserModuleListV2', {
+    method: 'GET',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 姝ゅ鍚庣娌℃湁鎻愪緵娉ㄩ噴 GET /api/BaseModuleNew/GetUserOrRoleModuleList */
 export async function getUserOrRoleModuleList(
   // 鍙犲姞鐢熸垚鐨凱aram绫诲瀷 (闈瀊ody鍙傛暟swagger榛樿娌℃湁鐢熸垚瀵硅薄)
diff --git a/src/services/api/ElectronSign.ts b/src/services/api/ElectronSign.ts
index 9f88cd0..9b1d048 100644
--- a/src/services/api/ElectronSign.ts
+++ b/src/services/api/ElectronSign.ts
@@ -44,6 +44,21 @@
   });
 }
 
+/** 鎵归噺鏇存柊瀹㈡埛鍚堝悓鍙傛暟鐘舵�� POST /api/ElectronSign/BatchUpdateCustomContractParamterStatus */
+export async function batchUpdateCustomContractParamterStatus(
+  body: API.BatchUpdateCustomContractParamterStatusInput,
+  options?: API.RequestConfig
+) {
+  return request<number>('/api/ElectronSign/BatchUpdateCustomContractParamterStatus', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鍒涘缓鎴栨洿鏂版ā鏉� POST /api/ElectronSign/CreateOrUpdateContractTemplate */
 export async function createOrUpdateContractTemplate(
   body: API.CreateOrUpdateContractTemplateInput,
@@ -175,6 +190,42 @@
   });
 }
 
+/** 鑾峰彇瀹㈡埛鍚堝悓鍙傛暟鍒楄〃 POST /api/ElectronSign/GetCustomContractParamterList */
+export async function getCustomContractParamterList(
+  body: API.GetCustomContractParamterListInput,
+  options?: API.RequestConfig
+) {
+  return request<API.GetCustomContractParamterListItemPageOutput>(
+    '/api/ElectronSign/GetCustomContractParamterList',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      data: body,
+      ...(options || {}),
+    }
+  );
+}
+
+/** 鑾峰彇瀹㈡埛鍚堝悓鍙傛暟閫夋嫨鍣� GET /api/ElectronSign/GetCustomContractParamterSelect */
+export async function getCustomContractParamterSelect(
+  // 鍙犲姞鐢熸垚鐨凱aram绫诲瀷 (闈瀊ody鍙傛暟swagger榛樿娌℃湁鐢熸垚瀵硅薄)
+  params: API.APIgetCustomContractParamterSelectParams,
+  options?: API.RequestConfig
+) {
+  return request<API.GetCustomContractParamterListItem[]>(
+    '/api/ElectronSign/GetCustomContractParamterSelect',
+    {
+      method: 'GET',
+      params: {
+        ...params,
+      },
+      ...(options || {}),
+    }
+  );
+}
+
 /** 鑾峰彇瀹㈡埛鍒楄〃 POST /api/ElectronSign/GetCustomerList */
 export async function getCustomerList(body: API.GetCustomerInput, options?: API.RequestConfig) {
   return request<API.GetCustomerDtoPageOutput>('/api/ElectronSign/GetCustomerList', {
@@ -280,6 +331,21 @@
   });
 }
 
+/** 淇濆瓨瀹㈡埛鍚堝悓鍙傛暟 POST /api/ElectronSign/SaveCustomContractParamter */
+export async function saveCustomContractParamter(
+  body: API.SaveCustomContractTemplateParamterInput,
+  options?: API.RequestConfig
+) {
+  return request<string>('/api/ElectronSign/SaveCustomContractParamter', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鍙戣捣绛剧害 POST /api/ElectronSign/SendContract */
 export async function sendContract(body: API.SendContractInput, options?: API.RequestConfig) {
   return request<API.SendContractOutput>('/api/ElectronSign/SendContract', {
diff --git a/src/services/api/EnterpriseApplyFile.ts b/src/services/api/EnterpriseApplyFile.ts
index a05e787..68c201a 100644
--- a/src/services/api/EnterpriseApplyFile.ts
+++ b/src/services/api/EnterpriseApplyFile.ts
@@ -32,6 +32,21 @@
   });
 }
 
+/** 纭鎻愪氦鏉愭枡涓婁紶V2 POST /api/EnterpriseApplyFile/CustomerUploadMonthApplyFileV2 */
+export async function customerUploadMonthApplyFileV2(
+  body: API.CustomerUploadMonthApplyFileInput,
+  options?: API.RequestConfig
+) {
+  return request<number>('/api/EnterpriseApplyFile/CustomerUploadMonthApplyFileV2', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鍒犻櫎瀹㈡埛鍥涙祦鏉愭枡 POST /api/EnterpriseApplyFile/DeleteEnterpriseApplyUploadFile */
 export async function deleteEnterpriseApplyUploadFile(
   // 鍙犲姞鐢熸垚鐨凱aram绫诲瀷 (闈瀊ody鍙傛暟swagger榛樿娌℃湁鐢熸垚瀵硅薄)
@@ -116,6 +131,24 @@
   );
 }
 
+/** 鑾峰彇鏈堜唤涓婁紶鏂囦欢璇︽儏V2 POST /api/EnterpriseApplyFile/GetCustomerUploadApplyFilesV2 */
+export async function getCustomerUploadApplyFilesV2(
+  body: API.GetCustomerUploadApplyFilesInput,
+  options?: API.RequestConfig
+) {
+  return request<API.GetCustomerUploadApplyFilesResponse>(
+    '/api/EnterpriseApplyFile/GetCustomerUploadApplyFilesV2',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      data: body,
+      ...(options || {}),
+    }
+  );
+}
+
 /** 鏍规嵁鏈堜唤鏌ヨ鏄惁瀛樺湪鎻愪氦璁板綍 POST /api/EnterpriseApplyFile/GetCustomerUploadFileRecord */
 export async function getCustomerUploadFileRecord(
   body: API.GetCustomerUploadFileRecordInput,
@@ -134,6 +167,24 @@
   );
 }
 
+/** 鏍规嵁鏈堜唤鏌ヨ鏄惁瀛樺湪鎻愪氦璁板綍V2 POST /api/EnterpriseApplyFile/GetCustomerUploadFileRecordV2 */
+export async function getCustomerUploadFileRecordV2(
+  body: API.GetCustomerUploadFileRecordInput,
+  options?: API.RequestConfig
+) {
+  return request<API.GetCustomerUploadFileRecordOutput>(
+    '/api/EnterpriseApplyFile/GetCustomerUploadFileRecordV2',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      data: body,
+      ...(options || {}),
+    }
+  );
+}
+
 /** 鎸夋湀浠芥煡璇紒涓氫笂浼犳潗鏂欏垪琛� POST /api/EnterpriseApplyFile/GetEnterpriseApplyUploadFile */
 export async function getEnterpriseApplyUploadFile(
   body: API.PageInput,
diff --git a/src/services/api/ParkBountyApply.ts b/src/services/api/ParkBountyApply.ts
index e420fb5..978cf23 100644
--- a/src/services/api/ParkBountyApply.ts
+++ b/src/services/api/ParkBountyApply.ts
@@ -790,6 +790,21 @@
   );
 }
 
+/** 瀵煎嚭鍥尯瀹㈡埛绠$悊鍒楄〃 POST /api/ParkBountyApply/GetParkCustomerManagePageNewExport */
+export async function getParkCustomerManagePageNewExport(
+  body: API.QueryParkCustomerManageInput,
+  options?: API.RequestConfig
+) {
+  return request<any>('/api/ParkBountyApply/GetParkCustomerManagePageNewExport', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鏌ヨ濂栧姳閲戠粺璁℃姤琛� POST /api/ParkBountyApply/GetRewardStatistics */
 export async function getRewardStatistics(
   body: API.GetRewardStatisticsInput,
diff --git a/src/services/api/UserRole.ts b/src/services/api/UserRole.ts
index 9d36735..e4e4376 100644
--- a/src/services/api/UserRole.ts
+++ b/src/services/api/UserRole.ts
@@ -32,6 +32,21 @@
   });
 }
 
+/** 鍒涘缓鏀垮姟绔鐞嗗瓙璐︽埛 POST /api/UserRole/CreateGovermentSubAccounts */
+export async function createGovermentSubAccounts(
+  body: API.CreateGovermentSubAccounts,
+  options?: API.RequestConfig
+) {
+  return request<string>('/api/UserRole/CreateGovermentSubAccounts', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鏂板瑙掕壊 POST /api/UserRole/CreateRole */
 export async function createRole(body: API.CreateBaseRoleInput, options?: API.RequestConfig) {
   return request<string>('/api/UserRole/CreateRole', {
@@ -104,6 +119,21 @@
   });
 }
 
+/** 鏀垮姟绔鐞嗗瓙璐︽埛鍒楄〃 POST /api/UserRole/GetGovermentSubAccounts */
+export async function getGovermentSubAccounts(
+  body: API.GetBackClientUsersInput,
+  options?: API.RequestConfig
+) {
+  return request<API.UserDtoPageOutput>('/api/UserRole/GetGovermentSubAccounts', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 瑙掕壊鍒楄〃 POST /api/UserRole/GetRoles */
 export async function getRoles(body: API.GetRolesInput, options?: API.RequestConfig) {
   return request<API.RoleInfoPageOutput>('/api/UserRole/GetRoles', {
@@ -161,6 +191,21 @@
   });
 }
 
+/** 缂栬緫鏀垮姟绔鐞嗗瓙璐︽埛 POST /api/UserRole/UpdateGovermentSubAccounts */
+export async function updateGovermentSubAccounts(
+  body: API.UpdateGovermentClientUserInput,
+  options?: API.RequestConfig
+) {
+  return request<number>('/api/UserRole/UpdateGovermentSubAccounts', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 瑙掕壊缂栬緫 POST /api/UserRole/UpdateRole */
 export async function updateRole(body: API.CreateOrUpdateRoleInput, options?: API.RequestConfig) {
   return request<number>('/api/UserRole/UpdateRole', {
diff --git a/src/services/api/typings.d.ts b/src/services/api/typings.d.ts
index e8377f6..0dbdc97 100644
--- a/src/services/api/typings.d.ts
+++ b/src/services/api/typings.d.ts
@@ -1381,6 +1381,15 @@
     moduleId?: string;
   }
 
+  interface APIgetCustomContractParamterSelectParams {
+    /** 瀹㈡埛Id */
+    customerId?: string;
+    /** 鏄惁榛樿 */
+    isDefault?: boolean;
+    /** 鍚堝悓妯℃澘Id */
+    templateId?: string;
+  }
+
   interface APIgetCustomerFileTypeHeadParams {
     enterpriseId?: string;
   }
@@ -2869,6 +2878,14 @@
     status?: EnumElectronSignContractParameterStatus;
   }
 
+  interface BatchUpdateCustomContractParamterStatusInput {
+    /** 瀹㈡埛Id */
+    customerId?: string;
+    /** 鍙傛暟Id */
+    ids?: string[];
+    status?: EnumElectronSignContractParameterStatus;
+  }
+
   interface BestSignDownloadImageDataResponse {
     /** 鍥剧墖鏂囦欢娴� */
     data?: any[];
@@ -4194,6 +4211,37 @@
     status?: CooperationApplyStatusEnum;
   }
 
+  interface CreateGovermentSubAccounts {
+    /** 鍚嶇О */
+    name?: string;
+    /** 鐢ㄦ埛鍚� */
+    userName?: string;
+    /** 澶囨敞 */
+    remark?: string;
+    /** 鎵嬫満鍙� */
+    phoneNumber?: string;
+    /** 鐢ㄦ埛绔疘d */
+    clientId?: string;
+    /** 鍥尯Ids */
+    industrialParkIds?: string[];
+    /** 瑙掕壊 */
+    roleNames?: string[];
+    /** 鏄惁鐞嗚禂鎻愰啋 */
+    sendClaimMessage?: boolean;
+    /** 鏄惁淇濆崟鍒版湡鎻愰啋 */
+    sendBillExpireMessage?: boolean;
+    /** 鏄惁鐭俊鎻愰啋 */
+    isSendMessage?: boolean;
+    /** 鏄惁浜哄憳鍙樻洿鎻愰啋 */
+    staffChangeMessage?: boolean;
+    /** 鏄惁鎵规敼鎻愰啋 */
+    batchUpdateMessage?: boolean;
+    /** 瀵嗙爜 */
+    password?: string;
+    /** 涓昏处鍙风敤鎴疯处鍙� */
+    subAccountCreator?: string;
+  }
+
   interface CreateGoverUserInput {
     /** 鍚嶇О */
     name?: string;
@@ -5046,6 +5094,8 @@
     isAutoSign?: boolean;
     /** 鑷姩绛炬巿鏉冧功 */
     autoSignPowerAttorneyUrl?: string;
+    /** 鑷畾涔夊唴瀹� */
+    customContents?: string[];
     /** 妯℃澘鍙橀噺 */
     values: CreateOrUpdateContractTemplateValueInput[];
   }
@@ -5781,6 +5831,8 @@
     applyAmount?: number;
     fileTypes?: CustomerUploadMonthApplyFileType[];
     enterpriseId?: string;
+    /** 鏄惁鏄繍钀ョ浠d笂浼� */
+    isAdminFileUpload?: boolean;
   }
 
   interface CustomerUploadMonthApplyFileType {
@@ -7283,6 +7335,17 @@
     data?: GetContractParamterListItem[];
   }
 
+  interface GetContractTemplateCustomContentDto {
+    /** 鍚堝悓妯℃澘Id */
+    templateId?: string;
+    /** 鍙橀噺鍚嶇О */
+    label?: string;
+    /** 鍙橀噺浠g爜 */
+    name?: string;
+    /** 鍊� */
+    value?: string;
+  }
+
   interface GetContractTemplateDto {
     /** Id */
     id?: string;
@@ -7299,6 +7362,8 @@
     isAutoSign?: boolean;
     /** 鑷姩绛炬巿鏉冧功 */
     autoSignPowerAttorneyUrl?: string;
+    /** 妯℃澘鍙橀噺 */
+    customContents?: GetContractTemplateCustomContentDto[];
     /** 妯℃澘鍙橀噺 */
     values?: GetContractTemplateValueDto[];
   }
@@ -7381,6 +7446,33 @@
     startDate?: string;
     /** 鎴鏃ユ湡 */
     endDate?: string;
+  }
+
+  interface GetCustomContractParamterListInput {
+    pageModel?: Pagination;
+    /** 瀹㈡埛Id */
+    customerId?: string;
+    /** 鍏抽敭瀛� */
+    keywords?: string;
+    status?: EnumElectronSignContractParameterStatus;
+  }
+
+  interface GetCustomContractParamterListItem {
+    /** 鍙傛暟Id */
+    id?: string;
+    /** 鍙橀噺鍚嶇О */
+    label?: string;
+    /** 鍙橀噺浠g爜 */
+    name?: string;
+    /** 鏄惁榛樿 */
+    isDefault?: boolean;
+    status?: EnumElectronSignContractParameterStatus;
+  }
+
+  interface GetCustomContractParamterListItemPageOutput {
+    pageModel?: Pagination;
+    objectData?: any;
+    data?: GetCustomContractParamterListItem[];
   }
 
   interface GetCustomerDto {
@@ -9580,6 +9672,7 @@
     bankBranchName?: string;
     /** 閾惰鍗″彿 */
     bankCardNumber?: string;
+    userCertificationStatus?: UserCertificationStatusEnum;
   }
 
   interface GetParkCustomerManageOutput {
@@ -15256,6 +15349,25 @@
     parentModuleName?: string;
   }
 
+  interface ModuleDtoV2 {
+    id?: string;
+    description?: string;
+    sortCode?: number;
+    enabledMark?: number;
+    parentId?: string;
+    name?: string;
+    isCache?: boolean;
+    path?: string;
+    viewAddress?: string;
+    levelNum?: number;
+    enCode?: string;
+    menuSource?: EnumMenuScene;
+    icon?: string;
+    hasCheck?: boolean;
+    isMenu?: number;
+    parentModuleName?: string;
+  }
+
   interface ModuleExtensionDto {
     entities?: Record<string, any>;
     configuration?: Record<string, any>;
@@ -20392,6 +20504,18 @@
     status?: EnumElectronSignContractParameterStatus;
   }
 
+  interface SaveCustomContractTemplateParamterInput {
+    /** 瀹㈡埛Id */
+    customerId?: string;
+    /** 鍙傛暟Id */
+    id?: string;
+    /** 鍙橀噺鍚嶇О */
+    label?: string;
+    /** 鍙橀噺浠g爜 */
+    name?: string;
+    status?: EnumElectronSignContractParameterStatus;
+  }
+
   interface SaveCustomerTemplateParamInput {
     /** 妯℃澘id */
     lgGigWorkerCustomerTemplateId?: string;
diff --git a/src/views/EnterpriseInfo/EnterpriseInfo.vue b/src/views/EnterpriseInfo/EnterpriseInfo.vue
index bfe6b5c..46bd33c 100644
--- a/src/views/EnterpriseInfo/EnterpriseInfo.vue
+++ b/src/views/EnterpriseInfo/EnterpriseInfo.vue
@@ -72,109 +72,19 @@
 import _ from 'lodash';
 import { ModelValueType } from 'element-plus';
 import { EnterpriseTypeText } from '@/constants';
+import { useAccess } from '@/hooks';
 
 defineOptions({
   name: 'EnterpriseInfo',
 });
 
-const column: API.CustomModuleColumnDto[] = [
-  {
-    id: '1',
-    enCode: 'enterpriseName',
-    name: '浼佷笟鍚�',
-    width: 250,
-  },
-  {
-    id: '2',
-    enCode: 'societyCreditCode',
-    name: '缁熶竴绀句細淇$敤浠g爜',
-    width: 200,
-  },
-  {
-    id: '3',
-    enCode: 'enterpriseType',
-    name: '浼佷笟绫诲瀷',
-    width: 150,
-  },
-  {
-    id: '4',
-    enCode: 'industrialParkName',
-    name: '鎵�灞炲洯鍖�',
-    width: 200,
-  },
-  {
-    id: '5',
-    enCode: 'parkTypName',
-    name: '鍥尯绫诲瀷',
-    width: 150,
-  },
-  {
-    id: '6',
-    enCode: 'applyCount',
-    name: '鐢虫姤娆℃暟',
-    width: 150,
-  },
-  {
-    id: '7',
-    enCode: 'lastApplyTime',
-    name: '鏈�杩戠敵鎶ユ棩鏈�',
-    width: 180,
-  },
-  {
-    id: '8',
-    enCode: 'financeCount',
-    name: '璐㈡斂鎷ㄤ粯娆℃暟',
-    width: 150,
-  },
-  {
-    id: '9',
-    enCode: 'lastFinanceTime',
-    name: '鏈�杩戣储鏀挎嫧浠樻棩鏈�',
-    width: 180,
-  },
-  {
-    id: '10',
-    enCode: 'financeSumAmount',
-    name: '璐㈡斂鎷ㄤ粯鎬婚',
-    width: 150,
-  },
-  {
-    id: '11',
-    enCode: 'settleCount',
-    name: '骞冲彴鎷ㄤ粯娆℃暟',
-    width: 150,
-  },
-  {
-    id: '12',
-    enCode: 'lastSettleTime',
-    name: '鏈�杩戝钩鍙版嫧浠樻棩鏈�',
-    width: 180,
-  },
-  {
-    id: '13',
-    enCode: 'settleSumAmount',
-    name: '骞冲彴鎷ㄤ粯鎬婚',
-    width: 150,
-  },
-  {
-    id: '14',
-    enCode: 'bountyAmount',
-    name: '骞冲彴鎷ㄤ粯浣欓',
-    width: 150,
-  },
-];
+const operationBtnMap: Record<string, OperationBtnType> = {
+  detailBtn: { emits: { onClick: (role) => goDetail(role) } },
+};
 
-const operationBtns = defineOperationBtns([
-  {
-    data: {
-      enCode: 'detailBtn',
-      name: '璇︽儏',
-    },
-    emits: {
-      onClick: (role) => goDetail(role),
-    },
-  },
-]);
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+  operationBtnMap,
+});
 
 const router = useRouter();
 const BaseState = {
diff --git a/src/views/MaterialReview/MaterialReReviewList.vue b/src/views/MaterialReview/MaterialReReviewList.vue
index bb422f0..da49c0b 100644
--- a/src/views/MaterialReview/MaterialReReviewList.vue
+++ b/src/views/MaterialReview/MaterialReReviewList.vue
@@ -71,90 +71,19 @@
 import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
 import _ from 'lodash';
 import { ModelValueType } from 'element-plus';
-import { useGlobalEventContext } from '@/hooks';
+import { useAccess, useGlobalEventContext } from '@/hooks';
 
 defineOptions({
   name: 'MaterialReviewList',
 });
 
-const column: API.CustomModuleColumnDto[] = [
-  {
-    id: '1',
-    enCode: 'batchNo',
-    name: '鐢宠鎵规鍙�',
-  },
-  {
-    id: '2',
-    enCode: 'parkName',
-    name: '鐢宠鍥尯',
-  },
-  {
-    id: '3',
-    enCode: 'parkTypeName',
-    name: '鍥尯绫诲瀷',
-  },
-  {
-    id: '4',
-    enCode: 'applyMonth',
-    name: '鐢宠濂栧姳閲戞湀浠�',
-  },
-  {
-    id: '5',
-    enCode: 'applySumAmount',
-    name: '濂栧姳閲戞眹鎬婚噾棰濓紙鍏冿級',
-  },
-  {
-    id: '6',
-    enCode: 'creationTime',
-    name: '鐢虫姤鏃ユ湡',
-  },
-  {
-    id: '6-1',
-    enCode: 'outCheckAuditOperator',
-    name: '鍒濆浜�',
-  },
-  {
-    id: '6-2',
-    enCode: 'outCheckTime',
-    name: '鍒濆鏃ユ湡',
-  },
-  {
-    id: '6-3',
-    enCode: 'outCheckStatus',
-    name: '鍒濆鐘舵��',
-  },
-  {
-    id: '7',
-    enCode: 'outReCheckAuditOperator',
-    name: '澶嶅浜�',
-  },
-  {
-    id: '8',
-    enCode: 'outReCheckTime',
-    name: '澶嶅鏃ユ湡',
-  },
-  {
-    id: '9',
-    enCode: 'outReCheckStatus',
-    name: '澶嶅鐘舵��',
-  },
-];
-
-const operationBtns = defineOperationBtns([
-  {
-    data: {
-      enCode: 'detailBtn',
-      name: '璇︽儏',
-    },
+const operationBtnMap: Record<string, OperationBtnType> = {
+  detailBtn: {
     emits: {
       onClick: (role) => goDetail(role),
     },
   },
-  {
-    data: {
-      enCode: 'auditBtn',
-      name: '瀹℃牳',
-    },
+  auditBtn: {
     emits: {
       onClick: (role) => goAudit(role),
     },
@@ -163,7 +92,11 @@
         row.outReCheckStatus !== BountyCheckStatusEnum.WaitCheck,
     },
   },
-]);
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+  operationBtnMap,
+});
 
 const router = useRouter();
 const BaseState = {
diff --git a/src/views/MaterialReview/MaterialReview.vue b/src/views/MaterialReview/MaterialReview.vue
index 15f6a7c..690d192 100644
--- a/src/views/MaterialReview/MaterialReview.vue
+++ b/src/views/MaterialReview/MaterialReview.vue
@@ -71,75 +71,19 @@
 import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
 import _ from 'lodash';
 import { ModelValueType } from 'element-plus';
-import { useGlobalEventContext } from '@/hooks';
+import { useAccess, useGlobalEventContext } from '@/hooks';
 
 defineOptions({
   name: 'MaterialReviewList',
 });
 
-const column: API.CustomModuleColumnDto[] = [
-  {
-    id: '1',
-    enCode: 'batchNo',
-    name: '鐢宠鎵规鍙�',
-  },
-  {
-    id: '2',
-    enCode: 'parkName',
-    name: '鐢宠鍥尯',
-  },
-  {
-    id: '3',
-    enCode: 'parkTypeName',
-    name: '鍥尯绫诲瀷',
-  },
-  {
-    id: '4',
-    enCode: 'applyMonth',
-    name: '鐢宠濂栧姳閲戞湀浠�',
-  },
-  {
-    id: '5',
-    enCode: 'applySumAmount',
-    name: '濂栧姳閲戞眹鎬婚噾棰濓紙鍏冿級',
-  },
-  {
-    id: '6',
-    enCode: 'creationTime',
-    name: '鐢虫姤鏃ユ湡',
-  },
-  {
-    id: '7',
-    enCode: 'outCheckAuditOperator',
-    name: '瀹℃牳浜�',
-  },
-  {
-    id: '8',
-    enCode: 'outCheckTime',
-    name: '瀹℃牳鏃ユ湡',
-  },
-  {
-    id: '9',
-    enCode: 'outCheckStatus',
-    name: '瀹℃牳鐘舵��',
-  },
-];
-
-const operationBtns = defineOperationBtns([
-  {
-    data: {
-      enCode: 'detailBtn',
-      name: '璇︽儏',
-    },
+const operationBtnMap: Record<string, OperationBtnType> = {
+  detailBtn: {
     emits: {
       onClick: (role) => goDetail(role),
     },
   },
-  {
-    data: {
-      enCode: 'auditBtn',
-      name: '瀹℃牳',
-    },
+  auditBtn: {
     emits: {
       onClick: (role) => goAudit(role),
     },
@@ -148,7 +92,11 @@
         row.outCheckStatus !== BountyCheckStatusEnum.WaitCheck,
     },
   },
-]);
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+  operationBtnMap,
+});
 
 const router = useRouter();
 const BaseState = {
diff --git a/src/views/Permission/ExternalAccountManage.vue b/src/views/Permission/ExternalAccountManage.vue
new file mode 100644
index 0000000..77cd7b3
--- /dev/null
+++ b/src/views/Permission/ExternalAccountManage.vue
@@ -0,0 +1,223 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableQueryFilterBar @on-reset="reset">
+        <template #query>
+          <QueryFilterItem>
+            <SearchInput
+              v-model="extraParamState.queryCondition"
+              style="width: 200px"
+              placeholder="璐﹀彿/濮撳悕/鎵嬫満鍙�"
+              @on-click-search="getList"
+            >
+            </SearchInput>
+          </QueryFilterItem>
+        </template>
+        <template #btn>
+          <el-button
+            v-if="checkSubModuleItemShow('pageButton', 'addBtn')"
+            @click="openDialog()"
+            icon="Plus"
+            type="primary"
+            >鏂板</el-button
+          >
+        </template>
+      </ProTableQueryFilterBar>
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+      </ProTableV2>
+    </AppContainer>
+    <AddOrEditExternalAccountDialog v-bind="dialogProps" />
+    <ResetPasswordDialog v-bind="resetPasswordDialogProps"></ResetPasswordDialog>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  ProTableQueryFilterBar,
+  ProTableV2,
+  SearchInput,
+  LoadingLayout,
+  AppContainer,
+  QueryFilterItem,
+  useTable,
+  useFormDialog,
+  defineOperationBtns,
+} from '@bole-core/components';
+import * as userRoleServices from '@/services/api/UserRole';
+import * as accountServices from '@/services/api/Account';
+import { Message, OrderInputType } from '@bole-core/core';
+import AddOrEditExternalAccountDialog from './components/AddOrEditExternalAccountDialog.vue';
+import ResetPasswordDialog from './components/ResetPasswordDialog.vue';
+import { useAccess } from '@/hooks';
+import { ExternalSystem, ExternalSystemText } from '@/constants';
+
+defineOptions({
+  name: 'ExternalAccountManage',
+});
+
+const operationBtnMap: Record<string, OperationBtnType> = {
+  editBtn: { emits: { onClick: (role) => openDialog(role) } },
+  resetPasswordBtn: { emits: { onClick: (role) => openResetPasswordDialog(role) } },
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+  operationBtnMap,
+});
+
+const BaseState = {
+  loading: true,
+};
+
+const state = reactive({ ...BaseState });
+
+onMounted(async () => {
+  await getList();
+  state.loading = false;
+});
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+  reset,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.GetBackClientUsersInput = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        queryCondition: extraParamState.queryCondition,
+      };
+      let res = await userRoleServices.getGovermentSubAccounts(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      orderInput: [{ property: 'id', order: OrderInputType.Desc }],
+      queryCondition: '',
+    },
+    columnsRenderProps: {
+      clientId: { type: 'enum', valueEnum: ExternalSystemText },
+    },
+  }
+);
+
+function openDialog(row?: API.UserDto) {
+  if (row) {
+    handleEdit({
+      id: row.id,
+      userName: row.userName,
+      name: row.name,
+      phoneNumber: row.phoneNumber,
+      password: '',
+      clientId: row.clientId,
+      industrialParkIds: row.industrialParkIds?.length > 0 ? row.industrialParkIds : [],
+      remark: row.remark,
+
+      isSendMessage: row.isSendMessage,
+      sendClaimMessage: row.sendClaimMessage,
+      sendBillExpireMessage: row.sendBillExpireMessage,
+      staffChangeMessage: row.staffChangeMessage,
+      batchUpdateMessage: row.batchUpdateMessage,
+
+      roleNames: row.roles.map((x) => x.name),
+    });
+  } else {
+    handleAdd();
+  }
+}
+
+const { dialogProps, handleAdd, handleEdit, editForm } = useFormDialog({
+  onConfirm: handleAddOrEdit,
+  defaultFormParams: {
+    id: '',
+    userName: '',
+    name: '',
+    phoneNumber: '',
+    clientId: '',
+    industrialParkIds: [] as string[],
+    password: '',
+    remark: '',
+
+    isSendMessage: false,
+    sendClaimMessage: false,
+    sendBillExpireMessage: false,
+    staffChangeMessage: false,
+    batchUpdateMessage: false,
+
+    roleNames: [] as string[],
+  },
+});
+
+async function handleAddOrEdit() {
+  try {
+    let isEdit = !!editForm.id;
+    let params: API.CreateGovermentSubAccounts = {
+      name: editForm.name,
+      userName: editForm.userName,
+      remark: editForm.remark,
+      phoneNumber: editForm.phoneNumber,
+      clientId: ExternalSystem.Goverend,
+      industrialParkIds: editForm.industrialParkIds,
+      roleNames: editForm.roleNames,
+      sendClaimMessage: editForm.sendClaimMessage,
+      sendBillExpireMessage: editForm.sendBillExpireMessage,
+      isSendMessage: editForm.isSendMessage,
+      staffChangeMessage: editForm.staffChangeMessage,
+      batchUpdateMessage: editForm.batchUpdateMessage,
+    };
+    let res;
+    if (isEdit) {
+      (params as API.UpdateGovermentClientUserInput).id = editForm.id;
+      res = await userRoleServices.updateGovermentSubAccounts(params);
+    } else {
+      (params as API.CreateGoverUserInput).password = editForm.password;
+      res = await userRoleServices.createGovermentSubAccounts(params);
+    }
+    if (res) {
+      Message.successMessage('鎿嶄綔鎴愬姛');
+      getList(isEdit ? paginationState.pageIndex : 1);
+    }
+  } catch (error) {}
+}
+
+const {
+  dialogProps: resetPasswordDialogProps,
+  handleAdd: handleResetPasswordAdd,
+  editForm: resetPasswordEditForm,
+} = useFormDialog({
+  onConfirm: resetPassword,
+  defaultFormParams: {
+    userId: '',
+    password: '',
+  },
+});
+
+function openResetPasswordDialog(row: API.UserDto) {
+  handleResetPasswordAdd({
+    userId: row.id,
+    password: '',
+  });
+}
+
+async function resetPassword() {
+  try {
+    let params: API.ResetPasswordBaseInput = {
+      userId: resetPasswordEditForm.userId,
+      password: resetPasswordEditForm.password,
+    };
+    let res = await accountServices.resetPassword(params);
+    if (res) {
+      Message.successMessage('鎿嶄綔鎴愬姛');
+      getList(paginationState.pageIndex);
+    }
+  } catch (error) {}
+}
+</script>
diff --git a/src/views/Permission/RoleManage.vue b/src/views/Permission/RoleManage.vue
index 5efdf97..c183cf6 100644
--- a/src/views/Permission/RoleManage.vue
+++ b/src/views/Permission/RoleManage.vue
@@ -25,11 +25,31 @@
         </template>
       </ProTableQueryFilterBar>
       <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+        <template #columns="{ row, column }">
+          <template v-if="column.property === 'departmentId'">
+            {{ DepartmentTypeText[row[column.property]] }}
+          </template>
+          <template v-else-if="column.property === 'dataRange'">
+            {{ DataRangeEnumText[row[column.property]] }}
+          </template>
+          <!-- <template v-else-if="column.property === 'isEnable'">
+            <FieldSwitch
+              active-text="鍚敤"
+              inactive-text="绂佺敤"
+              v-model="row.isEnable"
+              :before-change="() => roleEnableOrForbid(row)"
+            />
+          </template> -->
+        </template>
       </ProTableV2>
     </AppContainer>
     <AddOrEditRoleDialog v-bind="dialogProps" />
-    <DialogAuthorize v-model:authorizeId="rowState.authorizeId" authorizeType="Role" />
-    <!-- <DialogMember v-model:visibleId="rowState.setMemberRoleId" /> -->
+    <DialogAuthorize
+      v-model:authorizeId="rowState.authorizeId"
+      authorizeType="Role"
+      :menuScene="AppLocalConfig.menuScene"
+    />
+    <DialogMember v-model:visibleId="rowState.setMemberRoleId" />
   </LoadingLayout>
 </template>
 
@@ -44,13 +64,23 @@
   QueryFilterItem,
   useTable,
   useFormDialog,
+  FieldRadio,
 } from '@bole-core/components';
-import { useAccess, useAllRoleList } from '@/hooks';
-import * as userServices from '@/services/api/User';
+import { useAccess } from '@/hooks';
+import * as userRoleServices from '@/services/api/UserRole';
 import { Message, OrderInputType } from '@bole-core/core';
 import AddOrEditRoleDialog from './components/AddOrEditRoleDialog.vue';
-import { DataRangeEnum, DataRangeEnumText } from '@/constants';
 import DialogAuthorize from './components/dialogAuthorize.vue';
+import DialogMember from './components/dialogMember.vue';
+import {
+  DepartmentType,
+  DepartmentTypeText,
+  DataRangeEnum,
+  DataRangeEnumText,
+  EnumMenuSceneText,
+  EnumMenuScene,
+  AppLocalConfig,
+} from '@/constants';
 import { formatRoleName } from '@/utils';
 
 defineOptions({
@@ -61,17 +91,17 @@
   editBtn: { emits: { onClick: (role) => openDialog(role) } },
   delBtn: { emits: { onClick: (role) => handleDeleteRole(role) }, props: { type: 'danger' } },
   authorize: { emits: { onClick: (role) => openAuthorizeDialog(role) } },
-  // member: { emits: { onClick: (role) => openMemberDialog(role) } },
-  disabledBtn: {
-    emits: { onClick: (role) => roleEnableOrForbid(role) },
-    extraProps: {
-      hide: (row) => row.isEnable,
-    },
-  },
+  member: { emits: { onClick: (role) => openMemberDialog(role) } },
   enableBtn: {
     emits: { onClick: (role) => roleEnableOrForbid(role) },
     extraProps: {
-      hide: (row) => !row.isEnable,
+      hide: (row: API.RoleInfo) => row.isEnable,
+    },
+  },
+  disabledBtn: {
+    emits: { onClick: (role) => roleEnableOrForbid(role) },
+    extraProps: {
+      hide: (row: API.RoleInfo) => !row.isEnable,
     },
   },
 };
@@ -79,8 +109,6 @@
 const { checkSubModuleItemShow, column, operationBtns } = useAccess({
   operationBtnMap,
 });
-
-const { refetch } = useAllRoleList();
 
 const BaseState = {
   loading: true,
@@ -109,8 +137,9 @@
           orderInput: [{ property: 'sequence', order: OrderInputType.Asc }],
         },
         queryCondition: extraParamState.queryCondition,
+        menuScene: AppLocalConfig.menuScene,
       };
-      let res = await userServices.getRoles(params, {
+      let res = await userRoleServices.getRoles(params, {
         showLoading: !state.loading,
       });
       return {
@@ -140,6 +169,7 @@
       id: row.id,
       name: formatRoleName(row.name),
       remark: row.remark,
+      // departmentId: row.departmentId,
       dataRange: row.dataRange,
     });
   } else {
@@ -153,6 +183,7 @@
     id: '',
     name: '',
     remark: '',
+    // departmentId: DepartmentType.Market,
     dataRange: DataRangeEnum.All,
   },
 });
@@ -160,22 +191,24 @@
 async function handleAddOrEdit() {
   try {
     const isEdit = editForm.id;
-    let params: API.CreateOrUpdateRoleInput = {
+    let params: API.CreateBaseRoleInput = {
       name: editForm.name,
       remark: editForm.remark,
+      // departmentId: editForm.departmentId,
       dataRange: editForm.dataRange,
+      menuScene: AppLocalConfig.menuScene,
     };
     let res;
     if (isEdit) {
-      params.id = editForm.id;
-      res = await userServices.updateRole(params);
+      (params as API.CreateOrUpdateRoleInput).id = editForm.id;
+      res = await userRoleServices.updateRole(params);
     } else {
-      res = await userServices.createRole(params);
+      res = await userRoleServices.createRole(params);
     }
     if (res) {
       Message.successMessage('鎿嶄綔鎴愬姛');
       getList(isEdit ? paginationState.pageIndex : 1);
-      refetch({ type: 'inactive' });
+      dialogState.dialogVisible = false;
     }
   } catch (error) {}
 }
@@ -186,26 +219,24 @@
     let params = {
       id: row.id,
     };
-    let res = await userServices.deleteRole(params);
+    let res = await userRoleServices.deleteRole(params);
     if (res) {
       Message.successMessage('鎿嶄綔鎴愬姛');
       getList(paginationState.pageIndex);
-      refetch({ type: 'inactive' });
     }
   } catch (error) {}
 }
 
 async function roleEnableOrForbid(row: API.RoleInfo) {
   try {
-    await Message.tipMessage(`鏄惁${!row.isEnable ? '鍚敤' : '绂佺敤'}瑙掕壊`);
-    let res = await userServices.roleEnableOrForbid({
+    await Message.tipMessage(`鏄惁${!row.isEnable ? '鍚敤' : '绂佺敤'}鐢ㄦ埛`);
+    let res = await userRoleServices.roleEnableOrForbid({
       id: row.id,
       isEnable: !row.isEnable,
     });
     if (res) {
       Message.successMessage('鎿嶄綔鎴愬姛');
       getList(paginationState.pageIndex);
-      refetch({ type: 'inactive' });
       return !!res;
     }
   } catch (error) {}
@@ -220,7 +251,7 @@
   rowState.authorizeId = row.id;
 }
 
-// function openMemberDialog(row: API.IdentityRoleDto) {
-//   rowState.setMemberRoleId = row.id;
-// }
+function openMemberDialog(row: API.IdentityRoleDto) {
+  rowState.setMemberRoleId = row.id;
+}
 </script>
diff --git a/src/views/Permission/components/AddOrEditExternalAccountDialog.vue b/src/views/Permission/components/AddOrEditExternalAccountDialog.vue
new file mode 100644
index 0000000..796ff53
--- /dev/null
+++ b/src/views/Permission/components/AddOrEditExternalAccountDialog.vue
@@ -0,0 +1,210 @@
+<template>
+  <ProDialog
+    :title="form.title"
+    v-model="visible"
+    @close="onDialogClose"
+    destroy-on-close
+    draggable
+    :width="800"
+  >
+    <ProForm :model="form" ref="dialogForm" label-width="120px">
+      <ProFormItemV2
+        label="璐﹀彿:"
+        prop="userName"
+        :check-rules="[
+          { message: '璇疯緭鍏ヨ处鍙�' },
+          { message: '璐﹀彿浠呮敮鎸佸瓧姣嶅拰鏁板瓧', pattern: MyRegExp.PasswordRegexOnlyLetterNumber },
+        ]"
+      >
+        <ProFormText
+          placeholder="璇疯緭鍏ヨ处鍙�"
+          v-model.trim="form.userName"
+          :maxlength="30"
+        ></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2 label="濮撳悕:" prop="name" :check-rules="[{ message: '璇疯緭鍏ュ鍚�' }]">
+        <ProFormText
+          placeholder="璇疯緭鍏ュ鍚�"
+          v-model.trim="form.name"
+          :maxlength="30"
+        ></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2
+        label="鎵嬫満鍙�:"
+        prop="phoneNumber"
+        :check-rules="[{ message: '璇疯緭鍏ユ墜鏈哄彿', type: 'phone' }]"
+      >
+        <ProFormText placeholder="璇疯緭鍏ユ墜鏈哄彿" v-model.trim="form.phoneNumber"></ProFormText>
+      </ProFormItemV2>
+      <!-- <ProFormItemV2
+        label="澶栭儴绯荤粺:"
+        prop="clientId"
+        :check-rules="[{ message: '璇烽�夋嫨澶栭儴绯荤粺' }]"
+      >
+        <ProFormSelect
+          placeholder="璇烽�夋嫨澶栭儴绯荤粺"
+          v-model="form.clientId"
+          :value-enum="ExternalSystemText"
+        ></ProFormSelect>
+      </ProFormItemV2> -->
+
+      <ProFormItemV2
+        v-if="!isEdit"
+        label="瀵嗙爜:"
+        prop="password"
+        :check-rules="[{ message: '璇疯緭鍏ュ瘑鐮�', required: !form.id }]"
+      >
+        <ProFormText
+          placeholder="璇疯緭鍏ュ瘑鐮�"
+          v-model.trim="form.password"
+          :maxlength="30"
+        ></ProFormText>
+      </ProFormItemV2>
+
+      <ProFormItemV2 label="瑙掕壊" prop="roleNames" :check-rules="[{ message: '璇烽�夋嫨瑙掕壊' }]">
+        <ProFormCheckbox
+          v-model="form.roleNames"
+          :value-enum="enableRoleList"
+          enumLabelKey="name"
+          enum-value-key="realName"
+        ></ProFormCheckbox>
+      </ProFormItemV2>
+
+      <ProFormItemV2
+        v-if="form.clientId !== ExternalSystem.flexjob"
+        label="璐熻矗鍥尯:"
+        prop="industrialParkIds"
+        :check-rules="[{ message: '璇烽�夋嫨璐熻矗鍥尯' }]"
+      >
+        <ProFormSelect
+          placeholder="璇烽�夋嫨璐熻矗鍥尯"
+          v-model="form.industrialParkIds"
+          :value-enum="industrialParkList"
+          enum-label-key="parkName"
+          enum-value-key="id"
+          multiple
+        ></ProFormSelect>
+      </ProFormItemV2>
+      <template v-if="form.clientId === ExternalSystem.JYB">
+        <ProFormItemV2 label="鐭俊鎻愰啋:" prop="isSendMessage">
+          <ProFormRadio v-model="form.isSendMessage" :value-enum="BooleanOptions" />
+        </ProFormItemV2>
+        <ProFormItemV2
+          label="鎻愰啋鍐呭:"
+          prop="remind"
+          :check-rules="[
+            {
+              required: form.isSendMessage,
+              message: '璇烽�夋嫨鎻愰啋鍐呭',
+              validator: (rule, value, callback) => {
+                if (form.isSendMessage && !form.sendClaimMessage && !form.sendBillExpireMessage) {
+                  callback(new Error('璇烽�夋嫨鎻愰啋鍐呭'));
+                }
+                callback();
+              },
+            },
+          ]"
+        >
+          <el-checkbox v-model="form.sendClaimMessage" label="鐞嗚禂鎻愰啋" size="large" />
+          <el-checkbox v-model="form.sendBillExpireMessage" label="淇濆崟鍒版湡鎻愰啋" size="large" />
+          <el-checkbox v-model="form.staffChangeMessage" label="浜哄憳鍙樻洿鎻愰啋" size="large" />
+          <el-checkbox v-model="form.batchUpdateMessage" label="鎵规敼鎻愰啋" size="large" />
+        </ProFormItemV2>
+      </template>
+
+      <ProFormItemV2 label="澶囨敞:" prop="remark">
+        <ProFormTextArea
+          v-model="form.remark"
+          placeholder="璇疯緭鍏ュ娉�"
+          :maxlength="2000"
+        ></ProFormTextArea>
+      </ProFormItemV2>
+    </ProForm>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="emit('onCancel')">鍙� 娑�</el-button>
+        <el-button type="primary" @click="handleConfirm">纭� 瀹�</el-button>
+      </span>
+    </template>
+  </ProDialog>
+</template>
+
+<script setup lang="ts">
+import { FormInstance } from 'element-plus';
+import {
+  ProDialog,
+  ProForm,
+  ProFormItemV2,
+  ProFormText,
+  ProFormTextArea,
+  ProFormSelect,
+  ProFormRadio,
+  ProFormCheckbox,
+} from '@bole-core/components';
+import {
+  ExternalSystemText,
+  BooleanOptions,
+  ExternalSystem,
+  MyRegExp,
+  EnumMenuScene,
+} from '@/constants';
+import { useAllRoleList, useIndustrialParkDropDownList } from '@/hooks';
+import { BoleRegExp } from '@bole-core/core';
+
+defineOptions({
+  name: 'AddOrEditExternalAccountDialog',
+});
+
+// type Props = {};
+
+// const props = withDefaults(defineProps<Props>(), {});
+
+const visible = defineModel({ type: Boolean });
+const { industrialParkList } = useIndustrialParkDropDownList();
+
+type Form = {
+  title?: string;
+  id: string;
+  userName: string;
+  name: string;
+  phoneNumber: string;
+  clientId: string;
+  industrialParkIds: string[];
+  password: string;
+  remark: string;
+
+  isSendMessage?: boolean;
+  sendClaimMessage?: boolean;
+  sendBillExpireMessage?: boolean;
+  staffChangeMessage?: boolean;
+  batchUpdateMessage?: boolean;
+  roleNames: string[];
+};
+
+const { enableRoleList } = useAllRoleList({ menuScene: EnumMenuScene.Goverment });
+
+const form = defineModel<Form>('form');
+const isEdit = computed(() => !!form.value?.id);
+const emit = defineEmits<{
+  (e: 'onConfirm'): void;
+  (e: 'onCancel'): void;
+}>();
+
+const dialogForm = ref<FormInstance>();
+
+function onDialogClose() {
+  if (!dialogForm.value) return;
+  dialogForm.value.resetFields();
+}
+
+function handleConfirm() {
+  if (!dialogForm.value) return;
+  dialogForm.value.validate((valid) => {
+    if (valid) {
+      emit('onConfirm');
+    } else {
+      return;
+    }
+  });
+}
+</script>
diff --git a/src/views/Permission/components/ResetPasswordDialog.vue b/src/views/Permission/components/ResetPasswordDialog.vue
new file mode 100644
index 0000000..e974bfd
--- /dev/null
+++ b/src/views/Permission/components/ResetPasswordDialog.vue
@@ -0,0 +1,71 @@
+<template>
+  <ProDialog
+    :title="form.title"
+    v-model="visible"
+    @close="onDialogClose"
+    destroy-on-close
+    draggable
+    :width="800"
+  >
+    <ProForm :model="form" ref="dialogForm" label-width="120px">
+      <ProFormItemV2 label="瀵嗙爜:" prop="password" :check-rules="[{ message: '璇疯緭鍏ュ瘑鐮�' }]">
+        <ProFormText
+          placeholder="璇疯緭鍏ュ瘑鐮�"
+          v-model.trim="form.password"
+          :maxlength="30"
+        ></ProFormText>
+      </ProFormItemV2>
+    </ProForm>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="emit('onCancel')">鍙� 娑�</el-button>
+        <el-button type="primary" @click="handleConfirm">纭� 瀹�</el-button>
+      </span>
+    </template>
+  </ProDialog>
+</template>
+
+<script setup lang="ts">
+import { FormInstance } from 'element-plus';
+import { ProDialog, ProForm, ProFormItemV2, ProFormText } from '@bole-core/components';
+
+defineOptions({
+  name: 'ResetPasswordDialog',
+});
+
+// type Props = {};
+
+// const props = withDefaults(defineProps<Props>(), {});
+
+const visible = defineModel({ type: Boolean });
+
+type Form = {
+  title?: string;
+  userId: string;
+  password: string;
+};
+
+const form = defineModel<Form>('form');
+const emit = defineEmits<{
+  (e: 'onConfirm'): void;
+  (e: 'onCancel'): void;
+}>();
+
+const dialogForm = ref<FormInstance>();
+
+function onDialogClose() {
+  if (!dialogForm.value) return;
+  dialogForm.value.resetFields();
+}
+
+function handleConfirm() {
+  if (!dialogForm.value) return;
+  dialogForm.value.validate((valid) => {
+    if (valid) {
+      emit('onConfirm');
+    } else {
+      return;
+    }
+  });
+}
+</script>
diff --git a/src/views/Permission/components/dialogAuthorize.vue b/src/views/Permission/components/dialogAuthorize.vue
index 6708450..4f5f49e 100644
--- a/src/views/Permission/components/dialogAuthorize.vue
+++ b/src/views/Permission/components/dialogAuthorize.vue
@@ -156,10 +156,18 @@
 <script setup lang="ts">
 import { computed, reactive, watch } from 'vue';
 import * as baseModuleServices from '@/services/api/BaseModule';
+import * as baseModuleNewServices from '@/services/api/BaseModuleNew';
 import { Message } from '@bole-core/core';
-import { AuthorizeType, SubModuleType, SubModuleTitle } from '@/constants';
+import {
+  AuthorizeType,
+  SubModuleType,
+  SubModuleTitle,
+  EnumMenuSceneText,
+  EnumMenuScene,
+} from '@/constants';
 import { getTree } from '@/utils';
 import { templateRef } from '@vueuse/core';
+import { PropType } from 'vue';
 
 const TypeTip = defineComponent({
   name: 'TypeTip',
@@ -167,7 +175,6 @@
   render() {
     const { typeTip, isMenu } = this;
     const tipText = isMenu ? `鑿滃崟` : '椤甸潰';
-    console.log(typeTip);
     return h(
       'span',
       {
@@ -189,6 +196,10 @@
   authorizeType: {
     type: String,
     default: 'Role',
+  },
+  menuScene: {
+    type: Number as PropType<EnumMenuScene>,
+    default: EnumMenuScene.Back,
   },
 });
 const emit = defineEmits<{
@@ -333,12 +344,13 @@
 async function getModulesByUserOrRoleId(id) {
   const { authorizeType } = props;
 
-  const data = {
+  const data: API.APIgetUserOrRoleModuleListParams = {
     objectType: AuthorizeType[authorizeType],
     id,
+    menuScene: props.menuScene,
   };
 
-  const result = await baseModuleServices.getUserOrRoleModuleList(data);
+  const result = await baseModuleNewServices.getUserOrRoleModuleList(data);
 
   state.sysModules = getTree(result, null);
   elModuleTree.value.setCheckedKeys(result.filter((x) => x.hasCheck).map((x) => x.id));
diff --git a/src/views/Permission/components/dialogMember.vue b/src/views/Permission/components/dialogMember.vue
new file mode 100644
index 0000000..4010a4a
--- /dev/null
+++ b/src/views/Permission/components/dialogMember.vue
@@ -0,0 +1,286 @@
+<template>
+  <el-dialog :modelValue="visibleId != ''" width="1080px" title="鎴愬憳绠$悊" @close="handleClose">
+    <div class="setting-wrapper">
+      <div class="setting-wrapper-left">
+        <section class="table-wrapper">
+          <el-table :data="state.originAccountList" size="mini" stripe :max-height="400">
+            <el-table-column type="index" label="搴忓彿" width="100"> </el-table-column>
+            <el-table-column prop="userName" label="鐧诲綍璐﹀彿"> </el-table-column>
+            <el-table-column prop="name" label="濮撳悕"> </el-table-column>
+            <el-table-column label="" width="60">
+              <template #default="scope">
+                <el-button
+                  :icon="!scope.row.isCheck ? 'plus' : 'delete'"
+                  class="fa"
+                  link
+                  type="primary"
+                  @click="handleAddOrNot(scope.row.id)"
+                ></el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+
+          <div v-if="state.pagination.total !== 0" class="pagination-wrapper">
+            <el-pagination
+              layout=" prev, pager, next, jumper"
+              :page-sizes="[20, 50, 100, 200, 400, 500]"
+              :current-page="state.pagination.page"
+              :page-size="50"
+              :total="state.pagination.total"
+              @current-change="getAccountList"
+              @size-change="handleSizeChange"
+            >
+            </el-pagination>
+          </div>
+        </section>
+      </div>
+      <div class="setting-wrapper-right">
+        <el-scrollbar>
+          <el-table :data="state.checkedList" size="mini" stripe>
+            <el-table-column type="index" label="搴忓彿" width="55"> </el-table-column>
+            <el-table-column prop="userName" label="鐧诲綍璐﹀彿"> </el-table-column>
+            <el-table-column prop="name" label="濮撳悕"> </el-table-column>
+            <el-table-column label="" width="60">
+              <template #default="scope">
+                <el-button icon="delete" link type="primary" @click="handleAddOrNot(scope.row.id)">
+                </el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-scrollbar>
+      </div>
+    </div>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="handleClose"> 鍙栨秷 </el-button>
+        <el-button type="primary" @click="changeRoleAccount" class="btn-submit"> 淇濆瓨 </el-button>
+      </span>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import * as identityUserServices from '@/services/api/IdentityUser';
+import * as userRoleServices from '@/services/api/UserRole';
+
+import { Message } from '@bole-core/core';
+
+const props = defineProps({
+  visibleId: {
+    type: String,
+    default: '',
+  },
+});
+
+const emit = defineEmits<{
+  (e: 'update:visibleId', params: string): void;
+}>();
+
+watch(
+  () => props.visibleId,
+  async (newValue) => {
+    if (newValue) {
+      const result = await identityUserServices.getRoleUserList({
+        id: newValue,
+        pageModel: { rows: 100, page: 1 },
+      });
+
+      const { data } = result;
+      const list = data.map((item) => {
+        return {
+          id: item.id,
+          userName: item.userName,
+          name: item.name,
+        };
+      });
+      state.checkedList = list;
+      getAccountList();
+    }
+  }
+);
+
+const state = reactive({
+  checkedList: [],
+  originAccountList: [],
+  pagination: {
+    rows: 20,
+    page: 1,
+    orderInput: [{ property: 'Id', order: 'asc' }],
+    total: -1,
+  },
+});
+
+function handleClose() {
+  emit('update:visibleId', '');
+}
+
+function handleAddOrNot(id) {
+  const hitIndex = state.checkedList.findIndex((x) => x.id === id);
+
+  const isExistOrigin = state.originAccountList.findIndex((x) => x.id === id);
+
+  // 宸查��
+  if (hitIndex !== -1) {
+    //濡傛灉 褰撳墠account 鍙湁涓�涓猺ole涓旀槸褰撳墠鐨剅oleId visibleId鐨勮瘽灏变笉鑳藉垹闄�
+    if (isExistOrigin !== -1) {
+      const roles = state.originAccountList[isExistOrigin].roles;
+      const roleIndex = roles.findIndex((role) => role.id === props.visibleId);
+      if (roles.length === 1 && roleIndex !== -1) {
+        Message.warnMessage('璐﹀彿鏈変笖鍙湁璇ヨ鑹诧紝涓嶈兘鍒犻櫎');
+        return;
+      }
+    }
+    state.checkedList.splice(hitIndex, 1);
+  }
+
+  //鏈��
+  if (isExistOrigin !== -1) {
+    state.originAccountList[isExistOrigin]['isCheck'] = hitIndex === -1;
+
+    if (hitIndex === -1) {
+      const current = state.originAccountList[isExistOrigin];
+      state.checkedList.push({
+        id: current.id,
+        userName: current.userName,
+        name: current.name,
+        phone: current.phone,
+        isCheck: true,
+      });
+    }
+  }
+}
+
+async function getAccountList(pageIndex = 1) {
+  try {
+    state.pagination.page = pageIndex;
+
+    let params = {
+      pageModel: { rows: 100, page: 1 },
+    };
+
+    const result = await userRoleServices.getBackClientUsers(params);
+
+    const { data, pageModel } = result;
+
+    const { checkedList } = state;
+    data.forEach((x) => {
+      const isExistIndex = checkedList.findIndex((item) => x.id === item.id);
+      if (isExistIndex !== -1) {
+        //@ts-ignore
+        x.isCheck = true;
+      }
+    });
+
+    state.originAccountList = data;
+    state.pagination.total = pageModel.totalCount;
+  } catch (error) {
+    console.log(error);
+  }
+}
+
+function handleSizeChange(val) {
+  state.pagination.rows = val;
+  getAccountList();
+}
+
+async function changeRoleAccount() {
+  try {
+    const params = {
+      userId: state.checkedList.map((x) => x.id),
+      roleId: props.visibleId,
+    };
+    await identityUserServices.setRoleUser(params);
+    Message.successMessage('璁剧疆鎴愬姛!');
+    handleClose();
+  } catch (error) {
+    Message.errorMessage(error.message || '璁剧疆澶辫触!');
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+
+.setting-wrapper {
+  display: flex;
+  justify-content: space-between;
+  // position: relative;
+  width: 100%;
+  height: 440px;
+  border-bottom: 1px solid #e8e8e8;
+  background-color: #f5f5f5;
+
+  &-left {
+    position: relative;
+    display: flex;
+    width: 55%;
+    background-color: #ffffff;
+    box-shadow: 0px 2px 5px 0px rgba(112, 114, 117, 0.3);
+
+    .el-scrollbar {
+      height: 360px;
+
+      .el-scrollbar__bar.is-vertical {
+        padding-bottom: 18px;
+      }
+    }
+
+    .table-wrapper {
+      display: flex;
+      width: 100%;
+      flex-direction: column;
+
+      .pagination-wrapper {
+        display: flex;
+        justify-content: center;
+        margin: 6px 0;
+      }
+    }
+  }
+
+  &-right {
+    // width: 40%;
+    margin-left: 12px;
+    background-color: #ffffff;
+    box-shadow: 0px 2px 5px 0px rgba(112, 114, 117, 0.3);
+    flex: 1;
+
+    ul.selected-wrapper {
+      li {
+        position: relative;
+        padding-left: 30px;
+        width: 100%;
+        height: 47px;
+        font-size: 14px;
+        border-bottom: 1px solid #efefef;
+        color: #999999;
+        transition: all 0.45s ease;
+        line-height: 47px;
+
+        &:hover {
+          color: #ffffff;
+          background-color: boleGetCssVar('color', 'primary');
+
+          .el-icon-delete {
+            position: absolute;
+            display: inline-block;
+          }
+        }
+      }
+    }
+  }
+}
+
+.btn-wrapper {
+  justify-content: center;
+  padding: 4% 40px 4%;
+}
+
+:deep(.el-scrollbar) {
+  height: 100%;
+
+  .el-scrollbar__wrap {
+    overflow-x: hidden;
+  }
+}
+</style>
diff --git a/src/views/Reward/FinancialApproval.vue b/src/views/Reward/FinancialApproval.vue
index 93d7e26..4e491ce 100644
--- a/src/views/Reward/FinancialApproval.vue
+++ b/src/views/Reward/FinancialApproval.vue
@@ -45,11 +45,7 @@
           </QueryFilterItem>
         </template>
       </ProTableQueryFilterBar>
-      <ProTableV2
-        v-bind="proTableProps"
-        :columns="FinancialApprovalColumns"
-        :operationBtns="operationBtns"
-      >
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
       </ProTableV2>
       <RewardApplyTradeCheckDialog v-bind="dialogProps"></RewardApplyTradeCheckDialog>
     </AppContainer>
@@ -85,19 +81,15 @@
 import { ModelValueType } from 'element-plus';
 import RewardApplyTradeCheckDialog from './components/RewardApplyTradeCheckDialog.vue';
 import { convertApi2FormUrlObjectBySeparator, convertApi2FormUrlOnlyOne, format } from '@/utils';
-import { FinancialApprovalColumns } from './constants';
 import { useIndustrialParkDropDownList } from '@/hooks/industrialPark';
+import { useAccess } from '@/hooks';
 
 defineOptions({
   name: 'FinancialApproval',
 });
 
-const operationBtns = defineOperationBtns([
-  {
-    data: {
-      enCode: 'detailBtn',
-      name: '璇︽儏',
-    },
+const operationBtnMap: Record<string, OperationBtnType> = {
+  detailBtn: {
     emits: {
       onClick: (role) => openDialog(role, true),
     },
@@ -106,11 +98,7 @@
         row.financeAuditStatus === EnumParkBountyTradeDetailAuditStatus.Wait,
     },
   },
-  {
-    data: {
-      enCode: 'checkBtn',
-      name: '瀹℃壒',
-    },
+  checkBtn: {
     emits: {
       onClick: (row) => openDialog(row),
     },
@@ -119,7 +107,11 @@
         row.financeAuditStatus !== EnumParkBountyTradeDetailAuditStatus.Wait,
     },
   },
-]);
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+  operationBtnMap,
+});
 
 const BaseState = {
   loading: true,
diff --git a/src/views/Reward/RewardApplyTradeCheck.vue b/src/views/Reward/RewardApplyTradeCheck.vue
index 75bc690..af32caa 100644
--- a/src/views/Reward/RewardApplyTradeCheck.vue
+++ b/src/views/Reward/RewardApplyTradeCheck.vue
@@ -45,11 +45,7 @@
           </QueryFilterItem>
         </template>
       </ProTableQueryFilterBar>
-      <ProTableV2
-        v-bind="proTableProps"
-        :columns="RewardApplyTradeCheckColumns"
-        :operationBtns="operationBtns"
-      >
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
       </ProTableV2>
       <RewardApplyTradeCheckDialog isApplyTrade v-bind="dialogProps"></RewardApplyTradeCheckDialog>
     </AppContainer>
@@ -85,19 +81,15 @@
 import { ModelValueType } from 'element-plus';
 import RewardApplyTradeCheckDialog from './components/RewardApplyTradeCheckDialog.vue';
 import { convertApi2FormUrlObjectBySeparator, convertApi2FormUrlOnlyOne, format } from '@/utils';
-import { RewardApplyTradeCheckColumns } from './constants';
 import { useIndustrialParkDropDownList } from '@/hooks/industrialPark';
+import { useAccess } from '@/hooks';
 
 defineOptions({
   name: 'RewardApplyTradeCheck',
 });
 
-const operationBtns = defineOperationBtns([
-  {
-    data: {
-      enCode: 'detailBtn',
-      name: '璇︽儏',
-    },
+const operationBtnMap: Record<string, OperationBtnType> = {
+  detailBtn: {
     emits: {
       onClick: (role) => openDialog(role, true),
     },
@@ -106,11 +98,7 @@
         row.auditStatus === EnumParkBountyTradeDetailAuditStatus.Wait,
     },
   },
-  {
-    data: {
-      enCode: 'checkBtn',
-      name: '瀹℃壒',
-    },
+  checkBtn: {
     emits: {
       onClick: (row) => openDialog(row),
     },
@@ -119,7 +107,11 @@
         row.auditStatus !== EnumParkBountyTradeDetailAuditStatus.Wait,
     },
   },
-]);
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+  operationBtnMap,
+});
 
 const BaseState = {
   loading: true,
diff --git a/src/views/Reward/RewardGrant.vue b/src/views/Reward/RewardGrant.vue
index 3a18a2b..a132996 100644
--- a/src/views/Reward/RewardGrant.vue
+++ b/src/views/Reward/RewardGrant.vue
@@ -121,123 +121,16 @@
 import { useQueryClient } from '@tanstack/vue-query';
 import { TransferFileEnumInRewardGrandTableItem } from '@/components/commonView/types';
 import { FourStreamsMaterialUtils } from '@/components/commonView/utils';
+import { useAccess } from '@/hooks';
 
 defineOptions({
   name: 'RewardGrant',
 });
 
-const column: API.CustomModuleColumnDto[] = [
-  {
-    id: '1',
-    enCode: 'batchNo',
-    name: '鐢宠鎵规鍙�',
-    width: 160,
-  },
-  {
-    id: '2',
-    enCode: 'parkName',
-    name: '鐢宠鍥尯',
-    width: 250,
-  },
-  {
-    id: '3',
-    enCode: 'parkTypeName',
-    name: '鍥尯绫诲瀷',
-    width: 160,
-  },
-  {
-    id: '4',
-    enCode: 'applyMonth',
-    name: '鐢宠骞冲彴濂栧姳鏈堜唤',
-    width: 160,
-  },
-  {
-    id: '5',
-    enCode: 'applySumAmount',
-    name: '骞冲彴濂栧姳姹囨�婚噾棰濓紙鍏冿級',
-    width: 180,
-  },
-  {
-    id: '6',
-    enCode: 'creationTime',
-    name: '鐢虫姤鏃ユ湡',
-    width: 180,
-  },
-  {
-    id: '7',
-    enCode: 'financeStatus',
-    name: '璐㈡斂鎷ㄤ粯鐧昏鐘舵��',
-    width: 160,
-  },
-  {
-    id: '8',
-    enCode: 'financeTime',
-    name: '璐㈡斂鎷ㄤ粯鐧昏鏃ユ湡',
-    width: 180,
-  },
-  {
-    id: '9',
-    enCode: 'settleStatus',
-    name: '骞冲彴鎷ㄤ粯鐧昏鐘舵��',
-    width: 160,
-  },
-  {
-    id: '10',
-    enCode: 'settleTime',
-    name: '骞冲彴鎷ㄤ粯鐧昏鏃ユ湡',
-    width: 180,
-  },
-  {
-    id: '11',
-    enCode: 'settleAndFinanceOperator',
-    name: '鐧昏浜�',
-  },
-];
-
-const operationBtns = defineOperationBtns([
-  {
-    data: {
-      enCode: 'detailBtn',
-      name: '鐢虫姤璇︽儏',
-    },
-    emits: {
-      onClick: (role) => goDetail(role),
-    },
-  },
-  // {
-  //   data: {
-  //     enCode: 'financialBtn',
-  //     name: '璐㈡斂鎷ㄤ粯',
-  //   },
-  //   emits: {
-  //     onClick: (role) => openFinancialDialog(role),
-  //   },
-  //   extraProps: {
-  //     hide: (row: API.GetParkBountyApplyListOutput) =>
-  //       row.financeStatus === FinanceStatusEnum.HasIncome,
-  //   },
-  // },
-  // {
-  //   data: {
-  //     enCode: 'plateformBtn',
-  //     name: '骞冲彴鍏呭��',
-  //   },
-  //   emits: {
-  //     onClick: (role) => openPlateformDialog(role),
-  //   },
-  //   extraProps: {
-  //     hide: (row: API.GetParkBountyApplyListOutput) =>
-  //       row.settleStatus !== SettleStatusEnum.WaitForSettle,
-  //   },
-  // },
-  {
-    data: {
-      enCode: 'registerBtn',
-      name: '鐧昏',
-    },
-    emits: {
-      onClick: (role) => goRewardGrantRegister(role),
-    },
+const operationBtnMap: Record<string, OperationBtnType> = {
+  detailBtn: { emits: { onClick: (role) => goDetail(role) } },
+  registerBtn: {
+    emits: { onClick: (role) => goRewardGrantRegister(role) },
     extraProps: {
       hide: (row: API.GetParkBountyApplyListOutput) =>
         !(
@@ -246,27 +139,7 @@
         ),
     },
   },
-  // {
-  //   data: {
-  //     enCode: 'uploadCertBtn',
-  //     name: '涓婁紶鍑瘉',
-  //   },
-  //   emits: {
-  //     onClick: (role) => openCertRewardDialog(role),
-  //   },
-  //   extraProps: {
-  //     hide: (row: API.GetParkBountyApplyListOutput) =>
-  //       !(
-  //         row.settleStatus === SettleStatusEnum.HasSettle ||
-  //         row.financeStatus === FinanceStatusEnum.HasIncome
-  //       ),
-  //   },
-  // },
-  {
-    data: {
-      enCode: 'checkBtn',
-      name: '鏌ョ湅鍑瘉',
-    },
+  checkBtn: {
     emits: {
       onClick: (row) => openMaterialFileDialog(row),
     },
@@ -278,7 +151,11 @@
         ),
     },
   },
-]);
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+  operationBtnMap,
+});
 
 const router = useRouter();
 const BaseState = {
diff --git a/src/views/Reward/WithdrawalApproval.vue b/src/views/Reward/WithdrawalApproval.vue
index e068d2e..6776b22 100644
--- a/src/views/Reward/WithdrawalApproval.vue
+++ b/src/views/Reward/WithdrawalApproval.vue
@@ -64,70 +64,14 @@
 import WithdrawalApprovalAuditDialog from './components/WithdrawalApprovalAuditDialog.vue';
 import _ from 'lodash';
 import { ModelValueType } from 'element-plus';
+import { useAccess } from '@/hooks';
 
 defineOptions({
   name: 'WithdrawalApproval',
 });
 
-const column: API.CustomModuleColumnDto[] = [
-  {
-    id: '1',
-    enCode: 'enterpriseName',
-    name: '浼佷笟鍚嶇О',
-  },
-  {
-    id: '2',
-    enCode: 'societyCreditCode',
-    name: '缁熶竴绀句細淇$敤浠g爜',
-  },
-  {
-    id: '3',
-    enCode: 'enterpriseType',
-    name: '浼佷笟绫诲瀷',
-  },
-  {
-    id: '4',
-    enCode: 'parkName',
-    name: '鎵�灞炲洯鍖�',
-  },
-  {
-    id: '5',
-    enCode: 'parkType',
-    name: '鍥尯绫诲瀷',
-  },
-  {
-    id: '6',
-    enCode: 'creationTime',
-    name: '鐢宠鏃堕棿',
-  },
-  {
-    id: '7',
-    enCode: 'amount',
-    name: '鐢宠鎻愮幇閲戦锛堝厓锛�',
-  },
-  {
-    id: '8',
-    enCode: 'checkStatus',
-    name: '瀹℃牳鐘舵��',
-  },
-  {
-    id: '8',
-    enCode: 'checkOperator',
-    name: '瀹℃牳浜�',
-  },
-  {
-    id: '9',
-    enCode: 'checkTime',
-    name: '瀹℃牳鏃堕棿',
-  },
-];
-
-const operationBtns = defineOperationBtns([
-  {
-    data: {
-      enCode: 'detailBtn',
-      name: '璇︽儏',
-    },
+const operationBtnMap: Record<string, OperationBtnType> = {
+  detailBtn: {
     emits: {
       onClick: (role) => openDialog(role, true),
     },
@@ -136,11 +80,7 @@
         row.checkStatus === EnterpriseRechargeStatusEnum.WaitCheck,
     },
   },
-  {
-    data: {
-      enCode: 'auditBtn',
-      name: '瀹℃牳',
-    },
+  auditBtn: {
     emits: {
       onClick: (role) => openDialog(role),
     },
@@ -149,7 +89,11 @@
         row.checkStatus !== EnterpriseRechargeStatusEnum.WaitCheck,
     },
   },
-]);
+};
+
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({
+  operationBtnMap,
+});
 
 const router = useRouter();
 const BaseState = {
diff --git a/src/views/StatisticalReport/RewardStatistics.vue b/src/views/StatisticalReport/RewardStatistics.vue
index 16689e1..1aa7b2d 100644
--- a/src/views/StatisticalReport/RewardStatistics.vue
+++ b/src/views/StatisticalReport/RewardStatistics.vue
@@ -54,7 +54,13 @@
           </QueryFilterItem>
         </template>
         <template #btn>
-          <el-button @click="handleExport()" icon="Download" type="primary">瀵煎嚭</el-button>
+          <el-button
+            v-if="checkSubModuleItemShow('pageButton', 'exportBtn')"
+            @click="handleExport()"
+            icon="Download"
+            type="primary"
+            >瀵煎嚭</el-button
+          >
         </template>
       </ProTableQueryFilterBar>
       <ProTableV2 v-bind="proTableProps" :columns="column" :show-operation-column="false">
@@ -140,122 +146,7 @@
   name: 'RewardStatistics',
 });
 
-const column = defineColumns([
-  {
-    id: '1',
-    enCode: 'enterpriseName',
-    name: '浼佷笟鍚嶇О',
-    width: 250,
-  },
-  {
-    id: '2',
-    enCode: 'societyCreditCode',
-    name: '淇$敤浠g爜',
-    width: 200,
-  },
-  {
-    id: '3',
-    enCode: 'industrialParkName',
-    name: '鎵�灞炲洯鍖�',
-    width: 200,
-  },
-  {
-    id: '4',
-    enCode: 'contact',
-    name: '鑱旂郴浜�',
-    width: 150,
-  },
-  {
-    id: '5',
-    enCode: 'contactPhone',
-    name: '鑱旂郴鏂瑰紡',
-    width: 120,
-  },
-  {
-    id: '6',
-    enCode: 'month',
-    name: '鐢虫姤鏈堜唤',
-    width: 120,
-  },
-  {
-    id: '7',
-    enCode: 'batchNo',
-    name: '鐢虫姤鎵规鍙�',
-    width: 150,
-  },
-  {
-    id: '8',
-    enCode: 'sumFinanceAmount',
-    name: '璐㈡斂鎷ㄤ粯閲戦',
-    width: 120,
-  },
-  {
-    id: '9',
-    enCode: 'sumFinanceAmountBtn',
-    name: '璐㈡斂鎷ㄤ粯鏄庣粏',
-    width: 120,
-  },
-  {
-    id: '10',
-    enCode: 'sumTransferAmount',
-    name: '骞冲彴鎷ㄤ粯閲戦',
-    width: 120,
-  },
-  {
-    id: '11',
-    enCode: 'sumTransferAmountBtn',
-    name: '骞冲彴鎷ㄤ粯鏄庣粏',
-    width: 120,
-  },
-  {
-    id: '12',
-    enCode: 'sumRechargeAmount',
-    name: '浼佷笟鍏呭�兼�婚',
-    width: 120,
-  },
-  {
-    id: '13',
-    enCode: 'sumRechargeAmountBtn',
-    name: '浼佷笟鍏呭�兼槑缁�',
-    width: 120,
-  },
-  {
-    id: '14',
-    enCode: 'sumTradeAmount',
-    name: '浼佷笟娑堣垂鎬婚',
-    width: 120,
-  },
-  {
-    id: '15',
-    enCode: 'sumTradeAmountBtn',
-    name: '浼佷笟娑堣垂鏄庣粏',
-    width: 120,
-  },
-  {
-    id: '16',
-    enCode: 'sumDrawWithAmount',
-    name: '浼佷笟鎻愮幇鎬婚',
-    width: 120,
-  },
-  {
-    id: '17',
-    enCode: 'sumDrawWithAmountBtn',
-    name: '浼佷笟鎻愮幇鏄庣粏',
-    width: 120,
-  },
-  {
-    id: '18',
-    enCode: 'amount',
-    name: '璐︽埛浣欓',
-    width: 120,
-  },
-  {
-    id: '19',
-    enCode: 'amountBtn',
-    name: '浣欓鏄庣粏',
-    width: 120,
-  },
-]);
+const { checkSubModuleItemShow, column, operationBtns } = useAccess({});
 
 const BaseState = {
   loading: true,

--
Gitblit v1.9.1