提交 c7c95dd2 编写于 作者: V Vben

chore: type Descrition,Drawer,Excel,Dropdown

上级 6dbbdbac
import Description from './src/Description.vue';
import { withInstall } from '/@/utils';
import description from './src/Description.vue';
export { Description };
export * from './src/types';
export * from './src/typing';
export { useDescription } from './src/useDescription';
export const Description = withInstall(description);
<script lang="tsx">
import type { DescOptions, DescInstance, DescItem } from './types';
import type { DescriptionProps, DescInstance, DescItem } from './typing';
import type { DescriptionsProps } from 'ant-design-vue/es/descriptions/index';
import type { CSSProperties } from 'vue';
import type { CollapseContainerOptions } from '/@/components/Container/index';
import { defineComponent, computed, ref, unref } from 'vue';
import { get } from 'lodash-es';
import { Descriptions } from 'ant-design-vue';
import { CollapseContainer } from '/@/components/Container/index';
import { useDesign } from '/@/hooks/web/useDesign';
import { isFunction } from '/@/utils/is';
import { getSlot } from '/@/utils/helper/tsxHelper';
import descProps from './props';
import { useAttrs } from '/@/hooks/core/useAttrs';
const props = {
useCollapse: { type: Boolean, default: true },
title: { type: String, default: '' },
size: {
type: String,
validator: (v) => ['small', 'default', 'middle', undefined].includes(v),
default: 'small',
},
bordered: { type: Boolean, default: true },
column: {
type: [Number, Object] as PropType<number | Recordable>,
default: () => {
return { xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 };
},
},
collapseOptions: {
type: Object as PropType<CollapseContainerOptions>,
default: null,
},
schema: {
type: Array as PropType<DescItem[]>,
default: () => [],
},
data: { type: Object },
};
export default defineComponent({
name: 'Description',
props: descProps,
props,
emits: ['register'],
setup(props, { slots, emit }) {
const propsRef = ref<Partial<DescOptions> | null>(null);
const propsRef = ref<Partial<DescriptionProps> | null>(null);
const { prefixCls } = useDesign('description');
const attrs = useAttrs();
......@@ -32,7 +53,7 @@
return {
...props,
...(unref(propsRef) as Recordable),
} as DescOptions;
} as DescriptionProps;
});
const getProps = computed(() => {
......@@ -40,7 +61,7 @@
...unref(getMergeProps),
title: undefined,
};
return opt as DescOptions;
return opt as DescriptionProps;
});
/**
......@@ -66,7 +87,7 @@
/**
* @description:设置desc
*/
function setDescProps(descProps: Partial<DescOptions>): void {
function setDescProps(descProps: Partial<DescriptionProps>): void {
// Keep the last setDrawerProps
propsRef.value = { ...(unref(propsRef) as Recordable), ...descProps } as Recordable;
}
......@@ -79,7 +100,6 @@
const labelStyles: CSSProperties = {
...labelStyle,
minWidth: `${labelMinWidth}px `,
};
return <div style={labelStyles}>{label}</div>;
......@@ -97,7 +117,9 @@
const getContent = () => {
const _data = unref(getProps)?.data;
if (!_data) return null;
if (!_data) {
return null;
}
const getField = get(_data, field);
return isFunction(render) ? render(getField, _data) : getField ?? '';
};
......@@ -131,7 +153,6 @@
const renderContainer = () => {
const content = props.useCollapse ? renderDesc() : <div>{renderDesc()}</div>;
// Reduce the dom level
if (!props.useCollapse) {
return content;
}
......
import type { PropType } from 'vue';
import type { CollapseContainerOptions } from '/@/components/Container';
import type { DescItem } from './types';
import { propTypes } from '/@/utils/propTypes';
export default {
useCollapse: propTypes.bool.def(true),
title: propTypes.string.def(''),
size: propTypes.oneOf(['small', 'default', 'middle', undefined]).def('small'),
bordered: propTypes.bool.def(true),
column: {
type: [Number, Object] as PropType<number | Recordable>,
default: () => {
return { xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 };
},
},
collapseOptions: {
type: Object as PropType<CollapseContainerOptions>,
default: null,
},
schema: {
type: Array as PropType<Array<DescItem>>,
default: () => [],
},
data: propTypes.object,
};
......@@ -4,11 +4,8 @@ import type { DescriptionsProps } from 'ant-design-vue/es/descriptions/index';
export interface DescItem {
labelMinWidth?: number;
contentMinWidth?: number;
labelStyle?: CSSProperties;
field: string;
label: string | VNode | JSX.Element;
// Merge column
......@@ -21,7 +18,7 @@ export interface DescItem {
) => VNode | undefined | JSX.Element | Element | string | number;
}
export interface DescOptions extends DescriptionsProps {
export interface DescriptionProps extends DescriptionsProps {
// Whether to include the collapse component
useCollapse?: boolean;
/**
......@@ -42,7 +39,7 @@ export interface DescOptions extends DescriptionsProps {
}
export interface DescInstance {
setDescProps(descProps: Partial<DescOptions>): void;
setDescProps(descProps: Partial<DescriptionProps>): void;
}
export type Register = (descInstance: DescInstance) => void;
......
import type { DescriptionProps, DescInstance, UseDescReturnType } from './typing';
import { ref, getCurrentInstance, unref } from 'vue';
import { isProdMode } from '/@/utils/env';
import type { DescOptions, DescInstance, UseDescReturnType } from './types';
export function useDescription(props?: Partial<DescOptions>): UseDescReturnType {
export function useDescription(props?: Partial<DescriptionProps>): UseDescReturnType {
if (!getCurrentInstance()) {
throw new Error('Please put useDescription function in the setup function!');
throw new Error('useDescription() can only be used inside setup() or functional components!');
}
const descRef = ref<Nullable<DescInstance>>(null);
const loadedRef = ref(false);
const desc = ref<Nullable<DescInstance>>(null);
const loaded = ref(false);
function register(instance: DescInstance) {
if (unref(loadedRef) && isProdMode()) return;
descRef.value = instance;
if (unref(loaded) && isProdMode()) {
return;
}
desc.value = instance;
props && instance.setDescProps(props);
loadedRef.value = true;
loaded.value = true;
}
const methods: DescInstance = {
setDescProps: (descProps: Partial<DescOptions>): void => {
unref(descRef)?.setDescProps(descProps);
setDescProps: (descProps: Partial<DescriptionProps>): void => {
unref(desc)?.setDescProps(descProps);
},
};
......
import BasicDrawer from './src/BasicDrawer.vue';
import { withInstall } from '/@/utils';
import basicDrawer from './src/BasicDrawer.vue';
export { BasicDrawer };
export * from './src/types';
export const BasicDrawer = withInstall(basicDrawer);
export * from './src/typing';
export { useDrawer, useDrawerInner } from './src/useDrawer';
......@@ -31,9 +31,8 @@
</Drawer>
</template>
<script lang="ts">
import type { DrawerInstance, DrawerProps } from './types';
import type { DrawerInstance, DrawerProps } from './typing';
import type { CSSProperties } from 'vue';
import {
defineComponent,
ref,
......@@ -46,15 +45,12 @@
getCurrentInstance,
} from 'vue';
import { Drawer } from 'ant-design-vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { isFunction, isNumber } from '/@/utils/is';
import { deepMerge } from '/@/utils';
import DrawerFooter from './components/DrawerFooter.vue';
import DrawerHeader from './components/DrawerHeader.vue';
import { ScrollContainer } from '/@/components/Container';
import { basicProps } from './props';
import { useDesign } from '/@/hooks/web/useDesign';
import { useAttrs } from '/@/hooks/core/useAttrs';
......@@ -167,7 +163,7 @@
function setDrawerProps(props: Partial<DrawerProps>): void {
// Keep the last setDrawerProps
propsRef.value = deepMerge(unref(propsRef) || {}, props);
propsRef.value = deepMerge((unref(propsRef) as any) || {}, props);
if (Reflect.has(props, 'visible')) {
visibleRef.value = !!props.visible;
......
......@@ -40,6 +40,7 @@
function handleClose() {
emit('close');
}
return { prefixCls, handleClose };
},
});
......
import type { PropType } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { propTypes } from '/@/utils/propTypes';
const { t } = useI18n();
export const footerProps = {
confirmLoading: propTypes.bool,
confirmLoading: { type: Boolean },
/**
* @description: Show close button
*/
showCancelBtn: propTypes.bool.def(true),
showCancelBtn: { type: Boolean, default: true },
cancelButtonProps: Object as PropType<Recordable>,
cancelText: propTypes.string.def(t('common.cancelText')),
cancelText: { type: String, default: t('common.cancelText') },
/**
* @description: Show confirmation button
*/
showOkBtn: propTypes.bool.def(true),
showOkBtn: { type: Boolean, default: true },
okButtonProps: Object as PropType<Recordable>,
okText: propTypes.string.def(t('common.okText')),
okType: propTypes.string.def('primary'),
showFooter: propTypes.bool,
okText: { type: String, default: t('common.okText') },
okType: { type: String, default: 'primary' },
showFooter: { type: Boolean },
footerHeight: {
type: [String, Number] as PropType<string | number>,
default: 60,
},
};
export const basicProps = {
isDetail: propTypes.bool,
title: propTypes.string.def(''),
loadingText: propTypes.string,
showDetailBack: propTypes.bool.def(true),
visible: propTypes.bool,
loading: propTypes.bool,
maskClosable: propTypes.bool.def(true),
isDetail: { type: Boolean },
title: { type: String, default: '' },
loadingText: { type: String },
showDetailBack: { type: Boolean, default: true },
visible: { type: Boolean },
loading: { type: Boolean },
maskClosable: { type: Boolean, default: true },
getContainer: {
type: [Object, String] as PropType<any>,
},
......@@ -44,7 +43,7 @@ export const basicProps = {
type: [Function, Object] as PropType<any>,
default: null,
},
triggerWindowResize: propTypes.bool,
destroyOnClose: propTypes.bool,
triggerWindowResize: { type: Boolean },
destroyOnClose: { type: Boolean },
...footerProps,
};
......@@ -181,7 +181,6 @@ export interface DrawerProps extends DrawerFooterProps {
placement?: 'top' | 'right' | 'bottom' | 'left';
afterVisibleChange?: (visible?: boolean) => void;
keyboard?: boolean;
/**
* Specify a callback that will be called when a user clicks mask, close button or Cancel button.
*/
......
......@@ -4,7 +4,7 @@ import type {
ReturnMethods,
DrawerProps,
UseDrawerInnerReturnType,
} from './types';
} from './typing';
import {
ref,
......@@ -32,24 +32,27 @@ const visibleData = reactive<{ [key: number]: boolean }>({});
* @description: Applicable to separate drawer and call outside
*/
export function useDrawer(): UseDrawerReturnType {
const drawerRef = ref<DrawerInstance | null>(null);
const loadedRef = ref<Nullable<boolean>>(false);
const uidRef = ref<string>('');
if (!getCurrentInstance()) {
throw new Error('useDrawer() can only be used inside setup() or functional components!');
}
const drawer = ref<DrawerInstance | null>(null);
const loaded = ref<Nullable<boolean>>(false);
const uid = ref<string>('');
function register(drawerInstance: DrawerInstance, uuid: string) {
isProdMode() &&
tryOnUnmounted(() => {
drawerRef.value = null;
loadedRef.value = null;
dataTransferRef[unref(uidRef)] = null;
drawer.value = null;
loaded.value = null;
dataTransferRef[unref(uid)] = null;
});
if (unref(loadedRef) && isProdMode() && drawerInstance === unref(drawerRef)) {
if (unref(loaded) && isProdMode() && drawerInstance === unref(drawer)) {
return;
}
uidRef.value = uuid;
drawerRef.value = drawerInstance;
loadedRef.value = true;
uid.value = uuid;
drawer.value = drawerInstance;
loaded.value = true;
drawerInstance.emitVisible = (visible: boolean, uid: number) => {
visibleData[uid] = visible;
......@@ -57,7 +60,7 @@ export function useDrawer(): UseDrawerReturnType {
}
const getInstance = () => {
const instance = unref(drawerRef);
const instance = unref(drawer);
if (!instance) {
error('useDrawer instance is undefined!');
}
......@@ -70,7 +73,7 @@ export function useDrawer(): UseDrawerReturnType {
},
getVisible: computed((): boolean => {
return visibleData[~~unref(uidRef)];
return visibleData[~~unref(uid)];
}),
openDrawer: <T = any>(visible = true, data?: T, openOnSet = true): void => {
......@@ -80,13 +83,13 @@ export function useDrawer(): UseDrawerReturnType {
if (!data) return;
if (openOnSet) {
dataTransferRef[unref(uidRef)] = null;
dataTransferRef[unref(uidRef)] = toRaw(data);
dataTransferRef[unref(uid)] = null;
dataTransferRef[unref(uid)] = toRaw(data);
return;
}
const equal = isEqual(toRaw(dataTransferRef[unref(uidRef)]), toRaw(data));
const equal = isEqual(toRaw(dataTransferRef[unref(uid)]), toRaw(data));
if (!equal) {
dataTransferRef[unref(uidRef)] = toRaw(data);
dataTransferRef[unref(uid)] = toRaw(data);
}
},
};
......@@ -99,8 +102,8 @@ export const useDrawerInner = (callbackFn?: Fn): UseDrawerInnerReturnType => {
const currentInstance = getCurrentInstance();
const uidRef = ref<string>('');
if (!currentInstance) {
error('useDrawerInner instance is undefined!');
if (!getCurrentInstance()) {
throw new Error('useDrawerInner() can only be used inside setup() or functional components!');
}
const getInstance = () => {
......
import Dropdown from './src/Dropdown.vue';
import { withInstall } from '/@/utils';
import dropdown from './src/Dropdown.vue';
export * from './src/types';
export { Dropdown };
export * from './src/typing';
export const Dropdown = withInstall(dropdown);
<template>
<a-dropdown :trigger="trigger" v-bind="$attrs">
<Dropdown :trigger="trigger" v-bind="$attrs">
<span>
<slot></slot>
</span>
<template #overlay>
<a-menu :selectedKeys="selectedKeys">
<Menu :selectedKeys="selectedKeys">
<template v-for="item in dropMenuList" :key="`${item.event}`">
<a-menu-item
<MenuItem
v-bind="getAttr(item.event)"
@click="handleClickMenu(item)"
:disabled="item.disabled"
......@@ -19,17 +19,17 @@
<Icon :icon="item.icon" v-if="item.icon" />
<span class="ml-1">{{ item.text }}</span>
</template>
</a-menu-item>
<a-menu-divider v-if="item.divider" :key="`d-${item.event}`" />
</MenuItem>
<MenuDivider v-if="item.divider" :key="`d-${item.event}`" />
</template>
</a-menu>
</Menu>
</template>
</a-dropdown>
</Dropdown>
</template>
<script lang="ts">
import type { PropType } from 'vue';
import type { DropMenu } from './types';
import type { DropMenu } from './typing';
import { defineComponent } from 'vue';
import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
......@@ -38,10 +38,10 @@
export default defineComponent({
name: 'BasicDropdown',
components: {
[Dropdown.name]: Dropdown,
[Menu.name]: Menu,
[Menu.Item.name]: Menu.Item,
[Menu.Divider.name]: Menu.Divider,
Dropdown,
Menu,
MenuItem: Menu.Item,
MenuDivider: Menu.Divider,
Icon,
Popconfirm,
},
......@@ -75,6 +75,7 @@
emit('menuEvent', menu);
item.onClick?.();
}
return {
handleClickMenu,
getAttr: (key: string | number) => ({ key }),
......
......@@ -7,5 +7,3 @@ export interface DropMenu {
disabled?: boolean;
divider?: boolean;
}
// export type Trigger = 'click' | 'hover' | 'contextMenu';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export const ImpExcel = createAsyncComponent(() => import('./src/ImportExcel.vue'));
export const ExpExcelModel = createAsyncComponent(() => import('./src/ExportExcelModel.vue'));
export * from './src/types';
import { withInstall } from '/@/utils';
import impExcel from './src/ImportExcel.vue';
import expExcelModal from './src/ExportExcelModal.vue';
export const ImpExcel = withInstall(impExcel);
export const ExpExcelModal = withInstall(expExcelModal);
export * from './src/typing';
export { jsonToSheetXlsx, aoaToSheetXlsx } from './src/Export2Excel';
import xlsx from 'xlsx';
import type { WorkBook } from 'xlsx';
import type { JsonToSheet, AoAToSheet } from './types';
import type { JsonToSheet, AoAToSheet } from './typing';
const { utils, writeFile } = xlsx;
const DEF_FILE_NAME = 'excel-list.xlsx';
export function jsonToSheetXlsx<T = any>({
data,
header,
......
......@@ -14,7 +14,7 @@
</BasicModal>
</template>
<script lang="ts">
import type { ExportModalResult } from './types';
import type { ExportModalResult } from './typing';
import { defineComponent } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
......
......@@ -16,7 +16,7 @@
import { defineComponent, ref, unref } from 'vue';
import XLSX from 'xlsx';
import type { ExcelData } from './types';
import type { ExcelData } from './typing';
export default defineComponent({
name: 'ImportExcel',
emits: ['success', 'error'],
......
......@@ -6,10 +6,6 @@ export interface ExcelData<T = any> {
meta: { sheetName: string };
}
// export interface ImportProps {
// beforeUpload: (file: File) => boolean;
// }
export interface JsonToSheet<T = any> {
data: T[];
header?: T;
......
import type { DropMenu } from '/@/components/Dropdown/src/types';
import type { DropMenu } from '../components/Dropdown';
import type { LocaleSetting, LocaleType } from '/#/config';
export const LOCALE: { [key: string]: LocaleType } = {
......
......@@ -5,20 +5,20 @@
<a-button @click="openModal"> 导出 </a-button>
</template>
</BasicTable>
<ExpExcelModel @register="register" @success="defaultHeader" />
<ExpExcelModal @register="register" @success="defaultHeader" />
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicTable } from '/@/components/Table';
import { jsonToSheetXlsx, ExpExcelModel, ExportModalResult } from '/@/components/Excel';
import { jsonToSheetXlsx, ExpExcelModal, ExportModalResult } from '/@/components/Excel';
import { columns, data } from './data';
import { useModal } from '/@/components/Modal';
import { PageWrapper } from '/@/components/Page';
export default defineComponent({
components: { BasicTable, ExpExcelModel, PageWrapper },
components: { BasicTable, ExpExcelModal, PageWrapper },
setup() {
function defaultHeader({ filename, bookType }: ExportModalResult) {
// 默认Object.keys(data[0])作为header
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册