Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
This commit is contained in:
@@ -105,10 +105,17 @@ const shouldDraggable = computed(
|
||||
() => draggable.value && !shouldFullscreen.value && header.value,
|
||||
);
|
||||
|
||||
const getAppendTo = computed(() => {
|
||||
return appendToMain.value
|
||||
? `#${ELEMENT_ID_MAIN_CONTENT}>div:not(.absolute)>div`
|
||||
: undefined;
|
||||
});
|
||||
|
||||
const { dragging, transform } = useModalDraggable(
|
||||
dialogRef,
|
||||
headerRef,
|
||||
shouldDraggable,
|
||||
getAppendTo,
|
||||
);
|
||||
|
||||
const firstOpened = ref(false);
|
||||
@@ -198,11 +205,6 @@ function handleFocusOutside(e: Event) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
const getAppendTo = computed(() => {
|
||||
return appendToMain.value
|
||||
? `#${ELEMENT_ID_MAIN_CONTENT}>div:not(.absolute)>div`
|
||||
: undefined;
|
||||
});
|
||||
|
||||
const getForceMount = computed(() => {
|
||||
return !unref(destroyOnClose) && unref(firstOpened);
|
||||
@@ -224,7 +226,8 @@ function handleClosed() {
|
||||
:append-to="getAppendTo"
|
||||
:class="
|
||||
cn(
|
||||
'left-0 right-0 top-[10vh] mx-auto flex max-h-[80%] w-[520px] flex-col p-0 sm:rounded-[var(--radius)]',
|
||||
'left-0 right-0 top-[10vh] mx-auto flex max-h-[80%] w-[520px] flex-col p-0',
|
||||
shouldFullscreen ? 'sm:rounded-none' : 'sm:rounded-[var(--radius)]',
|
||||
modalClass,
|
||||
{
|
||||
'border-border border': bordered,
|
||||
|
||||
@@ -13,6 +13,7 @@ export function useModalDraggable(
|
||||
targetRef: Ref<HTMLElement | undefined>,
|
||||
dragRef: Ref<HTMLElement | undefined>,
|
||||
draggable: ComputedRef<boolean>,
|
||||
containerSelector?: ComputedRef<string | undefined>,
|
||||
) {
|
||||
const transform = reactive({
|
||||
offsetX: 0,
|
||||
@@ -30,20 +31,36 @@ export function useModalDraggable(
|
||||
}
|
||||
|
||||
const targetRect = targetRef.value.getBoundingClientRect();
|
||||
|
||||
const { offsetX, offsetY } = transform;
|
||||
const targetLeft = targetRect.left;
|
||||
const targetTop = targetRect.top;
|
||||
const targetWidth = targetRect.width;
|
||||
const targetHeight = targetRect.height;
|
||||
const docElement = document.documentElement;
|
||||
const clientWidth = docElement.clientWidth;
|
||||
const clientHeight = docElement.clientHeight;
|
||||
|
||||
const minLeft = -targetLeft + offsetX;
|
||||
const minTop = -targetTop + offsetY;
|
||||
const maxLeft = clientWidth - targetLeft - targetWidth + offsetX;
|
||||
const maxTop = clientHeight - targetTop - targetHeight + offsetY;
|
||||
let containerRect: DOMRect | null = null;
|
||||
|
||||
if (containerSelector?.value) {
|
||||
const container = document.querySelector(containerSelector.value);
|
||||
if (container) {
|
||||
containerRect = container.getBoundingClientRect();
|
||||
}
|
||||
}
|
||||
|
||||
let maxLeft, maxTop, minLeft, minTop;
|
||||
if (containerRect) {
|
||||
minLeft = containerRect.left - targetLeft + offsetX;
|
||||
maxLeft = containerRect.right - targetLeft - targetWidth + offsetX;
|
||||
minTop = containerRect.top - targetTop + offsetY;
|
||||
maxTop = containerRect.bottom - targetTop - targetHeight + offsetY;
|
||||
} else {
|
||||
const docElement = document.documentElement;
|
||||
const clientWidth = docElement.clientWidth;
|
||||
const clientHeight = docElement.clientHeight;
|
||||
minLeft = -targetLeft + offsetX;
|
||||
minTop = -targetTop + offsetY;
|
||||
maxLeft = clientWidth - targetLeft - targetWidth + offsetX;
|
||||
maxTop = clientHeight - targetTop - targetHeight + offsetY;
|
||||
}
|
||||
|
||||
const onMousemove = (e: MouseEvent) => {
|
||||
let moveX = offsetX + e.clientX - downX;
|
||||
|
||||
@@ -23,6 +23,7 @@ const props = withDefaults(defineProps<TreeProps>(), {
|
||||
defaultExpandedKeys: () => [],
|
||||
defaultExpandedLevel: 0,
|
||||
disabled: false,
|
||||
disabledField: 'disabled',
|
||||
expanded: () => [],
|
||||
iconField: 'icon',
|
||||
labelField: 'label',
|
||||
@@ -101,16 +102,37 @@ function updateTreeValue() {
|
||||
if (val === undefined) {
|
||||
treeValue.value = undefined;
|
||||
} else {
|
||||
treeValue.value = Array.isArray(val)
|
||||
? val.map((v) => getItemByValue(v))
|
||||
: getItemByValue(val);
|
||||
if (Array.isArray(val)) {
|
||||
const filteredValues = val.filter((v) => {
|
||||
const item = getItemByValue(v);
|
||||
return item && !get(item, props.disabledField);
|
||||
});
|
||||
treeValue.value = filteredValues.map((v) => getItemByValue(v));
|
||||
|
||||
if (filteredValues.length !== val.length) {
|
||||
modelValue.value = filteredValues;
|
||||
}
|
||||
} else {
|
||||
const item = getItemByValue(val);
|
||||
if (item && !get(item, props.disabledField)) {
|
||||
treeValue.value = item;
|
||||
} else {
|
||||
treeValue.value = undefined;
|
||||
modelValue.value = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateModelValue(val: Arrayable<Recordable<any>>) {
|
||||
modelValue.value = Array.isArray(val)
|
||||
? val.map((v) => get(v, props.valueField))
|
||||
: get(val, props.valueField);
|
||||
if (Array.isArray(val)) {
|
||||
const filteredVal = val.filter((v) => !get(v, props.disabledField));
|
||||
modelValue.value = filteredVal.map((v) => get(v, props.valueField));
|
||||
} else {
|
||||
if (val && !get(val, props.disabledField)) {
|
||||
modelValue.value = get(val, props.valueField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function expandToLevel(level: number) {
|
||||
@@ -149,10 +171,18 @@ function collapseAll() {
|
||||
expanded.value = [];
|
||||
}
|
||||
|
||||
function isNodeDisabled(item: FlattenedItem<Recordable<any>>) {
|
||||
return props.disabled || get(item.value, props.disabledField);
|
||||
}
|
||||
|
||||
function onToggle(item: FlattenedItem<Recordable<any>>) {
|
||||
emits('expand', item);
|
||||
}
|
||||
function onSelect(item: FlattenedItem<Recordable<any>>, isSelected: boolean) {
|
||||
if (isNodeDisabled(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!props.checkStrictly &&
|
||||
props.multiple &&
|
||||
@@ -224,28 +254,34 @@ defineExpose({
|
||||
:class="
|
||||
cn('cursor-pointer', getNodeClass?.(item), {
|
||||
'data-[selected]:bg-accent': !multiple,
|
||||
'cursor-not-allowed': disabled,
|
||||
'cursor-not-allowed': isNodeDisabled(item),
|
||||
})
|
||||
"
|
||||
v-bind="
|
||||
Object.assign(item.bind, {
|
||||
onfocus: disabled ? 'this.blur()' : undefined,
|
||||
onfocus: isNodeDisabled(item) ? 'this.blur()' : undefined,
|
||||
disabled: isNodeDisabled(item),
|
||||
})
|
||||
"
|
||||
@select="
|
||||
(event) => {
|
||||
(event: any) => {
|
||||
if (isNodeDisabled(item)) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
if (event.detail.originalEvent.type === 'click') {
|
||||
event.preventDefault();
|
||||
}
|
||||
!disabled && onSelect(item, event.detail.isSelected);
|
||||
onSelect(item, event.detail.isSelected);
|
||||
}
|
||||
"
|
||||
@toggle="
|
||||
(event) => {
|
||||
(event: any) => {
|
||||
if (event.detail.originalEvent.type === 'click') {
|
||||
event.preventDefault();
|
||||
}
|
||||
!disabled && onToggle(item);
|
||||
!isNodeDisabled(item) && onToggle(item);
|
||||
}
|
||||
"
|
||||
class="tree-node focus:ring-grass8 my-0.5 flex items-center rounded px-2 py-1 outline-none focus:ring-2"
|
||||
@@ -266,24 +302,32 @@ defineExpose({
|
||||
</div>
|
||||
<Checkbox
|
||||
v-if="multiple"
|
||||
:checked="isSelected"
|
||||
:disabled="disabled"
|
||||
:indeterminate="isIndeterminate"
|
||||
:checked="isSelected && !isNodeDisabled(item)"
|
||||
:disabled="isNodeDisabled(item)"
|
||||
:indeterminate="isIndeterminate && !isNodeDisabled(item)"
|
||||
@click="
|
||||
() => {
|
||||
!disabled && handleSelect();
|
||||
// onSelect(item, !isSelected);
|
||||
(event: MouseEvent) => {
|
||||
if (isNodeDisabled(item)) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
handleSelect();
|
||||
}
|
||||
"
|
||||
/>
|
||||
<div
|
||||
class="flex items-center gap-1 pl-2"
|
||||
@click="
|
||||
(_event) => {
|
||||
// $event.stopPropagation();
|
||||
// $event.preventDefault();
|
||||
!disabled && handleSelect();
|
||||
// onSelect(item, !isSelected);
|
||||
(event: MouseEvent) => {
|
||||
if (isNodeDisabled(item)) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
handleSelect();
|
||||
}
|
||||
"
|
||||
>
|
||||
|
||||
@@ -22,6 +22,8 @@ export interface TreeProps {
|
||||
defaultValue?: Arrayable<number | string>;
|
||||
/** 禁用 */
|
||||
disabled?: boolean;
|
||||
/** 禁用字段名 */
|
||||
disabledField?: string;
|
||||
/** 自定义节点类名 */
|
||||
getNodeClass?: (item: FlattenedItem<Recordable<any>>) => string;
|
||||
iconField?: string;
|
||||
|
||||
Reference in New Issue
Block a user