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