From 6b333bea26b7599a3cf39cfa88333572ad66261e Mon Sep 17 00:00:00 2001
From: wupengfei <834520024@qq.com>
Date: 星期三, 28 五月 2025 16:45:07 +0800
Subject: [PATCH] fix: bug

---
 src/components/Reward/RewardInfoCardContentItem.vue          |   45 +
 src/views/BalanceManage/components/ConsumeRecordView.vue     |  118 ++++
 src/services/api/typings.d.ts                                |  161 +++++
 src/components/Reward/RewardInfoCard.vue                     |   46 +
 src/components/Reward/RewardInfoCardList.vue                 |   22 
 pnpm-lock.yaml                                               |   84 +-
 src/components/Reward/RewardInfoCardPrice.vue                |   48 +
 src/utils/common/file.ts                                     |   15 
 src/views/BalanceManage/BalanceManage.vue                    |  188 ++++++
 src/services/api/index.ts                                    |    2 
 src/services/api/User.ts                                     |   35 +
 src/views/FileManage/FileManage.vue                          |  161 +++++
 src/constants/customerConsume.ts                             |   20 
 src/views/BalanceManage/components/RewardGrantRecordView.vue |  102 +++
 src/views/BalanceManage/components/RewardRechargeDialog.vue  |  266 +++++++++
 src/router/index.ts                                          |   59 ++
 src/constants/index.ts                                       |    1 
 src/services/api/ParkBountyApply.ts                          |   54 +
 src/utils/common/common.ts                                   |   41 +
 src/views/BalanceManage/components/RechargeRecordView.vue    |  143 +++++
 src/views/Home/Home.vue                                      |   12 
 21 files changed, 1,586 insertions(+), 37 deletions(-)

diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 942a7e9..a5da48f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -21,13 +21,13 @@
     version: 1.0.3(@bole-12333/chat-kit@1.0.1)(@tiptap/core@2.1.13)(@tiptap/extension-document@2.1.13)(@tiptap/extension-image@2.1.13)(@tiptap/extension-mention@2.1.13)(@tiptap/extension-paragraph@2.1.13)(@tiptap/extension-placeholder@2.1.13)(@tiptap/extension-text@2.1.13)(@tiptap/pm@2.1.13)(@tiptap/suggestion@2.1.13)(dayjs@1.11.6)(vue@3.5.11)
   '@bole-core/components':
     specifier: latest
-    version: 1.3.5(@bole-core/core@1.0.2)(@bole-core/sass-utils@0.0.1)(@element-plus/icons-vue@2.3.1)(@tanstack/vue-query@4.37.1)(@videojs-player/vue@1.0.0)(@vueuse/core@11.1.0)(@vueuse/shared@11.1.0)(dayjs@1.11.6)(element-plus@2.9.1)(lodash@4.17.21)(mitt@3.0.0)(senin-help@1.0.5)(senin-vue@1.0.4)(video.js@7.20.3)(vue-component-type-helpers@2.1.6)(vue@3.5.11)
+    version: 1.3.9(@bole-core/core@1.0.5)(@bole-core/sass-utils@0.0.1)(@element-plus/icons-vue@2.3.1)(@tanstack/vue-query@4.37.1)(@videojs-player/vue@1.0.0)(@vueuse/core@11.1.0)(@vueuse/shared@11.1.0)(dayjs@1.11.6)(element-plus@2.9.1)(lodash@4.17.21)(mitt@3.0.0)(senin-help@1.0.5)(senin-vue@1.0.4)(video.js@7.20.3)(vue-component-type-helpers@2.1.6)(vue@3.5.11)
   '@bole-core/core':
     specifier: latest
-    version: 1.0.2(@ywwlmm/openapi@0.0.3)(ali-oss@6.21.0)(axios@1.7.7)(dayjs@1.11.6)(element-plus@2.9.1)(file-saver@2.0.5)(jszip@3.10.1)(lodash@4.17.21)(senior-request@1.0.1)(vue-router@4.4.5)(vue@3.5.11)(xlsx-style@0.8.13)(xlsx@0.18.5)
+    version: 1.0.5(@ywwlmm/openapi@0.0.3)(ali-oss@6.21.0)(axios@1.7.7)(dayjs@1.11.6)(element-plus@2.9.1)(file-saver@2.0.5)(jszip@3.10.1)(lodash@4.17.21)(senior-request@1.0.1)(vue-router@4.4.5)(vue@3.5.11)(xlsx-style@0.8.13)(xlsx@0.18.5)
   '@bole-core/pretty-layout':
     specifier: latest
-    version: 1.2.0(@bole-core/core@1.0.2)(@bole-core/sass-utils@0.0.1)(@element-plus/icons-vue@2.3.1)(@vueuse/core@11.1.0)(element-plus@2.9.1)(fuse.js@6.6.2)(lottie-web@5.10.2)(path-browserify@1.0.1)(path-to-regexp@6.2.1)(pinia@2.2.4)(vue-router@4.4.5)(vue@3.5.11)
+    version: 1.2.0(@bole-core/core@1.0.5)(@bole-core/sass-utils@0.0.1)(@element-plus/icons-vue@2.3.1)(@vueuse/core@11.1.0)(element-plus@2.9.1)(fuse.js@6.6.2)(lottie-web@5.10.2)(path-browserify@1.0.1)(path-to-regexp@6.2.1)(pinia@2.2.4)(vue-router@4.4.5)(vue@3.5.11)
   '@bole-core/sass-utils':
     specifier: latest
     version: 0.0.1(element-plus@2.9.1)
@@ -1889,8 +1889,8 @@
       vue: 3.5.11(typescript@4.8.4)
     dev: false
 
-  /@bole-core/components@1.3.5(@bole-core/core@1.0.2)(@bole-core/sass-utils@0.0.1)(@element-plus/icons-vue@2.3.1)(@tanstack/vue-query@4.37.1)(@videojs-player/vue@1.0.0)(@vueuse/core@11.1.0)(@vueuse/shared@11.1.0)(dayjs@1.11.6)(element-plus@2.9.1)(lodash@4.17.21)(mitt@3.0.0)(senin-help@1.0.5)(senin-vue@1.0.4)(video.js@7.20.3)(vue-component-type-helpers@2.1.6)(vue@3.5.11):
-    resolution: {integrity: sha512-HSl3vo6hYNJwQx46p4FSeU46dPfAHgdxOcXOyN9sFdspgvUOiSktTBUBV+fqMSx8aA5ESJNVBcGtiRsY2LkQlg==}
+  /@bole-core/components@1.3.9(@bole-core/core@1.0.5)(@bole-core/sass-utils@0.0.1)(@element-plus/icons-vue@2.3.1)(@tanstack/vue-query@4.37.1)(@videojs-player/vue@1.0.0)(@vueuse/core@11.1.0)(@vueuse/shared@11.1.0)(dayjs@1.11.6)(element-plus@2.9.1)(lodash@4.17.21)(mitt@3.0.0)(senin-help@1.0.5)(senin-vue@1.0.4)(video.js@7.20.3)(vue-component-type-helpers@2.1.6)(vue@3.5.11):
+    resolution: {integrity: sha512-9lCPb9fKp0fUnC6YzMaGxDXiqcgYLMg/TuLNFOuClW1uuggEQfNPQxwSdWS4C/SynXuLVPPRArQUy08AheVNRw==}
     peerDependencies:
       '@bole-core/core': '*'
       '@bole-core/sass-utils': '*'
@@ -1909,7 +1909,7 @@
       vue: 3.5.11
       vue-component-type-helpers: ^2.1.6
     dependencies:
-      '@bole-core/core': 1.0.2(@ywwlmm/openapi@0.0.3)(ali-oss@6.21.0)(axios@1.7.7)(dayjs@1.11.6)(element-plus@2.9.1)(file-saver@2.0.5)(jszip@3.10.1)(lodash@4.17.21)(senior-request@1.0.1)(vue-router@4.4.5)(vue@3.5.11)(xlsx-style@0.8.13)(xlsx@0.18.5)
+      '@bole-core/core': 1.0.5(@ywwlmm/openapi@0.0.3)(ali-oss@6.21.0)(axios@1.7.7)(dayjs@1.11.6)(element-plus@2.9.1)(file-saver@2.0.5)(jszip@3.10.1)(lodash@4.17.21)(senior-request@1.0.1)(vue-router@4.4.5)(vue@3.5.11)(xlsx-style@0.8.13)(xlsx@0.18.5)
       '@bole-core/sass-utils': 0.0.1(element-plus@2.9.1)
       '@element-plus/icons-vue': 2.3.1(vue@3.5.11)
       '@tanstack/vue-query': 4.37.1(vue@3.5.11)
@@ -1927,8 +1927,8 @@
       vue-component-type-helpers: 2.1.6
     dev: false
 
-  /@bole-core/core@1.0.2(@ywwlmm/openapi@0.0.3)(ali-oss@6.21.0)(axios@1.7.7)(dayjs@1.11.6)(element-plus@2.9.1)(file-saver@2.0.5)(jszip@3.10.1)(lodash@4.17.21)(senior-request@1.0.1)(vue-router@4.4.5)(vue@3.5.11)(xlsx-style@0.8.13)(xlsx@0.18.5):
-    resolution: {integrity: sha512-v5XqgmuaFe1l5tBe9CHytW8UhqI8rh2m8R2J7F2F46XZy5wh7vGfiHshuaooTbfK6ex9A06jcepIWwDOklLs+A==}
+  /@bole-core/core@1.0.5(@ywwlmm/openapi@0.0.3)(ali-oss@6.21.0)(axios@1.7.7)(dayjs@1.11.6)(element-plus@2.9.1)(file-saver@2.0.5)(jszip@3.10.1)(lodash@4.17.21)(senior-request@1.0.1)(vue-router@4.4.5)(vue@3.5.11)(xlsx-style@0.8.13)(xlsx@0.18.5):
+    resolution: {integrity: sha512-qrLiGGb6Ei6xDLegubxswH/CSvcE2zRWslBA069KeZJTmjddLGQ/V3wqcMcRTLUj8bCSERguUB/BXM+TtQ25bg==}
     peerDependencies:
       '@ywwlmm/openapi': '*'
       ali-oss: '*'
@@ -1959,7 +1959,7 @@
       xlsx-style: 0.8.13(patch_hash=6ixwdxwh5a3amidwu6vee22jpi)
     dev: false
 
-  /@bole-core/pretty-layout@1.2.0(@bole-core/core@1.0.2)(@bole-core/sass-utils@0.0.1)(@element-plus/icons-vue@2.3.1)(@vueuse/core@11.1.0)(element-plus@2.9.1)(fuse.js@6.6.2)(lottie-web@5.10.2)(path-browserify@1.0.1)(path-to-regexp@6.2.1)(pinia@2.2.4)(vue-router@4.4.5)(vue@3.5.11):
+  /@bole-core/pretty-layout@1.2.0(@bole-core/core@1.0.5)(@bole-core/sass-utils@0.0.1)(@element-plus/icons-vue@2.3.1)(@vueuse/core@11.1.0)(element-plus@2.9.1)(fuse.js@6.6.2)(lottie-web@5.10.2)(path-browserify@1.0.1)(path-to-regexp@6.2.1)(pinia@2.2.4)(vue-router@4.4.5)(vue@3.5.11):
     resolution: {integrity: sha512-LvneMdMfGj6dpFR7voQd2F+v02P4zYHGP3BAWKcrTj8BMeWXRt08Sz7qBrhq1F8lidjqi7TCttQbx2cEV1qBEA==}
     peerDependencies:
       '@bole-core/core': '*'
@@ -1975,7 +1975,7 @@
       vue: 3.5.11
       vue-router: '*'
     dependencies:
-      '@bole-core/core': 1.0.2(@ywwlmm/openapi@0.0.3)(ali-oss@6.21.0)(axios@1.7.7)(dayjs@1.11.6)(element-plus@2.9.1)(file-saver@2.0.5)(jszip@3.10.1)(lodash@4.17.21)(senior-request@1.0.1)(vue-router@4.4.5)(vue@3.5.11)(xlsx-style@0.8.13)(xlsx@0.18.5)
+      '@bole-core/core': 1.0.5(@ywwlmm/openapi@0.0.3)(ali-oss@6.21.0)(axios@1.7.7)(dayjs@1.11.6)(element-plus@2.9.1)(file-saver@2.0.5)(jszip@3.10.1)(lodash@4.17.21)(senior-request@1.0.1)(vue-router@4.4.5)(vue@3.5.11)(xlsx-style@0.8.13)(xlsx@0.18.5)
       '@bole-core/sass-utils': 0.0.1(element-plus@2.9.1)
       '@element-plus/icons-vue': 2.3.1(vue@3.5.11)
       '@vueuse/core': 11.1.0(vue@3.5.11)
@@ -3692,21 +3692,21 @@
       vue-demi: 0.13.11(vue@3.5.11)
     dev: false
 
-  /@tencentcloud/call-engine-js@2.9.3:
-    resolution: {integrity: sha512-UtE3K7yIS9ECuvSscm6GA6aCpuaN06A3gfzmzXmhBEVjNTkiP5eCug7hHSMIYmR0sa5ILask4+Tki2NLq+A8Cw==}
+  /@tencentcloud/call-engine-js@3.0.1:
+    resolution: {integrity: sha512-OafM512KDbk4b9dpVVymLvuQuoVNqp7ZQmnZVjDmC5v/bQxA1FSUaAinty+7AU1Fb1FxQwxuHKDPysQAU+9M0g==}
     dependencies:
       '@tencentcloud/chat': 3.5.3
       core-js: 3.38.1
       eventemitter3: 4.0.7
       rtc-detect: 0.0.5
-      trtc-cloud-js-sdk: 2.8.7
+      trtc-cloud-js-sdk: 2.9.0
       tuikit-logger: 0.0.4-beta.1
     dev: false
 
-  /@tencentcloud/call-uikit-vue2.6@4.0.3(vue@3.5.11):
-    resolution: {integrity: sha512-DgsqCK4biGp/SVgbTjxKP9rQrxzEsN6x4qSjonLjiiT7BVT9pLlx8Mwxzv+MchPE9CGSqu440Lm/98uRkVlhRQ==}
+  /@tencentcloud/call-uikit-vue2.6@4.0.6(vue@3.5.11):
+    resolution: {integrity: sha512-As0qoW6TncyZ0y10Ogm6KrziZGznM5DX5HBPdYfZDbDm6eIYxG13HD3K8BzUC/GRlny8Nxn4EfhSkn48StBruQ==}
     dependencies:
-      '@tencentcloud/call-engine-js': 2.9.3
+      '@tencentcloud/call-engine-js': 3.0.1
       '@tencentcloud/chat': 3.5.3
       '@tencentcloud/tui-core': 2.4.0
       '@vue/composition-api': 1.7.2(vue@3.5.11)
@@ -3714,10 +3714,10 @@
       - vue
     dev: false
 
-  /@tencentcloud/call-uikit-vue2@4.0.3:
-    resolution: {integrity: sha512-xfPoIW/XEl8EGo/mOYA4z8BDgz+dmH5K+BjKGdFzLNuNZ8n5YxFuwDqrJTCVAl9ydijeJ+DhO68F5jQgsdDMkw==}
+  /@tencentcloud/call-uikit-vue2@4.0.6:
+    resolution: {integrity: sha512-egV/rS0T77vj3+d3YpurJxynFBJ41hbBO8WPmwc5z9BD2qjM2HSKgbMR2jGF6XAxjherCK/qlaIZLQQiNIKmNQ==}
     dependencies:
-      '@tencentcloud/call-engine-js': 2.9.3
+      '@tencentcloud/call-engine-js': 3.0.1
       '@tencentcloud/chat': 3.5.3
       '@tencentcloud/tui-core': 2.4.0
     dev: false
@@ -3729,10 +3729,10 @@
       tuicall-engine-webrtc: 3.1.7
     dev: false
 
-  /@tencentcloud/call-uikit-vue@4.0.3:
-    resolution: {integrity: sha512-EeZ0Q3x8igY5Ny5ghSD0T6seBiE3eDf0NagThASdGnD8+k6/GwBgD5HEBH8DrLpkC65rAMxf0ylE8JZPYilPQw==}
+  /@tencentcloud/call-uikit-vue@4.0.6:
+    resolution: {integrity: sha512-eqcIv2QcsH1iRdpbBJu6sv73wVMzaeb4Bap5A2B+uVJrnrwEd1KwOzk8wV4gNIbtF08fK933R4OnkuCRMhoH4A==}
     dependencies:
-      '@tencentcloud/call-engine-js': 2.9.3
+      '@tencentcloud/call-engine-js': 3.0.1
       '@tencentcloud/chat': 3.5.3
       '@tencentcloud/tui-core': 2.4.0
     dev: false
@@ -3740,7 +3740,15 @@
   /@tencentcloud/chat-uikit-engine@2.4.2:
     resolution: {integrity: sha512-L5rr1mO98S1Uz5IndJ2QdGv++5zbSUTnGSz4x3rKx5lWXlcJzSo1RY9DxYcWTKQKos9bG2d4JIIeg4DlfGb+Pg==}
     dependencies:
-      '@tencentcloud/chat': 3.5.3
+      '@tencentcloud/chat': 3.5.5
+      tim-profanity-filter-plugin: 1.1.0
+      tim-upload-plugin: 1.4.2
+    dev: false
+
+  /@tencentcloud/chat-uikit-engine@2.4.4:
+    resolution: {integrity: sha512-I26rCiRYcFMFN35Kf0QMJhphf0lBlJ7TXTAy255rJIiFzAXLBG1yV50cXbktGtBkjCjgOym8kvDUCmltPLPCRQ==}
+    dependencies:
+      '@tencentcloud/chat': 3.5.5
       tim-profanity-filter-plugin: 1.1.0
       tim-upload-plugin: 1.4.2
     dev: false
@@ -3758,10 +3766,10 @@
       '@tiptap/pm': ^2.0.0-beta.220
       '@tiptap/suggestion': ^2.0.0-beta.220
     dependencies:
-      '@tencentcloud/call-uikit-vue': 4.0.3
-      '@tencentcloud/call-uikit-vue2': 4.0.3
-      '@tencentcloud/call-uikit-vue2.6': 4.0.3(vue@3.5.11)
-      '@tencentcloud/chat-uikit-engine': 2.4.2
+      '@tencentcloud/call-uikit-vue': 4.0.6
+      '@tencentcloud/call-uikit-vue2': 4.0.6
+      '@tencentcloud/call-uikit-vue2.6': 4.0.6(vue@3.5.11)
+      '@tencentcloud/chat-uikit-engine': 2.4.4
       '@tencentcloud/tui-core': 2.4.0
       '@tencentcloud/tui-customer-service-plugin': 2.2.6(@tencentcloud/tui-core@2.4.0)(vue@3.5.11)
       '@tiptap/core': 2.1.13(@tiptap/pm@2.1.13)
@@ -3786,10 +3794,14 @@
     resolution: {integrity: sha512-1iC9CW+8sMcUtZXjB+97N65uyqRAV73InfKCzXtU/igxPqT8nfzfkrcjhi7JfywaKR3jGC1j8tDpsFNlLepFqQ==}
     dev: false
 
+  /@tencentcloud/chat@3.5.5:
+    resolution: {integrity: sha512-21kQw8PUns9D2nJMDv5KErnGusDAGSZ0xlFqoCO2VrpHaOXNp7diUs8yVccR/UHk+O/474zNbLe4n095UqLSVQ==}
+    dev: false
+
   /@tencentcloud/tui-core@2.0.0:
     resolution: {integrity: sha512-KBwDFWFV+IGtAZ82uCjRi891nMQcAen0wZHdPUUTSNHaWGjYiwOAHD7yw4gC1c5DYqVYMa3tVA7bSBd/hKVZKg==}
     dependencies:
-      '@tencentcloud/chat': 3.5.3
+      '@tencentcloud/chat': 3.5.5
       tim-profanity-filter-plugin: 0.9.0
       tim-upload-plugin: 1.3.0
     dev: false
@@ -3797,7 +3809,7 @@
   /@tencentcloud/tui-core@2.4.0:
     resolution: {integrity: sha512-OFXHoi8CQlPtWvNRLApg0wonWbW79uoTgAqqffqWO1icx3xDYd2RZDHMzpBexOsE3CHpWokrfXrqiXkpOmYWew==}
     dependencies:
-      '@tencentcloud/chat': 3.5.3
+      '@tencentcloud/chat': 3.5.5
       tim-profanity-filter-plugin: 1.1.0
       tim-upload-plugin: 1.4.2
     dev: false
@@ -14854,6 +14866,12 @@
       trtc-sdk-v5: 5.8.7-beta.1
     dev: false
 
+  /trtc-cloud-js-sdk@2.9.0:
+    resolution: {integrity: sha512-m2gufzg1yqnyPUanLJJXgyPzenRSyH1stK16EDrDINQo1FCPeCmY0kDARF1NiLZJLKm9lUP5DQsrUUKn4LYkPg==}
+    dependencies:
+      trtc-sdk-v5: 5.9.1
+    dev: false
+
   /trtc-js-sdk@4.15.19:
     resolution: {integrity: sha512-FFVvaji65d7+aq5o4hE+5lamvL1CEolNTPavaN7sRzh8Bb5UdDieBL9jV+lfxCnYpJ5lMi1YJt+EynDPX20Asw==}
     dependencies:
@@ -14862,6 +14880,12 @@
 
   /trtc-sdk-v5@5.8.7-beta.1:
     resolution: {integrity: sha512-kQdbrM4WBOmWm14QXcwPKYhlcitSX+7hkIN1bsLNhCekVxVohZ5VFEhjYVxIF9g3YYETXLzqIjKKJigzJEaLbA==}
+    dependencies:
+      webrtc-adapter: 8.2.3
+    dev: false
+
+  /trtc-sdk-v5@5.9.1:
+    resolution: {integrity: sha512-Vzu1UIzIQtQ3zUQHruha1Zh13aXsDsi/edMdwWdpO8URmRraqftsgKxjR8x2GPHd6p4cDreR/wY50xrWu9ZPlw==}
     dependencies:
       webrtc-adapter: 8.2.3
     dev: false
@@ -14942,7 +14966,7 @@
   /tuicall-engine-webrtc@3.1.7:
     resolution: {integrity: sha512-MRye9/x/8Gy5aRAfEACLtGhK5RcBLAev7cgCGi7OLNt0Uj28mEJkt1tHs4p7xTQiQj6vcB+7OVTdsxuSq7EmOA==}
     dependencies:
-      '@tencentcloud/chat': 3.5.3
+      '@tencentcloud/chat': 3.5.5
       rtc-ai-denoiser: 1.1.7
       trtc-cloud-js-sdk: 2.8.7
     dev: false
diff --git a/src/components/Reward/RewardInfoCard.vue b/src/components/Reward/RewardInfoCard.vue
new file mode 100644
index 0000000..f10c78d
--- /dev/null
+++ b/src/components/Reward/RewardInfoCard.vue
@@ -0,0 +1,46 @@
+<template>
+  <div class="reward-info-card-wrapper">
+    <div class="reward-info-card-title">
+      <slot name="title">{{ props.title }}</slot>
+    </div>
+    <div class="reward-info-card-content">
+      <slot></slot>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+defineOptions({
+  name: 'RewardInfoCard',
+});
+
+type Props = {
+  title?: string;
+};
+
+const props = withDefaults(defineProps<Props>(), {});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+
+.reward-info-card-wrapper {
+  display: flex;
+  padding: 16px;
+  border: 1px solid var(--el-border-color-light);
+  border-radius: 4px;
+  background-color: #ffffff;
+  flex-direction: column;
+
+  .reward-info-card-title {
+    margin-bottom: 12px;
+    font-size: 16px;
+    color: getCssVar('text-color', 'primary');
+  }
+
+  .reward-info-card-content {
+    flex: 1;
+    min-height: 0;
+  }
+}
+</style>
diff --git a/src/components/Reward/RewardInfoCardContentItem.vue b/src/components/Reward/RewardInfoCardContentItem.vue
new file mode 100644
index 0000000..f05f551
--- /dev/null
+++ b/src/components/Reward/RewardInfoCardContentItem.vue
@@ -0,0 +1,45 @@
+<template>
+  <div class="reward-info-card-content-item">
+    <div class="reward-info-card-content-item-label">{{ label }}</div>
+    <div class="reward-info-card-content-item-content"><slot></slot></div>
+  </div>
+</template>
+
+<script setup lang="ts">
+defineOptions({
+  name: 'RewardInfoCardContentItem',
+});
+
+type Props = {
+  label?: string;
+};
+
+const props = withDefaults(defineProps<Props>(), {});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+
+.reward-info-card-content-item {
+  display: flex;
+  align-items: center;
+  margin-bottom: 12px;
+  font-size: 14px;
+
+  &:last-child {
+    margin-bottom: 0;
+  }
+
+  .reward-info-card-content-item-label {
+    width: 80px;
+    color: getCssVar('text-color', 'regular');
+  }
+
+  .reward-info-card-content-item-content {
+    flex: 1;
+    min-width: 0;
+    @include utils-ellipsis;
+    color: getCssVar('text-color', 'primary');
+  }
+}
+</style>
diff --git a/src/components/Reward/RewardInfoCardList.vue b/src/components/Reward/RewardInfoCardList.vue
new file mode 100644
index 0000000..47be6ec
--- /dev/null
+++ b/src/components/Reward/RewardInfoCardList.vue
@@ -0,0 +1,22 @@
+<template>
+  <div class="reward-info-card-list">
+    <slot></slot>
+  </div>
+</template>
+
+<script setup lang="ts">
+defineOptions({
+  name: 'RewardInfoCardList',
+});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+
+.reward-info-card-list {
+  display: flex;
+  gap: 20px;
+  flex-wrap: wrap;
+  padding: 20px 0;
+}
+</style>
diff --git a/src/components/Reward/RewardInfoCardPrice.vue b/src/components/Reward/RewardInfoCardPrice.vue
new file mode 100644
index 0000000..093326b
--- /dev/null
+++ b/src/components/Reward/RewardInfoCardPrice.vue
@@ -0,0 +1,48 @@
+<template>
+  <div class="reward-info-card-price">
+    <div class="reward-info-card-value">{{ displayValue }}</div>
+    <div class="reward-info-card-unit">{{ unit }}</div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { toThousand } from '@/utils';
+
+defineOptions({
+  name: 'RewardInfoCardPrice',
+});
+
+type Props = {
+  value?: number;
+  useThousand?: boolean;
+  unit?: string;
+};
+
+const props = withDefaults(defineProps<Props>(), {
+  useThousand: true,
+  unit: '鍏�',
+});
+
+const displayValue = computed(() => (props.useThousand ? toThousand(props.value) : props.value));
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+
+.reward-info-card-price {
+  display: flex;
+  align-items: flex-end;
+
+  .reward-info-card-value {
+    margin-right: 4px;
+    font-size: 20px;
+    font-weight: bold;
+    color: getCssVar('text-color', 'primary');
+  }
+
+  .reward-info-card-unit {
+    font-size: 14px;
+    color: getCssVar('text-color', 'primary');
+  }
+}
+</style>
diff --git a/src/constants/customerConsume.ts b/src/constants/customerConsume.ts
new file mode 100644
index 0000000..9fe7902
--- /dev/null
+++ b/src/constants/customerConsume.ts
@@ -0,0 +1,20 @@
+export enum ParkBountyTradeAccessEnum {
+  /**姹熶綉鍏变繚 */
+  JYB = 1,
+}
+
+export const ParkBountyTradeAccessEnumText = {
+  [ParkBountyTradeAccessEnum.JYB]: '姹熶綉鍏变繚',
+};
+
+export enum FinanceTypeEnum {
+  /**棰勫厖鍊奸噾棰� */
+  Recharge = 10,
+  /**骞冲彴濂栧姳 */
+  PlatReward = 20,
+}
+
+export const FinanceTypeEnumText = {
+  [FinanceTypeEnum.Recharge]: '棰勫厖鍊奸噾棰�',
+  [FinanceTypeEnum.PlatReward]: '骞冲彴濂栧姳',
+};
diff --git a/src/constants/index.ts b/src/constants/index.ts
index 50ae80d..6bcaf99 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -11,3 +11,4 @@
 export * from './app';
 export * from './temp';
 export * from './insureBatchBill';
+export * from './customerConsume';
diff --git a/src/router/index.ts b/src/router/index.ts
index 0e33721..027c19a 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -2,6 +2,7 @@
 
 import Layout from '@/layout/MainLayout/Layout.vue';
 import ErrorLayout from '@/layout/ErrorLayout/ErrorLayout.vue';
+import { AppType } from '@/constants';
 
 // import { ElIcons } from '@/typings'
 
@@ -53,6 +54,7 @@
   children?: Route[];
 };
 
+//@ts-ignore
 export const constantRoutes: Route[] = [
   {
     path: '/redirect',
@@ -175,6 +177,61 @@
       },
     ],
   },
+  AppType === 'jx' && {
+    path: '/BalanceManage',
+    redirect: 'noRedirect',
+    component: Layout,
+    hidden: false,
+    alwaysShow: true,
+    meta: {
+      rank: 10010,
+      title: '浣欓绠$悊',
+      rootMenu: true,
+      icon: 'home',
+    },
+    children: [
+      {
+        path: '/BalanceManage',
+        name: 'BalanceManage',
+        hidden: false,
+        alwaysShow: true,
+        component: () => import('@/views/BalanceManage/BalanceManage.vue'),
+        meta: {
+          rank: 10011,
+          title: '浣欓绠$悊',
+          // rootMenu: true,
+          icon: 'home',
+        },
+      },
+    ],
+  },
+  // {
+  //   path: '/FileManage',
+  //   redirect: 'noRedirect',
+  //   component: Layout,
+  //   hidden: false,
+  //   alwaysShow: true,
+  //   meta: {
+  //     rank: 10020,
+  //     title: '鏂囦欢绠$悊',
+  //     rootMenu: true,
+  //     icon: 'home',
+  //   },
+  //   children: [
+  //     {
+  //       path: '/FileManage',
+  //       name: 'FileManage',
+  //       hidden: false,
+  //       alwaysShow: true,
+  //       component: () => import('@/views/FileManage/FileManage.vue'),
+  //       meta: {
+  //         rank: 10021,
+  //         title: '鏂囦欢绠$悊',
+  //         icon: 'home',
+  //       },
+  //     },
+  //   ],
+  // },
   {
     path: '/Login',
     name: 'Login',
@@ -213,7 +270,7 @@
       },
     ],
   },
-];
+].filter(Boolean);
 
 export const asyncRoutes: Route[] = [
   {
diff --git a/src/services/api/ParkBountyApply.ts b/src/services/api/ParkBountyApply.ts
new file mode 100644
index 0000000..e391fd4
--- /dev/null
+++ b/src/services/api/ParkBountyApply.ts
@@ -0,0 +1,54 @@
+/* eslint-disable */
+// @ts-ignore
+import { request } from '@/utils/request';
+
+/** 杩愯惀绔�-濂栧姳杩涘嚭璐﹁鎯� POST /api/ParkBountyApply/GetParkBountyTradeDetailList */
+export async function getParkBountyTradeDetailList(
+  body: API.GetParkBountyTradeDetailByIdInput,
+  options?: API.RequestConfig
+) {
+  return request<API.GetParkBountyTradeDetailOutputPageOutput>(
+    '/api/ParkBountyApply/GetParkBountyTradeDetailList',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      data: body,
+      ...(options || {}),
+    }
+  );
+}
+
+/** 杩愯惀绔�-濂栧姳閲戜娇鐢ㄧ鐞嗗垪琛� POST /api/ParkBountyApply/GetParkBountyTradeList */
+export async function getParkBountyTradeList(
+  body: API.GetParkBountyTradeInput,
+  options?: API.RequestConfig
+) {
+  return request<API.GetParkBountyTradeOutputPageOutput>(
+    '/api/ParkBountyApply/GetParkBountyTradeList',
+    {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      data: body,
+      ...(options || {}),
+    }
+  );
+}
+
+/** 杩愯惀绔�斿鍔遍噾-鍑鸿处 POST /api/ParkBountyApply/ParkBountyApplyTrade */
+export async function parkBountyApplyTrade(
+  body: API.CreateParkBountyTradeInput,
+  options?: API.RequestConfig
+) {
+  return request<number>('/api/ParkBountyApply/ParkBountyApplyTrade', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
diff --git a/src/services/api/User.ts b/src/services/api/User.ts
index a1d348f..706aab2 100644
--- a/src/services/api/User.ts
+++ b/src/services/api/User.ts
@@ -2,6 +2,21 @@
 // @ts-ignore
 import { request } from '@/utils/request';
 
+/** 鎵归噺鍚屾鐢ㄦ埛浣欓 POST /api/User/BatchSyncUserAmount */
+export async function batchSyncUserAmount(
+  body: API.BatchSyncUserAmountInput,
+  options?: API.RequestConfig
+) {
+  return request<any>('/api/User/BatchSyncUserAmount', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鏂板璐﹀彿淇℃伅 POST /api/User/CreateAccount */
 export async function createAccount(body: API.CreateAccountInput, options?: API.RequestConfig) {
   return request<string>('/api/User/CreateAccount', {
@@ -81,6 +96,14 @@
   });
 }
 
+/** 鑾峰彇瀹㈡埛浣欓淇℃伅 GET /api/User/GetUserAmountShow */
+export async function getUserAmountShow(options?: API.RequestConfig) {
+  return request<API.UserAmountShowDto>('/api/User/GetUserAmountShow', {
+    method: 'GET',
+    ...(options || {}),
+  });
+}
+
 /** 鑾峰彇鐢ㄦ埛璇︽儏 GET /api/User/GetUserDetail */
 export async function getUserDetail(
   // 鍙犲姞鐢熸垚鐨凱aram绫诲瀷 (闈瀊ody鍙傛暟swagger榛樿娌℃湁鐢熸垚瀵硅薄)
@@ -135,6 +158,18 @@
   });
 }
 
+/** 鍚屾鐢ㄦ埛 POST /api/User/SyncUser */
+export async function syncUser(body: API.SyncUserDto, options?: API.RequestConfig) {
+  return request<string>('/api/User/SyncUser', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鏇存柊璐﹀彿淇℃伅 POST /api/User/UpdateAccount */
 export async function updateAccount(body: API.UpdateAccountInput, options?: API.RequestConfig) {
   return request<number>('/api/User/UpdateAccount', {
diff --git a/src/services/api/index.ts b/src/services/api/index.ts
index e762d00..85637c9 100644
--- a/src/services/api/index.ts
+++ b/src/services/api/index.ts
@@ -13,6 +13,7 @@
 import * as InsuranceClaim from './InsuranceClaim';
 import * as InsuranceOrder from './InsuranceOrder';
 import * as InsureBatchBill from './InsureBatchBill';
+import * as ParkBountyApply from './ParkBountyApply';
 import * as Permissions from './Permissions';
 import * as PhoneMessage from './PhoneMessage';
 import * as Profile from './Profile';
@@ -31,6 +32,7 @@
   InsuranceClaim,
   InsuranceOrder,
   InsureBatchBill,
+  ParkBountyApply,
   Permissions,
   PhoneMessage,
   Profile,
diff --git a/src/services/api/typings.d.ts b/src/services/api/typings.d.ts
index 66ea985..b0138eb 100644
--- a/src/services/api/typings.d.ts
+++ b/src/services/api/typings.d.ts
@@ -474,6 +474,10 @@
     checkStatus?: BatchBillCheckStatus;
     /** 鐢熸晥鏃堕棿 */
     effectTime?: string;
+    /** 淇濆崟鐢熸晥鏃堕棿 */
+    effectStartTime?: string;
+    /** 淇濆崟澶辨晥鏃堕棿 */
+    effectEndTime?: string;
     /** 闄勪欢涓婁紶 */
     attachmentUrl?: string;
     /** 淇濆崟鍙� */
@@ -482,6 +486,10 @@
     enterpriseName?: string;
     /** 鎵规敼浜哄憳璇︽儏 */
     staffList?: InsureBatchBillDetailDto[];
+  }
+
+  interface BatchSyncUserAmountInput {
+    items?: SyncUserAmountInput[];
   }
 
   interface ChangePasswordInput {
@@ -577,6 +585,16 @@
     remark?: string;
     /** 瑙掕壊Id */
     id?: string;
+  }
+
+  interface CreateParkBountyTradeInput {
+    enterpriseId?: string;
+    /** 鏈�杩戝嚭璐﹂噾棰� */
+    tradeAmount?: number;
+    /** 鍑鸿处鍑瘉 */
+    payFileUrl?: string;
+    /** 娑堣垂绫诲瀷 */
+    payRemark?: string;
   }
 
   interface CurrentCultureDto {
@@ -728,6 +746,8 @@
     key?: string;
   }
 
+  type FinanceTypeEnum = 10 | 20;
+
   interface GetEffectingStaffListInput {
     claimDateTime?: string;
     idNumber?: string;
@@ -846,6 +866,73 @@
     pageModel?: Pagination;
     objectData?: any;
     data?: GetInsuranceStaffPageTemplate[];
+  }
+
+  interface GetParkBountyTradeDetailByIdInput {
+    pageModel?: Pagination;
+    /** 浼佷笟鍚�/淇$敤浠g爜 */
+    searchKeyWord?: string;
+    /** 鍑鸿处璧峰鏃ユ湡 */
+    transferTimeBegin?: string;
+    /** 鍑鸿处缁撴潫鏃ユ湡 */
+    transferTimeEnd?: string;
+    enterpriseId?: string;
+  }
+
+  interface GetParkBountyTradeDetailOutput {
+    id?: string;
+    /** 鏈�杩戝嚭璐﹂噾棰� */
+    tradeAmount?: number;
+    /** 鍑鸿处鍑瘉 */
+    payFileUrl?: string;
+    access?: ParkBountyTradeAccessEnum;
+    /** 娑堣垂绫诲瀷 */
+    payRemark?: string;
+    /** 鍑鸿处鏃堕棿 */
+    tradeTime?: string;
+    /** 濂栧姳閲戜綑棰� */
+    remianAmount?: number;
+    financeType?: FinanceTypeEnum;
+  }
+
+  interface GetParkBountyTradeDetailOutputPageOutput {
+    pageModel?: Pagination;
+    objectData?: any;
+    data?: GetParkBountyTradeDetailOutput[];
+  }
+
+  interface GetParkBountyTradeInput {
+    pageModel?: Pagination;
+    /** 浼佷笟鍚�/淇$敤浠g爜 */
+    searchKeyWord?: string;
+    /** 鍑鸿处璧峰鏃ユ湡 */
+    transferTimeBegin?: string;
+    /** 鍑鸿处缁撴潫鏃ユ湡 */
+    transferTimeEnd?: string;
+  }
+
+  interface GetParkBountyTradeOutput {
+    enterpriseId?: string;
+    /** 璐﹀彿 */
+    userName?: string;
+    /** 浼佷笟鍚嶇О */
+    enterpriseName?: string;
+    /** 鐢佃瘽 */
+    contactPhone?: string;
+    /** 绀句細缁熶竴淇$敤浠g爜 */
+    societyCreditCode?: string;
+    /** 鏈�杩戝嚭璐﹂噾棰� */
+    tradeAmount?: number;
+    /** 鍑鸿处鏃堕棿 */
+    tradeTime?: string;
+    /** 濂栧姳閲戜綑棰� */
+    remianAmount?: number;
+  }
+
+  interface GetParkBountyTradeOutputPageOutput {
+    pageModel?: Pagination;
+    objectData?: any;
+    data?: GetParkBountyTradeOutput[];
   }
 
   interface GetPermissionListResultDto {
@@ -1028,6 +1115,8 @@
   }
 
   interface ImportBatchStaffListInput {
+    /** 鍘熻淇濅汉濮撳悕 */
+    orginName?: string;
     orginIdNumber?: string;
     /** 鐢佃瘽鍙风爜 */
     phoneNumber?: string;
@@ -1041,6 +1130,7 @@
     workType?: string;
     birthDay?: string;
     remark?: string;
+    changeType?: BatchChangeTypeEnum;
   }
 
   interface ImportBatchUpdateOrderDataInput {
@@ -1188,11 +1278,13 @@
     accidentType?: string;
     /** 浜嬫晠鍙戠敓鏃堕棿 */
     accidentTime?: string;
-    /** 浼ゆ畫姣斾緥 */
     disabilityRatio?: number;
+    /** 浼ゆ畫姣斾緥 */
+    disabilityRatioStr?: string;
     claimResultStr?: string;
-    /** 涓嬫閲戦 */
     downPaymentAmount?: number;
+    /** 涓嬫閲戦 */
+    downPaymentAmountStr?: string;
     /** 缁�/鎾ゆ鏃ユ湡 */
     claimResultTime?: string;
     /** 鏈�鍚庢洿鏂版棩鏈� */
@@ -1573,6 +1665,8 @@
     descriptorName?: string;
   }
 
+  type ParkBountyTradeAccessEnum = 1;
+
   interface PasswordLoginInput {
     /** 璐﹀彿 */
     loginName: string;
@@ -1806,6 +1900,48 @@
     modules: ModuleTypeInfo[];
   }
 
+  interface SyncUserAmountInput {
+    /** 鐢ㄦ埛鍚嶇О */
+    id?: string;
+    /** 濂栧姳閲戜綑棰� */
+    bountyAmount?: number;
+    /** 鍏呭�间綑棰� */
+    rechargeAmount?: number;
+  }
+
+  interface SyncUserDto {
+    /** 寮�閫� */
+    open?: boolean;
+    /** 818鐢ㄦ埛Id */
+    humanResourcesServiceUserId?: string;
+    /** 鍚嶇О */
+    name?: string;
+    /** 鐧诲綍鐢ㄦ埛鍚� */
+    userName?: string;
+    /** 鐢ㄦ埛鎵嬫満鍙� */
+    phoneNumber?: string;
+    /** 浼佷笟鍚嶇О */
+    enterpriseName?: string;
+    /** 钀ヤ笟鎵х収鏂囦欢鍦板潃 */
+    licenseUrl?: string;
+    /** 缁熶竴绀句細淇$敤浠g爜 */
+    societyCreditCode?: string;
+    /** 閾惰鎬昏鍚嶇О */
+    bankName?: string;
+    /** 閾惰鏀鍚嶇О */
+    bankBranchName?: string;
+    /** 閾惰鍗″彿 */
+    bankCardNumber?: string;
+    /** 濂栧姳閲戜綑棰� */
+    bountyAmount?: number;
+    /** 鍏呭�间綑棰� */
+    rechargeAmount?: number;
+    /** 鑱旂郴浜� */
+    contact?: string;
+    /** 鑱旂郴鐢佃瘽 */
+    contactPhone?: string;
+  }
+
   interface TenantDto {
     extraProperties?: Record<string, any>;
     id?: string;
@@ -2002,6 +2138,27 @@
     listFiles?: string[];
   }
 
+  interface UserAmountShowDto {
+    /** 浼佷笟鍚嶇О */
+    enterpriseName?: string;
+    /** 钀ヤ笟鎵х収鏂囦欢鍦板潃 */
+    licenseUrl?: string;
+    /** 缁熶竴绀句細淇$敤浠g爜 */
+    societyCreditCode?: string;
+    /** 閾惰鎬昏鍚嶇О */
+    bankName?: string;
+    /** 閾惰鏀鍚嶇О */
+    bankBranchName?: string;
+    /** 閾惰鍗″彿 */
+    bankCardNumber?: string;
+    /** 濂栧姳閲戜綑棰� */
+    bountyAmount?: number;
+    /** 鍏呭�间綑棰� */
+    rechargeAmount?: number;
+    /** 璧勯噾鎬婚 */
+    totalAmount?: number;
+  }
+
   interface UserData {
     id?: string;
     tenantId?: string;
diff --git a/src/utils/common/common.ts b/src/utils/common/common.ts
index b05dfc3..72f10aa 100644
--- a/src/utils/common/common.ts
+++ b/src/utils/common/common.ts
@@ -1,5 +1,5 @@
 import dayjs from 'dayjs';
-import { BoleRegExp } from '@bole-core/core';
+import { BoleRegExp, Message } from '@bole-core/core';
 import { round, floor, omitBy } from 'lodash';
 
 export function format(date: string | Date, fmt = 'YYYY-MM-DD') {
@@ -106,3 +106,42 @@
 export function filterNumbersFromString(str: string) {
   return str.replace(/\D/g, '');
 }
+
+export function copyTextToClipboard(text: string) {
+  if (navigator.clipboard && window.isSecureContext) {
+    // navigator clipboard 鍚戝壀璐存澘鍐欐枃鏈�
+    navigator.clipboard
+      .writeText(text)
+      .then(() => {
+        Message.successMessage('宸插鍒�');
+      })
+      .catch((error) => {
+        console.error('Failed to copy text to clipboard:', error);
+      });
+  } else {
+    // 鍒涘缓text area
+    let textArea = document.createElement('textarea');
+    textArea.value = text;
+    // 浣縯ext area涓嶅湪viewport锛屽悓鏃惰缃笉鍙
+    textArea.style.position = 'absolute';
+    textArea.style.opacity = 0 as any;
+    textArea.style.left = '-999999px';
+    textArea.style.top = '-999999px';
+    document.body.appendChild(textArea);
+    textArea.select();
+    let res = document.execCommand('copy');
+    if (res) {
+      Message.successMessage('宸插鍒�');
+    }
+    textArea.remove();
+  }
+}
+
+export function addStarForString(str: string, start = 0, end = 0) {
+  return str.substring(0, start) + '*'.repeat(end - start) + str.substring(end);
+}
+
+export function addStarForEmail(str: string) {
+  const end = str.lastIndexOf('.');
+  return addStarForString(str, 2, end);
+}
diff --git a/src/utils/common/file.ts b/src/utils/common/file.ts
index 25cbd9a..0c2a668 100644
--- a/src/utils/common/file.ts
+++ b/src/utils/common/file.ts
@@ -25,6 +25,14 @@
   return path ? [convertApi2FormUrl(path)] : [];
 }
 
+export function convertApi2FormUrlBySeparator(path: string, separator = '|') {
+  return path ? path.split(separator).map((x) => setOSSLink(x)) : [];
+}
+
+export function convertApi2FormUrlObjectBySeparator(path: string, separator = '|') {
+  return path ? path.split(separator).map(convertApi2FormUrl) : [];
+}
+
 /**
  * 鎶妘pload鐨勮矾寰勮浆鎹负涓婁紶鍒癮pi鐨勮矾寰�
  */
@@ -32,6 +40,13 @@
   return urls.filter((x) => x.path).map((x) => urlOmitDomain(x.path));
 }
 
+export function convertFormUrl2ApiBySeparator<T extends { path?: string }>(
+  urls: T[],
+  separator = '|'
+) {
+  return convertFormUrl2Api(urls).join(separator);
+}
+
 export async function imageUrlToFile(url: string, filename: string) {
   const response = await fetch(`${url}?${new Date().getTime()}`);
   const blob = await response.blob();
diff --git a/src/views/BalanceManage/BalanceManage.vue b/src/views/BalanceManage/BalanceManage.vue
new file mode 100644
index 0000000..efdc980
--- /dev/null
+++ b/src/views/BalanceManage/BalanceManage.vue
@@ -0,0 +1,188 @@
+<template>
+  <LoadingLayout>
+    <AppContainer>
+      <RewardInfoCardList>
+        <RewardInfoCard class="reward-wrapper">
+          <template #title>
+            <div class="reward-wrapper-title">
+              <div class="reward-wrapper-title-amount">
+                <span>璧勯噾鎬婚锛堝厓锛�</span>
+                <span class="reward-wrapper-title-amount-value">{{
+                  toThousand(detail?.totalAmount ?? 0)
+                }}</span>
+              </div>
+            </div>
+          </template>
+          <div class="reward-wrapper-content">
+            <div class="reward-wrapper-content-item">
+              <div class="reward-wrapper-content-item-label">骞冲彴濂栧姳浣欓锛堝厓锛�</div>
+              <div class="reward-wrapper-content-item-value">
+                {{ toThousand(detail?.bountyAmount ?? 0) }}
+              </div>
+            </div>
+            <div class="reward-wrapper-content-item-line"></div>
+            <div class="reward-wrapper-content-item">
+              <div class="reward-wrapper-content-item-label">棰勫厖鍊奸噾棰濓紙鍏冿級</div>
+              <div class="reward-wrapper-content-item-value">
+                {{ toThousand(detail?.rechargeAmount ?? 0) }}
+              </div>
+            </div>
+          </div>
+        </RewardInfoCard>
+        <RewardInfoCard title="浼佷笟鍩烘湰淇℃伅" style="flex: 1">
+          <RewardInfoCardContentItem label="浼佷笟鍚嶇О锛�">
+            {{ detail?.enterpriseName ?? '' }}
+          </RewardInfoCardContentItem>
+          <RewardInfoCardContentItem label="淇$敤浠g爜锛�">
+            {{ detail?.societyCreditCode ?? '' }}
+          </RewardInfoCardContentItem>
+          <RewardInfoCardContentItem label="钀ヤ笟鎵х収锛�">
+            <el-button
+              v-if="!!detail?.licenseUrl"
+              type="primary"
+              link
+              class="link-style-clear"
+              @click="handlePreviewCertificate()"
+              >鏌ョ湅</el-button
+            >
+          </RewardInfoCardContentItem>
+        </RewardInfoCard>
+        <RewardInfoCard title="璐︽埛淇℃伅" style="flex: 1">
+          <RewardInfoCardContentItem label="寮�鎴锋�昏锛�">
+            {{ detail?.bankName ?? '' }}
+          </RewardInfoCardContentItem>
+          <RewardInfoCardContentItem label="寮�鎴锋敮琛岋細">
+            {{ detail?.bankBranchName ?? '' }}
+          </RewardInfoCardContentItem>
+          <RewardInfoCardContentItem label="閾惰甯愬彿锛�">
+            {{ detail?.bankCardNumber ?? '' }}
+          </RewardInfoCardContentItem>
+        </RewardInfoCard>
+      </RewardInfoCardList>
+      <ProTabs v-model="state.tabType" hasBorder class="reward-tabs">
+        <ProTabPane lazy label="娑堣垂璁板綍" name="Consume">
+          <ConsumeRecordView></ConsumeRecordView>
+        </ProTabPane>
+      </ProTabs>
+    </AppContainer>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import { LoadingLayout, AppContainer, ProTabs, ProTabPane } from '@bole-core/components';
+import * as userServices from '@/services/api/User';
+import RewardInfoCardList from '@/components/Reward/RewardInfoCardList.vue';
+import RewardInfoCard from '@/components/Reward/RewardInfoCard.vue';
+import RewardInfoCardContentItem from '@/components/Reward/RewardInfoCardContentItem.vue';
+import { setOSSLink, downloadFileByUrl, toThousand } from '@/utils';
+import ConsumeRecordView from './components/ConsumeRecordView.vue';
+import { useQuery } from '@tanstack/vue-query';
+import { useUser } from '@/hooks';
+
+defineOptions({
+  name: 'BalanceManage',
+});
+
+const BaseState = {
+  loading: true,
+  tabType: 'Consume',
+};
+
+const { user } = useUser();
+const state = reactive({ ...BaseState });
+
+const { isLoading, data: detail } = useQuery({
+  queryKey: ['userServices/getUserAmountShow'],
+  queryFn: async () => {
+    return await userServices.getUserAmountShow({
+      showLoading: false,
+    });
+  },
+  placeholderData: () => ({} as API.UserAmountShowDto),
+});
+
+function handlePreviewCertificate() {
+  downloadFileByUrl(setOSSLink(detail.value?.licenseUrl ?? ''));
+}
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+
+.pretty-layout-main-container .app-main-wrapper > .app-main {
+  background-color: #ffffff;
+}
+
+.reward-wrapper {
+  :deep() {
+    .reward-info-card-content {
+      display: flex;
+    }
+  }
+
+  .reward-wrapper-title {
+    display: flex;
+    justify-content: space-between;
+    padding-bottom: 10px;
+    border-bottom: 1px solid var(--el-border-color-light);
+
+    .reward-wrapper-title-amount {
+      display: flex;
+      align-items: flex-end;
+      min-width: 0;
+      flex: 1;
+    }
+
+    .reward-wrapper-title-amount-value {
+      font-size: 24px;
+      font-weight: bold;
+      color: getCssVar('text-color', 'primary');
+    }
+  }
+
+  .reward-wrapper-content {
+    display: flex;
+    justify-content: center;
+    padding: 10px;
+    min-width: 0;
+    min-height: 0;
+    border: 1px solid var(--el-border-color-light);
+    border-radius: 4px;
+    flex: 1;
+
+    .reward-wrapper-content-item-line {
+      margin: 0 20px;
+      width: 1px;
+      height: 100%;
+      background-color: var(--el-border-color-light);
+    }
+
+    .reward-wrapper-content-item {
+      flex: 1;
+      min-width: 0;
+
+      .reward-wrapper-content-item-label {
+        font-size: 14px;
+        white-space: nowrap;
+        color: getCssVar('text-color', 'regular');
+        line-height: 20px;
+      }
+
+      .reward-wrapper-content-item-value {
+        font-size: 16px;
+        line-height: 22px;
+        font-weight: bold;
+        color: getCssVar('color', 'primary');
+      }
+    }
+  }
+}
+
+.reward-tabs {
+  :deep() {
+    .pro-table-wrapper .pro-table-container {
+      padding-top: 20px;
+    }
+  }
+}
+</style>
diff --git a/src/views/BalanceManage/components/ConsumeRecordView.vue b/src/views/BalanceManage/components/ConsumeRecordView.vue
new file mode 100644
index 0000000..a486be6
--- /dev/null
+++ b/src/views/BalanceManage/components/ConsumeRecordView.vue
@@ -0,0 +1,118 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+        <template #operationBtn-checkBtn="{ data, row }">
+          <PreviewBtnV2
+            class="pro-table-operation-btn"
+            :url="convertApi2FormUrlBySeparator(row.payFileUrl ?? '')"
+            preview-btn-text="鏌ョ湅鍑瘉"
+          />
+        </template>
+      </ProTableV2>
+    </AppContainer>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  AppContainer,
+  useTable,
+  PreviewBtnV2,
+  ProTableV2,
+  defineOperationBtns,
+} from '@bole-core/components';
+import { OrderInputType } from '@bole-core/core';
+import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
+import { convertApi2FormUrlBySeparator } from '@/utils';
+import { FinanceTypeEnumText } from '@/constants';
+
+defineOptions({
+  name: 'ConsumeRecordView',
+});
+
+const column = [
+  {
+    id: '1',
+    enCode: 'tradeTime',
+    name: '娑堣垂鏃堕棿',
+  },
+  {
+    id: '2',
+    enCode: 'tradeAmount',
+    name: '娑堣垂閲戦',
+  },
+  {
+    id: '3',
+    enCode: 'payRemark',
+    name: '娑堣垂绫诲瀷',
+  },
+  {
+    id: '4',
+    enCode: 'financeType',
+    name: '璧勯噾绫诲瀷',
+  },
+];
+const operationBtns = defineOperationBtns([
+  {
+    data: {
+      enCode: 'checkBtn',
+      name: '鏌ョ湅鍑瘉',
+    },
+  },
+]);
+
+const route = useRoute();
+const router = useRouter();
+const id = route.params.id as string;
+const BaseState = {
+  loading: true,
+};
+
+const state = reactive({ ...BaseState });
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+  reset,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.GetParkBountyTradeDetailByIdInput = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        enterpriseId: id,
+      };
+      let res = await parkBountyApplyServices.getParkBountyTradeDetailList(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      keyWord: '',
+      orderInput: [{ property: 'tradeTime', order: OrderInputType.Asc }],
+    },
+    columnsRenderProps: {
+      tradeTime: { type: 'date', format: 'YYYY-MM-DD HH:mm:ss' },
+      tradeAmount: { type: 'money' },
+      financeType: { type: 'enum', valueEnum: FinanceTypeEnumText },
+    },
+  }
+);
+
+onMounted(async () => {
+  await getList();
+  state.loading = false;
+});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/BalanceManage/components/RechargeRecordView.vue b/src/views/BalanceManage/components/RechargeRecordView.vue
new file mode 100644
index 0000000..21c2153
--- /dev/null
+++ b/src/views/BalanceManage/components/RechargeRecordView.vue
@@ -0,0 +1,143 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns">
+        <template #checkStatus="{ data, row }">
+          <div style="display: flex; justify-content: center; align-items: center">
+            {{ EnterpriseRechargeStatusEnumText[row.checkStatus] }}
+            <el-tooltip
+              placement="top"
+              v-if="row.checkStatus === EnterpriseRechargeStatusEnum.CheckReject && row.checkRemark"
+              :content="row.checkRemark"
+            >
+              <el-icon color="#ff0000"><WarningFilled /></el-icon>
+            </el-tooltip>
+          </div>
+        </template>
+        <template #operationBtn-checkBtn="{ data, row }">
+          <PreviewBtnV2
+            class="pro-table-operation-btn"
+            :url="convertApi2FormUrlBySeparator(row.rechargeVoucherFileUrl ?? '')"
+            preview-btn-text="鏌ョ湅鍑瘉"
+          />
+        </template>
+      </ProTableV2>
+    </AppContainer>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  AppContainer,
+  useTable,
+  PreviewBtnV2,
+  ProTableV2,
+  defineOperationBtns,
+} from '@bole-core/components';
+import { OrderInputType } from '@bole-core/core';
+// import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
+import { useUser } from '@/hooks';
+// import {
+//   EnterprisePrechargeInComeStatusEnum,
+//   EnterprisePrechargeInComeStatusEnumText,
+//   EnterpriseRechargeStatusEnum,
+//   EnterpriseRechargeStatusEnumText,
+// } from '@/constants';
+import { convertApi2FormUrlBySeparator } from '@/utils';
+
+defineOptions({
+  name: 'RechargeRecordView',
+});
+
+const column = [
+  {
+    id: '1',
+    enCode: 'creationTime',
+    name: '鍏呭�兼椂闂�',
+  },
+  {
+    id: '2',
+    enCode: 'prechargeAmount',
+    name: '鍏呭�奸噾棰�',
+  },
+  {
+    id: '3',
+    enCode: 'checkStatus',
+    name: '瀹℃牳鐘舵��',
+  },
+  {
+    id: '4',
+    enCode: 'inComeStatus',
+    name: '鍏ヨ处鐘舵��',
+  },
+];
+
+const operationBtns = defineOperationBtns([
+  {
+    data: {
+      enCode: 'checkBtn',
+      name: '鏌ョ湅鍑瘉',
+    },
+    extraProps: {
+      hide: (row) => row.inComeStatus !== EnterprisePrechargeInComeStatusEnum.HasInCome,
+    },
+  },
+]);
+
+const route = useRoute();
+const router = useRouter();
+const id = route.params.id as string;
+const BaseState = {
+  loading: true,
+};
+
+const state = reactive({ ...BaseState });
+const { userDetail } = useUser();
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.PageInput = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+      };
+      let res = await parkBountyApplyServices.getEnterprisePrechargeList(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      orderInput: [{ property: 'id', order: OrderInputType.Desc }],
+    },
+    columnsRenderProps: {
+      creationTime: { type: 'date', format: 'YYYY-MM-DD' },
+      prechargeAmount: { type: 'money' },
+      checkStatus: { type: 'enum', valueEnum: EnterpriseRechargeStatusEnumText },
+      inComeStatus: { type: 'enum', valueEnum: EnterprisePrechargeInComeStatusEnumText },
+    },
+  }
+);
+
+onMounted(async () => {
+  await getList();
+  state.loading = false;
+});
+
+defineExpose({
+  getList,
+});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/BalanceManage/components/RewardGrantRecordView.vue b/src/views/BalanceManage/components/RewardGrantRecordView.vue
new file mode 100644
index 0000000..b3c3963
--- /dev/null
+++ b/src/views/BalanceManage/components/RewardGrantRecordView.vue
@@ -0,0 +1,102 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableV2 v-bind="proTableProps" :columns="column" :showOperationColumn="false">
+      </ProTableV2>
+    </AppContainer>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import { AppContainer, useTable, ProTableV2 } from '@bole-core/components';
+import { OrderInputType } from '@bole-core/core';
+// import * as parkBountyApplyServices from '@/services/api/ParkBountyApply';
+import { useUser } from '@/hooks';
+// import { TransferToStatusEnumText } from '@/constants';
+
+defineOptions({
+  name: 'RewardGrantRecordView',
+});
+
+const column = [
+  {
+    id: '1',
+    enCode: 'transferToTime',
+    name: '鍙戞斁鏃堕棿',
+  },
+  {
+    id: '2',
+    enCode: 'transferToAmount',
+    name: '鍙戞斁閲戦',
+  },
+  {
+    id: '3',
+    enCode: 'batchNo',
+    name: '鍙戞斁鎵规',
+  },
+  {
+    id: '4',
+    enCode: 'applyMonth',
+    name: '鍙戞斁鏈堜唤',
+  },
+  {
+    id: '4',
+    enCode: 'transferToStatus',
+    name: '鍙戞斁鐘舵��',
+  },
+];
+
+const route = useRoute();
+const router = useRouter();
+const id = route.params.id as string;
+const BaseState = {
+  loading: true,
+};
+
+const state = reactive({ ...BaseState });
+const { userDetail } = useUser();
+
+const {
+  getDataSource: getList,
+  proTableProps,
+  paginationState,
+  extraParamState,
+} = useTable(
+  async ({ pageIndex, pageSize }, extraParamState) => {
+    try {
+      let params: API.QueryParkCustomerBountyApplyInput = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        id: userDetail.value?.userId ?? '',
+      };
+      let res = await parkBountyApplyServices.getParkCustomerBountySettleList(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      orderInput: [{ property: 'settleTime', order: OrderInputType.Desc }],
+    },
+    columnsRenderProps: {
+      transferToStatus: { type: 'enum', valueEnum: TransferToStatusEnumText },
+      transferToTime: { type: 'date', format: 'YYYY-MM-DD' },
+      applyMonth: { type: 'date', format: 'YYYY骞碝M鏈�' },
+      transferToAmount: { type: 'money' },
+    },
+  }
+);
+
+onMounted(async () => {
+  await getList();
+  state.loading = false;
+});
+</script>
+
+<style lang="scss" scoped>
+@use '@/style/common.scss' as *;
+</style>
diff --git a/src/views/BalanceManage/components/RewardRechargeDialog.vue b/src/views/BalanceManage/components/RewardRechargeDialog.vue
new file mode 100644
index 0000000..0b823aa
--- /dev/null
+++ b/src/views/BalanceManage/components/RewardRechargeDialog.vue
@@ -0,0 +1,266 @@
+<template>
+  <ProDialog
+    title="鍏呭��"
+    v-model="innerVisible"
+    @close="onDialogClose"
+    destroy-on-close
+    draggable
+    top="10vh"
+    :width="900"
+  >
+    <div class="reward-recharge-wrapper">
+      <div class="reward-recharge-wrapper-title">
+        璇锋偍閫氳繃缃戦摱杞处鎴栫嚎涓嬫眹娆剧殑鏂瑰紡鎵撴鑷充笅鏂规寚瀹氳处鍙�
+      </div>
+      <div class="reward-recharge-wrapper-content">
+        <ProForm label-width="auto" is-read>
+          <ProFormItemV2 label="杩涜处鍗曚綅:">
+            <ProFormText :model-value="innerForm?.incomeEnterpriseName ?? ''"></ProFormText>
+          </ProFormItemV2>
+          <ProFormItemV2 label="寮�鎴峰悕绉�:">
+            <ProFormText :model-value="innerForm?.incomeEnterpriseName ?? ''"></ProFormText>
+          </ProFormItemV2>
+          <ProFormItemV2 label="寮�鎴烽摱琛�:">
+            <ProFormText :model-value="innerForm?.bankBranchName ?? ''"></ProFormText>
+          </ProFormItemV2>
+          <ProFormItemV2 label="閾惰璐﹀彿:">
+            <ProFormText :model-value="innerForm?.incomeBankNum">
+              <template #readContent>
+                <span>{{ StringUtils.insertSpaces(innerForm?.incomeBankNum) }}</span>
+                <el-button
+                  type="primary"
+                  link
+                  class="el-button-link-clear"
+                  style="margin-left: 16px"
+                  @click="copyTextToClipboard(innerForm?.incomeBankNum)"
+                  >澶嶅埗璐﹀彿</el-button
+                >
+              </template>
+            </ProFormText>
+          </ProFormItemV2>
+        </ProForm>
+      </div>
+    </div>
+    <ProForm :model="innerForm" label-width="120px" ref="dialogForm">
+      <FormCellV2 title="杞处/姹囨淇℃伅纭">
+        <ProFormCol>
+          <ProFormColItem :span="12">
+            <ProFormItemV2
+              label="姹囨璐︽埛鍚嶇О:"
+              prop="outEnterpriseName"
+              :check-rules="[{ message: '璇疯緭鍏ユ偍姹囨鐨勮处鎴峰悕绉�' }]"
+            >
+              <ProFormText
+                v-model.trim="innerForm.outEnterpriseName"
+                :maxlength="30"
+                placeholder="璇疯緭鍏ユ偍姹囨鐨勮处鎴峰悕绉�"
+              />
+            </ProFormItemV2>
+          </ProFormColItem>
+        </ProFormCol>
+        <ProFormCol>
+          <ProFormColItem :span="12">
+            <ProFormItemV2
+              label="姹囨閾惰璐﹀彿:"
+              prop="outBankNum"
+              :check-rules="[
+                {
+                  trigger: 'blur',
+                  validator: (rule, value, callback) => {
+                    const _value = value.replace(/\s+/g, '');
+                    if (!_value) {
+                      callback(new Error('璇疯緭鍏ユ偍姹囨鐨勫鍏笎鍙�!'));
+                    } else if (!BoleRegExp.RegBankCard.test(_value)) {
+                      callback(new Error('璇疯緭鍏ユ纭殑閾惰鍗″彿!'));
+                    } else {
+                      callback();
+                    }
+                  },
+                },
+              ]"
+            >
+              <ProFormText
+                v-model.trim="innerForm.outBankNum"
+                :maxlength="30"
+                placeholder="璇疯緭鍏ユ偍姹囨鐨勫鍏笎鍙�"
+                :formatter="(value: string) => value.replace(/\s+/g, '')"
+              />
+            </ProFormItemV2>
+          </ProFormColItem>
+        </ProFormCol>
+        <ProFormItemV2
+          label="姹囨閲戦:"
+          prop="prechargeAmount"
+          :check-rules="[{ type: 'number', message: '璇疯緭鍏ユ偍鐨勬眹娆鹃噾棰�' }]"
+        >
+          <ProFormInputNumber
+            v-model.trim="innerForm.prechargeAmount"
+            placeholder="璇疯緭鍏ユ偍鐨勬眹娆鹃噾棰�"
+            :controls="false"
+            :min="0"
+            :max="99999999999999"
+            :precision="2"
+            unit="鍏�"
+            style="width: 200px"
+          />
+        </ProFormItemV2>
+        <ProFormCol>
+          <ProFormColItem :span="12">
+            <ProFormItemV2
+              label="寮�鎴烽摱琛�:"
+              prop="outBankName"
+              :check-rules="[{ message: '璇疯緭鍏ユ偍鐨勫紑鎴烽摱琛�' }]"
+            >
+              <ProFormText
+                v-model.trim="innerForm.outBankName"
+                :maxlength="30"
+                placeholder="璇疯緭鍏ユ偍鐨勫紑鎴烽摱琛�"
+              />
+            </ProFormItemV2>
+          </ProFormColItem>
+        </ProFormCol>
+        <ProFormCol>
+          <ProFormColItem :span="12">
+            <ProFormItemV2 label="寮�鎴锋敮琛�:" prop="outBankResumeName">
+              <ProFormText
+                v-model.trim="innerForm.outBankResumeName"
+                :maxlength="30"
+                placeholder="璇疯緭鍏ユ偍鐨勫紑鎴锋敮琛�"
+              />
+            </ProFormItemV2>
+          </ProFormColItem>
+        </ProFormCol>
+        <ProFormItemV2
+          label="涓婁紶姹囨鍥炲崟:"
+          prop="outReceiptFileUrl"
+          :check-rules="[{ type: 'upload', message: '璇蜂笂浼犳眹娆惧洖鍗�' }]"
+        >
+          <ProFormUpload
+            v-model:file-url="innerForm.outReceiptFileUrl"
+            :limitFileSize="10"
+            accept="jpg/jpeg,png,pdf"
+          >
+          </ProFormUpload>
+        </ProFormItemV2>
+      </FormCellV2>
+    </ProForm>
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button type="default" @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,
+  ProFormUpload,
+  ProFormInputNumber,
+  UploadUserFile,
+  ProFormCol,
+  ProFormColItem,
+} from '@bole-core/components';
+import { StringUtils, copyTextToClipboard } from '@/utils';
+import { BoleRegExp } from '@bole-core/core';
+
+defineOptions({
+  name: 'RewardRechargeDialog',
+});
+
+type Props = {
+  modelValue: boolean;
+  form: {
+    title?: string;
+    incomeBankNum: string;
+    incomeEnterpriseName: string;
+    bankBranchName: string;
+    outBankNum: string;
+    outBankName: string;
+    outBankResumeName: string;
+    outEnterpriseName: string;
+    prechargeAmount: number;
+    outReceiptFileUrl: 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 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>
+<style lang="scss" scoped>
+.reward-recharge-wrapper {
+  margin-bottom: 24px;
+  padding: 20px;
+  border: 1px solid #e8e8e8;
+  border-radius: 4px;
+
+  .reward-recharge-wrapper-title {
+    margin-bottom: 24px;
+    font-size: 14px;
+    color: getCssVar('text-color', 'primary');
+    line-height: 19px;
+  }
+
+  .reward-recharge-wrapper-content {
+    padding: 20px 40px;
+    border: 1px dashed #ffd64f;
+    border-radius: 4px;
+    background: #fffcf2;
+
+    .el-form {
+      :deep() {
+        .el-form-item__label {
+          padding-right: 8px;
+        }
+      }
+    }
+  }
+}
+</style>
diff --git a/src/views/FileManage/FileManage.vue b/src/views/FileManage/FileManage.vue
new file mode 100644
index 0000000..78616cf
--- /dev/null
+++ b/src/views/FileManage/FileManage.vue
@@ -0,0 +1,161 @@
+<template>
+  <LoadingLayout :loading="state.loading">
+    <AppContainer>
+      <ProTableQueryFilterBar @on-reset="reset">
+        <template #query>
+          <QueryFilterItem>
+            <FieldDatePicker
+              v-model="extraParamState.creationDate"
+              type="daterange"
+              range-separator="~"
+              start-placeholder="璧峰鏃堕棿"
+              end-placeholder="缁撴潫鏃堕棿"
+              clearable
+              @change="getList()"
+              tooltipContent="鎿嶄綔鏃堕棿"
+            ></FieldDatePicker>
+          </QueryFilterItem>
+        </template>
+      </ProTableQueryFilterBar>
+      <ProTableV2 v-bind="proTableProps" :columns="columns" :operationBtns="operationBtns">
+      </ProTableV2>
+    </AppContainer>
+  </LoadingLayout>
+</template>
+
+<script setup lang="ts">
+import {
+  ProTableQueryFilterBar,
+  ProTableV2,
+  LoadingLayout,
+  AppContainer,
+  QueryFilterItem,
+  useTable,
+  FieldDatePicker,
+  defineOperationBtns,
+  defineColumns,
+} from '@bole-core/components';
+import * as insuranceOrderServices from '@/services/api/InsuranceOrder';
+import { OrderInputType, downloadFileByUrl } from '@bole-core/core';
+import { format, setOSSLink } from '@/utils';
+import { ModelValueType } from 'element-plus';
+import { InsurancePolicyStatusEnumText, InsurancePolicyStatusEnum } from '@/constants';
+
+defineOptions({
+  name: 'FileManage',
+});
+
+const columns = defineColumns([
+  {
+    id: '1',
+    enCode: 'q',
+    name: '鏍囬',
+  },
+  {
+    id: '2',
+    enCode: 'q',
+    name: '鏃堕棿',
+  },
+  {
+    id: '3',
+    enCode: 'q',
+    name: '鎿嶄綔',
+  },
+  {
+    id: '4',
+    enCode: 'q',
+    name: '鐘舵��',
+  },
+]);
+
+const operationBtns = defineOperationBtns([
+  {
+    data: {
+      enCode: 'downloadFileBtn',
+      name: '涓嬭浇鏂囦欢',
+    },
+    emits: {
+      onClick: (role) => handleDownloadFile(role),
+    },
+  },
+  {
+    data: {
+      enCode: 'downloadOriginalFileBtn',
+      name: '涓嬭浇鍘熸枃浠�',
+    },
+    emits: {
+      onClick: (role) => handleDownloadOriginalFile(role),
+    },
+  },
+  {
+    data: {
+      enCode: 'downloadErrorDataBtn',
+      name: '涓嬭浇閿欒鏁版嵁',
+    },
+    emits: {
+      onClick: (role) => handleDownloadErrorData(role),
+    },
+  },
+]);
+
+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.GetInsurancePageInput = {
+        pageModel: {
+          rows: pageSize,
+          page: pageIndex,
+          orderInput: extraParamState.orderInput,
+        },
+        importStartDateTime: format(extraParamState.creationDate?.[0] ?? '', 'YYYY-MM-DD 00:00:00'),
+        importEndDateTime: format(extraParamState.creationDate?.[1] ?? '', 'YYYY-MM-DD 23:59:59'),
+        insurancePeriod: extraParamState.insurancePeriod,
+        status: extraParamState.status,
+      };
+      let res = await insuranceOrderServices.getInsurancePage(params, {
+        showLoading: !state.loading,
+      });
+      return res;
+    } catch (error) {}
+  },
+  {
+    defaultExtraParams: {
+      orderInput: [{ property: 'id', order: OrderInputType.Desc }],
+      creationDate: [] as unknown as ModelValueType,
+      status: '' as any as InsurancePolicyStatusEnum,
+      insurancePeriod: '',
+    },
+    columnsRenderProps: {
+      status: { type: 'enum', valueEnum: InsurancePolicyStatusEnumText },
+      effectEndTime: { type: 'date', format: 'YYYY-MM-DD' },
+    },
+  }
+);
+
+function handleDownloadFile(row: API.GetInsurancePageOutput) {
+  downloadFileByUrl(setOSSLink(row.insureBillUrl));
+}
+function handleDownloadOriginalFile(row: API.GetInsurancePageOutput) {
+  downloadFileByUrl(setOSSLink(row.insureBillUrl));
+}
+function handleDownloadErrorData(row: API.GetInsurancePageOutput) {
+  downloadFileByUrl(setOSSLink(row.insureBillUrl));
+}
+</script>
diff --git a/src/views/Home/Home.vue b/src/views/Home/Home.vue
index 59d56da..e566cc1 100644
--- a/src/views/Home/Home.vue
+++ b/src/views/Home/Home.vue
@@ -47,11 +47,16 @@
           <el-button @click="handleDownload()" type="primary" style="margin-right: 10px" link
             >妯℃澘涓嬭浇</el-button
           >
-
           <el-button @click="handleUpload()" type="primary" style="margin-right: 10px"
-            >瀵煎叆</el-button
+            >瀵煎叆鎶曚繚浜哄憳</el-button
           >
-
+          <!-- <el-button
+            v-if="AppType === 'jx'"
+            @click="handleUpload()"
+            type="primary"
+            style="margin-right: 10px"
+            >澶ф壒閲忔暟鎹鍏�</el-button
+          > -->
           <el-button @click="getInsurancePageExport()" type="primary" link>瀵煎嚭淇濆崟鍒楄〃</el-button>
           <el-button @click="getInsuranceStaffPageExport()" type="primary" link
             >瀵煎嚭鍦ㄤ繚浜哄憳</el-button
@@ -103,6 +108,7 @@
   insuranceTypeText,
   InsurancePolicyStatusEnumText,
   InsurancePolicyStatusEnum,
+  AppType,
 } from '@/constants';
 import dayjs from 'dayjs';
 import _ from 'lodash';

--
Gitblit v1.9.1