chore: type Descrition,Drawer,Excel,Dropdown
1个文件已删除
15个文件已修改
5 文件已重命名
| | |
| | | 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(); |
| | |
| | | return { |
| | | ...props, |
| | | ...(unref(propsRef) as Recordable), |
| | | } as DescOptions; |
| | | } as DescriptionProps; |
| | | }); |
| | | |
| | | const getProps = computed(() => { |
| | |
| | | ...unref(getMergeProps), |
| | | title: undefined, |
| | | }; |
| | | return opt as DescOptions; |
| | | return opt as DescriptionProps; |
| | | }); |
| | | |
| | | /** |
| | |
| | | /** |
| | | * @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; |
| | | } |
| | |
| | | |
| | | const labelStyles: CSSProperties = { |
| | | ...labelStyle, |
| | | |
| | | minWidth: `${labelMinWidth}px `, |
| | | }; |
| | | return <div style={labelStyles}>{label}</div>; |
| | |
| | | |
| | | 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 ?? ''; |
| | | }; |
| | |
| | | const renderContainer = () => { |
| | | const content = props.useCollapse ? renderDesc() : <div>{renderDesc()}</div>; |
| | | // Reduce the dom level |
| | | |
| | | if (!props.useCollapse) { |
| | | return content; |
| | | } |
File was renamed from src/components/Description/src/types.ts |
| | |
| | | |
| | | export interface DescItem { |
| | | labelMinWidth?: number; |
| | | |
| | | contentMinWidth?: number; |
| | | |
| | | labelStyle?: CSSProperties; |
| | | |
| | | field: string; |
| | | label: string | VNode | JSX.Element; |
| | | // Merge column |
| | |
| | | ) => 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; |
| | | /** |
| | |
| | | } |
| | | |
| | | 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'; |
| | |
| | | </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, |
| | |
| | | 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'; |
| | |
| | | |
| | | 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; |
| | |
| | | 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>, |
| | | }, |
| | |
| | | type: [Function, Object] as PropType<any>, |
| | | default: null, |
| | | }, |
| | | triggerWindowResize: propTypes.bool, |
| | | destroyOnClose: propTypes.bool, |
| | | triggerWindowResize: { type: Boolean }, |
| | | destroyOnClose: { type: Boolean }, |
| | | ...footerProps, |
| | | }; |
File was renamed from src/components/Drawer/src/types.ts |
| | |
| | | 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. |
| | | */ |
| | |
| | | ReturnMethods, |
| | | DrawerProps, |
| | | UseDrawerInnerReturnType, |
| | | } from './types'; |
| | | } from './typing'; |
| | | |
| | | import { |
| | | ref, |
| | |
| | | * @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; |
| | |
| | | } |
| | | |
| | | const getInstance = () => { |
| | | const instance = unref(drawerRef); |
| | | const instance = unref(drawer); |
| | | if (!instance) { |
| | | error('useDrawer instance is undefined!'); |
| | | } |
| | |
| | | }, |
| | | |
| | | getVisible: computed((): boolean => { |
| | | return visibleData[~~unref(uidRef)]; |
| | | return visibleData[~~unref(uid)]; |
| | | }), |
| | | |
| | | openDrawer: <T = any>(visible = true, data?: T, openOnSet = true): void => { |
| | |
| | | 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); |
| | | } |
| | | }, |
| | | }; |
| | |
| | | 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" |
| | |
| | | <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'; |
| | |
| | | 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, |
| | | }, |
| | |
| | | emit('menuEvent', menu); |
| | | item.onClick?.(); |
| | | } |
| | | |
| | | return { |
| | | handleClickMenu, |
| | | getAttr: (key: string | number) => ({ key }), |
File was renamed from src/components/Dropdown/src/types.ts |
| | |
| | | disabled?: boolean; |
| | | divider?: boolean; |
| | | } |
| | | |
| | | // export type Trigger = 'click' | 'hover' | 'contextMenu'; |
| | |
| | | import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; |
| | | import { withInstall } from '/@/utils'; |
| | | import impExcel from './src/ImportExcel.vue'; |
| | | import expExcelModal from './src/ExportExcelModal.vue'; |
| | | |
| | | export const ImpExcel = createAsyncComponent(() => import('./src/ImportExcel.vue')); |
| | | export const ExpExcelModel = createAsyncComponent(() => import('./src/ExportExcelModel.vue')); |
| | | |
| | | export * from './src/types'; |
| | | |
| | | 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, |
File was renamed from src/components/Excel/src/ExportExcelModel.vue |
| | |
| | | </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'; |
| | |
| | | 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'], |
File was renamed from src/components/Excel/src/types.ts |
| | |
| | | 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 } = { |
| | |
| | | <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 |