From 55dc8d799de193e682e97e5333b6baa9a0e26361 Mon Sep 17 00:00:00 2001
From: wupengfei <834520024@qq.com>
Date: 星期四, 03 四月 2025 15:49:49 +0800
Subject: [PATCH] feat: init

---
 src/views/MaterialReview/MaterialReview.vue             |  209 ++++++++++
 src/views/EnterpriseInfo/EnterpriseInfoDetail.vue       |   13 
 src/views/Account/components/AddOrEditAccountDialog.vue |   20 -
 src/store/modules/user.ts                               |    3 
 src/views/EnterpriseInfo/EnterpriseInfo.vue             |  195 +++++++++
 src/hooks/index.ts                                      |    1 
 src/views/MaterialReview/MaterialReviewAudit.vue        |   13 
 src/views/Reward/Reward.vue                             |  231 +++++++++++
 /dev/null                                               |   25 -
 src/store/modules/permission.ts                         |    2 
 src/views/Account/AccountManageList.vue                 |  148 ++++---
 src/views/Reward/RewardDeclareDetail.vue                |   13 
 src/router/index.ts                                     |  185 +++++++-
 src/views/Reward/components/RewardGrantDialog.vue       |  105 +++++
 src/views/MaterialReview/MaterialReviewDetail.vue       |   13 
 15 files changed, 1,039 insertions(+), 137 deletions(-)

diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index 4e58653..cbe1cbd 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -6,4 +6,3 @@
 export * from './useEvent';
 export * from './useUser';
 export * from './help';
-export * from './insuranceClaim';
diff --git a/src/hooks/insuranceClaim.ts b/src/hooks/insuranceClaim.ts
deleted file mode 100644
index b276563..0000000
--- a/src/hooks/insuranceClaim.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import * as insuranceClaimServices from '@/services/api/InsuranceClaim';
-import { useQuery, useQueryClient } from '@tanstack/vue-query';
-
-export function useInsuranceClaimChannelList() {
-  const { data: insuranceClaimChannelList } = useQuery({
-    queryKey: ['insuranceClaimServices/getInsuranceClaimChannelList'],
-    queryFn: async () => {
-      let res = await insuranceClaimServices.getInsuranceClaimChannelList({ showLoading: false });
-      return res;
-    },
-    placeholderData: () => [] as string[],
-  });
-
-  const insuranceClaimChannelListForSelect = computed(() => {
-    return insuranceClaimChannelList.value.map((item) => ({
-      label: item,
-      value: item,
-    }));
-  });
-
-  return {
-    insuranceClaimChannelList,
-    insuranceClaimChannelListForSelect,
-  };
-}
diff --git a/src/router/index.ts b/src/router/index.ts
index 7e3ec75..e61e205 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -94,33 +94,164 @@
       rootMenu: true,
     },
   },
-  // {
-  //   path: '/InsuranceClaimDetail',
-  //   redirect: 'noRedirect',
-  //   component: Layout,
-  //   hidden: false,
-  //   alwaysShow: true,
-  //   meta: {
-  //     rank: 10001,
-  //     title: '鐞嗚禂',
-  //     rootMenu: true,
-  //     icon: 'home',
-  //   },
-  //   children: [
-  //     {
-  //       path: '/InsuranceClaimDetail/:id',
-  //       name: 'InsuranceClaimDetail',
-  //       hidden: true,
-  //       component: () => import('@/views/InsuranceClaim/InsuranceClaimDetail.vue'),
-  //       meta: {
-  //         rank: 10002,
-  //         title: '鐞嗚禂璇︽儏',
-  //         // rootMenu: true,
-  //         icon: 'home',
-  //       },
-  //     },
-  //   ],
-  // },
+  {
+    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',
+    component: Layout,
+    hidden: false,
+    alwaysShow: true,
+    meta: {
+      rank: 10020,
+      title: '鏉愭枡瀹℃牳',
+      rootMenu: true,
+      icon: 'home',
+    },
+    children: [
+      {
+        path: '/MaterialReviewList',
+        name: 'MaterialReviewList',
+        hidden: false,
+        alwaysShow: true,
+        component: () => import('@/views/MaterialReview/MaterialReview.vue'),
+        meta: {
+          rank: 10021,
+          title: '鏉愭枡瀹℃牳',
+          // rootMenu: true,
+          icon: 'home',
+        },
+      },
+      {
+        path: '/MaterialReviewDetail/:id',
+        name: 'MaterialReviewDetail',
+        hidden: true,
+        component: () => import('@/views/MaterialReview/MaterialReviewDetail.vue'),
+        meta: {
+          rank: 10022,
+          title: '鏉愭枡瀹℃牳璇︽儏',
+          rootMenu: false,
+        },
+      },
+      {
+        path: '/MaterialReviewAudit/:id',
+        name: 'MaterialReviewAudit',
+        hidden: true,
+        component: () => import('@/views/MaterialReview/MaterialReviewAudit.vue'),
+        meta: {
+          rank: 10023,
+          title: '瀹℃牳',
+          rootMenu: false,
+        },
+      },
+    ],
+  },
+  {
+    path: '/Reward',
+    redirect: 'noRedirect',
+    component: Layout,
+    hidden: false,
+    alwaysShow: true,
+    meta: {
+      rank: 10030,
+      title: '濂栧姳閲�',
+      rootMenu: true,
+      icon: 'home',
+    },
+    children: [
+      {
+        path: '/RewardList',
+        name: 'RewardList',
+        hidden: false,
+        alwaysShow: true,
+        component: () => import('@/views/Reward/Reward.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: '/Syatem',
+    redirect: 'noRedirect',
+    component: Layout,
+    hidden: false,
+    alwaysShow: true,
+    meta: {
+      rank: 10030,
+      title: '绯荤粺閰嶇疆',
+      rootMenu: true,
+      icon: 'home',
+    },
+    children: [
+      {
+        path: '/Account',
+        name: 'Account',
+        hidden: false,
+        alwaysShow: true,
+        component: () => import('@/views/Account/AccountManageList.vue'),
+        meta: {
+          rank: 10031,
+          title: '璐﹀彿绠$悊',
+          // rootMenu: true,
+          icon: 'home',
+        },
+      },
+    ],
+  },
+
   {
     path: '/Login',
     name: 'Login',
diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts
index 2fc37a5..925456d 100644
--- a/src/store/modules/permission.ts
+++ b/src/store/modules/permission.ts
@@ -33,7 +33,7 @@
           const res = await baseModuleServices.getCurrentUserModuleList({
             showLoading: false,
           });
-          const accessedRoutes = ascending(addAsyncRoutes(formatModuleList(res, null))); // createAccessedRoutes(userMenuList, userInfo)
+          const accessedRoutes = ascending(addAsyncRoutes(formatModuleList([], null))); // createAccessedRoutes(userMenuList, userInfo)
           //@ts-ignore
           accessedRoutes.push({ path: '/:pathMatch(.*)*', redirect: '/404', hidden: true });
 
diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts
index 4cf1068..49bd21d 100644
--- a/src/store/modules/user.ts
+++ b/src/store/modules/user.ts
@@ -4,7 +4,6 @@
 import { resetRouter, router } from '@/router';
 import { useTagsViewStoreHook } from './tagsView';
 import * as accountServices from '@/services/api/Account';
-import * as userServices from '@/services/api/User';
 import { usePermissionStoreHook } from './permission';
 import { getAccountInfoFromAccessToken, AccountInfo } from '@bole-core/core';
 import { useClearSubModule } from '@/hooks';
@@ -64,7 +63,7 @@
     // 鐢ㄦ埛鐧诲叆
     loginByUsername(data: API.AccessRequestDto) {
       return new Promise<void>((resolve, reject) => {
-        userServices
+        accountServices
           .getTokenForWeb(data, { showLoading: false })
           .then((res) => {
             if (res) {
diff --git a/src/views/Account/AccountManageList.vue b/src/views/Account/AccountManageList.vue
index 3633a05..c4a301b 100644
--- a/src/views/Account/AccountManageList.vue
+++ b/src/views/Account/AccountManageList.vue
@@ -14,13 +14,7 @@
           </QueryFilterItem>
         </template>
         <template #btn>
-          <el-button
-            v-if="checkSubModuleItemShow('pageButton', 'addBtn')"
-            @click="openDialog()"
-            icon="Plus"
-            type="primary"
-            >鏂板</el-button
-          >
+          <el-button @click="openDialog()" icon="Plus" type="primary">鏂板</el-button>
         </template>
       </ProTableQueryFilterBar>
       <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
@@ -33,7 +27,6 @@
 <script setup lang="ts">
 import {
   ProTableQueryFilterBar,
-  OperationBtnType,
   ProTableV2,
   SearchInput,
   LoadingLayout,
@@ -41,10 +34,9 @@
   QueryFilterItem,
   useTable,
   useFormDialog,
+  defineOperationBtns,
 } from '@bole-core/components';
-import { useAccess } from '@/hooks';
-import * as userServices from '@/services/api/User';
-import { RoleClientType } from '@/constants';
+import * as accountServices from '@/services/api/Account';
 import { Message, OrderInputType } from '@bole-core/core';
 import AddOrEditAccountDialog from './components/AddOrEditAccountDialog.vue';
 import { formatRoleName } from '@/utils';
@@ -53,13 +45,49 @@
   name: 'AccountManageList',
 });
 
-const operationBtnMap: Record<string, OperationBtnType> = {
-  editBtn: { emits: { onClick: (role) => openDialog(role) } },
-};
+const column: API.CustomModuleColumnDto[] = [
+  {
+    id: '1',
+    enCode: 'changeFlag',
+    name: '璐﹀彿',
+  },
+  {
+    id: '2',
+    enCode: 'name',
+    name: '濮撳悕',
+  },
+  {
+    id: '3',
+    enCode: 'idNumber',
+    name: '鎵嬫満鍙�',
+  },
+  {
+    id: '4',
+    enCode: 'workType',
+    name: '澶囨敞',
+  },
+];
 
-const { checkSubModuleItemShow, column, operationBtns } = useAccess({
-  operationBtnMap,
-});
+const operationBtns = defineOperationBtns([
+  {
+    data: {
+      enCode: 'editBtn',
+      name: '缂栬緫',
+    },
+    emits: {
+      onClick: (role) => openDialog(role),
+    },
+  },
+  {
+    data: {
+      enCode: 'resetPasswordBtn',
+      name: '閲嶇疆瀵嗙爜',
+    },
+    emits: {
+      onClick: (role) => handleResetPassword(),
+    },
+  },
+]);
 
 const BaseState = {
   loading: true,
@@ -80,35 +108,31 @@
   reset,
 } = useTable(
   async ({ pageIndex, pageSize }, extraParamState) => {
-    try {
-      let params: API.QueryUserPageInput = {
-        pageModel: {
-          rows: pageSize,
-          page: pageIndex,
-          orderInput: extraParamState.orderInput,
-        },
-        searchKey: extraParamState.keyword,
-      };
-      let res = await userServices.getUserPage(params, {
-        showLoading: !state.loading,
-      });
-      return res;
-    } catch (error) {}
+    // try {
+    //   let params: API.QueryUserPageInput = {
+    //     pageModel: {
+    //       rows: pageSize,
+    //       page: pageIndex,
+    //       orderInput: extraParamState.orderInput,
+    //     },
+    //     searchKey: extraParamState.keyword,
+    //   };
+    //   let res = await userServices.getUserPage(params, {
+    //     showLoading: !state.loading,
+    //   });
+    //   return res;
+    // } catch (error) {}
   },
   {
     defaultExtraParams: {
       orderInput: [{ property: 'id', order: OrderInputType.Desc }],
       keyword: '',
     },
-    columnsRenderProps: {
-      roleNames: {
-        formatter: (row: API.UserListOutput) => row.roleNames.map(formatRoleName).join(','),
-      },
-    },
+    columnsRenderProps: {},
   }
 );
 
-function openDialog(row?: API.UserListOutput) {
+function openDialog(row?: any) {
   if (row) {
     handleEdit({
       id: row.id,
@@ -148,29 +172,31 @@
 });
 
 async function handleAddOrEdit() {
-  try {
-    let isEdit = !!editForm.id;
-    let params: API.CreateAccountInput = {
-      name: editForm.name,
-      userName: editForm.userName,
-      remark: editForm.remark,
-      password: editForm.password,
-      phoneNumber: editForm.phoneNumber,
-      channel: editForm.channel,
-      // clientId: RoleClientType.RoleBackendClientId,
-      roleNames: [editForm.roleName],
-    };
-    let res;
-    if (isEdit) {
-      (params as API.UpdateAccountInput).id = editForm.id;
-      res = await userServices.updateAccount(params);
-    } else {
-      res = await userServices.createAccount(params);
-    }
-    if (res) {
-      Message.successMessage('鎿嶄綔鎴愬姛');
-      getList(isEdit ? paginationState.pageIndex : 1);
-    }
-  } catch (error) {}
+  // try {
+  //   let isEdit = !!editForm.id;
+  //   let params: API.CreateAccountInput = {
+  //     name: editForm.name,
+  //     userName: editForm.userName,
+  //     remark: editForm.remark,
+  //     password: editForm.password,
+  //     phoneNumber: editForm.phoneNumber,
+  //     channel: editForm.channel,
+  //     // clientId: RoleClientType.RoleBackendClientId,
+  //     roleNames: [editForm.roleName],
+  //   };
+  //   let res;
+  //   if (isEdit) {
+  //     (params as API.UpdateAccountInput).id = editForm.id;
+  //     res = await accountServices.updateAccount(params);
+  //   } else {
+  //     res = await accountServices.createAccount(params);
+  //   }
+  //   if (res) {
+  //     Message.successMessage('鎿嶄綔鎴愬姛');
+  //     getList(isEdit ? paginationState.pageIndex : 1);
+  //   }
+  // } catch (error) {}
 }
+
+function handleResetPassword() {}
 </script>
diff --git a/src/views/Account/components/AddOrEditAccountDialog.vue b/src/views/Account/components/AddOrEditAccountDialog.vue
index c0d3ffa..97a542a 100644
--- a/src/views/Account/components/AddOrEditAccountDialog.vue
+++ b/src/views/Account/components/AddOrEditAccountDialog.vue
@@ -29,13 +29,6 @@
       >
         <ProFormText placeholder="璇疯緭鍏ユ墜鏈哄彿" v-model.trim="form.phoneNumber"></ProFormText>
       </ProFormItemV2>
-      <ProFormItemV2 label="娓犻亾:" prop="channel" :check-rules="[{ message: '璇疯緭鍏ユ笭閬�' }]">
-        <ProFormText
-          placeholder="璇疯緭鍏ユ笭閬�"
-          v-model.trim="form.channel"
-          :maxlength="30"
-        ></ProFormText>
-      </ProFormItemV2>
       <ProFormItemV2
         label="瀵嗙爜:"
         prop="password"
@@ -46,16 +39,6 @@
           v-model.trim="form.password"
           :maxlength="30"
         ></ProFormText>
-      </ProFormItemV2>
-      <ProFormItemV2 label="瑙掕壊:" prop="roleName" :check-rules="[{ message: '璇烽�夋嫨瑙掕壊' }]">
-        <ProFormRadio
-          v-model.trim="form.roleName"
-          :value-enum="allRoleList"
-          :button-style="false"
-          enum-label-key="name"
-          enum-value-key="realName"
-          :disabled="!!form.id"
-        />
       </ProFormItemV2>
 
       <ProFormItemV2 label="澶囨敞:" prop="remark">
@@ -87,7 +70,6 @@
   ProFormCheckbox,
 } from '@bole-core/components';
 import { BooleanOptions } from '@/constants';
-import { useAllRoleList } from '@/hooks';
 
 defineOptions({
   name: 'AddOrEditAccountDialog',
@@ -122,8 +104,6 @@
 }>();
 
 const dialogForm = ref<FormInstance>();
-
-const { allRoleList } = useAllRoleList();
 
 function onDialogClose() {
   if (!dialogForm.value) return;
diff --git a/src/views/EnterpriseInfo/EnterpriseInfo.vue b/src/views/EnterpriseInfo/EnterpriseInfo.vue
new file mode 100644
index 0000000..304f063
--- /dev/null
+++ b/src/views/EnterpriseInfo/EnterpriseInfo.vue
@@ -0,0 +1,195 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableQueryFilterBar @on-reset="reset">
+        <template #query>
+          <QueryFilterItem tip-content="鏈�杩戠敵鎶ユ棩鏈�">
+            <FieldDatePicker
+              v-model="extraParamState.date"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              clearable
+              @change="getList()"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+          <QueryFilterItem tip-content="鏈�杩戝彂鏀炬棩鏈�">
+            <FieldDatePicker
+              v-model="extraParamState.date"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              clearable
+              @change="getList()"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+          <QueryFilterItem>
+            <SearchInput
+              v-model="extraParamState.keyword"
+              style="width: 300px"
+              placeholder="浼佷笟鍚�/缁熶竴淇$敤浠g爜"
+              @on-click-search="getList"
+            >
+            </SearchInput>
+          </QueryFilterItem>
+        </template>
+      </ProTableQueryFilterBar>
+
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+      </ProTableV2>
+    </AppContainer>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  LoadingLayout,
+  AppContainer,
+  useTable,
+  ProTableQueryFilterBar,
+  ProTableV2,
+  defineOperationBtns,
+  SearchInput,
+  QueryFilterItem,
+  FieldDatePicker,
+} from '@bole-core/components';
+import { OrderInputType } from '@bole-core/core';
+import { format } from '@/utils';
+import * as informationServices from '@/services/api/Information';
+import _ from 'lodash';
+import { ModelValueType } from 'element-plus';
+
+defineOptions({
+  name: 'EnterpriseInfo',
+});
+
+const column: API.CustomModuleColumnDto[] = [
+  {
+    id: '1',
+    enCode: 'changeFlag',
+    name: '浼佷笟鍚�',
+  },
+  {
+    id: '2',
+    enCode: 'name',
+    name: '缁熶竴绀句細淇$敤浠g爜',
+  },
+  {
+    id: '3',
+    enCode: 'idNumber',
+    name: '浼佷笟绫诲瀷',
+  },
+  {
+    id: '4',
+    enCode: 'workType',
+    name: '鎵�灞炲洯鍖�',
+  },
+  {
+    id: '5',
+    enCode: 'gender',
+    name: '鍥尯绫诲瀷',
+  },
+  {
+    id: '6',
+    enCode: 'age',
+    name: '濂栧姳閲戠敵鎶ユ鏁�',
+  },
+  {
+    id: '7',
+    enCode: 'birthDay',
+    name: '鏈�杩戠敵鎶ユ棩鏈�',
+  },
+  {
+    id: '8',
+    enCode: 'phoneNumber',
+    name: '濂栧姳閲戝彂鏀炬鏁�',
+  },
+  {
+    id: '9',
+    enCode: 'phoneNumber',
+    name: '鏈�杩戝彂鏀炬棩鏈�',
+  },
+  {
+    id: '10',
+    enCode: 'phoneNumber',
+    name: '濂栧姳閲戝彂鏀炬�婚',
+  },
+  {
+    id: '11',
+    enCode: 'phoneNumber',
+    name: '濂栧姳閲戜綑棰�',
+  },
+];
+
+const operationBtns = defineOperationBtns([
+  {
+    data: {
+      enCode: 'detailBtn',
+      name: '璇︽儏',
+    },
+    emits: {
+      onClick: (role) => goDetail(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.GetInformationForManageInput = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        publishStartDate: format(extraParamState.date?.[0] ?? '', 'YYYY-MM-DD 00:00:00'),
+        publishEndDate: format(extraParamState.date?.[1] ?? '', 'YYYY-MM-DD 23:59:59'),
+      };
+      let res = await informationServices.getInformationForManage(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      keyword: '',
+      date: [] as unknown as ModelValueType,
+      orderInput: [{ property: 'creationTime', order: OrderInputType.Desc }],
+    },
+  }
+);
+
+function goDetail(row: any) {
+  router.push({
+    name: 'EnterpriseInfoDetail',
+    params: {
+      id: row.id,
+    },
+  });
+}
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/EnterpriseInfo/EnterpriseInfoDetail.vue b/src/views/EnterpriseInfo/EnterpriseInfoDetail.vue
new file mode 100644
index 0000000..f6983da
--- /dev/null
+++ b/src/views/EnterpriseInfo/EnterpriseInfoDetail.vue
@@ -0,0 +1,13 @@
+<template>
+  <div>EnterpriseInfoDetail</div>
+</template>
+
+<script setup lang="ts">
+defineOptions({
+  name: 'EnterpriseInfoDetail',
+});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/MaterialReview/MaterialReview.vue b/src/views/MaterialReview/MaterialReview.vue
new file mode 100644
index 0000000..eae7f02
--- /dev/null
+++ b/src/views/MaterialReview/MaterialReview.vue
@@ -0,0 +1,209 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableQueryFilterBar @on-reset="reset">
+        <template #query>
+          <QueryFilterItem tip-content="鏈�杩戠敵鎶ユ棩鏈�">
+            <FieldDatePicker
+              v-model="extraParamState.date"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              clearable
+              @change="getList()"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+          <QueryFilterItem tip-content="鏈�杩戝彂鏀炬棩鏈�">
+            <FieldDatePicker
+              v-model="extraParamState.date"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              clearable
+              @change="getList()"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+          <QueryFilterItem>
+            <FieldRadio
+              v-model="extraParamState.showStatus"
+              :value-enum="DataRangeEnumText"
+              buttonStyle
+              showAllBtn
+              @change="getList()"
+            />
+          </QueryFilterItem>
+          <QueryFilterItem>
+            <SearchInput
+              v-model="extraParamState.keyword"
+              style="width: 200px"
+              placeholder="鎵规鍙�"
+              @on-click-search="getList"
+            >
+            </SearchInput>
+          </QueryFilterItem>
+        </template>
+      </ProTableQueryFilterBar>
+
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+      </ProTableV2>
+    </AppContainer>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  LoadingLayout,
+  AppContainer,
+  useTable,
+  ProTableQueryFilterBar,
+  ProTableV2,
+  defineOperationBtns,
+  SearchInput,
+  FieldRadio,
+  QueryFilterItem,
+  FieldDatePicker,
+} from '@bole-core/components';
+import { OrderInputType } from '@bole-core/core';
+import { format } from '@/utils';
+import { DataRangeEnum, DataRangeEnumText } from '@/constants';
+import * as informationServices from '@/services/api/Information';
+import _ from 'lodash';
+import { ModelValueType } from 'element-plus';
+
+defineOptions({
+  name: 'MaterialReview',
+});
+
+const column: API.CustomModuleColumnDto[] = [
+  {
+    id: '1',
+    enCode: 'changeFlag',
+    name: '鐢宠鎵规鍙�',
+  },
+  {
+    id: '2',
+    enCode: 'name',
+    name: '鐢宠鍥尯',
+  },
+  {
+    id: '3',
+    enCode: 'idNumber',
+    name: '鍥尯绫诲瀷',
+  },
+  {
+    id: '4',
+    enCode: 'workType',
+    name: '鐢宠濂栧姳閲戞湀浠�',
+  },
+  {
+    id: '5',
+    enCode: 'gender',
+    name: '濂栧姳閲戞眹鎬婚噾棰濓紙鍏冿級',
+  },
+  {
+    id: '6',
+    enCode: 'age',
+    name: '鐢虫姤鏃ユ湡',
+  },
+  {
+    id: '7',
+    enCode: 'birthDay',
+    name: '瀹℃牳鏃ユ湡',
+  },
+  {
+    id: '8',
+    enCode: 'phoneNumber',
+    name: '瀹℃牳鐘舵��',
+  },
+];
+
+const operationBtns = defineOperationBtns([
+  {
+    data: {
+      enCode: 'detailBtn',
+      name: '璇︽儏',
+    },
+    emits: {
+      onClick: (role) => goDetail(role),
+    },
+  },
+  {
+    data: {
+      enCode: 'auditBtn',
+      name: '瀹℃牳',
+    },
+    emits: {
+      onClick: (role) => goAudit(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.GetInformationForManageInput = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        publishStartDate: format(extraParamState.date?.[0] ?? '', 'YYYY-MM-DD 00:00:00'),
+        publishEndDate: format(extraParamState.date?.[1] ?? '', 'YYYY-MM-DD 23:59:59'),
+      };
+      let res = await informationServices.getInformationForManage(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      keyword: '',
+      showStatus: '' as any as DataRangeEnum,
+      date: [] as unknown as ModelValueType,
+      orderInput: [{ property: 'creationTime', order: OrderInputType.Desc }],
+    },
+  }
+);
+
+function goDetail(row: any) {
+  router.push({
+    name: 'MaterialReviewDetail',
+    params: {
+      id: row.id,
+    },
+  });
+}
+function goAudit(row: any) {
+  router.push({
+    name: 'MaterialReviewAudit',
+    params: {
+      id: row.id,
+    },
+  });
+}
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/MaterialReview/MaterialReviewAudit.vue b/src/views/MaterialReview/MaterialReviewAudit.vue
new file mode 100644
index 0000000..5812f49
--- /dev/null
+++ b/src/views/MaterialReview/MaterialReviewAudit.vue
@@ -0,0 +1,13 @@
+<template>
+  <div>MaterialReviewAudit</div>
+</template>
+
+<script setup lang="ts">
+defineOptions({
+  name: 'MaterialReviewAudit',
+});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/MaterialReview/MaterialReviewDetail.vue b/src/views/MaterialReview/MaterialReviewDetail.vue
new file mode 100644
index 0000000..62c93d0
--- /dev/null
+++ b/src/views/MaterialReview/MaterialReviewDetail.vue
@@ -0,0 +1,13 @@
+<template>
+  <div>MaterialReviewDetail</div>
+</template>
+
+<script setup lang="ts">
+defineOptions({
+  name: 'MaterialReviewDetail',
+});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/Reward/Reward.vue b/src/views/Reward/Reward.vue
new file mode 100644
index 0000000..94e7c5c
--- /dev/null
+++ b/src/views/Reward/Reward.vue
@@ -0,0 +1,231 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableQueryFilterBar @on-reset="reset">
+        <template #query>
+          <QueryFilterItem tip-content="鏈�杩戠敵鎶ユ棩鏈�">
+            <FieldDatePicker
+              v-model="extraParamState.date"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              clearable
+              @change="getList()"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+          <QueryFilterItem tip-content="鏈�杩戝彂鏀炬棩鏈�">
+            <FieldDatePicker
+              v-model="extraParamState.date"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="寮�濮嬫棩鏈�"
+              end-placeholder="缁撴潫鏃ユ湡"
+              clearable
+              @change="getList()"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+          <QueryFilterItem>
+            <FieldRadio
+              v-model="extraParamState.showStatus"
+              :value-enum="DataRangeEnumText"
+              buttonStyle
+              showAllBtn
+              @change="getList()"
+            />
+          </QueryFilterItem>
+          <QueryFilterItem>
+            <SearchInput
+              v-model="extraParamState.keyword"
+              style="width: 200px"
+              placeholder="鎵规鍙�"
+              @on-click-search="getList"
+            >
+            </SearchInput>
+          </QueryFilterItem>
+        </template>
+      </ProTableQueryFilterBar>
+
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+      </ProTableV2>
+
+      <RewardGrantDialog v-bind="dialogProps"></RewardGrantDialog>
+    </AppContainer>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  LoadingLayout,
+  AppContainer,
+  useTable,
+  ProTableQueryFilterBar,
+  ProTableV2,
+  defineOperationBtns,
+  SearchInput,
+  FieldRadio,
+  QueryFilterItem,
+  FieldDatePicker,
+  useFormDialog,
+  UploadUserFile,
+} from '@bole-core/components';
+import { OrderInputType } from '@bole-core/core';
+import { convertApi2FormUrlOnlyOne, format } from '@/utils';
+import { DataRangeEnum, DataRangeEnumText } from '@/constants';
+import * as informationServices from '@/services/api/Information';
+import RewardGrantDialog from './components/RewardGrantDialog.vue';
+import _ from 'lodash';
+import { ModelValueType } from 'element-plus';
+
+defineOptions({
+  name: 'Reward',
+});
+
+const column: API.CustomModuleColumnDto[] = [
+  {
+    id: '1',
+    enCode: 'changeFlag',
+    name: '鐢宠鎵规鍙�',
+  },
+  {
+    id: '2',
+    enCode: 'name',
+    name: '鐢宠鍥尯',
+  },
+  {
+    id: '3',
+    enCode: 'idNumber',
+    name: '鍥尯绫诲瀷',
+  },
+  {
+    id: '4',
+    enCode: 'workType',
+    name: '鐢宠濂栧姳閲戞湀浠�',
+  },
+  {
+    id: '5',
+    enCode: 'gender',
+    name: '濂栧姳閲戞眹鎬婚噾棰濓紙鍏冿級',
+  },
+  {
+    id: '6',
+    enCode: 'age',
+    name: '鐢虫姤鏃ユ湡',
+  },
+  {
+    id: '7',
+    enCode: 'phoneNumber',
+    name: '鍙戞斁鐘舵��',
+  },
+  {
+    id: '8',
+    enCode: 'phoneNumber',
+    name: '鍙戞斁鏃ユ湡',
+  },
+];
+
+const operationBtns = defineOperationBtns([
+  {
+    data: {
+      enCode: 'detailBtn',
+      name: '鐢虫姤璇︽儏',
+    },
+    emits: {
+      onClick: (role) => goDetail(role),
+    },
+  },
+  {
+    data: {
+      enCode: 'grantBtn',
+      name: '鍙戞斁',
+    },
+    emits: {
+      onClick: (role) => openDialog(role),
+    },
+  },
+  {
+    data: {
+      enCode: 'previewBtn',
+      name: '鏌ョ湅鍑瘉',
+    },
+    emits: {
+      onClick: (role) => handlePreview(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.GetInformationForManageInput = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        publishStartDate: format(extraParamState.date?.[0] ?? '', 'YYYY-MM-DD 00:00:00'),
+        publishEndDate: format(extraParamState.date?.[1] ?? '', 'YYYY-MM-DD 23:59:59'),
+      };
+      let res = await informationServices.getInformationForManage(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      keyword: '',
+      showStatus: '' as any as DataRangeEnum,
+      date: [] as unknown as ModelValueType,
+      orderInput: [{ property: 'creationTime', order: OrderInputType.Desc }],
+    },
+  }
+);
+
+function goDetail(row: any) {
+  router.push({
+    name: 'RewardDeclareDetail',
+    params: {
+      id: row.id,
+    },
+  });
+}
+
+const { dialogProps, handleAdd, handleEdit, editForm } = useFormDialog({
+  defaultFormParams: {
+    id: '',
+    url: [] as UploadUserFile[],
+  },
+});
+
+function openDialog(row?: API.IncentivePaymentsManageListOutput) {
+  handleEdit({
+    id: row.enterpriseName,
+    url: convertApi2FormUrlOnlyOne(row.issueVouchersUrl),
+  });
+}
+
+function handlePreview(row?: API.IncentivePaymentsManageListOutput) {}
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/Reward/RewardDeclareDetail.vue b/src/views/Reward/RewardDeclareDetail.vue
new file mode 100644
index 0000000..6510a7c
--- /dev/null
+++ b/src/views/Reward/RewardDeclareDetail.vue
@@ -0,0 +1,13 @@
+<template>
+  <div>RewardDeclareDetail</div>
+</template>
+
+<script setup lang="ts">
+defineOptions({
+  name: 'RewardDeclareDetail',
+});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/Reward/components/RewardGrantDialog.vue b/src/views/Reward/components/RewardGrantDialog.vue
new file mode 100644
index 0000000..a6b4b2c
--- /dev/null
+++ b/src/views/Reward/components/RewardGrantDialog.vue
@@ -0,0 +1,105 @@
+<template>
+  <ProDialog
+    title="濂栧姳閲戝彂鏀�"
+    v-model="innerVisible"
+    destroy-on-close
+    draggable
+    bodyNoPaddingBottom
+    @close="onDialogClose"
+    width="600px"
+  >
+    <ProForm :model="innerForm" ref="dialogForm" label-width="120px">
+      <ProFormItemV2
+        label="涓婁紶鍙戞斁鍑瘉:"
+        prop="url"
+        :check-rules="[{ message: '璇蜂笂浼犲彂鏀惧嚟璇�', type: 'upload' }]"
+      >
+        <ProFormUpload
+          v-model:file-url="innerForm.url"
+          :limit="1"
+          :limitFileSize="10"
+          accept="doc,docx,pdf"
+        >
+        </ProFormUpload>
+      </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 {
+  ProDialog,
+  UploadUserFile,
+  ProForm,
+  ProFormItemV2,
+  ProFormSelect,
+  ProFormInputNumber,
+  ProFormUpload,
+} from '@bole-core/components';
+import { FormInstance } from 'element-plus';
+
+defineOptions({
+  name: 'RewardGrantDialog',
+});
+
+type Props = {
+  modelValue: boolean;
+  form?: {
+    id: string;
+    url: UploadUserFile[];
+  };
+};
+
+const props = withDefaults(defineProps<Props>(), {
+  modelValue: false,
+});
+
+const emit = defineEmits<{
+  (e: 'update:modelValue', value: boolean): void;
+  (e: 'update:form', value: Props['form']): void;
+  (e: 'onConfirm'): void;
+  (e: 'onCancel'): void;
+}>();
+
+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);
+  },
+});
+
+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>

--
Gitblit v1.9.1