diff --git a/apps/daxpay-admin/src/adapter/component/vxe-table/index.less b/apps/daxpay-admin/src/adapter/component/vxe-table/index.less deleted file mode 100644 index 0c670809e..000000000 --- a/apps/daxpay-admin/src/adapter/component/vxe-table/index.less +++ /dev/null @@ -1,9 +0,0 @@ -/* vxe-table 样式入口文件 */ -/* 统一导入 vxe 相关样式 */ - -/* vxe 基础样式 */ -@import 'vxe-table/lib/style.css'; -@import 'vxe-pc-ui/lib/style.css'; - -/* 项目自定义 vxe 样式 */ -@import './vxe-table.less'; diff --git a/apps/daxpay-admin/src/bootstrap.ts b/apps/daxpay-admin/src/bootstrap.ts index 14e25ae3a..2dc82467e 100644 --- a/apps/daxpay-admin/src/bootstrap.ts +++ b/apps/daxpay-admin/src/bootstrap.ts @@ -14,16 +14,18 @@ import Antd from 'antdv-next'; import VxeUI from 'vxe-pc-ui'; import VxeUITable from 'vxe-table'; -import { setDark } from '#/adapter/component/vxe-table/vxe-table'; +import { setDark } from '@daxpay/ui-biz/adapter/component/vxe-table'; import { $t, setupI18n } from '#/locales'; -import { initComponentAdapter } from './adapter/component'; -import { initSetupVbenForm } from './adapter/form'; +import { initComponentAdapter } from '@daxpay/ui-biz/adapter/component'; +import { initSetupVbenForm } from '@daxpay/ui-biz/adapter/form'; import App from './app.vue'; import { router } from './router'; -// vxe 样式入口 -import '#/adapter/component/vxe-table/index.less'; +// vxe 样式: 基础库样式 + 项目自定义样式 +import 'vxe-pc-ui/lib/style.css'; +import 'vxe-table/lib/style.css'; +import '@daxpay/ui-biz/adapter/component/vxe-table/style'; // 项目公共样式入口 import '#/styles/index.less'; diff --git a/apps/daxpay-merchant/src/adapter/component/index.ts b/apps/daxpay-merchant/src/adapter/component/index.ts deleted file mode 100644 index 982d0512d..000000000 --- a/apps/daxpay-merchant/src/adapter/component/index.ts +++ /dev/null @@ -1,519 +0,0 @@ -/** - * 通用组件共同的使用的基础组件,原先放在 adapter/form 内部,限制了使用范围,这里提取出来,方便其他地方使用 - * 可用于 vben-form、vben-modal、vben-drawer 等组件使用, - */ - -/* eslint-disable vue/one-component-per-file */ - -import type { UploadChangeParam, UploadFile, UploadProps } from 'antdv-next'; - -import type { Component, Ref } from 'vue'; - -import type { BaseFormComponentType } from '@vben/common-ui'; -import type { Recordable } from '@vben/types'; - -import { computed, defineAsyncComponent, defineComponent, h, ref, render, unref, watch } from 'vue'; - -import { ApiComponent, globalShareState, VCropper } from '@vben/common-ui'; -import { IconifyIcon } from '@vben/icons'; -import { $t } from '@vben/locales'; -import { isEmpty } from '@vben/utils'; - -import { Modal } from 'antdv-next'; - -import { IconPicker } from '#/components/icon-picker'; -import { useMessage } from '#/hooks/useMessage'; - -const AutoComplete = defineAsyncComponent(() => import('antdv-next/dist/auto-complete/index')); -const Button = defineAsyncComponent(() => import('antdv-next/dist/button/index')); -const Checkbox = defineAsyncComponent(() => import('antdv-next/dist/checkbox/index')); -const CheckboxGroup = defineAsyncComponent(() => import('antdv-next/dist/checkbox/Group')); -const DatePicker = defineAsyncComponent(() => import('antdv-next/dist/date-picker/index')); -const Divider = defineAsyncComponent(() => import('antdv-next/dist/divider/index')); -const Input = defineAsyncComponent(() => import('antdv-next/dist/input/index')); -const InputNumber = defineAsyncComponent(() => import('antdv-next/dist/input-number/index')); -const InputPassword = defineAsyncComponent(() => - import('antdv-next/dist/input/index').then((res) => res.InputPassword), -); -const Mentions = defineAsyncComponent(() => import('antdv-next/dist/mentions/index')); -const Radio = defineAsyncComponent(() => import('antdv-next/dist/radio/index')); -const RadioGroup = defineAsyncComponent(() => import('antdv-next/dist/radio/index').then((res) => res.RadioGroup)); -const RangePicker = defineAsyncComponent(() => - import('antdv-next/dist/date-picker/index').then((res) => res.DateRangePicker), -); -const Rate = defineAsyncComponent(() => import('antdv-next/dist/rate/index')); -const Select = defineAsyncComponent(() => import('antdv-next/dist/select/index')); -const Space = defineAsyncComponent(() => import('antdv-next/dist/space/index')); -const Switch = defineAsyncComponent(() => import('antdv-next/dist/switch/index')); -const Textarea = defineAsyncComponent(() => import('antdv-next/dist/input/TextArea')); -const TimePicker = defineAsyncComponent(() => import('antdv-next/dist/time-picker/index')); -const TreeSelect = defineAsyncComponent(() => import('antdv-next/dist/tree-select/index')); -const Cascader = defineAsyncComponent(() => import('antdv-next/dist/cascader/index')); -const Upload = defineAsyncComponent(() => import('antdv-next/dist/upload/index')); -const Image = defineAsyncComponent(() => import('antdv-next/dist/image/index')); -const PreviewGroup = defineAsyncComponent(() => - import('antdv-next/dist/image/index').then((res) => res.ImagePreviewGroup), -); - -const withDefaultPlaceholder = ( - component: T, - type: 'input' | 'select', - componentProps: Recordable = {}, -) => { - return defineComponent({ - name: component.name, - inheritAttrs: false, - setup: (props: any, { attrs, expose, slots }) => { - // 占位符 - const placeholder = props?.placeholder || attrs?.placeholder || $t(`ui.placeholder.${type}`); - // 透传组件暴露的方法 - const innerRef = ref(); - expose( - new Proxy( - {}, - { - get: (_target, key) => innerRef.value?.[key], - has: (_target, key) => key in (innerRef.value || {}), - }, - ), - ); - return () => h(component, { ...componentProps, placeholder, ...props, ...attrs, ref: innerRef }, slots); - }, - }); -}; - -const withPreviewUpload = () => { - // 检查是否为图片文件的辅助函数 - const isImageFile = (file: UploadFile): boolean => { - const imageExtensions = new Set(['bmp', 'gif', 'jpeg', 'jpg', 'png', 'svg', 'webp']); - if (file.url) { - try { - const pathname = new URL(file.url, 'http://localhost').pathname; - const ext = pathname.split('.').pop()?.toLowerCase(); - return ext ? imageExtensions.has(ext) : false; - } catch { - const ext = file.url?.split('.').pop()?.toLowerCase(); - return ext ? imageExtensions.has(ext) : false; - } - } - if (!file.type) { - const ext = file.name?.split('.').pop()?.toLowerCase(); - return ext ? imageExtensions.has(ext) : false; - } - return file.type.startsWith('image/'); - }; - // 创建默认的上传按钮插槽 - const createDefaultSlotsWithUpload = (listType: string, placeholder: string) => { - switch (listType) { - case 'picture-card': { - return { - default: () => placeholder, - }; - } - default: { - return { - default: () => - h( - Button, - { - icon: h(IconifyIcon, { - icon: 'ant-design:upload-outlined', - class: 'mb-1 size-4', - }), - }, - () => placeholder, - ), - }; - } - } - }; - // 构建预览图片组 - const previewImage = async (file: UploadFile, visible: Ref, fileList: Ref) => { - // 如果当前文件不是图片,直接打开 - if (!isImageFile(file)) { - if (file.url) { - window.open(file.url, '_blank'); - } else if (file.preview) { - window.open(file.preview, '_blank'); - } else { - // 预览警告 - const { message } = useMessage(); - message.error($t('ui.formRules.previewWarning')); - } - return; - } - - // 对于图片文件,继续使用预览组 - const [ImageComponent, PreviewGroupComponent] = await Promise.all([Image, PreviewGroup]); - - const getBase64 = (file: File) => { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.readAsDataURL(file); - reader.addEventListener('load', () => resolve(reader.result)); - reader.addEventListener('error', (error) => reject(error)); - }); - }; - // 从fileList中过滤出所有图片文件 - const imageFiles = (unref(fileList) || []).filter((element) => isImageFile(element)); - - // 为所有没有预览地址的图片生成预览 - for (const imgFile of imageFiles) { - if (!imgFile.url && !imgFile.preview && imgFile.originFileObj) { - imgFile.preview = (await getBase64(imgFile.originFileObj)) as string; - } - } - const container: HTMLElement | null = document.createElement('div'); - document.body.append(container); - - // 用于追踪组件是否已卸载 - let isUnmounted = false; - - const PreviewWrapper = { - setup() { - return () => { - if (isUnmounted) return null; - return h( - PreviewGroupComponent, - { - class: 'hidden', - preview: { - open: visible.value, - // 设置初始显示的图片索引 - current: imageFiles.findIndex((f) => f.uid === file.uid), - onOpenChange: (value: boolean) => { - visible.value = value; - if (!value) { - // 延迟清理,确保动画完成 - setTimeout(() => { - if (!isUnmounted && container) { - isUnmounted = true; - render(null, container); - container.remove(); - } - }, 300); - } - }, - }, - }, - () => - // 渲染所有图片文件 - imageFiles.map((imgFile) => - h(ImageComponent, { - key: imgFile.uid, - src: imgFile.url || imgFile.preview, - }), - ), - ); - }; - }, - }; - - render(h(PreviewWrapper), container); - }; - - // 图片裁剪操作 - const cropImage = (file: File, aspectRatio: string | undefined) => { - return new Promise((resolve, reject) => { - const container: HTMLElement | null = document.createElement('div'); - document.body.append(container); - - // 用于追踪组件是否已卸载 - let isUnmounted = false; - let objectUrl: null | string = null; - - const open = ref(true); - const cropperRef = ref | null>(null); - - const closeModal = () => { - open.value = false; - // 延迟清理,确保动画完成 - setTimeout(() => { - if (!isUnmounted && container) { - if (objectUrl) { - URL.revokeObjectURL(objectUrl); - } - isUnmounted = true; - render(null, container); - container.remove(); - } - }, 300); - }; - - const CropperWrapper = { - setup() { - return () => { - if (isUnmounted) return null; - if (!objectUrl) { - objectUrl = URL.createObjectURL(file); - } - return h( - Modal, - { - open: open.value, - title: h('div', {}, [ - // 图片裁剪标题 - $t('ui.crop.title'), - h( - 'span', - { - class: `${aspectRatio ? '' : 'hidden'} ml-2 text-sm text-gray-400 font-normal`, - }, - // 图片裁剪标题提示 - $t('ui.crop.titleTip', [aspectRatio]), - ), - ]), - centered: true, - width: 548, - keyboard: false, - maskClosable: false, - closable: false, - // 取消 - cancelText: $t('common.cancel'), - // 确认裁剪 - okText: $t('ui.crop.confirm'), - destroyOnHidden: true, - onOk: async () => { - const cropper = cropperRef.value; - if (!cropper) { - reject(new Error('Cropper not found')); - closeModal(); - return; - } - try { - const dataUrl = await cropper.getCropImage(); - resolve(dataUrl); - } catch { - // 裁剪失败提示 - reject(new Error($t('ui.crop.errorTip'))); - } finally { - closeModal(); - } - }, - onCancel() { - resolve(''); - closeModal(); - }, - }, - () => - h(VCropper, { - ref: (ref: any) => (cropperRef.value = ref), - img: objectUrl as string, - aspectRatio, - }), - ); - }; - }, - }; - - render(h(CropperWrapper), container); - }); - }; - - return defineComponent({ - name: 'AUpload', - emits: ['update:modelValue'], - setup: (props: any, { attrs, slots, emit }: { attrs: any; emit: any; slots: any }) => { - const previewVisible = ref(false); - - // 上传占位符 - const placeholder = attrs?.placeholder || $t(`ui.placeholder.upload`); - - const listType = attrs?.listType || attrs?.['list-type'] || 'text'; - - const fileList = ref(attrs?.fileList || attrs?.['file-list'] || []); - - const maxSize = computed(() => attrs?.maxSize ?? attrs?.['max-size']); - const aspectRatio = computed(() => attrs?.aspectRatio ?? attrs?.['aspect-ratio']); - - const handleBeforeUpload = async (file: UploadFile, originFileList: Array) => { - if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) { - // 文件大小限制提示 - const { message } = useMessage(); - message.error($t('ui.formRules.sizeLimit', [maxSize.value])); - file.status = 'removed'; - return false; - } - // 多选或者非图片不唤起裁剪框 - if (attrs.crop && !attrs.multiple && originFileList[0] && isImageFile(file)) { - file.status = 'removed'; - // antd Upload组件问题 file参数获取的是UploadFile类型对象无法取到File类型 所以通过originFileList[0]获取 - const blob = await cropImage(originFileList[0], aspectRatio.value); - return new Promise((resolve, reject) => { - if (!blob) { - // 裁剪失败提示 - return reject(new Error($t('ui.crop.errorTip'))); - } - resolve(blob); - }); - } - - return attrs.beforeUpload?.(file) ?? true; - }; - - const handleChange = (event: UploadChangeParam) => { - try { - // 行内写法 handleChange: (event) => {} - attrs.handleChange?.(event); - // template写法 @handle-change="(event) => {}" - attrs.onHandleChange?.(event); - } catch (error) { - // Avoid breaking internal v-model sync on user handler errors - console.error(error); - } - fileList.value = event.fileList.filter((file) => file.status !== 'removed'); - emit('update:modelValue', event.fileList?.length ? fileList.value : undefined); - }; - - const handlePreview = async (file: UploadFile) => { - previewVisible.value = true; - await previewImage(file, previewVisible, fileList); - }; - - const renderUploadButton = (): any => { - const isDisabled = attrs.disabled; - - // 如果禁用,不渲染上传按钮 - if (isDisabled) { - return null; - } - - // 否则渲染默认上传按钮 - return isEmpty(slots) ? createDefaultSlotsWithUpload(listType, placeholder) : slots; - }; - - // 可以监听到表单API设置的值 - watch( - () => attrs.modelValue, - (res) => { - fileList.value = res; - }, - ); - - return () => - h( - Upload, - { - ...props, - ...attrs, - fileList: fileList.value, - beforeUpload: handleBeforeUpload, - onChange: handleChange, - onPreview: handlePreview, - }, - renderUploadButton(), - ); - }, - }); -}; - -// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 -export type ComponentType = - | 'ApiCascader' - | 'ApiSelect' - | 'ApiTreeSelect' - | 'AutoComplete' - | 'Cascader' - | 'Checkbox' - | 'CheckboxGroup' - | 'DatePicker' - | 'DefaultButton' - | 'Divider' - | 'IconPicker' - | 'Input' - | 'InputNumber' - | 'InputPassword' - | 'Mentions' - | 'PrimaryButton' - | 'Radio' - | 'RadioGroup' - | 'RangePicker' - | 'Rate' - | 'Select' - | 'Space' - | 'Switch' - | 'Textarea' - | 'TimePicker' - | 'TreeSelect' - | 'Upload' - | BaseFormComponentType; - -async function initComponentAdapter() { - const components: Partial> = { - // 如果你的组件体积比较大,可以使用异步加载 - // Button: () => - // import('xxx').then((res) => res.Button), - - ApiCascader: withDefaultPlaceholder(ApiComponent, 'select', { - component: Cascader, - fieldNames: { label: 'label', value: 'value', children: 'children' }, - loadingSlot: 'suffixIcon', - modelPropName: 'value', - visibleEvent: 'onVisibleChange', - }), - ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', { - component: Select, - loadingSlot: 'suffixIcon', - modelPropName: 'value', - visibleEvent: 'onVisibleChange', - }), - ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', { - component: TreeSelect, - fieldNames: { label: 'label', value: 'value', children: 'children' }, - loadingSlot: 'suffixIcon', - modelPropName: 'value', - optionsPropName: 'treeData', - visibleEvent: 'onVisibleChange', - }), - AutoComplete, - Cascader, - Checkbox, - CheckboxGroup, - DatePicker, - // 自定义默认按钮 - DefaultButton: (props, { attrs, slots }) => { - return h(Button, { ...props, attrs, type: 'default' }, slots); - }, - Divider, - IconPicker: withDefaultPlaceholder(IconPicker, 'select', { - modelValueProp: 'modelValue', - }), - Input: withDefaultPlaceholder(Input, 'input'), - InputNumber: withDefaultPlaceholder(InputNumber, 'input'), - InputPassword: withDefaultPlaceholder(InputPassword, 'input'), - Mentions: withDefaultPlaceholder(Mentions, 'input'), - // 自定义主要按钮 - PrimaryButton: (props, { attrs, slots }) => { - return h(Button, { ...props, attrs, type: 'primary' }, slots); - }, - Radio, - RadioGroup, - RangePicker, - Rate, - Select: withDefaultPlaceholder(Select, 'select'), - Space, - Switch, - Textarea: withDefaultPlaceholder(Textarea, 'input'), - TimePicker, - TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'), - Upload: withPreviewUpload(), - }; - - // 将组件注册到全局共享状态中 - globalShareState.setComponents(components); - - // 定义全局共享状态中的消息提示 - globalShareState.defineMessage({ - // 复制成功消息提示 - copyPreferencesSuccess: (title, content) => { - const { notification } = useMessage(); - notification.success({ - description: content, - title, - placement: 'bottomRight', - }); - }, - }); -} - -export { initComponentAdapter }; diff --git a/apps/daxpay-merchant/src/adapter/component/vxe-table/index.less b/apps/daxpay-merchant/src/adapter/component/vxe-table/index.less deleted file mode 100644 index 0c670809e..000000000 --- a/apps/daxpay-merchant/src/adapter/component/vxe-table/index.less +++ /dev/null @@ -1,9 +0,0 @@ -/* vxe-table 样式入口文件 */ -/* 统一导入 vxe 相关样式 */ - -/* vxe 基础样式 */ -@import 'vxe-table/lib/style.css'; -@import 'vxe-pc-ui/lib/style.css'; - -/* 项目自定义 vxe 样式 */ -@import './vxe-table.less'; diff --git a/apps/daxpay-merchant/src/adapter/component/vxe-table/vxe-table.less b/apps/daxpay-merchant/src/adapter/component/vxe-table/vxe-table.less deleted file mode 100644 index dd56b868e..000000000 --- a/apps/daxpay-merchant/src/adapter/component/vxe-table/vxe-table.less +++ /dev/null @@ -1,20 +0,0 @@ -/* vxe模态框样式 */ -.vxe-modal--wrapper { - /* 层级与保持antdv一致 */ - z-index: 1000 !important; -} -/* vxe表格相关 */ -.vxe-custom--option-wrapper { - /* 需要低于顶栏 */ - z-index: 8 !important; -} -.vxe-table--border-line { - /* 需要低于顶栏 */ - z-index: 8 !important; -} - -/* 工具栏自定义列配置, 优化高度和定位 */ -.vxe-table-custom-wrapper.is--active { - max-height: 500px !important; - top: 0 !important; -} diff --git a/apps/daxpay-merchant/src/adapter/component/vxe-table/vxe-table.ts b/apps/daxpay-merchant/src/adapter/component/vxe-table/vxe-table.ts deleted file mode 100644 index d031ccc6d..000000000 --- a/apps/daxpay-merchant/src/adapter/component/vxe-table/vxe-table.ts +++ /dev/null @@ -1,76 +0,0 @@ -import enUS from 'vxe-pc-ui/lib/language/en-US'; -import idID from 'vxe-pc-ui/lib/language/id-ID'; -import jaJP from 'vxe-pc-ui/lib/language/ja-JP'; -import koKR from 'vxe-pc-ui/lib/language/ko-KR'; -import msMY from 'vxe-pc-ui/lib/language/ms-MY'; -import thTH from 'vxe-pc-ui/lib/language/th-TH'; -import viVN from 'vxe-pc-ui/lib/language/vi-VN'; -import zhCN from 'vxe-pc-ui/lib/language/zh-CN'; -import zhHK from 'vxe-pc-ui/lib/language/zh-HK'; -import zhTW from 'vxe-pc-ui/lib/language/zh-TW'; -import VXETable from 'vxe-table'; -import { VxeUI } from 'vxe-table'; - -// 国际化配置 -// 不知道为什么, 必须添加default之后才能正常使用 -VxeUI.setI18n('en-US', enUS.default); -VxeUI.setI18n('zh-CN', zhCN.default); -VxeUI.setI18n('zh-TW', zhTW.default); -VxeUI.setI18n('zh-HK', zhHK.default); -VxeUI.setI18n('ja-JP', jaJP.default); -VxeUI.setI18n('ko-KR', koKR.default); -VxeUI.setI18n('id-ID', idID.default); -VxeUI.setI18n('vi-VN', viVN.default); -VxeUI.setI18n('th-TH', thTH.default); -VxeUI.setI18n('ms-MY', msMY.default); - -/** - * 是否设置暗黑模式 - * @param dark - */ -export function setDark(dark: boolean) { - if (dark) { - VXETable.setTheme('dark'); - } else { - VXETable.setTheme('light'); - } -} - -/** - * 配置 - */ -VXETable.setConfig({ - // 表格配置 - table: { - border: true, - stripe: true, - round: true, - showOverflow: 'title', - showHeaderOverflow: 'title', - size: 'medium', - tooltipConfig: { - enterable: true, - }, - columnConfig: { - resizable: true, - useKey: true, - isHover: true, - }, - rowConfig: { - isCurrent: true, - isHover: true, - }, - }, - // 工具条配置 - toolbar: { - custom: true, - buttons: [], - tools: [], - size: 'medium', - }, - // 分页配置 - pager: { - border: true, - size: 'medium', - }, -}); diff --git a/apps/daxpay-merchant/src/adapter/form.ts b/apps/daxpay-merchant/src/adapter/form.ts deleted file mode 100644 index ced23aa0a..000000000 --- a/apps/daxpay-merchant/src/adapter/form.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { VbenFormSchema as FormSchema, VbenFormProps } from '@vben/common-ui'; - -import type { ComponentType } from './component'; - -import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; -import { $t } from '@vben/locales'; - -async function initSetupVbenForm() { - setupVbenForm({ - config: { - // ant design vue组件库默认都是 v-model:value - baseModelPropName: 'value', - - // 一些组件是 v-model:checked 或者 v-model:fileList - modelPropNameMap: { - Checkbox: 'checked', - Radio: 'checked', - Switch: 'checked', - Upload: 'fileList', - }, - }, - defineRules: { - // 输入项目必填国际化适配 - required: (value, _params, ctx) => { - if (value === undefined || value === null || value.length === 0) { - return $t('ui.formRules.required', [ctx.label]); - } - return true; - }, - // 选择项目必填国际化适配 - selectRequired: (value, _params, ctx) => { - if (value === undefined || value === null) { - return $t('ui.formRules.selectRequired', [ctx.label]); - } - return true; - }, - }, - }); -} - -const useVbenForm = useForm; - -export { initSetupVbenForm, useVbenForm, z }; - -export type VbenFormSchema = FormSchema; -export type { VbenFormProps }; diff --git a/apps/daxpay-merchant/src/bootstrap.ts b/apps/daxpay-merchant/src/bootstrap.ts index 14e25ae3a..2dc82467e 100644 --- a/apps/daxpay-merchant/src/bootstrap.ts +++ b/apps/daxpay-merchant/src/bootstrap.ts @@ -14,16 +14,18 @@ import Antd from 'antdv-next'; import VxeUI from 'vxe-pc-ui'; import VxeUITable from 'vxe-table'; -import { setDark } from '#/adapter/component/vxe-table/vxe-table'; +import { setDark } from '@daxpay/ui-biz/adapter/component/vxe-table'; import { $t, setupI18n } from '#/locales'; -import { initComponentAdapter } from './adapter/component'; -import { initSetupVbenForm } from './adapter/form'; +import { initComponentAdapter } from '@daxpay/ui-biz/adapter/component'; +import { initSetupVbenForm } from '@daxpay/ui-biz/adapter/form'; import App from './app.vue'; import { router } from './router'; -// vxe 样式入口 -import '#/adapter/component/vxe-table/index.less'; +// vxe 样式: 基础库样式 + 项目自定义样式 +import 'vxe-pc-ui/lib/style.css'; +import 'vxe-table/lib/style.css'; +import '@daxpay/ui-biz/adapter/component/vxe-table/style'; // 项目公共样式入口 import '#/styles/index.less'; diff --git a/packages/business/ui-biz/package.json b/packages/business/ui-biz/package.json index ddb1943c8..63e9ed63e 100644 --- a/packages/business/ui-biz/package.json +++ b/packages/business/ui-biz/package.json @@ -5,6 +5,7 @@ "type": "module", "sideEffects": [ "**/*.css", + "**/*.less", "**/*.vue", "**/*.svg" ], @@ -29,6 +30,21 @@ "types": "./src/request/index.ts", "default": "./src/request/index.ts" }, + "./adapter/component": { + "types": "./src/adapter/component/index.ts", + "default": "./src/adapter/component/index.ts" + }, + "./adapter/form": { + "types": "./src/adapter/form.ts", + "default": "./src/adapter/form.ts" + }, + "./adapter/component/vxe-table": { + "types": "./src/adapter/component/vxe-table/vxe-table.ts", + "default": "./src/adapter/component/vxe-table/vxe-table.ts" + }, + "./adapter/component/vxe-table/style": { + "default": "./src/adapter/component/vxe-table/index.less" + }, "./enums/clientCode": { "types": "./src/enums/clientCode.ts", "default": "./src/enums/clientCode.ts" @@ -181,19 +197,23 @@ "dependencies": { "@vben-core/icons": "workspace:*", "@vben/access": "workspace:*", + "@vben/common-ui": "workspace:*", "@vben/hooks": "workspace:*", "@vben/icons": "workspace:*", "@vben/locales": "workspace:*", "@vben/preferences": "workspace:*", "@vben/request": "workspace:*", "@vben/stores": "workspace:*", + "@vben/types": "workspace:*", "@vben/utils": "workspace:*", "@vueuse/core": "catalog:", "@types/qrcode": "catalog:", "antdv-next": "catalog:", "qrcode": "catalog:", "vue": "catalog:", - "vue-router": "catalog:" + "vue-router": "catalog:", + "vxe-pc-ui": "catalog:", + "vxe-table": "catalog:" }, "devDependencies": { "axios": "catalog:" diff --git a/apps/daxpay-admin/src/adapter/component/index.ts b/packages/business/ui-biz/src/adapter/component/index.ts similarity index 99% rename from apps/daxpay-admin/src/adapter/component/index.ts rename to packages/business/ui-biz/src/adapter/component/index.ts index 982d0512d..e010b32bb 100644 --- a/apps/daxpay-admin/src/adapter/component/index.ts +++ b/packages/business/ui-biz/src/adapter/component/index.ts @@ -21,8 +21,8 @@ import { isEmpty } from '@vben/utils'; import { Modal } from 'antdv-next'; -import { IconPicker } from '#/components/icon-picker'; -import { useMessage } from '#/hooks/useMessage'; +import { IconPicker } from '../../components/icon-picker'; +import { useMessage } from '../../hooks/useMessage'; const AutoComplete = defineAsyncComponent(() => import('antdv-next/dist/auto-complete/index')); const Button = defineAsyncComponent(() => import('antdv-next/dist/button/index')); diff --git a/packages/business/ui-biz/src/adapter/component/vxe-table/index.less b/packages/business/ui-biz/src/adapter/component/vxe-table/index.less new file mode 100644 index 000000000..da1439bf4 --- /dev/null +++ b/packages/business/ui-biz/src/adapter/component/vxe-table/index.less @@ -0,0 +1,5 @@ +/* vxe-table 项目自定义样式 */ +/* vxe 基础库样式(vxe-table / vxe-pc-ui)由各 app 的 bootstrap.ts 通过 JS import 引入, */ +/* 避免包内 less @import node_modules 的 .css 在 postcss 阶段解析失败 */ + +@import './vxe-table.less'; diff --git a/apps/daxpay-admin/src/adapter/component/vxe-table/vxe-table.less b/packages/business/ui-biz/src/adapter/component/vxe-table/vxe-table.less similarity index 100% rename from apps/daxpay-admin/src/adapter/component/vxe-table/vxe-table.less rename to packages/business/ui-biz/src/adapter/component/vxe-table/vxe-table.less diff --git a/apps/daxpay-admin/src/adapter/component/vxe-table/vxe-table.ts b/packages/business/ui-biz/src/adapter/component/vxe-table/vxe-table.ts similarity index 100% rename from apps/daxpay-admin/src/adapter/component/vxe-table/vxe-table.ts rename to packages/business/ui-biz/src/adapter/component/vxe-table/vxe-table.ts diff --git a/apps/daxpay-admin/src/adapter/form.ts b/packages/business/ui-biz/src/adapter/form.ts similarity index 100% rename from apps/daxpay-admin/src/adapter/form.ts rename to packages/business/ui-biz/src/adapter/form.ts diff --git a/packages/business/ui-biz/src/components/AntdAppProvider.vue b/packages/business/ui-biz/src/components/AntdAppProvider.vue index 72422edf3..b3784f201 100644 --- a/packages/business/ui-biz/src/components/AntdAppProvider.vue +++ b/packages/business/ui-biz/src/components/AntdAppProvider.vue @@ -1,8 +1,8 @@ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f6f112e9b..a62fdfb98 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1293,6 +1293,9 @@ importers: '@vben/access': specifier: workspace:* version: link:../../effects/access + '@vben/common-ui': + specifier: workspace:* + version: link:../../effects/common-ui '@vben/hooks': specifier: workspace:* version: link:../../effects/hooks @@ -1311,6 +1314,9 @@ importers: '@vben/stores': specifier: workspace:* version: link:../../stores + '@vben/types': + specifier: workspace:* + version: link:../../types '@vben/utils': specifier: workspace:* version: link:../../utils @@ -1329,6 +1335,12 @@ importers: vue-router: specifier: 'catalog:' version: 5.1.0(@vue/compiler-sfc@3.5.38)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.38(typescript@5.9.3)))(vite@8.1.3(@types/node@26.0.0)(esbuild@0.28.1)(jiti@2.7.0)(less@4.6.6)(sass-embedded@1.100.0)(sass@1.101.0)(terser@5.48.0)(yaml@2.9.0))(vue@3.5.38(typescript@5.9.3)) + vxe-pc-ui: + specifier: 'catalog:' + version: 4.15.7(vue@3.5.38(typescript@5.9.3)) + vxe-table: + specifier: 'catalog:' + version: 4.19.17(vue@3.5.38(typescript@5.9.3)) devDependencies: axios: specifier: 'catalog:'