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