From ea776aa710e78e797d74e2261d7b1cf25e941b01 Mon Sep 17 00:00:00 2001 From: chewenye <15818182980@163.com> Date: Tue, 3 Jun 2025 06:07:06 +0800 Subject: [PATCH 01/25] =?UTF-8?q?types:=20=E6=89=A9=E5=B1=95user-dropdown?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E7=9A=84menus=E7=B1=BB=E5=9E=8B=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81iconify=20(#6283)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 车文烨 --- .../layouts/src/widgets/user-dropdown/user-dropdown.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue b/packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue index 8b5f499fb..8156324af 100644 --- a/packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue +++ b/packages/effects/layouts/src/widgets/user-dropdown/user-dropdown.vue @@ -46,7 +46,11 @@ interface Props { /** * 菜单数组 */ - menus?: Array<{ handler: AnyFunction; icon?: Component; text: string }>; + menus?: Array<{ + handler: AnyFunction; + icon?: Component | Function | string; + text: string; + }>; /** * 标签文本 From 4102cc221154215a1a6d4e4118e257e78b9e58fb Mon Sep 17 00:00:00 2001 From: Netfan Date: Tue, 3 Jun 2025 23:11:56 +0800 Subject: [PATCH 02/25] feat: improve vbenCheckButtonGroup (#6329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 按钮组支持单选清除和多选限制最大选项数 * 按钮组支持icon插槽来定制图标 --- .../shadcn-ui/src/components/button/button.ts | 11 ++++++ .../components/button/check-button-group.vue | 34 ++++++++++++++----- .../src/views/examples/button-group/index.vue | 34 +++++++++++++++++++ 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/packages/@core/ui-kit/shadcn-ui/src/components/button/button.ts b/packages/@core/ui-kit/shadcn-ui/src/components/button/button.ts index 01394caa7..bcb7a0c7e 100644 --- a/packages/@core/ui-kit/shadcn-ui/src/components/button/button.ts +++ b/packages/@core/ui-kit/shadcn-ui/src/components/button/button.ts @@ -29,14 +29,25 @@ export type ValueType = boolean | number | string; export interface VbenButtonGroupProps extends Pick { + /** 单选模式下允许清除选中 */ + allowClear?: boolean; + /** 值改变前的回调 */ beforeChange?: ( value: ValueType, isChecked: boolean, ) => boolean | PromiseLike | undefined; + /** 按钮样式 */ btnClass?: any; + /** 按钮间隔距离 */ gap?: number; + /** 多选模式下限制最多选择的数量。0表示不限制 */ + maxCount?: number; + /** 是否允许多选 */ multiple?: boolean; + /** 选项 */ options?: { [key: string]: any; label: CustomRenderType; value: ValueType }[]; + /** 显示图标 */ showIcon?: boolean; + /** 尺寸 */ size?: 'large' | 'middle' | 'small'; } diff --git a/packages/@core/ui-kit/shadcn-ui/src/components/button/check-button-group.vue b/packages/@core/ui-kit/shadcn-ui/src/components/button/check-button-group.vue index 6e9378910..fd87396eb 100644 --- a/packages/@core/ui-kit/shadcn-ui/src/components/button/check-button-group.vue +++ b/packages/@core/ui-kit/shadcn-ui/src/components/button/check-button-group.vue @@ -19,6 +19,8 @@ const props = withDefaults(defineProps(), { multiple: false, showIcon: true, size: 'middle', + allowClear: false, + maxCount: 0, }); const emit = defineEmits(['btnClick']); const btnDefaultProps = computed(() => { @@ -82,12 +84,22 @@ async function onBtnClick(value: ValueType) { if (innerValue.value.includes(value)) { innerValue.value = innerValue.value.filter((item) => item !== value); } else { + if (props.maxCount > 0 && innerValue.value.length >= props.maxCount) { + innerValue.value = innerValue.value.slice(0, props.maxCount - 1); + } innerValue.value.push(value); } modelValue.value = innerValue.value; } else { - innerValue.value = [value]; - modelValue.value = value; + if (props.allowClear && innerValue.value.includes(value)) { + innerValue.value = []; + modelValue.value = undefined; + emit('btnClick', undefined); + return; + } else { + innerValue.value = [value]; + modelValue.value = value; + } } emit('btnClick', value); } @@ -112,12 +124,18 @@ async function onBtnClick(value: ValueType) { @click="onBtnClick(btn.value)" >
- - - + + + + +
diff --git a/playground/src/views/examples/button-group/index.vue b/playground/src/views/examples/button-group/index.vue index 2bc350c81..23861da40 100644 --- a/playground/src/views/examples/button-group/index.vue +++ b/playground/src/views/examples/button-group/index.vue @@ -9,6 +9,7 @@ import { VbenButtonGroup, VbenCheckButtonGroup, } from '@vben/common-ui'; +import { LoaderCircle, Square, SquareCheckBig } from '@vben/icons'; import { Button, Card, message } from 'ant-design-vue'; @@ -51,6 +52,7 @@ const compProps = reactive({ gap: 0, showIcon: true, size: 'middle', + allowClear: false, } as Recordable); const [Form] = useVbenForm({ @@ -63,6 +65,9 @@ const [Form] = useVbenForm({ } }); }, + commonConfig: { + labelWidth: 150, + }, schema: [ { component: 'RadioGroup', @@ -109,6 +114,20 @@ const [Form] = useVbenForm({ fieldName: 'beforeChange', label: '前置回调', }, + { + component: 'Switch', + defaultValue: false, + fieldName: 'allowClear', + label: '允许清除', + help: '单选时是否允许取消选中(值为undefined)', + }, + { + component: 'InputNumber', + defaultValue: 0, + fieldName: 'maxCount', + label: '最大选中数量', + help: '多选时有效,0表示不限制', + }, ], showDefaultActions: false, submitOnChange: true, @@ -186,6 +205,21 @@ function onBtnClick(value: any) { v-bind="compProps" /> +

自定义图标{{ checkValue }}

+
+ + + +
From b9aef618feabc9c65e5d04112cf8ea73d257aa4f Mon Sep 17 00:00:00 2001 From: vben Date: Wed, 4 Jun 2025 05:33:06 +0800 Subject: [PATCH 03/25] chore: release 5.5.7 --- apps/web-antd/package.json | 2 +- apps/web-ele/package.json | 2 +- apps/web-naive/package.json | 2 +- docs/package.json | 2 +- internal/lint-configs/commitlint-config/package.json | 2 +- internal/lint-configs/stylelint-config/package.json | 2 +- internal/node-utils/package.json | 2 +- internal/tailwind-config/package.json | 2 +- internal/tsconfig/package.json | 2 +- package.json | 2 +- packages/@core/base/design/package.json | 2 +- packages/@core/base/icons/package.json | 2 +- packages/@core/base/shared/package.json | 2 +- packages/@core/base/typings/package.json | 2 +- packages/@core/composables/package.json | 2 +- packages/@core/preferences/package.json | 2 +- packages/@core/ui-kit/form-ui/package.json | 2 +- packages/@core/ui-kit/layout-ui/package.json | 2 +- packages/@core/ui-kit/menu-ui/package.json | 2 +- packages/@core/ui-kit/shadcn-ui/package.json | 2 +- packages/@core/ui-kit/tabs-ui/package.json | 2 +- packages/constants/package.json | 2 +- packages/effects/access/package.json | 2 +- packages/effects/common-ui/package.json | 2 +- packages/effects/hooks/package.json | 2 +- packages/effects/layouts/package.json | 2 +- packages/effects/request/package.json | 2 +- packages/icons/package.json | 2 +- packages/locales/package.json | 2 +- packages/preferences/package.json | 2 +- packages/stores/package.json | 2 +- packages/styles/package.json | 2 +- packages/types/package.json | 2 +- packages/utils/package.json | 2 +- playground/package.json | 2 +- scripts/turbo-run/package.json | 2 +- 36 files changed, 36 insertions(+), 36 deletions(-) diff --git a/apps/web-antd/package.json b/apps/web-antd/package.json index bb5ab7e12..6dcb91848 100644 --- a/apps/web-antd/package.json +++ b/apps/web-antd/package.json @@ -1,6 +1,6 @@ { "name": "@vben/web-antd", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://vben.pro", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/apps/web-ele/package.json b/apps/web-ele/package.json index a51f5a9b6..386c36840 100644 --- a/apps/web-ele/package.json +++ b/apps/web-ele/package.json @@ -1,6 +1,6 @@ { "name": "@vben/web-ele", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://vben.pro", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/apps/web-naive/package.json b/apps/web-naive/package.json index ed95930c2..b97ab64f7 100644 --- a/apps/web-naive/package.json +++ b/apps/web-naive/package.json @@ -1,6 +1,6 @@ { "name": "@vben/web-naive", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://vben.pro", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/docs/package.json b/docs/package.json index a53005342..f57dfc854 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "@vben/docs", - "version": "5.5.6", + "version": "5.5.7", "private": true, "scripts": { "build": "vitepress build", diff --git a/internal/lint-configs/commitlint-config/package.json b/internal/lint-configs/commitlint-config/package.json index c17cde2a2..a137f947b 100644 --- a/internal/lint-configs/commitlint-config/package.json +++ b/internal/lint-configs/commitlint-config/package.json @@ -1,6 +1,6 @@ { "name": "@vben/commitlint-config", - "version": "5.5.6", + "version": "5.5.7", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/internal/lint-configs/stylelint-config/package.json b/internal/lint-configs/stylelint-config/package.json index ee55c702a..8e2a97c2c 100644 --- a/internal/lint-configs/stylelint-config/package.json +++ b/internal/lint-configs/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@vben/stylelint-config", - "version": "5.5.6", + "version": "5.5.7", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/internal/node-utils/package.json b/internal/node-utils/package.json index 782c0b30f..8b8db7454 100644 --- a/internal/node-utils/package.json +++ b/internal/node-utils/package.json @@ -1,6 +1,6 @@ { "name": "@vben/node-utils", - "version": "5.5.6", + "version": "5.5.7", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/internal/tailwind-config/package.json b/internal/tailwind-config/package.json index 9f62a1b70..8506891b5 100644 --- a/internal/tailwind-config/package.json +++ b/internal/tailwind-config/package.json @@ -1,6 +1,6 @@ { "name": "@vben/tailwind-config", - "version": "5.5.6", + "version": "5.5.7", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/internal/tsconfig/package.json b/internal/tsconfig/package.json index dd4f6321c..44ee3f1b0 100644 --- a/internal/tsconfig/package.json +++ b/internal/tsconfig/package.json @@ -1,6 +1,6 @@ { "name": "@vben/tsconfig", - "version": "5.5.6", + "version": "5.5.7", "private": true, "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", diff --git a/package.json b/package.json index 0583d01cf..72db822c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vben-admin-monorepo", - "version": "5.5.6", + "version": "5.5.7", "private": true, "keywords": [ "monorepo", diff --git a/packages/@core/base/design/package.json b/packages/@core/base/design/package.json index 4bdfbe32c..33e924749 100644 --- a/packages/@core/base/design/package.json +++ b/packages/@core/base/design/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/design", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/@core/base/icons/package.json b/packages/@core/base/icons/package.json index 4d758ca84..9a349883c 100644 --- a/packages/@core/base/icons/package.json +++ b/packages/@core/base/icons/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/icons", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/@core/base/shared/package.json b/packages/@core/base/shared/package.json index 05bb218ae..b02cc6e47 100644 --- a/packages/@core/base/shared/package.json +++ b/packages/@core/base/shared/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/shared", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/@core/base/typings/package.json b/packages/@core/base/typings/package.json index dc99de243..e2ab18701 100644 --- a/packages/@core/base/typings/package.json +++ b/packages/@core/base/typings/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/typings", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/@core/composables/package.json b/packages/@core/composables/package.json index 3e03540f7..08db5106f 100644 --- a/packages/@core/composables/package.json +++ b/packages/@core/composables/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/composables", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/@core/preferences/package.json b/packages/@core/preferences/package.json index 828370fde..726b473db 100644 --- a/packages/@core/preferences/package.json +++ b/packages/@core/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/preferences", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/@core/ui-kit/form-ui/package.json b/packages/@core/ui-kit/form-ui/package.json index 651b3dc54..36ae1678f 100644 --- a/packages/@core/ui-kit/form-ui/package.json +++ b/packages/@core/ui-kit/form-ui/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/form-ui", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/@core/ui-kit/layout-ui/package.json b/packages/@core/ui-kit/layout-ui/package.json index d62d18646..57a462fe1 100644 --- a/packages/@core/ui-kit/layout-ui/package.json +++ b/packages/@core/ui-kit/layout-ui/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/layout-ui", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/@core/ui-kit/menu-ui/package.json b/packages/@core/ui-kit/menu-ui/package.json index 1ff5741c7..760d7646e 100644 --- a/packages/@core/ui-kit/menu-ui/package.json +++ b/packages/@core/ui-kit/menu-ui/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/menu-ui", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/@core/ui-kit/shadcn-ui/package.json b/packages/@core/ui-kit/shadcn-ui/package.json index 989004675..11d2918f1 100644 --- a/packages/@core/ui-kit/shadcn-ui/package.json +++ b/packages/@core/ui-kit/shadcn-ui/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/shadcn-ui", - "version": "5.5.6", + "version": "5.5.7", "#main": "./dist/index.mjs", "#module": "./dist/index.mjs", "homepage": "https://github.com/vbenjs/vue-vben-admin", diff --git a/packages/@core/ui-kit/tabs-ui/package.json b/packages/@core/ui-kit/tabs-ui/package.json index 86afff5b9..bc84b4d6a 100644 --- a/packages/@core/ui-kit/tabs-ui/package.json +++ b/packages/@core/ui-kit/tabs-ui/package.json @@ -1,6 +1,6 @@ { "name": "@vben-core/tabs-ui", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/constants/package.json b/packages/constants/package.json index 072d6b626..c71e11847 100644 --- a/packages/constants/package.json +++ b/packages/constants/package.json @@ -1,6 +1,6 @@ { "name": "@vben/constants", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/effects/access/package.json b/packages/effects/access/package.json index 51beaa83e..e4c39eb2a 100644 --- a/packages/effects/access/package.json +++ b/packages/effects/access/package.json @@ -1,6 +1,6 @@ { "name": "@vben/access", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/effects/common-ui/package.json b/packages/effects/common-ui/package.json index 58bdd8c0f..c9674985a 100644 --- a/packages/effects/common-ui/package.json +++ b/packages/effects/common-ui/package.json @@ -1,6 +1,6 @@ { "name": "@vben/common-ui", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/effects/hooks/package.json b/packages/effects/hooks/package.json index 25a5836ab..004f3c50e 100644 --- a/packages/effects/hooks/package.json +++ b/packages/effects/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@vben/hooks", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/effects/layouts/package.json b/packages/effects/layouts/package.json index f645da901..a8439a021 100644 --- a/packages/effects/layouts/package.json +++ b/packages/effects/layouts/package.json @@ -1,6 +1,6 @@ { "name": "@vben/layouts", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/effects/request/package.json b/packages/effects/request/package.json index 57e5c20ec..527f6d904 100644 --- a/packages/effects/request/package.json +++ b/packages/effects/request/package.json @@ -1,6 +1,6 @@ { "name": "@vben/request", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/icons/package.json b/packages/icons/package.json index d7fbc7d43..858383947 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@vben/icons", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/locales/package.json b/packages/locales/package.json index 6ab5ed5e3..5e92de548 100644 --- a/packages/locales/package.json +++ b/packages/locales/package.json @@ -1,6 +1,6 @@ { "name": "@vben/locales", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/preferences/package.json b/packages/preferences/package.json index c650bcea7..de276c726 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,6 +1,6 @@ { "name": "@vben/preferences", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/stores/package.json b/packages/stores/package.json index f6f9518ba..c9860b59c 100644 --- a/packages/stores/package.json +++ b/packages/stores/package.json @@ -1,6 +1,6 @@ { "name": "@vben/stores", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/styles/package.json b/packages/styles/package.json index 7eada0dc8..127bd4d58 100644 --- a/packages/styles/package.json +++ b/packages/styles/package.json @@ -1,6 +1,6 @@ { "name": "@vben/styles", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/types/package.json b/packages/types/package.json index b74ca47ec..2fa047d84 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@vben/types", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/packages/utils/package.json b/packages/utils/package.json index 4d135be39..38a6ca199 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@vben/utils", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://github.com/vbenjs/vue-vben-admin", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/playground/package.json b/playground/package.json index 9446f38be..8bfd17d51 100644 --- a/playground/package.json +++ b/playground/package.json @@ -1,6 +1,6 @@ { "name": "@vben/playground", - "version": "5.5.6", + "version": "5.5.7", "homepage": "https://vben.pro", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "repository": { diff --git a/scripts/turbo-run/package.json b/scripts/turbo-run/package.json index 83832d81b..4639c873e 100644 --- a/scripts/turbo-run/package.json +++ b/scripts/turbo-run/package.json @@ -1,6 +1,6 @@ { "name": "@vben/turbo-run", - "version": "5.5.6", + "version": "5.5.7", "private": true, "license": "MIT", "type": "module", From 6cede50dcc2f7b228873565aeb3b56fcc3f68ddd Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Wed, 4 Jun 2025 14:20:19 +0800 Subject: [PATCH 04/25] feat: crm permission --- .../src/views/crm/permission/modules/data.ts | 231 ++++++++++++++++++ .../permission/modules/permission-form.vue | 85 +------ .../permission/modules/permission-list.vue | 58 ++--- .../crm/permission/modules/transfer-form.vue | 88 +------ 4 files changed, 255 insertions(+), 207 deletions(-) create mode 100644 apps/web-antd/src/views/crm/permission/modules/data.ts diff --git a/apps/web-antd/src/views/crm/permission/modules/data.ts b/apps/web-antd/src/views/crm/permission/modules/data.ts new file mode 100644 index 000000000..b3405eca5 --- /dev/null +++ b/apps/web-antd/src/views/crm/permission/modules/data.ts @@ -0,0 +1,231 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { BizTypeEnum, PermissionLevelEnum } from '#/api/crm/permission'; +import { getSimpleUserList } from '#/api/system/user'; +import { DICT_TYPE, getDictOptions } from '#/utils'; + +/** 新增/修改的表单 */ +export function useTransferFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'ownerUserId', + label: '选择新负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + rules: 'required', + }, + { + fieldName: 'oldOwnerHandler', + label: '老负责人', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '加入团队', + value: true, + }, + { + label: '移除', + value: false, + }, + ], + }, + rules: 'required', + }, + { + fieldName: 'oldOwnerPermissionLevel', + label: '老负责人权限级别', + component: 'RadioGroup', + componentProps: { + options: getDictOptions( + DICT_TYPE.CRM_PERMISSION_LEVEL, + 'number', + ).filter((dict) => dict.value !== PermissionLevelEnum.OWNER), + }, + dependencies: { + triggerFields: ['oldOwnerHandler'], + show: (values) => values.oldOwnerHandler, + trigger(values) { + if (!values.oldOwnerHandler) { + values.oldOwnerPermissionLevel = undefined; + } + }, + }, + rules: 'required', + }, + { + fieldName: 'toBizTypes', + label: '同时转移', + component: 'CheckboxGroup', + componentProps: { + options: [ + { + label: '联系人', + value: BizTypeEnum.CRM_CONTACT, + }, + { + label: '商机', + value: BizTypeEnum.CRM_BUSINESS, + }, + { + label: '合同', + value: BizTypeEnum.CRM_CONTRACT, + }, + ], + }, + }, + ]; +} + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'bizId', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'ids', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'userId', + label: '选择人员', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + dependencies: { + triggerFields: ['ids'], + show: (values) => { + return values.ids === undefined; + }, + }, + }, + { + fieldName: 'level', + label: '权限级别', + component: 'RadioGroup', + componentProps: { + options: getDictOptions( + DICT_TYPE.CRM_PERMISSION_LEVEL, + 'number', + ).filter((dict) => dict.value !== PermissionLevelEnum.OWNER), + }, + rules: 'required', + }, + { + fieldName: 'bizType', + label: 'Crm 类型', + component: 'RadioGroup', + componentProps: { + options: [ + { + label: '联系人', + value: BizTypeEnum.CRM_CONTACT, + }, + { + label: '商机', + value: BizTypeEnum.CRM_BUSINESS, + }, + { + label: '合同', + value: BizTypeEnum.CRM_CONTRACT, + }, + ], + }, + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'toBizTypes', + label: '同时添加至', + component: 'CheckboxGroup', + componentProps: { + options: [ + { + label: '联系人', + value: BizTypeEnum.CRM_CONTACT, + }, + { + label: '商机', + value: BizTypeEnum.CRM_BUSINESS, + }, + { + label: '合同', + value: BizTypeEnum.CRM_CONTRACT, + }, + ], + }, + dependencies: { + triggerFields: ['ids', 'bizType'], + show: (values) => { + return ( + values.ids === undefined && + values.bizType === BizTypeEnum.CRM_CUSTOMER + ); + }, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + }, + { + field: 'nickname', + title: '姓名', + }, + { + field: 'deptName', + title: '部门', + }, + { + field: 'postNames', + title: '岗位', + }, + { + field: 'level', + title: '权限级别', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_PERMISSION_LEVEL }, + }, + }, + { + field: 'createTime', + title: '加入时间', + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-antd/src/views/crm/permission/modules/permission-form.vue b/apps/web-antd/src/views/crm/permission/modules/permission-form.vue index e6e8fa462..c2c5df01a 100644 --- a/apps/web-antd/src/views/crm/permission/modules/permission-form.vue +++ b/apps/web-antd/src/views/crm/permission/modules/permission-form.vue @@ -8,15 +8,10 @@ import { useVbenModal } from '@vben/common-ui'; import { message } from 'ant-design-vue'; import { useVbenForm } from '#/adapter/form'; -import { - BizTypeEnum, - createPermission, - PermissionLevelEnum, - updatePermission, -} from '#/api/crm/permission'; -import { getSimpleUserList } from '#/api/system/user'; +import { createPermission, updatePermission } from '#/api/crm/permission'; import { $t } from '#/locales'; -import { DICT_TYPE, getDictOptions } from '#/utils'; + +import { useFormSchema } from './data'; const emit = defineEmits(['success']); const formData = ref(); @@ -35,74 +30,7 @@ const [Form, formApi] = useVbenForm({ labelWidth: 80, }, layout: 'horizontal', - schema: [ - { - fieldName: 'ids', - component: 'Input', - dependencies: { - triggerFields: [''], - show: () => false, - }, - }, - { - fieldName: 'userId', - label: '选择人员', - component: 'ApiSelect', - componentProps: { - api: getSimpleUserList, - labelField: 'nickname', - valueField: 'id', - }, - dependencies: { - triggerFields: ['ids'], - show: (values) => { - return values.ids === undefined; - }, - }, - }, - { - fieldName: 'level', - label: '权限级别', - component: 'RadioGroup', - componentProps: { - options: getDictOptions( - DICT_TYPE.CRM_PERMISSION_LEVEL, - 'number', - ).filter((dict) => dict.value !== PermissionLevelEnum.OWNER), - }, - rules: 'required', - }, - { - fieldName: 'toBizTypes', - label: '同时添加至', - component: 'CheckboxGroup', - componentProps: { - options: [ - { - label: '联系人', - value: BizTypeEnum.CRM_CONTACT, - }, - { - label: '商机', - value: BizTypeEnum.CRM_BUSINESS, - }, - { - label: '合同', - value: BizTypeEnum.CRM_CONTRACT, - }, - ], - }, - dependencies: { - triggerFields: ['ids', 'bizType'], - show: (values) => { - return ( - values.ids === undefined && - formData.value?.bizType === BizTypeEnum.CRM_CUSTOMER - ); - }, - }, - }, - ], + schema: useFormSchema(), showDefaultActions: false, }); @@ -114,8 +42,7 @@ const [Modal, modalApi] = useVbenModal({ } modalApi.lock(); // 提交表单 - let data = (await formApi.getValues()) as CrmPermissionApi.Permission; - data = Object.assign(data, formData.value); + const data = (await formApi.getValues()) as CrmPermissionApi.Permission; try { await (formData.value?.ids ? updatePermission(data) @@ -141,7 +68,7 @@ const [Modal, modalApi] = useVbenModal({ modalApi.lock(); try { formData.value = { - ids: data.ids || [data.id] || undefined, + ids: data.ids ?? (data.id ? [data.id] : undefined), userId: undefined, bizType: data.bizType, bizId: data.bizId, diff --git a/apps/web-antd/src/views/crm/permission/modules/permission-list.vue b/apps/web-antd/src/views/crm/permission/modules/permission-list.vue index 65b202261..fbc649d43 100644 --- a/apps/web-antd/src/views/crm/permission/modules/permission-list.vue +++ b/apps/web-antd/src/views/crm/permission/modules/permission-list.vue @@ -17,8 +17,8 @@ import { PermissionLevelEnum, } from '#/api/crm/permission'; import { $t } from '#/locales'; -import { DICT_TYPE } from '#/utils'; +import { useGridColumns } from './data'; import Form from './permission-form.vue'; defineOptions({ name: 'CrmPermissionList' }); @@ -50,13 +50,13 @@ function onRefresh() { gridApi.query(); } -const checkedIds = ref([]); -function setCheckedIds({ +const checkedRows = ref([]); +function setCheckedRows({ records, }: { records: CrmPermissionApi.Permission[]; }) { - checkedIds.value = records; + checkedRows.value = records; } function handleCreate() { @@ -69,11 +69,11 @@ function handleCreate() { } function handleEdit() { - if (checkedIds.value.length === 0) { + if (checkedRows.value.length === 0) { message.error('请先选择团队成员后操作!'); return; } - if (checkedIds.value.length > 1) { + if (checkedRows.value.length > 1) { message.error('只能选择一个团队成员进行编辑!'); return; } @@ -81,25 +81,25 @@ function handleEdit() { .setData({ bizType: props.bizType, bizId: props.bizId, - id: checkedIds.value[0]?.id, - level: checkedIds.value[0]?.level, + id: checkedRows.value[0]?.id, + level: checkedRows.value[0]?.level, }) .open(); } function handleDelete() { - if (checkedIds.value.length === 0) { + if (checkedRows.value.length === 0) { message.error('请先选择团队成员后操作!'); return; } return new Promise((resolve, reject) => { confirm({ - content: `你要将${checkedIds.value.map((item) => item.nickname).join(',')}移出团队吗?`, + content: `你要将${checkedRows.value.map((item) => item.nickname).join(',')}移出团队吗?`, }) .then(async () => { // 更新用户状态 const res = await deletePermissionBatch( - checkedIds.value.map((item) => item.id as number), + checkedRows.value.map((item) => item.id as number), ); if (res) { // 提示并返回成功 @@ -144,37 +144,7 @@ async function handleQuit() { const [Grid, gridApi] = useVbenVxeGrid({ gridOptions: { - columns: [ - { - type: 'checkbox', - width: 50, - }, - { - field: 'nickname', - title: '姓名', - }, - { - field: 'deptName', - title: '部门', - }, - { - field: 'postNames', - title: '岗位', - }, - { - field: 'level', - title: '权限级别', - cellRender: { - name: 'CellDict', - props: { type: DICT_TYPE.CRM_PERMISSION_LEVEL }, - }, - }, - { - field: 'createTime', - title: '加入时间', - formatter: 'formatDateTime', - }, - ], + columns: useGridColumns(), height: 'auto', pagerConfig: { enabled: false, @@ -201,8 +171,8 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, } as VxeTableGridOptions, gridEvents: { - checkboxAll: setCheckedIds, - checkboxChange: setCheckedIds, + checkboxAll: setCheckedRows, + checkboxChange: setCheckedRows, }, }); diff --git a/apps/web-antd/src/views/crm/permission/modules/transfer-form.vue b/apps/web-antd/src/views/crm/permission/modules/transfer-form.vue index f849cdfc9..d68a38f0a 100644 --- a/apps/web-antd/src/views/crm/permission/modules/transfer-form.vue +++ b/apps/web-antd/src/views/crm/permission/modules/transfer-form.vue @@ -13,10 +13,10 @@ import { transferClue } from '#/api/crm/clue'; import { transferContact } from '#/api/crm/contact'; import { transferContract } from '#/api/crm/contract'; import { transferCustomer } from '#/api/crm/customer'; -import { BizTypeEnum, PermissionLevelEnum } from '#/api/crm/permission'; -import { getSimpleUserList } from '#/api/system/user'; +import { BizTypeEnum } from '#/api/crm/permission'; import { $t } from '#/locales'; -import { DICT_TYPE, getDictOptions } from '#/utils'; + +import { useTransferFormSchema } from './data'; defineOptions({ name: 'CrmTransferForm' }); @@ -56,87 +56,7 @@ const [Form, formApi] = useVbenForm({ labelWidth: 120, }, layout: 'horizontal', - schema: [ - { - fieldName: 'id', - component: 'Input', - dependencies: { - triggerFields: [''], - show: () => false, - }, - }, - { - fieldName: 'ownerUserId', - label: '选择新负责人', - component: 'ApiSelect', - componentProps: { - api: getSimpleUserList, - labelField: 'nickname', - valueField: 'id', - }, - rules: 'required', - }, - { - fieldName: 'oldOwnerHandler', - label: '老负责人', - component: 'RadioGroup', - componentProps: { - options: [ - { - label: '加入团队', - value: true, - }, - { - label: '移除', - value: false, - }, - ], - }, - rules: 'required', - }, - { - fieldName: 'oldOwnerPermissionLevel', - label: '老负责人权限级别', - component: 'RadioGroup', - componentProps: { - options: getDictOptions( - DICT_TYPE.CRM_PERMISSION_LEVEL, - 'number', - ).filter((dict) => dict.value !== PermissionLevelEnum.OWNER), - }, - dependencies: { - triggerFields: ['oldOwnerHandler'], - show: (values) => values.oldOwnerHandler, - trigger(values) { - if (!values.oldOwnerHandler) { - formApi.setFieldValue('oldOwnerPermissionLevel', undefined); - } - }, - }, - rules: 'required', - }, - { - fieldName: 'toBizTypes', - label: '同时转移', - component: 'CheckboxGroup', - componentProps: { - options: [ - { - label: '联系人', - value: BizTypeEnum.CRM_CONTACT, - }, - { - label: '商机', - value: BizTypeEnum.CRM_BUSINESS, - }, - { - label: '合同', - value: BizTypeEnum.CRM_CONTRACT, - }, - ], - }, - }, - ], + schema: useTransferFormSchema(), showDefaultActions: false, }); From 5990386498e18fd1d134ddacb22b5221b6912839 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Wed, 4 Jun 2025 14:59:56 +0800 Subject: [PATCH 05/25] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/crm/permission/modules/permission-list.vue | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/web-antd/src/views/crm/permission/modules/permission-list.vue b/apps/web-antd/src/views/crm/permission/modules/permission-list.vue index fbc649d43..87ca2078f 100644 --- a/apps/web-antd/src/views/crm/permission/modules/permission-list.vue +++ b/apps/web-antd/src/views/crm/permission/modules/permission-list.vue @@ -56,6 +56,11 @@ function setCheckedRows({ }: { records: CrmPermissionApi.Permission[]; }) { + if (records.some((item) => item.level === PermissionLevelEnum.OWNER)) { + message.warning('不能选择负责人!'); + gridApi.grid.setAllCheckboxRow(false); + return; + } checkedRows.value = records; } From f36803cea9572cf579ae8650864dbfcb0500312f Mon Sep 17 00:00:00 2001 From: zz Date: Wed, 4 Jun 2025 13:53:08 +0800 Subject: [PATCH 06/25] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E6=95=B0=E6=8D=AE=E5=BA=93=E6=8E=A5=E5=8F=A3=E3=80=81?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=8A=B6=E6=80=81=E4=BF=AE=E6=94=B9=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=B0=83=E7=94=A8=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/api/infra/codegen/index.ts | 10 +++++++--- apps/web-antd/src/api/infra/job/index.ts | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/web-antd/src/api/infra/codegen/index.ts b/apps/web-antd/src/api/infra/codegen/index.ts index d8fea0453..482284cfc 100644 --- a/apps/web-antd/src/api/infra/codegen/index.ts +++ b/apps/web-antd/src/api/infra/codegen/index.ts @@ -112,9 +112,13 @@ export function updateCodegenTable(data: InfraCodegenApi.CodegenUpdateReqVO) { /** 基于数据库的表结构,同步数据库的表和字段定义 */ export function syncCodegenFromDB(tableId: number) { - return requestClient.put('/infra/codegen/sync-from-db', { - params: { tableId }, - }); + return requestClient.put( + '/infra/codegen/sync-from-db', + {}, + { + params: { tableId }, + }, + ); } /** 预览生成代码 */ diff --git a/apps/web-antd/src/api/infra/job/index.ts b/apps/web-antd/src/api/infra/job/index.ts index 3bd20fdb5..bacdbc4a1 100644 --- a/apps/web-antd/src/api/infra/job/index.ts +++ b/apps/web-antd/src/api/infra/job/index.ts @@ -57,7 +57,7 @@ export function updateJobStatus(id: number, status: number) { id, status, }; - return requestClient.put('/infra/job/update-status', { params }); + return requestClient.put('/infra/job/update-status', {}, { params }); } /** 定时任务立即执行一次 */ From d8bab3eadca4516dde9dbee7a5889d86d104048a Mon Sep 17 00:00:00 2001 From: zz Date: Wed, 4 Jun 2025 14:02:15 +0800 Subject: [PATCH 07/25] =?UTF-8?q?fix:=20=E6=9C=AA=E8=AE=BE=E7=BD=AEaction.?= =?UTF-8?q?icon=E6=97=B6=E4=B8=8D=E5=A2=9E=E5=8A=A0ml-1=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=EF=BC=8C=E8=A7=A3=E5=86=B3=E5=88=97=E8=A1=A8=E4=B8=AD=E6=9B=B4?= =?UTF-8?q?=E5=A4=9A=E8=8F=9C=E5=8D=95=E4=B8=AD=E7=9A=84=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E9=A1=B9=E6=9C=AA=E5=AF=B9=E9=BD=90=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/components/table-action/table-action.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web-antd/src/components/table-action/table-action.vue b/apps/web-antd/src/components/table-action/table-action.vue index 1ad69eb26..d86a7f2c1 100644 --- a/apps/web-antd/src/components/table-action/table-action.vue +++ b/apps/web-antd/src/components/table-action/table-action.vue @@ -204,7 +204,9 @@ function handleMenuClick(e: any) { " > - {{ action.text }} + {{ + action.text + }} From e60bbe4ab12cc3f06dcf47f5072f59a84cac1482 Mon Sep 17 00:00:00 2001 From: zz Date: Wed, 4 Jun 2025 14:03:24 +0800 Subject: [PATCH 08/25] =?UTF-8?q?fix:=20=E4=BB=A3=E7=A0=81=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=88=97=E8=A1=A8=E4=B8=AD=E6=9B=B4=E5=A4=9A=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E4=B8=AD=E7=9A=84=E5=88=A0=E9=99=A4=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E5=BC=B9=E7=AA=97title=E5=8F=96=E8=A1=A8=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/views/infra/codegen/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web-antd/src/views/infra/codegen/index.vue b/apps/web-antd/src/views/infra/codegen/index.vue index fd41a9d92..88bb7b438 100644 --- a/apps/web-antd/src/views/infra/codegen/index.vue +++ b/apps/web-antd/src/views/infra/codegen/index.vue @@ -237,7 +237,7 @@ initDataSourceConfig(); danger: true, auth: ['infra:codegen:delete'], popConfirm: { - title: $t('ui.actionMessage.deleteConfirm', [row.name]), + title: $t('ui.actionMessage.deleteConfirm', [row.tableName]), confirm: handleDelete.bind(null, row), }, }, From 17889fce667378df2ede33582a42db0c54cfda0d Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Wed, 4 Jun 2025 16:46:46 +0800 Subject: [PATCH 09/25] feat: clue detail --- apps/web-antd/src/api/crm/clue/index.ts | 2 +- apps/web-antd/src/views/crm/clue/data.ts | 39 +++-- .../views/crm/clue/modules/detail-info.vue | 8 +- .../src/views/crm/clue/modules/detail.vue | 98 +++++++------ .../src/views/crm/clue/modules/transfer.vue | 78 ---------- .../web-antd/src/views/crm/followup/index.vue | 64 ++++----- .../src/views/crm/followup/modules/form.vue | 133 ++++++++++++++---- .../src/views/crm/permission/modules/data.ts | 2 +- .../permission/modules/permission-list.vue | 1 + 9 files changed, 214 insertions(+), 211 deletions(-) delete mode 100644 apps/web-antd/src/views/crm/clue/modules/transfer.vue diff --git a/apps/web-antd/src/api/crm/clue/index.ts b/apps/web-antd/src/api/crm/clue/index.ts index 9d3447b88..a3a378b67 100644 --- a/apps/web-antd/src/api/crm/clue/index.ts +++ b/apps/web-antd/src/api/crm/clue/index.ts @@ -77,7 +77,7 @@ export function transferClue(data: CrmPermissionApi.TransferReq) { /** 线索转化为客户 */ export function transformClue(id: number) { - return requestClient.put('/crm/clue/transform', { id }); + return requestClient.put(`/crm/clue/transform?id=${id}`); } /** 获得分配给我的、待跟进的线索数量 */ diff --git a/apps/web-antd/src/views/crm/clue/data.ts b/apps/web-antd/src/views/crm/clue/data.ts index abc05ed4e..4d3926695 100644 --- a/apps/web-antd/src/views/crm/clue/data.ts +++ b/apps/web-antd/src/views/crm/clue/data.ts @@ -7,6 +7,7 @@ import { h } from 'vue'; import { formatDateTime } from '@vben/utils'; import { getAreaTree } from '#/api/system/area'; +import { getSimpleUserList } from '#/api/system/user'; import { DictTag } from '#/components/dict-tag'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; @@ -32,7 +33,7 @@ export function useFormSchema(): VbenFormSchema[] { label: '客户来源', component: 'Select', componentProps: { - options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_SOURCE), + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_SOURCE, 'number'), }, rules: 'required', }, @@ -44,9 +45,12 @@ export function useFormSchema(): VbenFormSchema[] { { fieldName: 'ownerUserId', label: '负责人', - component: 'Select', + component: 'ApiSelect', componentProps: { - api: 'getSimpleUserList', + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + allowClear: true, }, rules: 'required', }, @@ -75,7 +79,7 @@ export function useFormSchema(): VbenFormSchema[] { label: '客户行业', component: 'Select', componentProps: { - options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_INDUSTRY), + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_INDUSTRY, 'number'), }, }, { @@ -83,7 +87,7 @@ export function useFormSchema(): VbenFormSchema[] { label: '客户级别', component: 'Select', componentProps: { - options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_LEVEL), + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_LEVEL, 'number'), }, }, { @@ -299,10 +303,6 @@ export function useDetailBaseSchema(): DescriptionItemSchema[] { field: 'mobile', label: '手机', }, - { - field: 'ownerUserName', - label: '负责人', - }, { field: 'telephone', label: '电话', @@ -312,13 +312,18 @@ export function useDetailBaseSchema(): DescriptionItemSchema[] { label: '邮箱', }, { - field: 'wechat', - label: '微信', + field: 'areaName', + label: '地址', + content: (data) => data?.areaName + data?.detailAddress, }, { field: 'qq', label: 'QQ', }, + { + field: 'wechat', + label: '微信', + }, { field: 'industryId', label: '客户行业', @@ -337,14 +342,6 @@ export function useDetailBaseSchema(): DescriptionItemSchema[] { value: data?.level, }), }, - { - field: 'areaId', - label: '地址', - }, - { - field: 'detailAddress', - label: '详细地址', - }, { field: 'contactNextTime', label: '下次联系时间', @@ -369,9 +366,9 @@ export function useDetailSystemSchema(): DescriptionItemSchema[] { label: '最后跟进记录', }, { - field: 'contactLastContent', + field: 'contactLastTime', label: '最后跟进时间', - content: (data) => formatDateTime(data?.contactLastContent) as string, + content: (data) => formatDateTime(data?.contactLastTime) as string, }, { field: 'creatorName', diff --git a/apps/web-antd/src/views/crm/clue/modules/detail-info.vue b/apps/web-antd/src/views/crm/clue/modules/detail-info.vue index 36784a1df..ea3cb1fbf 100644 --- a/apps/web-antd/src/views/crm/clue/modules/detail-info.vue +++ b/apps/web-antd/src/views/crm/clue/modules/detail-info.vue @@ -9,7 +9,7 @@ import { useDetailBaseSchema, useDetailSystemSchema } from '../data'; defineOptions({ name: 'CrmClueDetailsInfo' }); -const { clue } = defineProps<{ +defineProps<{ clue: CrmClueApi.Clue; // 线索信息 }>(); @@ -21,7 +21,6 @@ const [BaseDescription] = useDescription({ class: 'mx-4', }, schema: useDetailBaseSchema(), - data: clue, }); const [SystemDescription] = useDescription({ @@ -32,14 +31,13 @@ const [SystemDescription] = useDescription({ class: 'mx-4', }, schema: useDetailSystemSchema(), - data: clue, }); diff --git a/apps/web-antd/src/views/crm/clue/modules/detail.vue b/apps/web-antd/src/views/crm/clue/modules/detail.vue index 7c9d29b2a..fc07fdbd9 100644 --- a/apps/web-antd/src/views/crm/clue/modules/detail.vue +++ b/apps/web-antd/src/views/crm/clue/modules/detail.vue @@ -1,18 +1,22 @@ diff --git a/apps/web-antd/src/views/crm/clue/modules/transfer.vue b/apps/web-antd/src/views/crm/clue/modules/transfer.vue deleted file mode 100644 index d076ec4e6..000000000 --- a/apps/web-antd/src/views/crm/clue/modules/transfer.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/crm/followup/index.vue b/apps/web-antd/src/views/crm/followup/index.vue index 410e10c13..b6b81dda2 100644 --- a/apps/web-antd/src/views/crm/followup/index.vue +++ b/apps/web-antd/src/views/crm/followup/index.vue @@ -1,18 +1,22 @@ diff --git a/apps/web-antd/src/views/crm/permission/modules/data.ts b/apps/web-antd/src/views/crm/permission/modules/data.ts index b3405eca5..2ef822aa2 100644 --- a/apps/web-antd/src/views/crm/permission/modules/data.ts +++ b/apps/web-antd/src/views/crm/permission/modules/data.ts @@ -17,7 +17,7 @@ export function useTransferFormSchema(): VbenFormSchema[] { }, }, { - fieldName: 'ownerUserId', + fieldName: 'newOwnerUserId', label: '选择新负责人', component: 'ApiSelect', componentProps: { diff --git a/apps/web-antd/src/views/crm/permission/modules/permission-list.vue b/apps/web-antd/src/views/crm/permission/modules/permission-list.vue index 87ca2078f..4871f7aa5 100644 --- a/apps/web-antd/src/views/crm/permission/modules/permission-list.vue +++ b/apps/web-antd/src/views/crm/permission/modules/permission-list.vue @@ -109,6 +109,7 @@ function handleDelete() { if (res) { // 提示并返回成功 message.success($t('ui.actionMessage.operationSuccess')); + onRefresh(); resolve(true); } else { reject(new Error('移出失败')); From e789fea9ecf4615af69c4ca9851466e78d460a8c Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Wed, 4 Jun 2025 16:50:20 +0800 Subject: [PATCH 10/25] =?UTF-8?q?fix:=20=E4=BB=A3=E7=A0=81=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/src/api/infra/codegen/index.ts | 17 +++-------------- .../components/table-action/table-action.vue | 6 +++--- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/apps/web-antd/src/api/infra/codegen/index.ts b/apps/web-antd/src/api/infra/codegen/index.ts index 482284cfc..1c2d97ba3 100644 --- a/apps/web-antd/src/api/infra/codegen/index.ts +++ b/apps/web-antd/src/api/infra/codegen/index.ts @@ -112,30 +112,19 @@ export function updateCodegenTable(data: InfraCodegenApi.CodegenUpdateReqVO) { /** 基于数据库的表结构,同步数据库的表和字段定义 */ export function syncCodegenFromDB(tableId: number) { - return requestClient.put( - '/infra/codegen/sync-from-db', - {}, - { - params: { tableId }, - }, - ); + return requestClient.put(`/infra/codegen/sync-from-db?tableId=${tableId}`); } /** 预览生成代码 */ export function previewCodegen(tableId: number) { return requestClient.get( - '/infra/codegen/preview', - { - params: { tableId }, - }, + `/infra/codegen/preview?tableId=${tableId}`, ); } /** 下载生成代码 */ export function downloadCodegen(tableId: number) { - return requestClient.download('/infra/codegen/download', { - params: { tableId }, - }); + return requestClient.download(`/infra/codegen/download?tableId=${tableId}`); } /** 获得表定义 */ diff --git a/apps/web-antd/src/components/table-action/table-action.vue b/apps/web-antd/src/components/table-action/table-action.vue index d86a7f2c1..7595b87c1 100644 --- a/apps/web-antd/src/components/table-action/table-action.vue +++ b/apps/web-antd/src/components/table-action/table-action.vue @@ -204,9 +204,9 @@ function handleMenuClick(e: any) { " > - {{ - action.text - }} + + {{ action.text }} + From dba14c5e451c19bc6d36b19c6eba05d2dc0f9cfb Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Wed, 4 Jun 2025 16:53:33 +0800 Subject: [PATCH 11/25] =?UTF-8?q?perf:=20=E4=BD=BF=E7=94=A8=20defineAsyncC?= =?UTF-8?q?omponent=20=E5=8A=A0=E8=BD=BD=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/crm/clue/modules/detail.vue | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/web-antd/src/views/crm/clue/modules/detail.vue b/apps/web-antd/src/views/crm/clue/modules/detail.vue index fc07fdbd9..d521241e7 100644 --- a/apps/web-antd/src/views/crm/clue/modules/detail.vue +++ b/apps/web-antd/src/views/crm/clue/modules/detail.vue @@ -15,13 +15,26 @@ import { getClue, transformClue } from '#/api/crm/clue'; import { getOperateLogPage } from '#/api/crm/operateLog'; import { BizTypeEnum } from '#/api/crm/permission'; import { useDescription } from '#/components/description'; -import { OperateLog } from '#/components/operate-log'; -import FollowUp from '#/views/crm/followup/index.vue'; -import { PermissionList, TransferForm } from '#/views/crm/permission'; import { useDetailSchema } from '../data'; import ClueForm from './form.vue'; +const FollowUp = defineAsyncComponent( + () => import('#/views/crm/followup/index.vue'), +); + +const PermissionList = defineAsyncComponent( + () => import('#/views/crm/permission/modules/permission-list.vue'), +); + +const TransferForm = defineAsyncComponent( + () => import('#/views/crm/permission/modules/transfer-form.vue'), +); + +const OperateLog = defineAsyncComponent( + () => import('#/components/operate-log'), +); + const ClueDetailsInfo = defineAsyncComponent(() => import('./detail-info.vue')); const loading = ref(false); From c18d70b0bcf09170841e19b50aecf54921a60939 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Wed, 4 Jun 2025 17:38:28 +0800 Subject: [PATCH 12/25] feat: crm customer detail --- apps/web-antd/src/views/crm/clue/data.ts | 33 ----- .../views/crm/clue/modules/detail-info.vue | 5 +- apps/web-antd/src/views/crm/customer/data.ts | 68 ++++----- .../crm/customer/modules/detail-info.vue | 43 +++++- .../src/views/crm/customer/modules/detail.vue | 134 ++++++++++++------ apps/web-antd/src/views/crm/followup/data.ts | 36 +++++ 6 files changed, 197 insertions(+), 122 deletions(-) create mode 100644 apps/web-antd/src/views/crm/followup/data.ts diff --git a/apps/web-antd/src/views/crm/clue/data.ts b/apps/web-antd/src/views/crm/clue/data.ts index 4d3926695..bd2924aad 100644 --- a/apps/web-antd/src/views/crm/clue/data.ts +++ b/apps/web-antd/src/views/crm/clue/data.ts @@ -353,36 +353,3 @@ export function useDetailBaseSchema(): DescriptionItemSchema[] { }, ]; } - -/** 详情系统信息的配置 */ -export function useDetailSystemSchema(): DescriptionItemSchema[] { - return [ - { - field: 'ownerUserName', - label: '负责人', - }, - { - field: 'contactLastContent', - label: '最后跟进记录', - }, - { - field: 'contactLastTime', - label: '最后跟进时间', - content: (data) => formatDateTime(data?.contactLastTime) as string, - }, - { - field: 'creatorName', - label: '创建人', - }, - { - field: 'createTime', - label: '创建时间', - content: (data) => formatDateTime(data?.createTime) as string, - }, - { - field: 'updateTime', - label: '更新时间', - content: (data) => formatDateTime(data?.updateTime) as string, - }, - ]; -} diff --git a/apps/web-antd/src/views/crm/clue/modules/detail-info.vue b/apps/web-antd/src/views/crm/clue/modules/detail-info.vue index ea3cb1fbf..6abc70a99 100644 --- a/apps/web-antd/src/views/crm/clue/modules/detail-info.vue +++ b/apps/web-antd/src/views/crm/clue/modules/detail-info.vue @@ -4,8 +4,9 @@ import type { CrmClueApi } from '#/api/crm/clue'; import { Divider } from 'ant-design-vue'; import { useDescription } from '#/components/description'; +import { useFollowUpDetailSchema } from '#/views/crm/followup/data'; -import { useDetailBaseSchema, useDetailSystemSchema } from '../data'; +import { useDetailBaseSchema } from '../data'; defineOptions({ name: 'CrmClueDetailsInfo' }); @@ -30,7 +31,7 @@ const [SystemDescription] = useDescription({ column: 3, class: 'mx-4', }, - schema: useDetailSystemSchema(), + schema: useFollowUpDetailSchema(), }); diff --git a/apps/web-antd/src/views/crm/customer/data.ts b/apps/web-antd/src/views/crm/customer/data.ts index 551569da0..840d56636 100644 --- a/apps/web-antd/src/views/crm/customer/data.ts +++ b/apps/web-antd/src/views/crm/customer/data.ts @@ -243,7 +243,24 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { /** 详情页的字段 */ export function useDetailSchema(): DescriptionItemSchema[] { - return [...useDetailBaseSchema(), ...useDetailSystemSchema()]; + return [ + { + field: 'level', + label: '客户级别', + content: (data) => + h(DictTag, { type: DICT_TYPE.CRM_CUSTOMER_LEVEL, value: data?.level }), + }, + { + field: 'dealStatus', + label: '成交状态', + content: (data) => (data.dealStatus ? '已成交' : '未成交'), + }, + { + field: 'createTime', + label: '创建时间', + content: (data) => formatDateTime(data?.createTime) as string, + }, + ]; } /** 详情页的基础字段 */ @@ -275,13 +292,21 @@ export function useDetailBaseSchema(): DescriptionItemSchema[] { label: '邮箱', }, { - field: 'wechat', - label: '微信', + field: 'areaName', + label: '地址', + }, + { + field: 'detailAddress', + label: '详细地址', }, { field: 'qq', label: 'QQ', }, + { + field: 'wechat', + label: '微信', + }, { field: 'industryId', label: '客户行业', @@ -297,14 +322,6 @@ export function useDetailBaseSchema(): DescriptionItemSchema[] { content: (data) => h(DictTag, { type: DICT_TYPE.CRM_CUSTOMER_LEVEL, value: data?.level }), }, - { - field: 'areaName', - label: '地址', - }, - { - field: 'detailAddress', - label: '详细地址', - }, { field: 'contactNextTime', label: '下次联系时间', @@ -316,32 +333,3 @@ export function useDetailBaseSchema(): DescriptionItemSchema[] { }, ]; } - -/** 详情页的系统字段 */ -export function useDetailSystemSchema(): DescriptionItemSchema[] { - return [ - { - field: 'ownerUserName', - label: '负责人', - }, - { - field: 'ownerUserDeptName', - label: '所属部门', - }, - { - field: 'contactLastTime', - label: '最后跟进时间', - content: (data) => formatDateTime(data?.contactLastTime) as string, - }, - { - field: 'createTime', - label: '创建时间', - content: (data) => formatDateTime(data?.createTime) as string, - }, - { - field: 'updateTime', - label: '更新时间', - content: (data) => formatDateTime(data?.updateTime) as string, - }, - ]; -} diff --git a/apps/web-antd/src/views/crm/customer/modules/detail-info.vue b/apps/web-antd/src/views/crm/customer/modules/detail-info.vue index c651e23e0..12b2526d2 100644 --- a/apps/web-antd/src/views/crm/customer/modules/detail-info.vue +++ b/apps/web-antd/src/views/crm/customer/modules/detail-info.vue @@ -1,5 +1,44 @@ - + diff --git a/apps/web-antd/src/views/crm/customer/modules/detail.vue b/apps/web-antd/src/views/crm/customer/modules/detail.vue index 19c2b2695..1697075eb 100644 --- a/apps/web-antd/src/views/crm/customer/modules/detail.vue +++ b/apps/web-antd/src/views/crm/customer/modules/detail.vue @@ -5,15 +5,15 @@ import type { SystemOperateLogApi } from '#/api/system/operate-log'; import { defineAsyncComponent, onMounted, ref } from 'vue'; import { useRoute, useRouter } from 'vue-router'; -import { Page } from '@vben/common-ui'; +import { confirm, Page, useVbenModal } from '@vben/common-ui'; +import { useTabs } from '@vben/hooks'; -import { Button, Card, Modal, Tabs } from 'ant-design-vue'; +import { Button, Card, message, Tabs } from 'ant-design-vue'; import { getCustomer, updateCustomerDealStatus } from '#/api/crm/customer'; import { getOperateLogPage } from '#/api/crm/operateLog'; import { BizTypeEnum } from '#/api/crm/permission'; import { useDescription } from '#/components/description'; -import { OperateLog } from '#/components/operate-log'; import { useDetailSchema } from '../data'; @@ -21,15 +21,37 @@ const CustomerDetailsInfo = defineAsyncComponent( () => import('./detail-info.vue'), ); +const FollowUp = defineAsyncComponent( + () => import('#/views/crm/followup/index.vue'), +); + +const PermissionList = defineAsyncComponent( + () => import('#/views/crm/permission/modules/permission-list.vue'), +); + +const TransferForm = defineAsyncComponent( + () => import('#/views/crm/permission/modules/transfer-form.vue'), +); + +const OperateLog = defineAsyncComponent( + () => import('#/components/operate-log'), +); + +const CustomerForm = defineAsyncComponent( + () => import('#/views/crm/customer/modules/form.vue'), +); + const loading = ref(false); const route = useRoute(); const router = useRouter(); +const tabs = useTabs(); const customerId = ref(0); const customer = ref({} as CrmCustomerApi.Customer); -const permissionListRef = ref(); // 团队成员列表 Ref +const customerLogList = ref([]); +const permissionListRef = ref>(); // 团队成员列表 Ref const [Description] = useDescription({ componentProps: { @@ -40,91 +62,107 @@ const [Description] = useDescription({ schema: useDetailSchema(), }); +const [FormModal, formModalApi] = useVbenModal({ + connectedComponent: CustomerForm, + destroyOnClose: true, +}); + +const [TransferModal, transferModalApi] = useVbenModal({ + connectedComponent: TransferForm, + destroyOnClose: true, +}); + /** 加载详情 */ async function loadCustomerDetail() { loading.value = true; customerId.value = Number(route.params.id); const data = await getCustomer(customerId.value); - await getOperateLog(); + const logList = await getOperateLogPage({ + bizType: BizTypeEnum.CRM_CUSTOMER, + bizId: customerId.value, + }); + customerLogList.value = logList.list; customer.value = data; loading.value = false; } +/** 返回列表页 */ +function handleBack() { + tabs.closeCurrentTab(); + router.push('/crm/customer'); +} + /** 编辑 */ function handleEdit() { - // formModalApi.setData({ id: clueId }).open(); + formModalApi.setData({ id: customerId.value }).open(); } /** 转移线索 */ function handleTransfer() { - // transferModalApi.setData({ id: clueId }).open(); + transferModalApi.setData({ id: customerId.value }).open(); } /** 锁定客户 */ function handleLock() { - // transferModalApi.setData({ id: clueId }).open(); + transferModalApi.setData({ id: customerId.value }).open(); } /** 解锁客户 */ function handleUnlock() { - // transferModalApi.setData({ id: clueId }).open(); + transferModalApi.setData({ id: customerId.value }).open(); } /** 领取客户 */ function handleReceive() { - // transferModalApi.setData({ id: clueId }).open(); + transferModalApi.setData({ id: customerId.value }).open(); } /** 分配客户 */ function handleDistributeForm() { - // transferModalApi.setData({ id: clueId }).open(); + transferModalApi.setData({ id: customerId.value }).open(); } /** 客户放入公海 */ function handlePutPool() { - // transferModalApi.setData({ id: clueId }).open(); + transferModalApi.setData({ id: customerId.value }).open(); } /** 更新成交状态操作 */ -async function handleUpdateDealStatus() { - const dealStatus = !customer.value.dealStatus; - try { - await Modal.confirm({ - title: '提示', +async function handleUpdateDealStatus(): Promise { + return new Promise((resolve, reject) => { + const dealStatus = !customer.value.dealStatus; + confirm({ content: `确定更新成交状态为【${dealStatus ? '已成交' : '未成交'}】吗?`, - }); - await updateCustomerDealStatus(customerId.value, dealStatus); - Modal.success({ - title: '成功', - content: '更新成交状态成功', - }); - await loadCustomerDetail(); - } catch { - // 用户取消操作 - } -} - -/** 获取操作日志 */ -const logList = ref([]); // 操作日志列表 -async function getOperateLog() { - if (!customerId.value) { - return; - } - const data = await getOperateLogPage({ - bizType: BizTypeEnum.CRM_CUSTOMER, - bizId: customerId.value, + }) + .then(async () => { + const res = await updateCustomerDealStatus( + customerId.value, + dealStatus, + ); + if (res) { + message.success('更新成交状态成功'); + resolve(true); + } else { + reject(new Error('更新成交状态失败')); + } + }) + .catch(() => { + reject(new Error('取消操作')); + }); }); - logList.value = data.list; } // 加载数据 onMounted(async () => { + customerId.value = Number(route.params.id); await loadCustomerDetail(); });