diff --git a/apps/web-antd/src/adapter/vxe-table.ts b/apps/web-antd/src/adapter/vxe-table.ts index e0524886c..7e71fd5ff 100644 --- a/apps/web-antd/src/adapter/vxe-table.ts +++ b/apps/web-antd/src/adapter/vxe-table.ts @@ -1,3 +1,4 @@ +import type { VxeTableGridOptions } from '@vben/plugins/vxe-table'; import type { Recordable } from '@vben/types'; import { h } from 'vue'; @@ -63,7 +64,7 @@ setupVbenVxeTable({ round: true, showOverflow: true, size: 'small', - }, + } as VxeTableGridOptions, }); // 表格配置项可以用 cellRender: { name: 'CellImage' }, diff --git a/apps/web-antd/src/api/mall/trade/delivery/pickUpStore/index.ts b/apps/web-antd/src/api/mall/trade/delivery/pickUpStore/index.ts index 3cce03875..fe1d9d395 100644 --- a/apps/web-antd/src/api/mall/trade/delivery/pickUpStore/index.ts +++ b/apps/web-antd/src/api/mall/trade/delivery/pickUpStore/index.ts @@ -35,6 +35,9 @@ export namespace MallDeliveryPickUpStoreApi { /** 绑定自提店员请求 */ export interface BindStaffRequest { + id?: number; + /** 门店名称 */ + name: string; /** 门店编号 */ storeId: number; /** 用户编号列表 */ diff --git a/apps/web-antd/src/api/mall/trade/order/index.ts b/apps/web-antd/src/api/mall/trade/order/index.ts index cde8a71c0..6017fa5f5 100644 --- a/apps/web-antd/src/api/mall/trade/order/index.ts +++ b/apps/web-antd/src/api/mall/trade/order/index.ts @@ -176,13 +176,13 @@ export namespace MallOrderApi { /** 交易订单统计 */ export interface OrderSummary { /** 订单数量 */ - orderCount?: number; + orderCount: number; /** 订单金额 */ - orderPayPrice?: string; + orderPayPrice: number; /** 退款单数 */ - afterSaleCount?: number; + afterSaleCount: number; /** 退款金额 */ - afterSalePrice?: string; + afterSalePrice: number; } /** 订单发货请求 */ diff --git a/apps/web-antd/src/components/summary-card/index.ts b/apps/web-antd/src/components/summary-card/index.ts new file mode 100644 index 000000000..598d73d61 --- /dev/null +++ b/apps/web-antd/src/components/summary-card/index.ts @@ -0,0 +1,2 @@ +export { default as SummaryCard } from './summary-card.vue'; +export type { SummaryCardProps } from './typing'; diff --git a/apps/web-antd/src/components/summary-card/summary-card.vue b/apps/web-antd/src/components/summary-card/summary-card.vue new file mode 100644 index 000000000..6778a9c40 --- /dev/null +++ b/apps/web-antd/src/components/summary-card/summary-card.vue @@ -0,0 +1,52 @@ + + diff --git a/apps/web-antd/src/components/summary-card/typing.ts b/apps/web-antd/src/components/summary-card/typing.ts new file mode 100644 index 000000000..0ef1fdc6f --- /dev/null +++ b/apps/web-antd/src/components/summary-card/typing.ts @@ -0,0 +1,11 @@ +export interface SummaryCardProps { + title: string; + tooltip?: string; + icon?: string; + iconColor?: string; + iconBgColor?: string; + prefix?: string; + value?: number; + decimals?: number; + percent?: number | string; +} diff --git a/apps/web-antd/src/views/crm/customer/limitConfig/data.ts b/apps/web-antd/src/views/crm/customer/limitConfig/data.ts index 0895e1d21..a9966635d 100644 --- a/apps/web-antd/src/views/crm/customer/limitConfig/data.ts +++ b/apps/web-antd/src/views/crm/customer/limitConfig/data.ts @@ -30,7 +30,7 @@ export function useFormSchema(confType: LimitConfType): VbenFormSchema[] { label: 'nickname', value: 'id', }, - multiple: true, + mode: 'tags', allowClear: true, }, rules: 'required', diff --git a/apps/web-antd/src/views/mall/trade/delivery/pickUpOrder/data.ts b/apps/web-antd/src/views/mall/trade/delivery/pickUpOrder/data.ts new file mode 100644 index 000000000..1c56a70ff --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/delivery/pickUpOrder/data.ts @@ -0,0 +1,126 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeGridPropTypes } from '#/adapter/vxe-table'; +import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore'; + +import { ref } from 'vue'; + +import { getSimpleDeliveryPickUpStoreList } from '#/api/mall/trade/delivery/pickUpStore'; +import { + DeliveryTypeEnum, + DICT_TYPE, + getRangePickerDefaultProps, +} from '#/utils'; + +const pickUpStoreList = ref([]); + +getSimpleDeliveryPickUpStoreList().then((res) => { + pickUpStoreList.value = res; +}); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + { + fieldName: 'pickUpStoreId', + label: '自提门店', + component: 'ApiSelect', + componentProps: { + api: getSimpleDeliveryPickUpStoreList, + fieldNames: { + label: 'name', + value: 'id', + }, + }, + dependencies: { + triggerFields: ['deliveryType'], + show: (values) => values.deliveryType === DeliveryTypeEnum.PICK_UP.type, + }, + }, + ]; +} + +/** 表格列配置 */ +export function useGridColumns(): VxeGridPropTypes.Columns { + return [ + { + field: 'no', + title: '订单号', + fixed: 'left', + minWidth: 180, + }, + { + field: 'user.nickname', + title: '用户信息', + minWidth: 100, + }, + { + field: 'brokerageUser.nickname', + title: '推荐人信息', + minWidth: 100, + }, + { + field: 'spuName', + title: '商品信息', + minWidth: 100, + formatter: ({ row }) => { + if (row.items.length > 1) { + return row.items.map((item: any) => item.spuName).join(','); + } + }, + }, + { + field: 'payPrice', + title: '实付金额(元)', + formatter: 'formatAmount2', + minWidth: 180, + }, + { + field: 'storeStaffName', + title: '核销员', + minWidth: 160, + }, + { + field: 'pickUpStoreId', + title: '核销门店', + minWidth: 160, + formatter: ({ row }) => { + return pickUpStoreList.value.find( + (item) => item.id === row.pickUpStoreId, + )?.name; + }, + }, + { + field: 'payStatus', + title: '支付状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + minWidth: 80, + }, + { + field: 'status', + title: '订单状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.TRADE_ORDER_STATUS }, + }, + minWidth: 80, + }, + { + field: 'createTime', + title: '下单时间', + formatter: 'formatDateTime', + minWidth: 160, + }, + ]; +} diff --git a/apps/web-antd/src/views/mall/trade/delivery/pickUpOrder/index.vue b/apps/web-antd/src/views/mall/trade/delivery/pickUpOrder/index.vue index 2e1a8ea51..2f003f25e 100644 --- a/apps/web-antd/src/views/mall/trade/delivery/pickUpOrder/index.vue +++ b/apps/web-antd/src/views/mall/trade/delivery/pickUpOrder/index.vue @@ -1,38 +1,106 @@ diff --git a/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/data.ts b/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/data.ts new file mode 100644 index 000000000..65d1f0fb9 --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/data.ts @@ -0,0 +1,248 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { z } from '#/adapter/form'; +import { getAreaTree } from '#/api/system/area'; +import { getSimpleUserList } from '#/api/system/user'; +import { + CommonStatusEnum, + DICT_TYPE, + getDictOptions, + getRangePickerDefaultProps, +} from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'ImageUpload', + fieldName: 'logo', + label: '门店logo', + componentProps: { + maxSize: 1, + }, + rules: 'required', + }, + { + component: 'Input', + fieldName: 'name', + label: '门店名称', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'phone', + label: '门店手机', + rules: 'mobileRequired', + }, + { + component: 'Textarea', + fieldName: 'introduction', + label: '门店简介', + }, + { + fieldName: 'areaId', + label: '地址', + component: 'ApiTreeSelect', + componentProps: { + api: () => getAreaTree(), + fieldNames: { label: 'name', value: 'id', children: 'children' }, + }, + }, + { + component: 'Input', + fieldName: 'detailAddress', + label: '详细地址', + rules: 'required', + }, + { + component: 'TimePicker', + fieldName: 'openingTime', + label: '营业开始时间', + rules: 'required', + }, + { + component: 'TimePicker', + fieldName: 'closingTime', + label: '营业结束时间', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'longitude', + label: '经度', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'latitude', + label: '纬度', + rules: 'required', + }, + { + component: 'Input', + fieldName: 'getGeo', + label: '获取经纬度', + }, + { + fieldName: 'status', + label: '门店状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + buttonStyle: 'solid', + optionType: 'button', + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 绑定店员的表单 */ +export function useBindFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '门店名称', + dependencies: { + triggerFields: ['id'], + disabled: () => true, + }, + }, + { + component: 'ApiSelect', + fieldName: 'verifyUserIds', + label: '门店店员', + rules: 'required', + componentProps: { + api: () => getSimpleUserList(), + fieldNames: { label: 'nickname', value: 'id' }, + mode: 'tags', + allowClear: true, + }, + }, + { + component: 'Select', + fieldName: 'verifyUsers', + label: '店员列表', + rules: 'required', + componentProps: { + options: [], + mode: 'tags', + }, + dependencies: { + triggerFields: ['verifyUserIds'], + trigger(values, form) { + form.setFieldValue('verifyUsers', values.verifyUserIds); + }, + disabled: () => true, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'phone', + label: '门店手机', + component: 'Input', + }, + { + fieldName: 'name', + label: '门店名称', + component: 'Input', + }, + { + fieldName: 'status', + label: '门店状态', + component: 'Select', + componentProps: { + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + }, + { + field: 'logo', + title: '门店logo', + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'name', + title: '门店名称', + }, + { + field: 'phone', + title: '门店手机', + }, + { + field: 'detailAddress', + title: '地址', + }, + { + field: 'openingTime', + title: '营业时间', + formatter: ({ row }) => { + return `${row.openingTime} ~ ${row.closingTime}`; + }, + }, + { + field: 'status', + title: '开启状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/index.vue b/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/index.vue index de4700a85..0fec6490a 100644 --- a/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/index.vue +++ b/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/index.vue @@ -1,34 +1,149 @@ diff --git a/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/bind-form.vue b/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/bind-form.vue new file mode 100644 index 000000000..8b16fbda2 --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/bind-form.vue @@ -0,0 +1,87 @@ + + + diff --git a/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/form.vue b/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/form.vue new file mode 100644 index 000000000..f240a2626 --- /dev/null +++ b/apps/web-antd/src/views/mall/trade/delivery/pickUpStore/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-antd/src/views/system/role/modules/assign-data-permission-form.vue b/apps/web-antd/src/views/system/role/modules/assign-data-permission-form.vue index 2ac46dbd7..2d160ea25 100644 --- a/apps/web-antd/src/views/system/role/modules/assign-data-permission-form.vue +++ b/apps/web-antd/src/views/system/role/modules/assign-data-permission-form.vue @@ -135,12 +135,12 @@ function getAllNodeIds(nodes: any[], ids: number[] = []): number[] {
diff --git a/apps/web-ele/src/adapter/vxe-table.ts b/apps/web-ele/src/adapter/vxe-table.ts index 5f66c94e3..d160c3c9b 100644 --- a/apps/web-ele/src/adapter/vxe-table.ts +++ b/apps/web-ele/src/adapter/vxe-table.ts @@ -1,3 +1,4 @@ +import type { VxeTableGridOptions } from '@vben/plugins/vxe-table'; import type { Recordable } from '@vben/types'; import { h } from 'vue'; @@ -63,7 +64,7 @@ setupVbenVxeTable({ round: true, showOverflow: true, size: 'small', - }, + } as VxeTableGridOptions, }); // 表格配置项可以用 cellRender: { name: 'CellImage' }, diff --git a/apps/web-naive/src/adapter/vxe-table.ts b/apps/web-naive/src/adapter/vxe-table.ts index 1b25a0e1d..175854332 100644 --- a/apps/web-naive/src/adapter/vxe-table.ts +++ b/apps/web-naive/src/adapter/vxe-table.ts @@ -1,3 +1,4 @@ +import type { VxeTableGridOptions } from '@vben/plugins/vxe-table'; import type { Recordable } from '@vben/types'; import { h } from 'vue'; @@ -57,7 +58,7 @@ setupVbenVxeTable({ round: true, showOverflow: true, size: 'small', - }, + } as VxeTableGridOptions, }); // 表格配置项可以用 cellRender: { name: 'CellImage' }, 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 fd87396eb..4172d82b1 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 @@ -122,6 +122,7 @@ async function onBtnClick(value: ValueType) { v-bind="btnDefaultProps" :variant="innerValue.includes(btn.value) ? 'default' : 'outline'" @click="onBtnClick(btn.value)" + type="button" >
number) | number; + /** 鼠标离开延迟时间 */ + leaveDelay?: (() => number) | number; +} + +const DEFAULT_LEAVE_DELAY = 500; // 鼠标离开延迟时间,默认为 500ms +const DEFAULT_ENTER_DELAY = 0; // 鼠标进入延迟时间,默认为 0(立即响应) + /** * 监测鼠标是否在元素内部,如果在元素内部则返回 true,否则返回 false * @param refElement 所有需要检测的元素。如果提供了一个数组,那么鼠标在任何一个元素内部都会返回 true - * @param delay 延迟更新状态的时间 + * @param delay 延迟更新状态的时间,可以是数字或包含进入/离开延迟的配置对象 * @returns 返回一个数组,第一个元素是一个 ref,表示鼠标是否在元素内部,第二个元素是一个控制器,可以通过 enable 和 disable 方法来控制监听器的启用和禁用 */ export function useHoverToggle( refElement: Arrayable, - delay: (() => number) | number = 500, + delay: (() => number) | HoverDelayOptions | number = DEFAULT_LEAVE_DELAY, ) { + // 兼容旧版本API + const normalizedOptions: HoverDelayOptions = + typeof delay === 'number' || isFunction(delay) + ? { enterDelay: DEFAULT_ENTER_DELAY, leaveDelay: delay } + : { + enterDelay: DEFAULT_ENTER_DELAY, + leaveDelay: DEFAULT_LEAVE_DELAY, + ...delay, + }; + const isHovers: Array> = []; const value = ref(false); - const timer = ref | undefined>(); + const enterTimer = ref | undefined>(); + const leaveTimer = ref | undefined>(); const refs = Array.isArray(refElement) ? refElement : [refElement]; refs.forEach((refEle) => { const eleRef = computed(() => { @@ -32,15 +53,47 @@ export function useHoverToggle( }); const isOutsideAll = computed(() => isHovers.every((v) => !v.value)); + function clearTimers() { + if (enterTimer.value) { + clearTimeout(enterTimer.value); + enterTimer.value = undefined; + } + if (leaveTimer.value) { + clearTimeout(leaveTimer.value); + leaveTimer.value = undefined; + } + } + function setValueDelay(val: boolean) { - timer.value && clearTimeout(timer.value); - timer.value = setTimeout( - () => { - value.value = val; - timer.value = undefined; - }, - isFunction(delay) ? delay() : delay, - ); + clearTimers(); + + if (val) { + // 鼠标进入 + const enterDelay = normalizedOptions.enterDelay ?? DEFAULT_ENTER_DELAY; + const delayTime = isFunction(enterDelay) ? enterDelay() : enterDelay; + + if (delayTime <= 0) { + value.value = true; + } else { + enterTimer.value = setTimeout(() => { + value.value = true; + enterTimer.value = undefined; + }, delayTime); + } + } else { + // 鼠标离开 + const leaveDelay = normalizedOptions.leaveDelay ?? DEFAULT_LEAVE_DELAY; + const delayTime = isFunction(leaveDelay) ? leaveDelay() : leaveDelay; + + if (delayTime <= 0) { + value.value = false; + } else { + leaveTimer.value = setTimeout(() => { + value.value = false; + leaveTimer.value = undefined; + }, delayTime); + } + } } const watcher = watch( @@ -61,7 +114,7 @@ export function useHoverToggle( }; onUnmounted(() => { - timer.value && clearTimeout(timer.value); + clearTimers(); }); return [value, controller] as [typeof value, typeof controller]; diff --git a/packages/effects/plugins/src/vxe-table/api.ts b/packages/effects/plugins/src/vxe-table/api.ts index 50879b674..2b60d602e 100644 --- a/packages/effects/plugins/src/vxe-table/api.ts +++ b/packages/effects/plugins/src/vxe-table/api.ts @@ -26,14 +26,14 @@ function getDefaultState(): VxeGridProps { }; } -export class VxeGridApi { +export class VxeGridApi = any> { public formApi = {} as ExtendedFormApi; // private prevState: null | VxeGridProps = null; - public grid = {} as VxeGridInstance; - public state: null | VxeGridProps = null; + public grid = {} as VxeGridInstance; + public state: null | VxeGridProps = null; - public store: Store; + public store: Store>; private isMounted = false; @@ -99,8 +99,8 @@ export class VxeGridApi { setState( stateOrFn: - | ((prev: VxeGridProps) => Partial) - | Partial, + | ((prev: VxeGridProps) => Partial>) + | Partial>, ) { if (isFunction(stateOrFn)) { this.store.setState((prev) => { diff --git a/packages/effects/plugins/src/vxe-table/types.ts b/packages/effects/plugins/src/vxe-table/types.ts index da8a014c0..8b9aea47d 100644 --- a/packages/effects/plugins/src/vxe-table/types.ts +++ b/packages/effects/plugins/src/vxe-table/types.ts @@ -9,7 +9,7 @@ import type { Ref } from 'vue'; import type { ClassType, DeepPartial } from '@vben/types'; -import type { VbenFormProps } from '@vben-core/form-ui'; +import type { BaseFormComponentType, VbenFormProps } from '@vben-core/form-ui'; import type { VxeGridApi } from './api'; @@ -35,7 +35,11 @@ export interface SeparatorOptions { show?: boolean; backgroundColor?: string; } -export interface VxeGridProps { + +export interface VxeGridProps< + T extends Record = any, + D extends BaseFormComponentType = BaseFormComponentType, +> { /** * 标题 */ @@ -55,15 +59,15 @@ export interface VxeGridProps { /** * vxe-grid 配置 */ - gridOptions?: DeepPartial; + gridOptions?: DeepPartial>; /** * vxe-grid 事件 */ - gridEvents?: DeepPartial; + gridEvents?: DeepPartial>; /** * 表单配置 */ - formOptions?: VbenFormProps; + formOptions?: VbenFormProps; /** * 显示搜索表单 */ @@ -74,9 +78,12 @@ export interface VxeGridProps { separator?: boolean | SeparatorOptions; } -export type ExtendedVxeGridApi = VxeGridApi & { - useStore: >( - selector?: (state: NoInfer) => T, +export type ExtendedVxeGridApi< + D extends Record = any, + F extends BaseFormComponentType = BaseFormComponentType, +> = VxeGridApi & { + useStore: >>( + selector?: (state: NoInfer>) => T, ) => Readonly>; }; diff --git a/packages/effects/plugins/src/vxe-table/use-vxe-grid.ts b/packages/effects/plugins/src/vxe-table/use-vxe-grid.ts index b15435ed1..e69ae35b5 100644 --- a/packages/effects/plugins/src/vxe-table/use-vxe-grid.ts +++ b/packages/effects/plugins/src/vxe-table/use-vxe-grid.ts @@ -1,3 +1,5 @@ +import type { BaseFormComponentType } from '@vben-core/form-ui'; + import type { ExtendedVxeGridApi, VxeGridProps } from './types'; import { defineComponent, h, onBeforeUnmount } from 'vue'; @@ -7,16 +9,19 @@ import { useStore } from '@vben-core/shared/store'; import { VxeGridApi } from './api'; import VxeGrid from './use-vxe-grid.vue'; -export function useVbenVxeGrid(options: VxeGridProps) { +export function useVbenVxeGrid< + T extends Record = any, + D extends BaseFormComponentType = BaseFormComponentType, +>(options: VxeGridProps) { // const IS_REACTIVE = isReactive(options); const api = new VxeGridApi(options); - const extendedApi: ExtendedVxeGridApi = api as ExtendedVxeGridApi; + const extendedApi: ExtendedVxeGridApi = api as ExtendedVxeGridApi; extendedApi.useStore = (selector) => { return useStore(api.store, selector); }; const Grid = defineComponent( - (props: VxeGridProps, { attrs, slots }) => { + (props: VxeGridProps, { attrs, slots }) => { onBeforeUnmount(() => { api.unmount(); }); diff --git a/packages/effects/request/src/request-client/modules/uploader.ts b/packages/effects/request/src/request-client/modules/uploader.ts index de251ca8c..1353222ab 100644 --- a/packages/effects/request/src/request-client/modules/uploader.ts +++ b/packages/effects/request/src/request-client/modules/uploader.ts @@ -1,6 +1,8 @@ import type { RequestClient } from '../request-client'; import type { RequestClientConfig } from '../types'; +import { isUndefined } from '@vben/utils'; + class FileUploader { private client: RequestClient; @@ -18,10 +20,10 @@ class FileUploader { Object.entries(data).forEach(([key, value]) => { if (Array.isArray(value)) { value.forEach((item, index) => { - formData.append(`${key}[${index}]`, item); + !isUndefined(item) && formData.append(`${key}[${index}]`, item); }); } else { - formData.append(key, value); + !isUndefined(value) && formData.append(key, value); } }); diff --git a/playground/src/adapter/vxe-table.ts b/playground/src/adapter/vxe-table.ts index 71a0ecb49..24dfd4cdc 100644 --- a/playground/src/adapter/vxe-table.ts +++ b/playground/src/adapter/vxe-table.ts @@ -1,10 +1,16 @@ +import type { VxeTableGridOptions } from '@vben/plugins/vxe-table'; import type { Recordable } from '@vben/types'; +import type { ComponentType } from './component'; + import { h } from 'vue'; import { IconifyIcon } from '@vben/icons'; import { $te } from '@vben/locales'; -import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table'; +import { + setupVbenVxeTable, + useVbenVxeGrid as useGrid, +} from '@vben/plugins/vxe-table'; import { get, isFunction, isString } from '@vben/utils'; import { objectOmit } from '@vueuse/core'; @@ -42,7 +48,7 @@ setupVbenVxeTable({ round: true, showOverflow: true, size: 'small', - }, + } as VxeTableGridOptions, }); /** @@ -277,7 +283,10 @@ setupVbenVxeTable({ useVbenForm, }); -export { useVbenVxeGrid }; +export const useVbenVxeGrid = >( + ...rest: Parameters> +) => useGrid(...rest); + export type OnActionClickParams> = { code: string; row: T; diff --git a/playground/src/views/examples/vxe-table/basic.vue b/playground/src/views/examples/vxe-table/basic.vue index 1216468d4..d20472461 100644 --- a/playground/src/views/examples/vxe-table/basic.vue +++ b/playground/src/views/examples/vxe-table/basic.vue @@ -43,7 +43,22 @@ const gridEvents: VxeGridListeners = { }, }; -const [Grid, gridApi] = useVbenVxeGrid({ gridEvents, gridOptions }); +const [Grid, gridApi] = useVbenVxeGrid({ + // 放开注释查看表单组件的类型 + // formOptions: { + // schema: [ + // { + // component: 'Switch', + // fieldName: 'name', + // }, + // ], + // }, + gridEvents, + gridOptions, +}); + +// 放开注释查看当前表格实例的类型 +// gridApi.grid const showBorder = gridApi.useStore((state) => state.gridOptions?.border); const showStripe = gridApi.useStore((state) => state.gridOptions?.stripe); diff --git a/playground/src/views/system/menu/modules/form.vue b/playground/src/views/system/menu/modules/form.vue index 6701a2e59..3cf40e356 100644 --- a/playground/src/views/system/menu/modules/form.vue +++ b/playground/src/views/system/menu/modules/form.vue @@ -241,10 +241,10 @@ const schema: VbenFormSchema[] = [ component: 'Input', dependencies: { rules: (values) => { - return values.type === 'action' ? 'required' : null; + return values.type === 'button' ? 'required' : null; }, show: (values) => { - return ['action', 'catalog', 'embedded', 'menu'].includes(values.type); + return ['button', 'catalog', 'embedded', 'menu'].includes(values.type); }, triggerFields: ['type'], }, @@ -277,7 +277,7 @@ const schema: VbenFormSchema[] = [ }, dependencies: { show: (values) => { - return values.type !== 'action'; + return values.type !== 'button'; }, triggerFields: ['type'], }, @@ -295,7 +295,7 @@ const schema: VbenFormSchema[] = [ }, dependencies: { show: (values) => { - return values.type !== 'action'; + return values.type !== 'button'; }, triggerFields: ['type'], }, @@ -314,7 +314,7 @@ const schema: VbenFormSchema[] = [ }, dependencies: { show: (values) => { - return values.type !== 'action'; + return values.type !== 'button'; }, triggerFields: ['type'], }, @@ -325,7 +325,7 @@ const schema: VbenFormSchema[] = [ component: 'Divider', dependencies: { show: (values) => { - return !['action', 'link'].includes(values.type); + return !['button', 'link'].includes(values.type); }, triggerFields: ['type'], }, @@ -372,7 +372,7 @@ const schema: VbenFormSchema[] = [ component: 'Checkbox', dependencies: { show: (values) => { - return !['action'].includes(values.type); + return !['button'].includes(values.type); }, triggerFields: ['type'], }, @@ -402,7 +402,7 @@ const schema: VbenFormSchema[] = [ component: 'Checkbox', dependencies: { show: (values) => { - return !['action', 'link'].includes(values.type); + return !['button', 'link'].includes(values.type); }, triggerFields: ['type'], }, @@ -417,7 +417,7 @@ const schema: VbenFormSchema[] = [ component: 'Checkbox', dependencies: { show: (values) => { - return !['action', 'link'].includes(values.type); + return !['button', 'link'].includes(values.type); }, triggerFields: ['type'], },