Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

自由容器组件支持层级调整及重叠时点击选中 #11432

Merged
merged 2 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/amis-editor-core/src/component/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,11 @@ export default class Editor extends Component<EditorProps> {
<MobileDevTool
container={this.mainPreviewRef.current}
previewBody={this.mainPreviewBodyRef.current?.currentDom}
onChangeScale={scale => {
if (scale >= 0) {
this.store.setScale(scale / 100);
}
}}
/>
)}
<Preview
Expand Down
42 changes: 42 additions & 0 deletions packages/amis-editor-core/src/component/HighlightBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,46 @@ export default observer(function ({
manager.startDrag(id, e);
}, []);

// 组件选中状态支持点击激活内部的组件
const handleClick = React.useCallback((e: React.MouseEvent) => {
let left = e.clientX;
let top = e.clientY;

const layer: HTMLElement = store.getLayer()!;
const layerRect = layer.getBoundingClientRect();
const iframe = store.getIframe();

// 计算鼠标位置在页面中的实际位置,如果iframe存在,需要考虑iframe偏移量以及iframe的缩放比例
let scrollTop = 0;
if (iframe) {
scrollTop = iframe.contentWindow?.scrollY || 0;
left -= layerRect.left;
top -= layerRect.top;
top += scrollTop;
// 如果有缩放比例,重新计算位置
const scale = store.getScale();
if (scale >= 0) {
left = left / scale;
top = top / scale;
}
} else {
scrollTop = document.querySelector('.ae-Preview-body')!.scrollTop || 0;
top += scrollTop;
}

let elements = store.getDoc().elementsFromPoint(left, top);

let node = elements.find(
(ele: Element) =>
ele.hasAttribute('data-editor-id') &&
ele.getAttribute('data-editor-id') !== id
);
if (node) {
const nodeId = node.getAttribute('data-editor-id')!;
store.setActiveId(nodeId);
}
}, []);

const mainRef = React.createRef<HTMLDivElement>();
const toolbars = store.sortedToolbars;
const secondaryToolbars = store.sortedSecondaryToolbars;
Expand Down Expand Up @@ -251,12 +291,14 @@ export default observer(function ({
onMouseEnter={handleMouseEnter}
draggable={!!curFreeContainerId || isDraggableContainer}
onDragStart={handleDragStart}
onClick={handleClick}
>
{isActive && !readonly ? (
<div
className={`ae-Editor-toolbarPopover ${
isRightElem ? 'is-right-elem' : ''
}`}
onClick={e => e.stopPropagation()}
>
<div className="ae-Editor-nav">
{node.host ? (
Expand Down
33 changes: 33 additions & 0 deletions packages/amis-editor-core/src/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1476,6 +1476,39 @@ export class EditorManager {

closeContextMenu() {}

/**
* 自由容器内元素置于顶层
*/
moveTop() {
const store = this.store;
if (!store.activeId) {
return;
}

const node = store.getNodeById(store.activeId)!;
const regionNode = node.parent;
this.move(regionNode.id, regionNode.region, node.id);
}

/**
* 自由容器内元素置于底层
*/
moveBottom() {
const store = this.store;
if (!store.activeId) {
return;
}
const node = store.getNodeById(store.activeId)!;
const regionNode = node.parent;

this.move(
regionNode.id,
regionNode.region,
node.id,
regionNode.children[0].id
);
}

/**
* 将当前选中的节点上移
*/
Expand Down
75 changes: 54 additions & 21 deletions packages/amis-editor-core/src/plugin/BasicToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,60 @@ export class BasicToolbarPlugin extends BasePlugin {

menus.push('|');

const idx = Array.isArray(parent) ? parent.indexOf(schema) : -1;
if (host?.schema?.isFreeContainer) {
menus.push({
label: '调整层级',
disabled:
!Array.isArray(parent) || parent.length <= 1 || !node.moveable,
children: [
{
id: 'move-top',
label: '置于顶层',
disabled: idx === parent.length - 1,
onSelect: () => manager.moveTop()
},
{
id: 'move-bottom',
label: '置于底层',
disabled: idx === 0,
onSelect: () => manager.moveBottom()
},
{
id: 'move-forward',
label: '上移一层',
disabled: idx === parent.length - 1,
onSelect: () => manager.moveDown()
},
{
id: 'move-backward',
label: '下移一层',
disabled: idx === 0,
onSelect: () => manager.moveUp()
}
]
});
} else {
menus.push({
id: 'move-forward',
label: '向前移动',
disabled: !(Array.isArray(parent) && idx > 0) || !node.moveable,
// || !node.prevSibling,
onSelect: () => manager.moveUp()
});

menus.push({
id: 'move-backward',
label: '向后移动',
disabled:
!(Array.isArray(parent) && idx < parent.length - 1) ||
!node.moveable,
// || !node.nextSibling,
onSelect: () => manager.moveDown()
});
}
menus.push('|');

menus.push({
id: 'copy',
label: '重复一份',
Expand Down Expand Up @@ -408,27 +462,6 @@ export class BasicToolbarPlugin extends BasePlugin {
onSelect: () => manager.del(id)
});

menus.push('|');

const idx = Array.isArray(parent) ? parent.indexOf(schema) : -1;

menus.push({
id: 'move-forward',
label: '向前移动',
disabled: !(Array.isArray(parent) && idx > 0) || !node.moveable,
// || !node.prevSibling,
onSelect: () => manager.moveUp()
});

menus.push({
id: 'move-backward',
label: '向后移动',
disabled:
!(Array.isArray(parent) && idx < parent.length - 1) || !node.moveable,
// || !node.nextSibling,
onSelect: () => manager.moveDown()
});

/** 「点选(默认向后插入)」+ 「向前移动」可以替换 「前面插入节点」 */
/*
menus.push({
Expand Down
8 changes: 8 additions & 0 deletions packages/amis-editor-core/src/store/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,7 @@ export const MainStore = types
let versionIdIndex = 0;
let subEditor: any = null;
let layer: HTMLElement | undefined = undefined;
let scale: number = 1;
let doc: Document = document;
let iframe: HTMLIFrameElement | undefined = undefined;

Expand Down Expand Up @@ -1142,6 +1143,13 @@ export const MainStore = types
getLayer() {
return layer;
},
// iframe 缩放比例
setScale(num: number) {
scale = num;
},
getScale() {
return scale;
},
setDoc(value: any) {
doc = value;
},
Expand Down
5 changes: 4 additions & 1 deletion packages/amis-ui/src/components/MobileDevTool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export default function MobileDevTool(props: {
container: HTMLElement | null;
previewBody: HTMLElement | null;
border?: number;
onChangeScale?: (scale: number) => void;
}) {
const [dimension, setDimension] = React.useState(
() =>
Expand All @@ -114,7 +115,7 @@ export default function MobileDevTool(props: {
const [scale, setScale] = React.useState(100);
const [autoScale, setAutoScale] = React.useState(100);

const {container, previewBody} = props;
const {container, previewBody, onChangeScale} = props;

const resizeObserver = new ResizeObserver(debounce(updateAutoScale, 300));

Expand All @@ -137,6 +138,7 @@ export default function MobileDevTool(props: {
defaultScale.current = scale;
}
setScale(scale);
onChangeScale?.(scale);

updatePreviewScale(scale);
resizeObserver.observe(container);
Expand Down Expand Up @@ -167,6 +169,7 @@ export default function MobileDevTool(props: {

function updateScale(scale: number) {
setScale(scale);
onChangeScale?.(scale);
localStorage.setItem('amis-mobile-dev-tool-scale', scale + '');
}

Expand Down
Loading