mirror of
https://github.com/vbenjs/gf-vben-admin.git
synced 2025-01-23 11:50:20 +08:00
fix: hmr error fixed
修复部分组件可能会造成热更新异常的问题
This commit is contained in:
parent
9c5f11a54b
commit
5af452754b
@ -16,7 +16,9 @@
|
||||
- 修复点击关闭按钮、最大化按钮旁边的空白区域也会导致`Modal`关闭的问题
|
||||
- **BasicTree** 修复节点插槽不起作用的问题
|
||||
- **CodeEditor** 修复可能会造成的`Build`失败的问题
|
||||
- **其它** 修复多标签在某些情况下关闭页签不会跳转路由的问题
|
||||
- **其它**
|
||||
- 修复多标签在某些情况下关闭页签不会跳转路由的问题
|
||||
- 修复部分组件可能会造成热更新异常的问题
|
||||
|
||||
## 2.7.2(2021-09-14)
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<Dropdown :trigger="trigger" v-bind="$attrs">
|
||||
<a-dropdown :trigger="trigger" v-bind="$attrs">
|
||||
<span>
|
||||
<slot></slot>
|
||||
</span>
|
||||
<template #overlay>
|
||||
<Menu :selectedKeys="selectedKeys">
|
||||
<a-menu :selectedKeys="selectedKeys">
|
||||
<template v-for="item in dropMenuList" :key="`${item.event}`">
|
||||
<MenuItem
|
||||
<a-menu-item
|
||||
v-bind="getAttr(item.event)"
|
||||
@click="handleClickMenu(item)"
|
||||
:disabled="item.disabled"
|
||||
>
|
||||
<Popconfirm
|
||||
<a-popconfirm
|
||||
v-if="popconfirm && item.popConfirm"
|
||||
v-bind="getPopConfirmAttrs(item.popConfirm)"
|
||||
>
|
||||
@ -22,86 +22,73 @@
|
||||
<Icon :icon="item.icon" v-if="item.icon" />
|
||||
<span class="ml-1">{{ item.text }}</span>
|
||||
</div>
|
||||
</Popconfirm>
|
||||
</a-popconfirm>
|
||||
<template v-else>
|
||||
<Icon :icon="item.icon" v-if="item.icon" />
|
||||
<span class="ml-1">{{ item.text }}</span>
|
||||
</template>
|
||||
</MenuItem>
|
||||
<MenuDivider v-if="item.divider" :key="`d-${item.event}`" />
|
||||
</a-menu-item>
|
||||
<a-menu-divider v-if="item.divider" :key="`d-${item.event}`" />
|
||||
</template>
|
||||
</Menu>
|
||||
</a-menu>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { computed, PropType } from 'vue';
|
||||
import type { DropMenu } from './typing';
|
||||
|
||||
import { defineComponent } from 'vue';
|
||||
import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
|
||||
import { Icon } from '/@/components/Icon';
|
||||
import { omit } from 'lodash-es';
|
||||
import { isFunction } from '/@/utils/is';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BasicDropdown',
|
||||
components: {
|
||||
Dropdown,
|
||||
Menu,
|
||||
MenuItem: Menu.Item,
|
||||
MenuDivider: Menu.Divider,
|
||||
Icon,
|
||||
Popconfirm,
|
||||
},
|
||||
props: {
|
||||
popconfirm: Boolean,
|
||||
/**
|
||||
* the trigger mode which executes the drop-down action
|
||||
* @default ['hover']
|
||||
* @type string[]
|
||||
*/
|
||||
trigger: {
|
||||
type: [Array] as PropType<('contextmenu' | 'click' | 'hover')[]>,
|
||||
default: () => {
|
||||
return ['contextmenu'];
|
||||
},
|
||||
},
|
||||
dropMenuList: {
|
||||
type: Array as PropType<(DropMenu & Recordable)[]>,
|
||||
default: () => [],
|
||||
},
|
||||
selectedKeys: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
const ADropdown = Dropdown;
|
||||
const AMenu = Menu;
|
||||
const AMenuItem = Menu.Item;
|
||||
const AMenuDivider = Menu.Divider;
|
||||
const APopconfirm = Popconfirm;
|
||||
|
||||
const props = defineProps({
|
||||
popconfirm: Boolean,
|
||||
/**
|
||||
* the trigger mode which executes the drop-down action
|
||||
* @default ['hover']
|
||||
* @type string[]
|
||||
*/
|
||||
trigger: {
|
||||
type: [Array] as PropType<('contextmenu' | 'click' | 'hover')[]>,
|
||||
default: () => {
|
||||
return ['contextmenu'];
|
||||
},
|
||||
},
|
||||
emits: ['menuEvent'],
|
||||
setup(props, { emit }) {
|
||||
function handleClickMenu(item: DropMenu) {
|
||||
const { event } = item;
|
||||
const menu = props.dropMenuList.find((item) => `${item.event}` === `${event}`);
|
||||
emit('menuEvent', menu);
|
||||
item.onClick?.();
|
||||
}
|
||||
|
||||
const getPopConfirmAttrs = computed(() => {
|
||||
return (attrs) => {
|
||||
const originAttrs = omit(attrs, ['confirm', 'cancel', 'icon']);
|
||||
if (!attrs.onConfirm && attrs.confirm && isFunction(attrs.confirm))
|
||||
originAttrs['onConfirm'] = attrs.confirm;
|
||||
if (!attrs.onCancel && attrs.cancel && isFunction(attrs.cancel))
|
||||
originAttrs['onCancel'] = attrs.cancel;
|
||||
return originAttrs;
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
handleClickMenu,
|
||||
getPopConfirmAttrs,
|
||||
getAttr: (key: string | number) => ({ key }),
|
||||
};
|
||||
dropMenuList: {
|
||||
type: Array as PropType<(DropMenu & Recordable)[]>,
|
||||
default: () => [],
|
||||
},
|
||||
selectedKeys: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['menuEvent']);
|
||||
|
||||
function handleClickMenu(item: DropMenu) {
|
||||
const { event } = item;
|
||||
const menu = props.dropMenuList.find((item) => `${item.event}` === `${event}`);
|
||||
emit('menuEvent', menu);
|
||||
item.onClick?.();
|
||||
}
|
||||
|
||||
const getPopConfirmAttrs = computed(() => {
|
||||
return (attrs) => {
|
||||
const originAttrs = omit(attrs, ['confirm', 'cancel', 'icon']);
|
||||
if (!attrs.onConfirm && attrs.confirm && isFunction(attrs.confirm))
|
||||
originAttrs['onConfirm'] = attrs.confirm;
|
||||
if (!attrs.onCancel && attrs.cancel && isFunction(attrs.cancel))
|
||||
originAttrs['onCancel'] = attrs.cancel;
|
||||
return originAttrs;
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
@ -7,7 +7,7 @@
|
||||
v-model:value="currentSelect"
|
||||
>
|
||||
<template #addonAfter>
|
||||
<Popover
|
||||
<a-popover
|
||||
placement="bottomLeft"
|
||||
trigger="click"
|
||||
v-model="visible"
|
||||
@ -17,7 +17,7 @@
|
||||
<div class="flex justify-between">
|
||||
<a-input
|
||||
:placeholder="t('component.icon.search')"
|
||||
@change="handleSearchChange"
|
||||
@change="debounceHandleSearchChange"
|
||||
allowClear
|
||||
/>
|
||||
</div>
|
||||
@ -53,7 +53,7 @@
|
||||
</ul>
|
||||
</ScrollContainer>
|
||||
<div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize">
|
||||
<Pagination
|
||||
<a-pagination
|
||||
showLessItems
|
||||
size="small"
|
||||
:pageSize="pageSize"
|
||||
@ -63,7 +63,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<template v-else
|
||||
><div class="p-5"><Empty /></div>
|
||||
><div class="p-5"><a-empty /></div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -71,16 +71,14 @@
|
||||
<SvgIcon :name="currentSelect" />
|
||||
</span>
|
||||
<Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else />
|
||||
</Popover>
|
||||
</a-popover>
|
||||
</template>
|
||||
</a-input>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, watchEffect, watch, unref } from 'vue';
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watchEffect, watch, unref } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { ScrollContainer } from '/@/components/Container';
|
||||
|
||||
import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
|
||||
import Icon from './Icon.vue';
|
||||
import SvgIcon from './SvgIcon.vue';
|
||||
@ -94,6 +92,12 @@
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import svgIcons from 'virtual:svg-icons-names';
|
||||
|
||||
// 没有使用别名引入,是因为WebStorm当前版本还不能正确识别,会报unused警告
|
||||
const AInput = Input;
|
||||
const APopover = Popover;
|
||||
const APagination = Pagination;
|
||||
const AEmpty = Empty;
|
||||
|
||||
function getIcons() {
|
||||
const data = iconsData as any;
|
||||
const prefix: string = data?.prefix ?? '';
|
||||
@ -110,88 +114,70 @@
|
||||
return svgIcons.map((icon) => icon.replace('icon-', ''));
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'IconPicker',
|
||||
components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty, SvgIcon },
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
value: propTypes.string,
|
||||
width: propTypes.string.def('100%'),
|
||||
pageSize: propTypes.number.def(140),
|
||||
copy: propTypes.bool.def(false),
|
||||
mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
|
||||
},
|
||||
emits: ['change', 'update:value'],
|
||||
setup(props, { emit }) {
|
||||
const isSvgMode = props.mode === 'svg';
|
||||
const icons = isSvgMode ? getSvgIcons() : getIcons();
|
||||
|
||||
const currentSelect = ref('');
|
||||
const visible = ref(false);
|
||||
const currentList = ref(icons);
|
||||
|
||||
const { t } = useI18n();
|
||||
const { prefixCls } = useDesign('icon-picker');
|
||||
|
||||
const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);
|
||||
const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const { getPaginationList, getTotal, setCurrentPage } = usePagination(
|
||||
currentList,
|
||||
props.pageSize,
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
currentSelect.value = props.value;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => currentSelect.value,
|
||||
(v) => {
|
||||
emit('update:value', v);
|
||||
return emit('change', v);
|
||||
},
|
||||
);
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
setCurrentPage(page);
|
||||
}
|
||||
|
||||
function handleClick(icon: string) {
|
||||
currentSelect.value = icon;
|
||||
if (props.copy) {
|
||||
clipboardRef.value = icon;
|
||||
if (unref(isSuccessRef)) {
|
||||
createMessage.success(t('component.icon.copy'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearchChange(e: ChangeEvent) {
|
||||
const value = e.target.value;
|
||||
if (!value) {
|
||||
setCurrentPage(1);
|
||||
currentList.value = icons;
|
||||
return;
|
||||
}
|
||||
currentList.value = icons.filter((item) => item.includes(value));
|
||||
}
|
||||
|
||||
return {
|
||||
t,
|
||||
prefixCls,
|
||||
visible,
|
||||
isSvgMode,
|
||||
getTotal,
|
||||
getPaginationList,
|
||||
handlePageChange,
|
||||
handleClick,
|
||||
currentSelect,
|
||||
handleSearchChange: debounceHandleSearchChange,
|
||||
};
|
||||
},
|
||||
const props = defineProps({
|
||||
value: propTypes.string,
|
||||
width: propTypes.string.def('100%'),
|
||||
pageSize: propTypes.number.def(140),
|
||||
copy: propTypes.bool.def(false),
|
||||
mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
|
||||
});
|
||||
|
||||
const emit = defineEmits(['change', 'update:value']);
|
||||
|
||||
const isSvgMode = props.mode === 'svg';
|
||||
const icons = isSvgMode ? getSvgIcons() : getIcons();
|
||||
|
||||
const currentSelect = ref('');
|
||||
const visible = ref(false);
|
||||
const currentList = ref(icons);
|
||||
|
||||
const { t } = useI18n();
|
||||
const { prefixCls } = useDesign('icon-picker');
|
||||
|
||||
const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);
|
||||
const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const { getPaginationList, getTotal, setCurrentPage } = usePagination(
|
||||
currentList,
|
||||
props.pageSize,
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
currentSelect.value = props.value;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => currentSelect.value,
|
||||
(v) => {
|
||||
emit('update:value', v);
|
||||
return emit('change', v);
|
||||
},
|
||||
);
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
setCurrentPage(page);
|
||||
}
|
||||
|
||||
function handleClick(icon: string) {
|
||||
currentSelect.value = icon;
|
||||
if (props.copy) {
|
||||
clipboardRef.value = icon;
|
||||
if (unref(isSuccessRef)) {
|
||||
createMessage.success(t('component.icon.copy'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearchChange(e: ChangeEvent) {
|
||||
const value = e.target.value;
|
||||
if (!value) {
|
||||
setCurrentPage(1);
|
||||
currentList.value = icons;
|
||||
return;
|
||||
}
|
||||
currentList.value = icons.filter((item) => item.includes(value));
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
@prefix-cls: ~'@{namespace}-icon-picker';
|
||||
|
Loading…
Reference in New Issue
Block a user