From 42d60f50072ebde98549157420bd18639712af43 Mon Sep 17 00:00:00 2001
From: wupengfei <834520024@qq.com>
Date: 星期五, 17 十月 2025 09:16:38 +0800
Subject: [PATCH] feat: 1.2.0.1

---
 src/constants/user.ts                                              |    4 
 src/views/EmploymentManage/constants/columns.ts                    |   34 +
 src/constants/task.ts                                              |    1 
 .eslintrc-auto-import.json                                         |    2 
 src/hooks/useUser.ts                                               |   31 +
 src/services/api/typings.d.ts                                      |  129 ++++++-
 src/views/UserManage/UserManageList.vue                            |  170 ++++++++++
 src/views/EmploymentManage/components/ManualCheckManageDialog.vue  |  208 +++++++++++++
 src/views/UserManage/constants/columns.ts                          |   34 ++
 src/views/UserManage/constants/index.ts                            |    1 
 src/views/ServiceChargeManage/components/EditAccountInfoDialog.vue |    2 
 src/views/EmploymentManage/components/CheckManageDialog.vue        |    2 
 auto-imports.d.ts                                                  |    5 
 src/views/EmploymentManage/CheckReceiveTaskDetail.vue              |    9 
 src/views/EmploymentManage/components/AddOrEditEmploymentView.vue  |   81 ++++
 src/router/index.ts                                                |   29 +
 src/constants/index.ts                                             |    1 
 src/views/UserManage/components/AddOrEditUserDialog.vue            |  143 ++++++++
 src/services/api/user.ts                                           |   72 +++-
 19 files changed, 897 insertions(+), 61 deletions(-)

diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json
index 3ba2b6f..0a842b5 100644
--- a/.eslintrc-auto-import.json
+++ b/.eslintrc-auto-import.json
@@ -98,6 +98,7 @@
     "EnumUserGenderTextForPerson": true,
     "EnumUserRealMethod": true,
     "EnumUserStatus": true,
+    "EnumUserStatusText": true,
     "EnumUserType": true,
     "EnumUserTypeText": true,
     "EnumUserWalletTransactionType": true,
@@ -269,6 +270,7 @@
     "useTaskSelect": true,
     "useTemplateRef": true,
     "useUser": true,
+    "useUserInfoRoles": true,
     "useVModel": true,
     "useVModels": true,
     "watch": true,
diff --git a/auto-imports.d.ts b/auto-imports.d.ts
index d777da5..ddc517f 100644
--- a/auto-imports.d.ts
+++ b/auto-imports.d.ts
@@ -105,6 +105,7 @@
   const EnumUserInfoStatus: typeof import('./src/constants/apiEnum')['EnumUserInfoStatus']
   const EnumUserRealMethod: typeof import('./src/constants/apiEnum')['EnumUserRealMethod']
   const EnumUserStatus: typeof import('./src/constants/apiEnum')['EnumUserStatus']
+  const EnumUserStatusText: typeof import('./src/constants/user')['EnumUserStatusText']
   const EnumUserType: typeof import('./src/constants/apiEnum')['EnumUserType']
   const EnumUserTypeText: typeof import('./src/constants/apiEnumText')['EnumUserTypeText']
   const EnumUserWalletTransactionType: typeof import('./src/constants/apiEnum')['EnumUserWalletTransactionType']
@@ -223,6 +224,7 @@
   const unref: typeof import('vue')['unref']
   const useAccess: typeof import('./src/hooks/useAccess')['useAccess']
   const useAllAreaList: typeof import('./src/hooks/dic')['useAllAreaList']
+  const useAllRoleList: typeof import('./src/hooks/useUser')['useAllRoleList']
   const useArea: typeof import('./src/hooks/dic')['useArea']
   const useAreaByCascader: typeof import('./src/hooks/dic')['useAreaByCascader']
   const useAttrs: typeof import('vue')['useAttrs']
@@ -260,6 +262,7 @@
   const useTaskSelect: typeof import('./src/hooks/settlement')['useTaskSelect']
   const useTemplateRef: typeof import('vue')['useTemplateRef']
   const useUser: typeof import('./src/hooks/useUser')['useUser']
+  const useUserInfoRoles: typeof import('./src/hooks/useUser')['useUserInfoRoles']
   const useVModel: typeof import('./src/hooks/help')['useVModel']
   const useVModels: typeof import('./src/hooks/help')['useVModels']
   const watch: typeof import('vue')['watch']
@@ -403,6 +406,7 @@
     readonly EnumUserGenderTextForPerson: UnwrapRef<typeof import('./src/constants/task')['EnumUserGenderTextForPerson']>
     readonly EnumUserRealMethod: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumUserRealMethod']>
     readonly EnumUserStatus: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumUserStatus']>
+    readonly EnumUserStatusText: UnwrapRef<typeof import('./src/constants/user')['EnumUserStatusText']>
     readonly EnumUserType: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumUserType']>
     readonly EnumUserTypeText: UnwrapRef<typeof import('./src/constants/apiEnumText')['EnumUserTypeText']>
     readonly EnumUserWalletTransactionType: UnwrapRef<typeof import('./src/constants/apiEnum')['EnumUserWalletTransactionType']>
@@ -552,6 +556,7 @@
     readonly useTaskSelect: UnwrapRef<typeof import('./src/hooks/settlement')['useTaskSelect']>
     readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
     readonly useUser: UnwrapRef<typeof import('./src/hooks/useUser')['useUser']>
+    readonly useUserInfoRoles: UnwrapRef<typeof import('./src/hooks/useUser')['useUserInfoRoles']>
     readonly useVModel: UnwrapRef<typeof import('./src/hooks/help')['useVModel']>
     readonly useVModels: UnwrapRef<typeof import('./src/hooks/help')['useVModels']>
     readonly watch: UnwrapRef<typeof import('vue')['watch']>
diff --git a/src/constants/index.ts b/src/constants/index.ts
index e1c7625..c391531 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -16,3 +16,4 @@
 export * from './enterpriseWallet';
 export * from './finance';
 export * from './common';
+export * from './user';
diff --git a/src/constants/task.ts b/src/constants/task.ts
index 64d2bfa..4e94d14 100644
--- a/src/constants/task.ts
+++ b/src/constants/task.ts
@@ -84,6 +84,7 @@
   [EnumBillingMethod.Day]: '鎸夋棩',
   [EnumBillingMethod.Hour]: '鎸夋椂',
   [EnumBillingMethod.Piece]: '璁′欢',
+  // [EnumBillingMethod.face]: '闈㈣',
 };
 
 export const EnumBillingMethodUnitText = {
diff --git a/src/constants/user.ts b/src/constants/user.ts
new file mode 100644
index 0000000..fbad019
--- /dev/null
+++ b/src/constants/user.ts
@@ -0,0 +1,4 @@
+export const EnumUserStatusText = {
+  [EnumUserStatus.Normal]: '鍚敤',
+  [EnumUserStatus.Disabled]: '绂佺敤',
+};
diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts
index 5587aef..76c5306 100644
--- a/src/hooks/useUser.ts
+++ b/src/hooks/useUser.ts
@@ -1,6 +1,7 @@
 import { useUserStore } from '@/store/modules/user';
 import { UserUtils } from '@bole-core/core';
 import { useQuery, useQueryClient } from '@tanstack/vue-query';
+import * as userServices from '@/services/api/user';
 
 export function useUser() {
   const userStore = useUserStore();
@@ -13,3 +14,33 @@
     userDetail: userDetail,
   };
 }
+
+type UseUserInfoRolesOptions = {
+  userInfoId: MaybeRef<string>;
+  userType: EnumUserType;
+  clientType: EnumClientType;
+};
+
+export function useUserInfoRoles({ userInfoId, userType, clientType }: UseUserInfoRolesOptions) {
+  const { data: userInfoRoles } = useQuery({
+    queryKey: ['userServices/getUserInfoRoles'],
+    queryFn: async () => {
+      let res = await userServices.getUserInfoRoles(
+        {
+          userInfoId: unref(userInfoId),
+          userType: userType,
+          clientType: clientType,
+        },
+        { showLoading: false }
+      );
+      return res;
+    },
+    select(data) {
+      return data;
+    },
+  });
+
+  return {
+    userInfoRoles,
+  };
+}
diff --git a/src/router/index.ts b/src/router/index.ts
index 4b21b9b..f101ed8 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -394,6 +394,35 @@
       // },
     ],
   },
+
+  {
+    path: '/UserManage',
+    redirect: 'noRedirect',
+    component: Layout,
+    hidden: false,
+    alwaysShow: true,
+    meta: {
+      rank: 10100,
+      title: '鐢ㄦ埛绠$悊',
+      rootMenu: true,
+      icon: 'home',
+    },
+    children: [
+      {
+        path: '/UserManageList',
+        name: 'UserManageList',
+        hidden: false,
+        alwaysShow: true,
+        component: () => import('@/views/UserManage/UserManageList.vue'),
+        meta: {
+          rank: 10101,
+          title: '鐢ㄦ埛绠$悊',
+          // rootMenu: true,
+          icon: 'home',
+        },
+      },
+    ],
+  },
   {
     path: '/Login',
     name: 'Login',
diff --git a/src/services/api/typings.d.ts b/src/services/api/typings.d.ts
index c9749cb..b56cf10 100644
--- a/src/services/api/typings.d.ts
+++ b/src/services/api/typings.d.ts
@@ -286,8 +286,15 @@
   interface APIgetUserInfoRolesParams {
     /** 鐢ㄦ埛Id */
     userInfoId?: string;
+    /** 鐢ㄦ埛绫诲瀷 */
+    userType?: EnumUserType;
     /** 瀹㈡埛绔被鍨� */
     clientType?: EnumClientType;
+  }
+
+  interface APIgetUserParams {
+    /** 鐢ㄦ埛Id */
+    id?: string;
   }
 
   interface APIgetUserResumeCredentialParams {
@@ -1884,6 +1891,24 @@
     timestamp?: number;
   }
 
+  interface FriendlyResultGetOperationUserInfosQueryResult {
+    /** 璺熻釜Id */
+    traceId?: string;
+    /** 鐘舵�佺爜 */
+    code?: number;
+    /** 閿欒鐮� */
+    errorCode?: string;
+    data?: GetOperationUserInfosQueryResult;
+    /** 鎵ц鎴愬姛 */
+    success?: boolean;
+    /** 閿欒淇℃伅 */
+    msg?: any;
+    /** 闄勫姞鏁版嵁 */
+    extras?: any;
+    /** 鏃堕棿鎴� */
+    timestamp?: number;
+  }
+
   interface FriendlyResultGetPersonalApplyTaskInfosQueryResult {
     /** 璺熻釜Id */
     traceId?: string;
@@ -2360,6 +2385,24 @@
     /** 閿欒鐮� */
     errorCode?: string;
     data?: GetTraceIdLogQueryResult;
+    /** 鎵ц鎴愬姛 */
+    success?: boolean;
+    /** 閿欒淇℃伅 */
+    msg?: any;
+    /** 闄勫姞鏁版嵁 */
+    extras?: any;
+    /** 鏃堕棿鎴� */
+    timestamp?: number;
+  }
+
+  interface FriendlyResultGetUserQueryResult {
+    /** 璺熻釜Id */
+    traceId?: string;
+    /** 鐘舵�佺爜 */
+    code?: number;
+    /** 閿欒鐮� */
+    errorCode?: string;
+    data?: GetUserQueryResult;
     /** 鎵ц鎴愬姛 */
     success?: boolean;
     /** 閿欒淇℃伅 */
@@ -3009,24 +3052,6 @@
     /** 閿欒鐮� */
     errorCode?: string;
     data?: PagedListQueryResultGetEnterprisesQueryResultItem;
-    /** 鎵ц鎴愬姛 */
-    success?: boolean;
-    /** 閿欒淇℃伅 */
-    msg?: any;
-    /** 闄勫姞鏁版嵁 */
-    extras?: any;
-    /** 鏃堕棿鎴� */
-    timestamp?: number;
-  }
-
-  interface FriendlyResultPagedListQueryResultGetOperationUserInfosQueryResultItem {
-    /** 璺熻釜Id */
-    traceId?: string;
-    /** 鐘舵�佺爜 */
-    code?: number;
-    /** 閿欒鐮� */
-    errorCode?: string;
-    data?: PagedListQueryResultGetOperationUserInfosQueryResultItem;
     /** 鎵ц鎴愬姛 */
     success?: boolean;
     /** 閿欒淇℃伅 */
@@ -4618,10 +4643,10 @@
     pageModel?: PagedListQueryPageModel;
   }
 
-  interface GetOperationUserInfosQuery {
-    /** 鍏抽敭瀛� */
-    keywords?: string;
-    pageModel?: PagedListQueryPageModel;
+  interface GetOperationUserInfosQueryResult {
+    pageModel?: PagedListQueryResultPageModel;
+    /** 鏁版嵁 */
+    data?: GetOperationUserInfosQueryResultItem[];
   }
 
   interface GetOperationUserInfosQueryResultItem {
@@ -5860,6 +5885,29 @@
     isChecked?: boolean;
   }
 
+  interface GetUserQueryResult {
+    /** 鐢ㄦ埛Id */
+    id?: string;
+    /** 濮撳悕 */
+    name?: string;
+    /** 鐢ㄦ埛鍚� */
+    userName?: string;
+    /** 鎵嬫満鍙� */
+    phoneNumber?: string;
+    /** 瑙掕壊Id */
+    roles?: GetUserQueryResultRole[];
+    status?: EnumUserStatus;
+    /** 澶囨敞 */
+    remark?: string;
+  }
+
+  interface GetUserQueryResultRole {
+    /** 瑙掕壊Id */
+    id?: string;
+    /** 鍚嶇О */
+    name?: string;
+  }
+
   interface GetUserResumeCredentialQueryResult {
     /** 璧勬牸璇佷功Id */
     id?: string;
@@ -6120,6 +6168,12 @@
     workExperience?: string;
   }
 
+  interface GetUsersQuery {
+    /** 鍏抽敭瀛� */
+    keywords?: string;
+    pageModel?: PagedListQueryPageModel;
+  }
+
   type GetWxmpSettingsQuery = Record<string, any>;
 
   interface GetWxmpSettingsQueryResult {
@@ -6352,12 +6406,6 @@
     data?: GetEnterprisesQueryResultItem[];
   }
 
-  interface PagedListQueryResultGetOperationUserInfosQueryResultItem {
-    pageModel?: PagedListQueryResultPageModel;
-    /** 鏁版嵁 */
-    data?: GetOperationUserInfosQueryResultItem[];
-  }
-
   interface PagedListQueryResultGetRolesQueryResultItem {
     pageModel?: PagedListQueryResultPageModel;
     /** 鏁版嵁 */
@@ -6476,6 +6524,13 @@
   interface ResendResourceCommand {
     /** 璧勬簮鏃ュ織Id */
     id?: string;
+  }
+
+  interface ResetUserPasswordsCommand {
+    /** Id */
+    ids?: string[];
+    /** 瀵嗙爜 */
+    password?: string;
   }
 
   interface RevokeTaskSettlementOrderCommand {
@@ -6866,6 +6921,24 @@
     id?: string;
   }
 
+  interface SaveUserCommand {
+    /** 濮撳悕 */
+    name?: string;
+    /** 鐢ㄦ埛鍚� */
+    userName?: string;
+    /** 鎵嬫満鍙� */
+    phoneNumber?: string;
+    /** 瀵嗙爜 */
+    password?: string;
+    /** 瑙掕壊Id */
+    roleIds?: string[];
+    status?: EnumUserStatus;
+    /** 澶囨敞 */
+    remark?: string;
+    /** Id */
+    id?: string;
+  }
+
   interface SaveUserResumeCredentialCommand {
     /** 璇佷功绫诲瀷缂栧彿 */
     typeCode: string;
diff --git a/src/services/api/user.ts b/src/services/api/user.ts
index 10561c9..e62b980 100644
--- a/src/services/api/user.ts
+++ b/src/services/api/user.ts
@@ -17,24 +17,6 @@
   });
 }
 
-/** 鏌ヨ杩愯惀绔敤鎴峰垎椤靛垪琛ㄦ暟鎹� POST /api/user/user/getOperationUserInfos */
-export async function getOperationUserInfos(
-  body: API.GetOperationUserInfosQuery,
-  options?: API.RequestConfig
-) {
-  return request<API.PagedListQueryResultGetOperationUserInfosQueryResultItem>(
-    '/api/user/user/getOperationUserInfos',
-    {
-      method: 'POST',
-      headers: {
-        'Content-Type': 'application/json-patch+json',
-      },
-      data: body,
-      ...(options || {}),
-    }
-  );
-}
-
 /** 鏌ヨ涓汉鐢ㄦ埛閾惰鍗′俊鎭� GET /api/user/user/getPersonalUserBankCard */
 export async function getPersonalUserBankCard(
   // 鍙犲姞鐢熸垚鐨凱aram绫诲瀷 (闈瀊ody鍙傛暟swagger榛樿娌℃湁鐢熸垚瀵硅薄)
@@ -137,6 +119,21 @@
   );
 }
 
+/** 鏌ヨ鐢ㄦ埛璇︽儏 GET /api/user/user/getUser */
+export async function getUser(
+  // 鍙犲姞鐢熸垚鐨凱aram绫诲瀷 (闈瀊ody鍙傛暟swagger榛樿娌℃湁鐢熸垚瀵硅薄)
+  params: API.APIgetUserParams,
+  options?: API.RequestConfig
+) {
+  return request<API.GetUserQueryResult>('/api/user/user/getUser', {
+    method: 'GET',
+    params: {
+      ...params,
+    },
+    ...(options || {}),
+  });
+}
+
 /** 鏌ヨ鐢ㄦ埛瑙掕壊鍒楄〃 GET /api/user/user/getUserInfoRoles */
 export async function getUserInfoRoles(
   // 鍙犲姞鐢熸垚鐨凱aram绫诲瀷 (闈瀊ody鍙傛暟swagger榛樿娌℃湁鐢熸垚瀵硅薄)
@@ -152,6 +149,33 @@
   });
 }
 
+/** 鏌ヨ鐢ㄦ埛鍒嗛〉鍒楄〃鏁版嵁 POST /api/user/user/getUsers */
+export async function getUsers(body: API.GetUsersQuery, options?: API.RequestConfig) {
+  return request<API.GetOperationUserInfosQueryResult>('/api/user/user/getUsers', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json-patch+json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
+/** 閲嶇疆鐢ㄦ埛瀵嗙爜 POST /api/user/user/resetUserPasswords */
+export async function resetUserPasswords(
+  body: API.ResetUserPasswordsCommand,
+  options?: API.RequestConfig
+) {
+  return request<number>('/api/user/user/resetUserPasswords', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json-patch+json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 淇濆瓨鐢ㄦ埛閾惰鍗′俊鎭� POST /api/user/user/savePersonalUserBankCard */
 export async function savePersonalUserBankCard(
   body: API.SavePersonalUserBankCardCommand,
@@ -167,6 +191,18 @@
   });
 }
 
+/** 淇濆瓨鐢ㄦ埛 POST /api/user/user/saveUser */
+export async function saveUser(body: API.SaveUserCommand, options?: API.RequestConfig) {
+  return request<string>('/api/user/user/saveUser', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json-patch+json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鍙戦�佺粦瀹氶摱琛屽崱鐭俊 POST /api/user/user/sendSavePersonalUserBankCardVerifyCode */
 export async function sendSavePersonalUserBankCardVerifyCode(
   body: API.SendSavePersonalUserBankCardVerifyCodeCommand,
diff --git a/src/views/EmploymentManage/CheckReceiveTaskDetail.vue b/src/views/EmploymentManage/CheckReceiveTaskDetail.vue
index a16ce8b..303d615 100644
--- a/src/views/EmploymentManage/CheckReceiveTaskDetail.vue
+++ b/src/views/EmploymentManage/CheckReceiveTaskDetail.vue
@@ -48,6 +48,7 @@
       </ProTableV2>
     </AppContainer>
     <CheckManageDialog v-bind="dialogProps" />
+    <ManualCheckManageDialog v-bind="dialogManualProps" />
   </LoadingLayout>
 </template>
 
@@ -72,6 +73,7 @@
 import { EnumBillingMethodUnitText } from '@/constants';
 import dayjs from 'dayjs';
 import CheckManageDialog from './components/CheckManageDialog.vue';
+import ManualCheckManageDialog from './components/ManualCheckManageDialog.vue';
 
 defineOptions({
   name: 'CheckReceiveTaskDetail',
@@ -183,4 +185,11 @@
     isDetail: false,
   },
 });
+
+const { dialogProps: dialogManualProps, handleEdit: handleManualEdit } = useFormDialog({
+  defaultFormParams: {
+    id: '',
+    isDetail: false,
+  },
+});
 </script>
diff --git a/src/views/EmploymentManage/components/AddOrEditEmploymentView.vue b/src/views/EmploymentManage/components/AddOrEditEmploymentView.vue
index c2ea175..fdb4e19 100644
--- a/src/views/EmploymentManage/components/AddOrEditEmploymentView.vue
+++ b/src/views/EmploymentManage/components/AddOrEditEmploymentView.vue
@@ -53,6 +53,37 @@
               </ProFormItemV2>
             </ProFormColItem>
           </ProFormCol>
+          <template v-if="form.billingMethod === EnumBillingMethod.Hour">
+            <ProFormCol>
+              <ProFormColItem :span="12">
+                <ProFormItemV2 label="鏍稿畾宸ユ椂:" prop="name">
+                  <ProFormInputNumber
+                    :controls="false"
+                    v-model="form.serviceFee"
+                    placeholder="璇疯緭鍏ユ牳瀹氬伐鏃�"
+                    :min="0"
+                    :max="999999999999"
+                    unit="灏忔椂/澶�"
+                  ></ProFormInputNumber>
+                </ProFormItemV2>
+              </ProFormColItem>
+            </ProFormCol>
+            <ProFormCol>
+              <ProFormColItem :span="12">
+                <ProFormItemV2 label="瓒呮椂鏈嶅姟璐�:" prop="name">
+                  <ProFormInputNumber
+                    :controls="false"
+                    v-model="form.serviceFee"
+                    placeholder="璇疯緭鍏ヨ秴鏃舵湇鍔¤垂"
+                    :min="0"
+                    :max="999999999999"
+                    unit="鍏�/灏忔椂"
+                  ></ProFormInputNumber>
+                </ProFormItemV2>
+              </ProFormColItem>
+            </ProFormCol>
+          </template>
+
           <ProFormCol>
             <ProFormColItem :span="12">
               <ProFormItemV2
@@ -199,12 +230,19 @@
           </ProFormCol>
           <ProFormCol>
             <ProFormColItem :span="12">
-              <ProFormItemV2
-                label="璇︾粏鍦板潃:"
-                prop="addressDetail"
-                :check-rules="[{ message: '璇疯緭鍏ヨ缁嗗湴鍧�' }]"
-              >
-                <ProFormText v-model.trim="form.addressDetail" placeholder="璇疯緭鍏ヨ缁嗗湴鍧�" />
+              <ProFormItemV2 label="鍦扮偣璇存槑:" prop="addressDetail">
+                <ProFormText v-model.trim="form.addressDetail" placeholder="璇疯緭鍏ュ湴鐐硅鏄�" />
+              </ProFormItemV2>
+            </ProFormColItem>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormColItem :span="12">
+              <ProFormItemV2 label="浠诲姟鎻忚堪:" prop="addressDetail">
+                <ProFormTextArea
+                  :rows="4"
+                  v-model.trim="form.addressDetail"
+                  placeholder="璇疯緭鍏ヤ换鍔℃弿杩�"
+                />
               </ProFormItemV2>
             </ProFormColItem>
           </ProFormCol>
@@ -223,6 +261,35 @@
                   end-placeholder="缁撴潫鏃ユ湡"
                   :disabled-date="disabledDate"
                 ></ProFormDatePicker>
+              </ProFormItemV2>
+            </ProFormColItem>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormColItem :span="12">
+              <ProFormItemV2
+                label="鎶ュ悕鏃堕棿:"
+                prop="time"
+                :check-rules="[{ message: '璇烽�夋嫨鎶ュ悕鏃堕棿', type: 'array' }]"
+              >
+                <ProFormDatePicker
+                  v-model="form.time"
+                  type="daterange"
+                  range-separator="鑷�"
+                  start-placeholder="寮�濮嬫棩鏈�"
+                  end-placeholder="缁撴潫鏃ユ湡"
+                  :disabled-date="disabledDate"
+                ></ProFormDatePicker>
+              </ProFormItemV2>
+            </ProFormColItem>
+          </ProFormCol>
+          <ProFormCol>
+            <ProFormColItem :span="12">
+              <ProFormItemV2
+                label="楠屾敹鏂瑰紡:"
+                prop="genderLimit"
+                :check-rules="[{ message: '璇烽�夋嫨楠屾敹鏂瑰紡' }]"
+              >
+                <ProFormRadio v-model="form.genderLimit" :value-enum="[]"></ProFormRadio>
               </ProFormItemV2>
             </ProFormColItem>
           </ProFormCol>
@@ -250,6 +317,7 @@
   ProFormDatePicker,
   ProFormCheckbox,
   ProFormSelect,
+  ProFormTextArea,
 } from '@bole-core/components';
 import { FormInstance, ModelValueType } from 'element-plus';
 import { Message } from '@bole-core/core';
@@ -258,6 +326,7 @@
 import * as taskServices from '@/services/api/task';
 import {
   EnumUserGenderTextForEdit,
+  EnumBillingMethod,
   EnumBillingMethodText,
   EnumBillingMethodUnitText,
   EnumSettlementCycleText,
diff --git a/src/views/EmploymentManage/components/CheckManageDialog.vue b/src/views/EmploymentManage/components/CheckManageDialog.vue
index eb08a57..81a4ecb 100644
--- a/src/views/EmploymentManage/components/CheckManageDialog.vue
+++ b/src/views/EmploymentManage/components/CheckManageDialog.vue
@@ -27,7 +27,7 @@
 import { useGlobalEventContext } from '@/hooks';
 
 defineOptions({
-  name: 'EnterpriseConsumptionDetailDialog',
+  name: 'CheckManageDialog',
 });
 
 type Form = {
diff --git a/src/views/EmploymentManage/components/ManualCheckManageDialog.vue b/src/views/EmploymentManage/components/ManualCheckManageDialog.vue
new file mode 100644
index 0000000..dfc1918
--- /dev/null
+++ b/src/views/EmploymentManage/components/ManualCheckManageDialog.vue
@@ -0,0 +1,208 @@
+<template>
+  <ProDialog :title="title" v-model="visible" destroy-on-close draggable>
+    <ProDialogTableWrapper :height="400">
+      <ProTableV2 v-bind="proTableProps" :columns="columns" :operationBtns="operationBtns">
+      </ProTableV2>
+    </ProDialogTableWrapper>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="emit('onCancel')" type="primary">纭畾</el-button>
+      </span>
+    </template>
+  </ProDialog>
+</template>
+
+<script setup lang="ts">
+import {
+  ProDialog,
+  ProTableV2,
+  ProDialogTableWrapper,
+  defineColumns,
+  defineOperationBtns,
+  useTable,
+} from '@bole-core/components';
+import * as taskCheckReceiveServices from '@/services/api/taskCheckReceive';
+import { setOSSLink } from '@/utils';
+import { downloadWithZip, Message } from '@bole-core/core';
+import { useGlobalEventContext } from '@/hooks';
+
+defineOptions({
+  name: 'ManualCheckManageDialog',
+});
+
+type Form = {
+  id: string;
+  isDetail: boolean;
+};
+
+const visible = defineModel({ type: Boolean });
+const form = defineModel<Form>('form');
+const title = computed(() => (form.value.isDetail ? '璇︽儏' : '楠屾敹'));
+const emit = defineEmits<{
+  (e: 'onCancel'): void;
+}>();
+
+const eventContext = useGlobalEventContext();
+
+const columns = defineColumns([
+  {
+    id: '1',
+    enCode: 'date',
+    name: '浠诲姟鏃ユ湡',
+  },
+  {
+    id: '2',
+    enCode: 'createdTime',
+    name: '绛惧埌鏃堕棿',
+  },
+  {
+    id: '3',
+    enCode: 'files',
+    name: '绛惧嚭鏃堕棿',
+  },
+  {
+    id: '4',
+    enCode: 'checkReceiveStatus',
+    name: '楠屾敹鐘舵��',
+  },
+  {
+    id: '5',
+    enCode: 'checkReceiveTime',
+    name: '鎿嶄綔浜�',
+  },
+]);
+
+const operationBtns = defineOperationBtns([
+  {
+    data: {
+      enCode: 'checkReceiveBtn',
+      name: '楠屾敹閫氳繃',
+    },
+    emits: {
+      onClick: (role) => checkReceiveTask(role, EnumTaskUserSubmitCheckReceiveStatus.Success),
+    },
+    extraProps: {
+      hide: (row: API.GetCheckReceiveTaskUserSubmitsQueryResultItem) =>
+        !(
+          row.checkReceiveStatus === EnumTaskUserSubmitCheckReceiveStatus.WaitSubmit ||
+          row.checkReceiveStatus === EnumTaskUserSubmitCheckReceiveStatus.WaitCheckReceive
+        ) || form.value.isDetail,
+    },
+  },
+  {
+    data: {
+      enCode: 'checkReceiveBtn',
+      name: '楠屾敹鏈�氳繃',
+    },
+    emits: {
+      onClick: (role) => checkReceiveTask(role, EnumTaskUserSubmitCheckReceiveStatus.Fail),
+    },
+    extraProps: {
+      hide: (row: API.GetCheckReceiveTaskUserSubmitsQueryResultItem) =>
+        !(
+          row.checkReceiveStatus === EnumTaskUserSubmitCheckReceiveStatus.WaitSubmit ||
+          row.checkReceiveStatus === EnumTaskUserSubmitCheckReceiveStatus.WaitCheckReceive
+        ) || form.value.isDetail,
+    },
+  },
+  {
+    data: {
+      enCode: 'downloadBtn',
+      name: '涓嬭浇',
+    },
+    emits: {
+      onClick: (role) => handleDownload(role),
+    },
+    extraProps: {
+      hide: (row: API.GetCheckReceiveTaskUserSubmitsQueryResultItem) => row.files?.length === 0,
+    },
+  },
+]);
+
+watch(
+  visible,
+  (val) => {
+    if (val) {
+      if (form.value.id) {
+        getList();
+      }
+    }
+  },
+  {
+    immediate: true,
+  }
+);
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+  reset,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.GetCheckReceiveTaskUserSubmitsQuery = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        id: form.value.id,
+      };
+      let res = await taskCheckReceiveServices.getCheckReceiveTaskUserSubmits(params);
+      return res;
+    } catch (error) {
+      console.log('error: ', error);
+    }
+  },
+  {
+    defaultExtraParams: {
+      orderInput: [{ property: 'date', order: EnumPagedListOrder.Desc }],
+    },
+    queryKey: ['taskCheckReceiveServices/getCheckReceiveTaskUserSubmits'],
+    columnsRenderProps: {
+      createdTime: { type: 'date' },
+      checkReceiveTime: { type: 'date' },
+      date: { type: 'date', format: 'YYYY-MM-DD' },
+      checkReceiveStatus: { type: 'enum', valueEnum: EnumTaskUserSubmitCheckReceiveStatusText },
+      files: {
+        type: 'url',
+        //@ts-ignore
+        formatter: (row: API.GetCheckReceiveTaskUserSubmitsQueryResultItem) =>
+          row.files?.length > 0 && (row.files ?? []).map((x) => setOSSLink(x)),
+        showDownloadBtn: false,
+      },
+    },
+  }
+);
+
+function handleDownload(row: API.GetCheckReceiveTaskUserSubmitsQueryResultItem) {
+  if (row.files?.length > 0) {
+    downloadWithZip(
+      row.files.map((x) => ({
+        data: `${setOSSLink(x)}`,
+      })),
+      '楠屾敹鐓х墖'
+    );
+  }
+}
+
+async function checkReceiveTask(
+  row: API.GetCheckReceiveTaskUserSubmitsQueryResultItem,
+  checkReceiveStatus: EnumTaskUserSubmitCheckReceiveStatus
+) {
+  try {
+    let params: API.CheckReceiveTaskCommand = {
+      id: row.id,
+      checkReceiveStatus: checkReceiveStatus,
+    };
+    let res = await taskCheckReceiveServices.checkReceiveTask(params);
+    if (res) {
+      Message.successMessage('鎿嶄綔鎴愬姛');
+      getList(paginationState.pageIndex);
+      eventContext.emit('checkReceiveTask');
+    }
+  } catch (error) {}
+}
+</script>
diff --git a/src/views/EmploymentManage/constants/columns.ts b/src/views/EmploymentManage/constants/columns.ts
index 825600f..b220bae 100644
--- a/src/views/EmploymentManage/constants/columns.ts
+++ b/src/views/EmploymentManage/constants/columns.ts
@@ -38,26 +38,41 @@
   },
   {
     id: '8',
+    enCode: 'userCount',
+    name: '鎶ュ悕寮�濮�',
+  },
+  {
+    id: '9',
+    enCode: 'userCount',
+    name: '鎶ュ悕缁撴潫',
+  },
+  {
+    id: '10',
+    enCode: 'userCount',
+    name: '鎶ュ悕鐘舵��',
+  },
+  {
+    id: '11',
     enCode: 'status',
     name: '浠诲姟鐘舵��',
   },
   {
-    id: '9',
+    id: '12',
     enCode: 'createdTime',
     name: '鍙戝竷鏃ユ湡',
   },
   {
-    id: '10',
+    id: '13',
     enCode: 'beginTime',
-    name: '寮�濮嬫棩鏈�',
+    name: '浠诲姟寮�濮嬫棩鏈�',
   },
   {
-    id: '11',
+    id: '14',
     enCode: 'endTime',
-    name: '缁撴潫鏃ユ湡',
+    name: '浠诲姟缁撴潫鏃ユ湡',
   },
   {
-    id: '12',
+    id: '15',
     enCode: 'releaseStatus',
     name: '鍙戝竷鐘舵��',
   },
@@ -183,10 +198,15 @@
   {
     id: '8',
     enCode: 'checkReceiveStatus',
-    name: '浠诲姟楠屾敹鐘舵��',
+    name: '楠屾敹鏂瑰紡',
   },
   {
     id: '9',
+    enCode: 'checkReceiveStatus',
+    name: '浠诲姟楠屾敹鐘舵��',
+  },
+  {
+    id: '10',
     enCode: 'lastCheckReceiveTime',
     name: '鏈�杩戦獙鏀舵椂闂�',
   },
diff --git a/src/views/ServiceChargeManage/components/EditAccountInfoDialog.vue b/src/views/ServiceChargeManage/components/EditAccountInfoDialog.vue
index 7450ad0..42b5ef7 100644
--- a/src/views/ServiceChargeManage/components/EditAccountInfoDialog.vue
+++ b/src/views/ServiceChargeManage/components/EditAccountInfoDialog.vue
@@ -21,7 +21,7 @@
       <ProFormItemV2
         label="鏀舵璐︽埛锛�"
         prop="receiveAccount"
-        :check-rules="[{ message: '璇疯緭鍏ユ敹娆捐处鎴�', type: 'bankCard' }]"
+        :check-rules="[{ message: '璇疯緭鍏ユ敹娆捐处鎴�' }]"
       >
         <ProFormText placeholder="璇疯緭鍏ユ敹娆捐处鎴�" v-model.trim="form.receiveAccount"></ProFormText>
       </ProFormItemV2>
diff --git a/src/views/UserManage/UserManageList.vue b/src/views/UserManage/UserManageList.vue
new file mode 100644
index 0000000..3ea919e
--- /dev/null
+++ b/src/views/UserManage/UserManageList.vue
@@ -0,0 +1,170 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableQueryFilterBar @on-reset="reset">
+        <template #query>
+          <QueryFilterItem>
+            <SearchInput
+              v-model="extraParamState.keywords"
+              style="width: 260px"
+              placeholder="濮撳悕/鐢ㄦ埛鍚�/鎵嬫満鍙�"
+              @on-click-search="getList"
+            >
+            </SearchInput>
+          </QueryFilterItem>
+        </template>
+        <template #btn>
+          <el-button @click="openDialog()" icon="Plus" type="primary">鏂板</el-button>
+        </template>
+      </ProTableQueryFilterBar>
+      <ProTableV2
+        v-bind="proTableProps"
+        :columns="UserManageColumns"
+        :operationBtns="operationBtns"
+      >
+      </ProTableV2>
+    </AppContainer>
+    <AddOrEditUserDialog v-bind="dialogProps" />
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  ProTableQueryFilterBar,
+  ProTableV2,
+  SearchInput,
+  LoadingLayout,
+  AppContainer,
+  QueryFilterItem,
+  useTable,
+  useFormDialog,
+  defineOperationBtns,
+} from '@bole-core/components';
+import * as userServices from '@/services/api/user';
+import { UserManageColumns } from './constants';
+import { EnumUserStatusText } from '@/constants';
+import { ModelValueType } from 'element-plus';
+import { Message } from '@bole-core/core';
+import AddOrEditUserDialog from './components/AddOrEditUserDialog.vue';
+
+defineOptions({
+  name: 'UserManageList',
+});
+
+const operationBtns = defineOperationBtns([
+  {
+    data: {
+      enCode: 'editBtn',
+      name: '缂栬緫',
+    },
+    emits: {
+      onClick: (role) => openDialog(role),
+    },
+  },
+]);
+
+const router = useRouter();
+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.GetUsersQuery = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        keywords: extraParamState.keywords,
+      };
+
+      let res = await userServices.getUsers(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      keywords: '',
+      status: '',
+      time: [] as unknown as ModelValueType,
+      orderInput: [{ property: 'id', order: EnumPagedListOrder.Desc }],
+    },
+    columnsRenderProps: {
+      roles: {
+        formatter: (role: API.GetOperationUserInfosQueryResultItem) =>
+          role.roles?.length > 0 ? role.roles.map((x) => x.name).join(',') : '',
+      },
+      status: { type: 'enum', valueEnum: EnumUserStatusText },
+    },
+  }
+);
+
+const { dialogProps, handleEdit, handleAdd, editForm, dialogState } = useFormDialog({
+  onConfirm: handleAddOrEdit,
+  defaultFormParams: {
+    id: '',
+    name: '',
+    userName: '',
+    phoneNumber: '',
+    remark: '',
+    roleIds: [] as string[],
+    password: '',
+  },
+});
+
+function openDialog(row?: API.GetOperationUserInfosQueryResultItem) {
+  if (row) {
+    handleEdit({
+      id: row.id,
+      name: row.name,
+      userName: row.userName,
+      phoneNumber: row.phoneNumber,
+      remark: row.remark,
+      roleIds: row.roles?.map((x) => x.id) ?? [],
+      password: '',
+    });
+  } else {
+    handleAdd();
+  }
+}
+
+async function handleAddOrEdit() {
+  const isEdit = editForm.id;
+  try {
+    let params: API.SaveUserCommand = {
+      name: editForm.name,
+      userName: editForm.userName,
+      phoneNumber: editForm.phoneNumber,
+      password: editForm.password,
+      roleIds: editForm.roleIds,
+      remark: editForm.remark,
+    };
+    if (editForm.id) {
+      params.id = editForm.id;
+    }
+    let res = await userServices.saveUser(params);
+    if (res) {
+      Message.successMessage('鎿嶄綔鎴愬姛');
+      getList(isEdit ? paginationState.pageIndex : 1);
+      dialogState.dialogVisible = false;
+    }
+  } catch (error) {}
+}
+</script>
diff --git a/src/views/UserManage/components/AddOrEditUserDialog.vue b/src/views/UserManage/components/AddOrEditUserDialog.vue
new file mode 100644
index 0000000..47e23b2
--- /dev/null
+++ b/src/views/UserManage/components/AddOrEditUserDialog.vue
@@ -0,0 +1,143 @@
+<template>
+  <ProDialog
+    :title="innerForm.title"
+    v-model="innerVisible"
+    @close="onDialogClose"
+    destroy-on-close
+    draggable
+  >
+    <ProForm :model="innerForm" ref="dialogForm" label-width="90px">
+      <ProFormItemV2 label="濮撳悕" prop="name" :check-rules="[{ message: '璇疯緭鍏ュ鍚�' }]">
+        <ProFormText placeholder="璇疯緭鍏ュ鍚�" v-model.trim="innerForm.name"></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2
+        label="鎵嬫満鍙�"
+        prop="phoneNumber"
+        :check-rules="[{ message: '璇疯緭鍏ユ墜鏈哄彿', type: 'phone' }]"
+      >
+        <ProFormText placeholder="璇疯緭鍏ユ墜鏈哄彿" v-model.trim="innerForm.phoneNumber"></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2 label="鐢ㄦ埛鍚�" prop="userName" :check-rules="[{ message: '璇疯緭鍏ョ敤鎴峰悕' }]">
+        <ProFormText placeholder="璇疯緭鍏ョ敤鎴峰悕" v-model.trim="innerForm.userName"></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2
+        v-if="!isEdit"
+        label="瀵嗙爜"
+        prop="password"
+        :check-rules="[{ message: '璇疯緭鍏ュ瘑鐮�' }]"
+      >
+        <ProFormText placeholder="璇疯緭鍏ヨ处鍙�" v-model.trim="innerForm.password"></ProFormText>
+      </ProFormItemV2>
+      <ProFormItemV2 label="瑙掕壊" prop="roleIds" :check-rules="[{ message: '璇烽�夋嫨瑙掕壊' }]">
+        <ProFormCheckbox
+          v-model="innerForm.roleIds"
+          :value-enum="userInfoRoles"
+          enumLabelKey="name"
+          enum-value-key="id"
+        ></ProFormCheckbox>
+      </ProFormItemV2>
+      <ProFormItemV2 label="澶囨敞:" prop="remark">
+        <ProFormTextArea
+          v-model="innerForm.remark"
+          placeholder="璇疯緭鍏ュ娉�"
+          show-word-limit
+          :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 { FormRules, FormInstance } from 'element-plus';
+import {
+  ProDialog,
+  ProForm,
+  ProFormItemV2,
+  ProFormText,
+  ProFormTextArea,
+  ProFormCheckbox,
+  ProFormSelect,
+} from '@bole-core/components';
+import { BoleRegExp } from '@bole-core/core';
+import { useUserInfoRoles } from '@/hooks';
+
+defineOptions({
+  name: 'AddOrEditUserDialog',
+});
+
+type Props = {
+  modelValue: boolean;
+  form: {
+    name: string;
+    title?: string;
+    id: string;
+    userName: string;
+    phoneNumber: string;
+    remark: string;
+    roleIds: string[];
+    password: string;
+  };
+};
+
+const props = withDefaults(defineProps<Props>(), {
+  modelValue: false,
+});
+
+const { userInfoRoles } = useUserInfoRoles({
+  userInfoId: toRef(props.form, 'id'),
+  userType: EnumUserType.Enterprise,
+  clientType: EnumClientType.PcWeb,
+});
+
+const isEdit = computed(() => !!props.form.id);
+
+const emit = defineEmits<{
+  (e: 'update:modelValue', value: boolean): void;
+  (e: 'update:form', value: Props['form']): void;
+  (e: 'onConfirm'): void;
+  (e: 'onCancel'): void;
+}>();
+
+const dialogForm = ref<FormInstance>();
+
+const innerVisible = computed({
+  get() {
+    return props.modelValue;
+  },
+  set(val) {
+    emit('update:modelValue', val);
+  },
+});
+
+const innerForm = computed({
+  get() {
+    return props.form;
+  },
+  set(val) {
+    emit('update:form', val);
+  },
+});
+
+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/UserManage/constants/columns.ts b/src/views/UserManage/constants/columns.ts
new file mode 100644
index 0000000..caf8385
--- /dev/null
+++ b/src/views/UserManage/constants/columns.ts
@@ -0,0 +1,34 @@
+import { defineColumns } from '@bole-core/components';
+
+export const UserManageColumns = defineColumns([
+  {
+    id: '1',
+    enCode: 'name',
+    name: '濮撳悕',
+  },
+  {
+    id: '2',
+    enCode: 'userName',
+    name: '鐢ㄦ埛鍚�',
+  },
+  {
+    id: '3',
+    enCode: 'phoneNumber',
+    name: '鎵嬫満鍙�',
+  },
+  {
+    id: '4',
+    enCode: 'roles',
+    name: '瑙掕壊',
+  },
+  {
+    id: '5',
+    enCode: 'status',
+    name: '鐘舵��',
+  },
+  {
+    id: '6',
+    enCode: 'remark',
+    name: '澶囨敞',
+  },
+]);
diff --git a/src/views/UserManage/constants/index.ts b/src/views/UserManage/constants/index.ts
new file mode 100644
index 0000000..a7f066b
--- /dev/null
+++ b/src/views/UserManage/constants/index.ts
@@ -0,0 +1 @@
+export * from './columns';

--
Gitblit v1.9.1