mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-27 14:13:40 +08:00
perf(import): perf components import
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
import { withInstall } from '../util';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
import AppLogo from './src/AppLogo.vue';
|
||||
import AppProvider from './src/AppProvider.vue';
|
||||
import { withInstall } from '../util';
|
||||
|
||||
export const AppLocalePicker = createAsyncComponent(() => import('./src/AppLocalePicker.vue'));
|
||||
export const AppProvider = createAsyncComponent(() => import('./src/AppProvider.vue'));
|
||||
export const AppSearch = createAsyncComponent(() => import('./src/search/AppSearch.vue'), {
|
||||
loading: true,
|
||||
});
|
||||
// export const AppLogo = createAsyncComponent(() => import('./src/AppLogo.vue'));
|
||||
|
||||
withInstall(AppLocalePicker, AppLogo, AppProvider, AppSearch);
|
||||
|
||||
export { useAppProviderContext } from './src/useAppContext';
|
||||
export { AppLogo };
|
||||
export { AppLogo, AppProvider };
|
||||
|
||||
withInstall(AppLogo, AppProvider);
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { withInstall } from '../util';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
export const Authority = createAsyncComponent(() => import('./src/index.vue'));
|
||||
import Authority from './src/index.vue';
|
||||
|
||||
withInstall(Authority);
|
||||
|
||||
export { Authority };
|
||||
|
@@ -1,8 +1,5 @@
|
||||
import { withInstall } from '../util';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
export const BasicArrow = createAsyncComponent(() => import('./src/BasicArrow.vue'));
|
||||
export const BasicHelp = createAsyncComponent(() => import('./src/BasicHelp.vue'));
|
||||
export const BasicTitle = createAsyncComponent(() => import('./src/BasicTitle.vue'));
|
||||
|
||||
withInstall(BasicArrow, BasicHelp, BasicTitle);
|
||||
|
@@ -2,5 +2,4 @@ import Button from './src/BasicButton.vue';
|
||||
import { withInstall } from '../util';
|
||||
|
||||
withInstall(Button);
|
||||
|
||||
export { Button };
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { withInstall } from '../util';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
export const ClickOutSide = createAsyncComponent(() => import('./src/index.vue'));
|
||||
import ClickOutSide from './src/index.vue';
|
||||
|
||||
withInstall(ClickOutSide);
|
||||
|
||||
export { ClickOutSide };
|
||||
|
@@ -1,14 +1,8 @@
|
||||
import { withInstall } from '../util';
|
||||
import CollapseContainer from './src/collapse/CollapseContainer.vue';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const ScrollContainer = createAsyncComponent(() => import('./src/ScrollContainer.vue'));
|
||||
|
||||
// export const CollapseContainer = createAsyncComponent(
|
||||
// () => import('./src/collapse/CollapseContainer.vue')
|
||||
// );
|
||||
export const LazyContainer = createAsyncComponent(() => import('./src/LazyContainer.vue'));
|
||||
import ScrollContainer from './src/ScrollContainer.vue';
|
||||
import LazyContainer from './src/LazyContainer.vue';
|
||||
|
||||
withInstall(ScrollContainer, CollapseContainer, LazyContainer);
|
||||
|
||||
export { CollapseContainer };
|
||||
export { CollapseContainer, ScrollContainer, LazyContainer };
|
||||
export * from './src/types';
|
||||
|
@@ -1,8 +1,4 @@
|
||||
// Transform vue-count-to to support vue3 version
|
||||
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const CountTo = createAsyncComponent(() => import('./src/index.vue'));
|
||||
|
||||
withInstall(CountTo);
|
||||
|
@@ -1,9 +1,5 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const Description = createAsyncComponent(() => import('./src/index'));
|
||||
|
||||
withInstall(Description);
|
||||
|
||||
export * from './src/types';
|
||||
export { useDescription } from './src/useDescription';
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const BasicDrawer = createAsyncComponent(() => import('./src/BasicDrawer'));
|
||||
import BasicDrawer from './src/BasicDrawer';
|
||||
|
||||
withInstall(BasicDrawer);
|
||||
export { BasicDrawer };
|
||||
export * from './src/types';
|
||||
export { useDrawer, useDrawerInner } from './src/useDrawer';
|
||||
|
||||
withInstall(BasicDrawer);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import Dropdown from './src/Dropdown';
|
||||
import Dropdown from './src/Dropdown.vue';
|
||||
|
||||
withInstall(Dropdown);
|
||||
export * from './src/types';
|
||||
|
@@ -1,57 +0,0 @@
|
||||
import type { Trigger } from './types';
|
||||
|
||||
import { defineComponent, computed, unref } from 'vue';
|
||||
import { Dropdown, Menu } from 'ant-design-vue';
|
||||
import Icon from '/@/components/Icon/index';
|
||||
|
||||
import { basicDropdownProps } from './props';
|
||||
import { getSlot } from '/@/utils/helper/tsxHelper';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Dropdown',
|
||||
props: basicDropdownProps,
|
||||
emits: ['menuEvent'],
|
||||
setup(props, { slots, emit, attrs }) {
|
||||
const getMenuList = computed(() => props.dropMenuList);
|
||||
|
||||
function handleClickMenu({ key }: any) {
|
||||
const menu = unref(getMenuList).find((item) => `${item.event}` === `${key}`);
|
||||
emit('menuEvent', menu);
|
||||
}
|
||||
|
||||
function renderMenus() {
|
||||
return (
|
||||
<Menu onClick={handleClickMenu} selectedKeys={props.selectedKeys}>
|
||||
{() => (
|
||||
<>
|
||||
{unref(getMenuList).map((item) => {
|
||||
const { disabled, icon, text, divider, event } = item;
|
||||
return [
|
||||
<Menu.Item key={`${event}`} disabled={disabled}>
|
||||
{() => (
|
||||
<>
|
||||
{icon && <Icon icon={icon} />}
|
||||
<span class="ml-1">{text}</span>
|
||||
</>
|
||||
)}
|
||||
</Menu.Item>,
|
||||
// @ts-ignore
|
||||
divider && <Menu.Divider key={`d-${event}`} />,
|
||||
];
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
|
||||
return () => (
|
||||
<Dropdown trigger={props.trigger as Trigger[]} {...attrs}>
|
||||
{{
|
||||
default: () => <span>{getSlot(slots)}</span>,
|
||||
overlay: () => renderMenus(),
|
||||
}}
|
||||
</Dropdown>
|
||||
);
|
||||
},
|
||||
});
|
70
src/components/Dropdown/src/Dropdown.vue
Normal file
70
src/components/Dropdown/src/Dropdown.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<a-dropdown :trigger="trigger" v-bind="$attrs">
|
||||
<span>
|
||||
<slot />
|
||||
</span>
|
||||
<template #overlay>
|
||||
<a-menu :selectedKeys="selectedKeys">
|
||||
<template v-for="item in getMenuList" :key="`${item.event}`">
|
||||
<a-menu-item @click="handleClickMenu({ key: item.event })" :disabled="item.disabled">
|
||||
<Icon :icon="item.icon" v-if="item.icon" />
|
||||
<span class="ml-1">{{ item.text }}</span>
|
||||
</a-menu-item>
|
||||
<a-menu-divider v-if="item.divider" :key="`d-${item.event}`" />
|
||||
</template>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
import type { DropMenu } from './types';
|
||||
|
||||
import { defineComponent, computed, unref } from 'vue';
|
||||
import { Dropdown, Menu } from 'ant-design-vue';
|
||||
import Icon from '/@/components/Icon/index';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BasicDropdown',
|
||||
components: {
|
||||
[Dropdown.name]: Dropdown,
|
||||
[Menu.name]: Menu,
|
||||
[Menu.Item.name]: Menu.Item,
|
||||
[Menu.Divider.name]: Menu.Divider,
|
||||
Icon,
|
||||
},
|
||||
props: {
|
||||
/**
|
||||
* the trigger mode which executes the drop-down action
|
||||
* @default ['hover']
|
||||
* @type string[]
|
||||
*/
|
||||
trigger: {
|
||||
type: [Array] as PropType<string[]>,
|
||||
default: () => {
|
||||
return ['contextmenu'];
|
||||
},
|
||||
},
|
||||
dropMenuList: {
|
||||
type: Array as PropType<DropMenu[]>,
|
||||
default: () => [],
|
||||
},
|
||||
selectedKeys: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
emits: ['menuEvent'],
|
||||
setup(props, { emit }) {
|
||||
const getMenuList = computed(() => props.dropMenuList);
|
||||
|
||||
function handleClickMenu({ key }: { key: string }) {
|
||||
const menu = unref(getMenuList).find((item) => `${item.event}` === `${key}`);
|
||||
emit('menuEvent', menu);
|
||||
}
|
||||
|
||||
return { handleClickMenu, getMenuList };
|
||||
},
|
||||
});
|
||||
</script>
|
@@ -1,26 +0,0 @@
|
||||
import type { PropType } from 'vue';
|
||||
import type { DropMenu } from './types';
|
||||
|
||||
export const dropdownProps = {
|
||||
/**
|
||||
* the trigger mode which executes the drop-down action
|
||||
* @default ['hover']
|
||||
* @type string[]
|
||||
*/
|
||||
trigger: {
|
||||
type: [Array] as PropType<string[]>,
|
||||
default: () => {
|
||||
return ['contextmenu'];
|
||||
},
|
||||
},
|
||||
};
|
||||
export const basicDropdownProps = Object.assign({}, dropdownProps, {
|
||||
dropMenuList: {
|
||||
type: Array as PropType<DropMenu[]>,
|
||||
default: () => [],
|
||||
},
|
||||
selectedKeys: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
@@ -7,4 +7,4 @@ export interface DropMenu {
|
||||
divider?: boolean;
|
||||
}
|
||||
|
||||
export type Trigger = 'click' | 'hover' | 'contextMenu';
|
||||
// export type Trigger = 'click' | 'hover' | 'contextMenu';
|
||||
|
@@ -1,12 +1,8 @@
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
import { withInstall } from '../util';
|
||||
|
||||
export const ImpExcel = createAsyncComponent(() => import('./src/ImportExcel.vue'));
|
||||
export const ExpExcelModel = createAsyncComponent(() => import('./src/ExportExcelModel.vue'));
|
||||
|
||||
withInstall(ImpExcel, ExpExcelModel);
|
||||
|
||||
export * from './src/types';
|
||||
|
||||
export { jsonToSheetXlsx, aoaToSheetXlsx } from './src/Export2Excel';
|
||||
|
@@ -1,14 +0,0 @@
|
||||
@import (reference) '../../design/index.less';
|
||||
|
||||
.app-iconify {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
span.iconify {
|
||||
display: block;
|
||||
min-width: 1em;
|
||||
min-height: 1em;
|
||||
background: @iconify-bg-color;
|
||||
border-radius: 100%;
|
||||
}
|
7
src/components/Icon/index.ts
Normal file
7
src/components/Icon/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { withInstall } from '../util';
|
||||
import Icon from './src/index.vue';
|
||||
|
||||
withInstall(Icon);
|
||||
|
||||
export { Icon };
|
||||
export default Icon;
|
@@ -1,83 +0,0 @@
|
||||
import './index.less';
|
||||
|
||||
import type { PropType } from 'vue';
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
watch,
|
||||
onMounted,
|
||||
nextTick,
|
||||
unref,
|
||||
computed,
|
||||
CSSProperties,
|
||||
} from 'vue';
|
||||
import Iconify from '@purge-icons/generated';
|
||||
import { isString } from '/@/utils/is';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
export default defineComponent({
|
||||
name: 'GIcon',
|
||||
props: {
|
||||
// icon name
|
||||
icon: propTypes.string,
|
||||
// icon color
|
||||
color: propTypes.string,
|
||||
// icon size
|
||||
size: {
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
default: 16,
|
||||
},
|
||||
prefix: propTypes.string.def(''),
|
||||
},
|
||||
setup(props, { attrs }) {
|
||||
const elRef = ref<ElRef>(null);
|
||||
|
||||
const getIconRef = computed(() => {
|
||||
const { icon, prefix } = props;
|
||||
return `${prefix ? prefix + ':' : ''}${icon}`;
|
||||
});
|
||||
|
||||
const update = async () => {
|
||||
const el = unref(elRef);
|
||||
if (el) {
|
||||
await nextTick();
|
||||
const icon = unref(getIconRef);
|
||||
|
||||
const svg = Iconify.renderSVG(icon, {});
|
||||
|
||||
if (svg) {
|
||||
el.textContent = '';
|
||||
el.appendChild(svg);
|
||||
} else {
|
||||
const span = document.createElement('span');
|
||||
span.className = 'iconify';
|
||||
span.dataset.icon = icon;
|
||||
el.textContent = '';
|
||||
el.appendChild(span);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const wrapStyleRef = computed(
|
||||
(): CSSProperties => {
|
||||
const { size, color } = props;
|
||||
let fs = size;
|
||||
if (isString(size)) {
|
||||
fs = parseInt(size, 10);
|
||||
}
|
||||
return {
|
||||
fontSize: `${fs}px`,
|
||||
color,
|
||||
display: 'inline-flex',
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
watch(() => props.icon, update, { flush: 'post' });
|
||||
|
||||
onMounted(update);
|
||||
|
||||
return () => (
|
||||
<span ref={elRef} class={[attrs.class, 'app-iconify anticon']} style={unref(wrapStyleRef)} />
|
||||
);
|
||||
},
|
||||
});
|
100
src/components/Icon/src/index.vue
Normal file
100
src/components/Icon/src/index.vue
Normal file
@@ -0,0 +1,100 @@
|
||||
<template>
|
||||
<span ref="elRef" :class="[$attrs.class, 'app-iconify anticon']" :style="getWrapStyle" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
watch,
|
||||
onMounted,
|
||||
nextTick,
|
||||
unref,
|
||||
computed,
|
||||
CSSProperties,
|
||||
} from 'vue';
|
||||
import Iconify from '@purge-icons/generated';
|
||||
import { isString } from '/@/utils/is';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
export default defineComponent({
|
||||
name: 'GIcon',
|
||||
props: {
|
||||
// icon name
|
||||
icon: propTypes.string,
|
||||
// icon color
|
||||
color: propTypes.string,
|
||||
// icon size
|
||||
size: {
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
default: 16,
|
||||
},
|
||||
prefix: propTypes.string.def(''),
|
||||
},
|
||||
setup(props) {
|
||||
const elRef = ref<ElRef>(null);
|
||||
|
||||
const getIconRef = computed(() => {
|
||||
const { icon, prefix } = props;
|
||||
return `${prefix ? prefix + ':' : ''}${icon}`;
|
||||
});
|
||||
|
||||
const update = async () => {
|
||||
const el = unref(elRef);
|
||||
if (el) {
|
||||
await nextTick();
|
||||
const icon = unref(getIconRef);
|
||||
|
||||
const svg = Iconify.renderSVG(icon, {});
|
||||
|
||||
if (svg) {
|
||||
el.textContent = '';
|
||||
el.appendChild(svg);
|
||||
} else {
|
||||
const span = document.createElement('span');
|
||||
span.className = 'iconify';
|
||||
span.dataset.icon = icon;
|
||||
el.textContent = '';
|
||||
el.appendChild(span);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getWrapStyle = computed(
|
||||
(): CSSProperties => {
|
||||
const { size, color } = props;
|
||||
let fs = size;
|
||||
if (isString(size)) {
|
||||
fs = parseInt(size, 10);
|
||||
}
|
||||
return {
|
||||
fontSize: `${fs}px`,
|
||||
color,
|
||||
display: 'inline-flex',
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
watch(() => props.icon, update, { flush: 'post' });
|
||||
|
||||
onMounted(update);
|
||||
|
||||
return { elRef, getWrapStyle };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
@import (reference) '../../../design/index.less';
|
||||
|
||||
.app-iconify {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
span.iconify {
|
||||
display: block;
|
||||
min-width: 1em;
|
||||
min-height: 1em;
|
||||
background: @iconify-bg-color;
|
||||
border-radius: 100%;
|
||||
}
|
||||
</style>
|
@@ -1,9 +1,5 @@
|
||||
import './src/indicator';
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const Loading = createAsyncComponent(() => import('./src/index.vue'));
|
||||
|
||||
withInstall(Loading);
|
||||
export { useLoading } from './src/useLoading';
|
||||
export { createLoading } from './src/createLoading';
|
||||
|
@@ -1,9 +0,0 @@
|
||||
// If you need to modify the default icon, you can open the comment and modify it here
|
||||
|
||||
// import { Spin } from 'ant-design-vue';
|
||||
// import { LoadingOutlined } from '@ant-design/icons-vue';
|
||||
// Spin.setDefaultIndicator({
|
||||
// indicator: () => {
|
||||
// return <LoadingOutlined spin />;
|
||||
// },
|
||||
// });
|
@@ -8,6 +8,10 @@ export interface UseLoadingOptions {
|
||||
props?: Partial<LoadingProps>;
|
||||
}
|
||||
|
||||
interface Fn {
|
||||
(): void;
|
||||
}
|
||||
|
||||
export function useLoading(props: Partial<LoadingProps>): [Fn, Fn];
|
||||
export function useLoading(opt: Partial<UseLoadingOptions>): [Fn, Fn];
|
||||
|
||||
|
@@ -1,8 +1,4 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const MarkDown = createAsyncComponent(() => import('./src/index.vue'));
|
||||
|
||||
withInstall(MarkDown);
|
||||
|
||||
export * from './src/types';
|
||||
|
@@ -1,17 +1,8 @@
|
||||
<template>
|
||||
<div class="markdown" ref="wrapRef" />
|
||||
<div ref="wrapRef" />
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
onMounted,
|
||||
unref,
|
||||
onUnmounted,
|
||||
nextTick,
|
||||
// watch,
|
||||
computed,
|
||||
} from 'vue';
|
||||
import { defineComponent, ref, onMounted, unref, onUnmounted, nextTick, computed } from 'vue';
|
||||
import Vditor from 'vditor';
|
||||
import 'vditor/dist/index.css';
|
||||
|
||||
@@ -75,21 +66,6 @@
|
||||
initedRef.value = true;
|
||||
}
|
||||
|
||||
// watch(
|
||||
// () => props.value,
|
||||
// () => {
|
||||
// nextTick(() => {
|
||||
// const vditor = unref(vditorRef);
|
||||
// if (unref(initedRef) && props.value && vditor) {
|
||||
// vditor.setValue(props.value);
|
||||
// }
|
||||
// });
|
||||
// },
|
||||
// {
|
||||
// immediate: true,
|
||||
// }
|
||||
// );
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
init();
|
||||
|
@@ -1,13 +1,5 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
export const BasicMenu = createAsyncComponent(() => import('./src/BasicMenu.vue'), {
|
||||
loading: false,
|
||||
});
|
||||
export const BasicMenu = createAsyncComponent(() => import('./src/BasicMenu.vue'));
|
||||
|
||||
export const MenuTag = createAsyncComponent(() => import('./src/components/MenuItemTag.vue'), {
|
||||
loading: false,
|
||||
});
|
||||
|
||||
withInstall(BasicMenu);
|
||||
export const MenuTag = createAsyncComponent(() => import('./src/components/MenuItemTag.vue'));
|
||||
|
@@ -1,11 +1,10 @@
|
||||
import './src/index.less';
|
||||
import { withInstall } from '../util';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
export const BasicModal = createAsyncComponent(() => import('./src/BasicModal'));
|
||||
import BasicModal from './src/BasicModal';
|
||||
|
||||
withInstall(BasicModal);
|
||||
|
||||
export { BasicModal };
|
||||
export { useModalContext } from './src/useModalContext';
|
||||
export { useModal, useModalInner } from './src/useModal';
|
||||
export * from './src/types';
|
||||
|
@@ -1,6 +1,2 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const PageFooter = createAsyncComponent(() => import('./src/PageFooter.vue'));
|
||||
|
||||
withInstall(PageFooter);
|
||||
|
@@ -1,7 +1,4 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const QrCode = createAsyncComponent(() => import('./src/index.vue'));
|
||||
|
||||
withInstall(QrCode);
|
||||
export * from './src/types';
|
||||
|
@@ -3,10 +3,9 @@
|
||||
*/
|
||||
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const Scrollbar = createAsyncComponent(() => import('./src/index.vue'));
|
||||
import Scrollbar from './src/index.vue';
|
||||
|
||||
withInstall(Scrollbar);
|
||||
|
||||
export { Scrollbar };
|
||||
export type { ScrollbarType } from './src/types';
|
||||
|
@@ -1,7 +1,3 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
export const StrengthMeter = createAsyncComponent(() => import('./src/index'));
|
||||
|
||||
withInstall(StrengthMeter);
|
||||
export const StrengthMeter = createAsyncComponent(() => import('./src/index.vue'));
|
@@ -1,69 +0,0 @@
|
||||
@import (reference) '../../../design/index.less';
|
||||
|
||||
.strength-meter {
|
||||
position: relative;
|
||||
|
||||
&-bar {
|
||||
position: relative;
|
||||
height: 4px;
|
||||
margin: 10px auto 6px;
|
||||
background: @disabled-color;
|
||||
border-radius: 3px;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: block;
|
||||
width: 20%;
|
||||
height: inherit;
|
||||
background: transparent;
|
||||
border-color: @white;
|
||||
border-style: solid;
|
||||
border-width: 0 5px 0 5px;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: 20%;
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: 20%;
|
||||
}
|
||||
|
||||
&__fill {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: inherit;
|
||||
background: transparent;
|
||||
border-radius: inherit;
|
||||
transition: width 0.5s ease-in-out, background 0.25s;
|
||||
|
||||
&[data-score='0'] {
|
||||
width: 20%;
|
||||
background: darken(@error-color, 10%);
|
||||
}
|
||||
|
||||
&[data-score='1'] {
|
||||
width: 40%;
|
||||
background: @error-color;
|
||||
}
|
||||
|
||||
&[data-score='2'] {
|
||||
width: 60%;
|
||||
background: @warning-color;
|
||||
}
|
||||
|
||||
&[data-score='3'] {
|
||||
width: 80%;
|
||||
background: fade(@success-color, 50%);
|
||||
}
|
||||
|
||||
&[data-score='4'] {
|
||||
width: 100%;
|
||||
background: @success-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,77 +0,0 @@
|
||||
import './index.less';
|
||||
|
||||
import { PropType } from 'vue';
|
||||
|
||||
import { defineComponent, computed, ref, watch, unref, watchEffect } from 'vue';
|
||||
|
||||
import { Input } from 'ant-design-vue';
|
||||
|
||||
import zxcvbn from 'zxcvbn';
|
||||
import { extendSlots } from '/@/utils/helper/tsxHelper';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
||||
const prefixCls = 'strength-meter';
|
||||
export default defineComponent({
|
||||
name: 'StrengthMeter',
|
||||
props: {
|
||||
value: propTypes.string,
|
||||
|
||||
userInputs: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
|
||||
showInput: propTypes.bool.def(true),
|
||||
disabled: propTypes.bool,
|
||||
},
|
||||
emits: ['score-change', 'change'],
|
||||
setup(props, { emit, attrs, slots }) {
|
||||
const innerValueRef = ref('');
|
||||
const getPasswordStrength = computed(() => {
|
||||
const { userInputs, disabled } = props;
|
||||
if (disabled) return null;
|
||||
const innerValue = unref(innerValueRef);
|
||||
const score = innerValue
|
||||
? zxcvbn(unref(innerValueRef), (userInputs as string[]) || null).score
|
||||
: null;
|
||||
emit('score-change', score);
|
||||
return score;
|
||||
});
|
||||
|
||||
function handleChange(e: ChangeEvent) {
|
||||
innerValueRef.value = e.target.value;
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
innerValueRef.value = props.value || '';
|
||||
});
|
||||
watch(
|
||||
() => unref(innerValueRef),
|
||||
(val) => {
|
||||
emit('change', val);
|
||||
}
|
||||
);
|
||||
|
||||
return () => {
|
||||
const { showInput, disabled } = props;
|
||||
return (
|
||||
<div class={prefixCls}>
|
||||
{showInput && (
|
||||
<Input.Password
|
||||
{...attrs}
|
||||
allowClear={true}
|
||||
value={unref(innerValueRef)}
|
||||
onChange={handleChange}
|
||||
disabled={disabled}
|
||||
>
|
||||
{extendSlots(slots)}
|
||||
</Input.Password>
|
||||
)}
|
||||
<div class={`${prefixCls}-bar`}>
|
||||
<div class={`${prefixCls}-bar__fill`} data-score={unref(getPasswordStrength)}></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
156
src/components/StrengthMeter/src/index.vue
Normal file
156
src/components/StrengthMeter/src/index.vue
Normal file
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<div :class="prefixCls">
|
||||
<InputPassword
|
||||
v-if="showInput"
|
||||
v-bind="$attrs"
|
||||
allowClear
|
||||
:value="innerValueRef"
|
||||
@change="handleChange"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<template #[item]="data" v-for="item in Object.keys($slots)">
|
||||
<slot :name="item" v-bind="data" />
|
||||
</template>
|
||||
</InputPassword>
|
||||
<div :class="`${prefixCls}-bar`">
|
||||
<div :class="`${prefixCls}-bar--fill`" :data-score="getPasswordStrength"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { PropType } from 'vue';
|
||||
|
||||
import { defineComponent, computed, ref, watch, unref, watchEffect } from 'vue';
|
||||
|
||||
import { Input } from 'ant-design-vue';
|
||||
|
||||
import zxcvbn from 'zxcvbn';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'StrengthMeter',
|
||||
components: { InputPassword: Input.Password },
|
||||
props: {
|
||||
value: propTypes.string,
|
||||
|
||||
userInputs: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
|
||||
showInput: propTypes.bool.def(true),
|
||||
disabled: propTypes.bool,
|
||||
},
|
||||
emits: ['score-change', 'change'],
|
||||
setup(props, { emit }) {
|
||||
const innerValueRef = ref('');
|
||||
const { prefixCls } = useDesign('strength-meter');
|
||||
|
||||
const getPasswordStrength = computed(() => {
|
||||
const { userInputs, disabled } = props;
|
||||
if (disabled) return null;
|
||||
const innerValue = unref(innerValueRef);
|
||||
const score = innerValue
|
||||
? zxcvbn(unref(innerValueRef), (userInputs as string[]) || null).score
|
||||
: null;
|
||||
emit('score-change', score);
|
||||
return score;
|
||||
});
|
||||
|
||||
function handleChange(e: ChangeEvent) {
|
||||
innerValueRef.value = e.target.value;
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
innerValueRef.value = props.value || '';
|
||||
});
|
||||
watch(
|
||||
() => unref(innerValueRef),
|
||||
(val) => {
|
||||
emit('change', val);
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
getPasswordStrength,
|
||||
handleChange,
|
||||
prefixCls,
|
||||
innerValueRef,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import (reference) '../../../design/index.less';
|
||||
@prefix-cls: ~'@{namespace}-strength-meter';
|
||||
|
||||
.@{prefix-cls} {
|
||||
position: relative;
|
||||
|
||||
&-bar {
|
||||
position: relative;
|
||||
height: 4px;
|
||||
margin: 10px auto 6px;
|
||||
background: @disabled-color;
|
||||
border-radius: 3px;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
display: block;
|
||||
width: 20%;
|
||||
height: inherit;
|
||||
background: transparent;
|
||||
border-color: @white;
|
||||
border-style: solid;
|
||||
border-width: 0 5px 0 5px;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: 20%;
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: 20%;
|
||||
}
|
||||
|
||||
&--fill {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: inherit;
|
||||
background: transparent;
|
||||
border-radius: inherit;
|
||||
transition: width 0.5s ease-in-out, background 0.25s;
|
||||
|
||||
&[data-score='0'] {
|
||||
width: 20%;
|
||||
background: darken(@error-color, 10%);
|
||||
}
|
||||
|
||||
&[data-score='1'] {
|
||||
width: 40%;
|
||||
background: @error-color;
|
||||
}
|
||||
|
||||
&[data-score='2'] {
|
||||
width: 60%;
|
||||
background: @warning-color;
|
||||
}
|
||||
|
||||
&[data-score='3'] {
|
||||
width: 80%;
|
||||
background: fade(@success-color, 50%);
|
||||
}
|
||||
|
||||
&[data-score='4'] {
|
||||
width: 100%;
|
||||
background: @success-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -1,6 +1,2 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const Tinymce = createAsyncComponent(() => import('./src/Editor.vue'));
|
||||
|
||||
withInstall(Tinymce);
|
||||
|
@@ -1,9 +1,6 @@
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
import { withInstall } from '../util';
|
||||
|
||||
export const BasicTree = createAsyncComponent(() => import('./src/BasicTree'));
|
||||
|
||||
withInstall(BasicTree);
|
||||
|
||||
export type { ContextMenuItem } from '/@/hooks/web/useContextMenu';
|
||||
export * from './src/types';
|
||||
|
@@ -1,6 +1,2 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
export const BasicUpload = createAsyncComponent(() => import('./src/BasicUpload.vue'));
|
||||
|
||||
withInstall(BasicUpload);
|
||||
|
@@ -1,10 +1,6 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
export const BasicDragVerify = createAsyncComponent(() => import('./src/DragVerify'));
|
||||
export const RotateDragVerify = createAsyncComponent(() => import('./src/ImgRotate'));
|
||||
|
||||
withInstall(BasicDragVerify, RotateDragVerify);
|
||||
|
||||
export * from './src/types';
|
||||
|
@@ -1,7 +1,3 @@
|
||||
import { withInstall } from '../util';
|
||||
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
export const VScroll = createAsyncComponent(() => import('./src/index'));
|
||||
|
||||
withInstall(VScroll);
|
||||
|
Reference in New Issue
Block a user