From 3547c53f890c85982b0066380262af8a999af69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=90=A6?= Date: Mon, 10 Aug 2026 17:56:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=201.=20=E6=9B=B4=E6=96=B0=E6=A1=86?= =?UTF-8?q?=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-antd/package.json | 11 +- apps/web-antd/src/adapter/component/index.ts | 73 +- apps/web-antd/src/layouts/basic.vue | 2 +- .../components/CompareTrendChart.vue | 84 +- .../components/InputCountTrendChart.vue | 87 +- apps/web-antd/vite.config.ts | 6 + pnpm-lock.yaml | 8158 +++++++++-------- 7 files changed, 4436 insertions(+), 3985 deletions(-) diff --git a/apps/web-antd/package.json b/apps/web-antd/package.json index 4a011332..1e518e99 100644 --- a/apps/web-antd/package.json +++ b/apps/web-antd/package.json @@ -53,6 +53,15 @@ "xlsx": "^0.18.5" }, "devDependencies": { - "@types/sortablejs": "catalog:" + "@types/sortablejs": "catalog:", + "@fortawesome/fontawesome-free": "^6.7.2", + "@vueup/vue-quill": "^1.2.0", + "axios": "^1.10.0", + "html2canvas": "^1.4.1", + "js-base64": "^3.7.7", + "lodash-es": "^4.17.21", + "lucide-vue-next": "^0.487.0", + "md-editor-v3": "^5.4.5", + "xgplayer": "^3.0.24" } } diff --git a/apps/web-antd/src/adapter/component/index.ts b/apps/web-antd/src/adapter/component/index.ts index 8206814e..add1f8d0 100644 --- a/apps/web-antd/src/adapter/component/index.ts +++ b/apps/web-antd/src/adapter/component/index.ts @@ -3,38 +3,9 @@ * 可用于 vben-form、vben-modal、vben-drawer 等组件使用, */ +/* eslint-disable vue/one-component-per-file */ -// import type { Component, SetupContext } from 'vue'; -import { h } from 'vue'; - -import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui'; -import { $t } from '@vben/locales'; - -import { - AutoComplete, - Button, - Cascader, - Checkbox, - CheckboxGroup, - DatePicker, - Divider, - Input, - InputNumber, - InputPassword, - Mentions, - notification, - Radio, - RadioGroup, - RangePicker, - Rate, - Select, - Space, - Switch, - Textarea, - TimePicker, - TreeSelect, - Upload, - +import type { AutoCompleteProps, ButtonProps, CascaderProps, @@ -60,7 +31,7 @@ import { } from 'ant-design-vue'; import type { RangePickerProps } from 'ant-design-vue/es/date-picker'; -import type { Component, Ref, SetupContext } from 'vue'; +import type { Component, Ref } from 'vue'; import type { ApiComponentSharedProps, @@ -84,8 +55,6 @@ import { watch, } from 'vue'; -import { registerComponent } from '#/components/form/component-map'; - import { ApiComponent, globalShareState, @@ -109,6 +78,13 @@ type AdapterUploadProps = UploadProps & { onHandleChange?: (event: UploadChangeParam) => void; }; +// ============================================================ +// 所有 antd 组件统一用 defineAsyncComponent 异步加载 +// ⚠️ 不要再从 'ant-design-vue' 同步 import 这些组件! +// 否则会和下面的 const 声明冲突,导致 +// "Identifier 'Xxx' has already been declared" +// ============================================================ + const AutoComplete = defineAsyncComponent( () => import('ant-design-vue/es/auto-complete'), ); @@ -162,13 +138,17 @@ const PreviewGroup = defineAsyncComponent(() => import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup), ); +// ============================================================ +// withDefaultPlaceholder:给组件注入 i18n placeholder + ref 透传 +// ============================================================ + const withDefaultPlaceholder = ( component: Component, type: 'input' | 'select', componentProps: Recordable = {}, ) => { return defineComponent({ - name: component.name, + name: (component as any).name, inheritAttrs: false, setup: (props: any, { attrs, expose, slots }) => { const placeholder = @@ -351,7 +331,7 @@ function cropImage(file: File, aspectRatio: string | undefined) { let isUnmounted = false; let objectUrl: null | string = null; - const open = ref(true); + const open = ref(true); const cropperRef = ref | null>(null); const closeModal = () => { @@ -425,7 +405,7 @@ function cropImage(file: File, aspectRatio: string | undefined) { }, () => h(VCropper, { - ref: (ref: any) => (cropperRef.value = ref), + ref: (refValue: any) => (cropperRef.value = refValue), img: objectUrl as string, aspectRatio, }), @@ -443,7 +423,7 @@ function cropImage(file: File, aspectRatio: string | undefined) { */ const withPreviewUpload = () => { return defineComponent({ - name: Upload.name, + name: 'Upload', emits: ['update:modelValue'], setup( props: any, @@ -535,7 +515,7 @@ const withPreviewUpload = () => { [data-upload-id="${uploadId}"] .ant-upload-list-item { cursor: move; } [data-upload-id="${uploadId}"] .ant-upload-list-item:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.15); } `; - document.head.append(style); + document.head?.append(style); } } @@ -552,7 +532,7 @@ const withPreviewUpload = () => { const container = document.querySelector( `[data-upload-id="${uploadId}"] .ant-upload-list`, - ) as HTMLElement; + ) as HTMLElement | null; if (!container) { if (retryCount < 5) { @@ -567,7 +547,7 @@ const withPreviewUpload = () => { delayOnTouchOnly: true, filter: '.ant-upload-select, .ant-upload-list-item-error, .ant-upload-list-item-uploading', - onEnd: (evt) => { + onEnd: (evt: { oldIndex?: number; newIndex?: number }) => { const { oldIndex, newIndex } = evt; if ( oldIndex === undefined || @@ -640,7 +620,6 @@ export type ComponentType = | 'DatePicker' | 'DefaultButton' | 'Divider' - | 'GalleryPickLink' // OA 场景表单的图片/文件素材选择(透传 acceptTypes 过滤类型) | 'IconPicker' | 'Input' | 'InputNumber' @@ -658,10 +637,6 @@ export type ComponentType = | 'TimePicker' | 'TreeSelect' | 'Upload' - | 'UploadImage' - | 'UploadImageSortable' - | 'UploadOssFile' - | 'UploadDraggerPaste' | BaseFormComponentType; /** @@ -730,7 +705,7 @@ async function initComponentAdapter() { CheckboxGroup, DatePicker, // 自定义默认按钮 - DefaultButton: (props, { attrs, slots }) => { + DefaultButton: (props: any, { attrs, slots }: any) => { return h(Button, { ...props, attrs, type: 'default' }, slots); }, Divider, @@ -746,7 +721,7 @@ async function initComponentAdapter() { InputPassword: withDefaultPlaceholder(InputPassword, 'input'), Mentions: withDefaultPlaceholder(Mentions, 'input'), // 自定义主要按钮 - PrimaryButton: (props, { attrs, slots }) => { + PrimaryButton: (props: any, { attrs, slots }: any) => { return h(Button, { ...props, attrs, type: 'primary' }, slots); }, Radio, @@ -762,8 +737,6 @@ async function initComponentAdapter() { Upload: withPreviewUpload(), }; - // 自动注册自定义组件 - registerComponent(components); // 将组件注册到全局共享状态中 globalShareState.setComponents(components); diff --git a/apps/web-antd/src/layouts/basic.vue b/apps/web-antd/src/layouts/basic.vue index 581d4e1c..9e688b71 100644 --- a/apps/web-antd/src/layouts/basic.vue +++ b/apps/web-antd/src/layouts/basic.vue @@ -2,7 +2,6 @@ import type { NotificationItem } from '@vben/layouts'; import {computed, onUnmounted, ref, watch} from 'vue'; -import { useRouter } from 'vue-router'; import { AuthenticationLoginExpiredModal } from '@vben/common-ui'; @@ -38,6 +37,7 @@ import { useRouter } from 'vue-router'; import {getNoticeListApi, readAllApi} from "#/views/notice/api"; import {formatTimeToRelative} from "#/util/tool"; import {notification} from "ant-design-vue"; +import { $t } from "@vben/locales"; const router = useRouter(); const switchAccountModalRef = ref>(); diff --git a/apps/web-antd/src/views/system/salesperson-dashboard/components/CompareTrendChart.vue b/apps/web-antd/src/views/system/salesperson-dashboard/components/CompareTrendChart.vue index 3ea72bb1..15d3f626 100644 --- a/apps/web-antd/src/views/system/salesperson-dashboard/components/CompareTrendChart.vue +++ b/apps/web-antd/src/views/system/salesperson-dashboard/components/CompareTrendChart.vue @@ -1,83 +1 @@ - - - - - + \ No newline at end of file diff --git a/apps/web-antd/src/views/system/salesperson-dashboard/components/InputCountTrendChart.vue b/apps/web-antd/src/views/system/salesperson-dashboard/components/InputCountTrendChart.vue index e449fb68..a5b06e12 100644 --- a/apps/web-antd/src/views/system/salesperson-dashboard/components/InputCountTrendChart.vue +++ b/apps/web-antd/src/views/system/salesperson-dashboard/components/InputCountTrendChart.vue @@ -1,86 +1 @@ - - - - - +