11import {
22 IPublicEnumContextMenuType ,
3+ IPublicEnumDragObjectType ,
34 IPublicEnumTransformStage ,
45 IPublicModelNode ,
56 IPublicModelPluginContext ,
7+ IPublicTypeDragNodeDataObject ,
8+ IPublicTypeI18nData ,
69 IPublicTypeNodeSchema ,
710} from '@alilc/lowcode-types' ;
8- import { isProjectSchema } from '@alilc/lowcode-utils' ;
11+ import { isI18nData , isProjectSchema } from '@alilc/lowcode-utils' ;
912import { Notification } from '@alifd/next' ;
10- import { intl } from '../locale' ;
13+ import { intl , getLocale } from '../locale' ;
1114
1215function getNodesSchema ( nodes : IPublicModelNode [ ] ) {
1316 const componentsTree = nodes . map ( ( node ) => node ?. exportSchema ( IPublicEnumTransformStage . Clone ) ) ;
1417 const data = { type : 'nodeSchema' , componentsMap : { } , componentsTree } ;
1518 return data ;
1619}
1720
21+ function getIntlStr ( data : string | IPublicTypeI18nData ) {
22+ if ( ! isI18nData ( data ) ) {
23+ return data ;
24+ }
25+
26+ const locale = getLocale ( ) ;
27+ return data [ locale ] || data [ 'zh-CN' ] || data [ 'zh_CN' ] || data [ 'en-US' ] || data [ 'en_US' ] || '' ;
28+ }
29+
1830async function getClipboardText ( ) : Promise < IPublicTypeNodeSchema [ ] > {
1931 return new Promise ( ( resolve , reject ) => {
2032 // 使用 Clipboard API 读取剪贴板内容
@@ -71,12 +83,18 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
7183 material . addContextMenuOption ( {
7284 name : 'copyAndPaste' ,
7385 title : intl ( 'CopyAndPaste' ) ,
86+ disabled : ( nodes ) => {
87+ return nodes ?. filter ( ( node ) => ! node ?. canPerformAction ( 'copy' ) ) . length > 0 ;
88+ } ,
7489 condition : ( nodes ) => {
7590 return nodes . length === 1 ;
7691 } ,
7792 action ( nodes ) {
7893 const node = nodes [ 0 ] ;
7994 const { document : doc , parent, index } = node ;
95+ const data = getNodesSchema ( nodes ) ;
96+ clipboard . setData ( data ) ;
97+
8098 if ( parent ) {
8199 const newNode = doc ?. insertNode ( parent , node , ( index ?? 0 ) + 1 , true ) ;
82100 newNode ?. select ( ) ;
@@ -87,6 +105,9 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
87105 material . addContextMenuOption ( {
88106 name : 'copy' ,
89107 title : intl ( 'Copy' ) ,
108+ disabled : ( nodes ) => {
109+ return nodes ?. filter ( ( node ) => ! node ?. canPerformAction ( 'copy' ) ) . length > 0 ;
110+ } ,
90111 condition ( nodes ) {
91112 return nodes . length > 0 ;
92113 } ,
@@ -101,7 +122,7 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
101122 } ) ;
102123
103124 material . addContextMenuOption ( {
104- name : 'zhantieToBottom ' ,
125+ name : 'pasteToBottom ' ,
105126 title : intl ( 'PasteToTheBottom' ) ,
106127 condition : ( nodes ) => {
107128 return nodes . length === 1 ;
@@ -116,10 +137,30 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
116137
117138 try {
118139 const nodeSchema = await getClipboardText ( ) ;
140+ if ( nodeSchema . length === 0 ) {
141+ return ;
142+ }
119143 if ( parent ) {
120- nodeSchema . forEach ( ( schema , schemaIndex ) => {
121- doc ?. insertNode ( parent , schema , ( index ?? 0 ) + 1 + schemaIndex , true ) ;
144+ let canAddNodes = nodeSchema . filter ( ( nodeSchema : IPublicTypeNodeSchema ) => {
145+ const dragNodeObject : IPublicTypeDragNodeDataObject = {
146+ type : IPublicEnumDragObjectType . NodeData ,
147+ data : nodeSchema ,
148+ } ;
149+ return doc ?. checkNesting ( parent , dragNodeObject ) ;
150+ } ) ;
151+ if ( canAddNodes . length === 0 ) {
152+ Notification . open ( {
153+ content : `${ nodeSchema . map ( d => getIntlStr ( d . title || d . componentName ) ) . join ( ',' ) } 等组件无法放置到${ getIntlStr ( parent . title || parent . componentName as any ) } 内` ,
154+ type : 'error' ,
155+ } ) ;
156+ return ;
157+ }
158+ const nodes : IPublicModelNode [ ] = [ ] ;
159+ canAddNodes . forEach ( ( schema , schemaIndex ) => {
160+ const node = doc ?. insertNode ( parent , schema , ( index ?? 0 ) + 1 + schemaIndex , true ) ;
161+ node && nodes . push ( node ) ;
122162 } ) ;
163+ doc ?. selection . selectAll ( nodes . map ( ( node ) => node ?. id ) ) ;
123164 }
124165 } catch ( error ) {
125166 console . error ( error ) ;
@@ -128,7 +169,7 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
128169 } ) ;
129170
130171 material . addContextMenuOption ( {
131- name : 'zhantieToInner ' ,
172+ name : 'pasteToInner ' ,
132173 title : intl ( 'PasteToTheInside' ) ,
133174 condition : ( nodes ) => {
134175 return nodes . length === 1 ;
@@ -140,19 +181,35 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
140181 } ,
141182 async action ( nodes ) {
142183 const node = nodes [ 0 ] ;
143- const { document : doc , parent } = node ;
184+ const { document : doc } = node ;
144185
145186 try {
146187 const nodeSchema = await getClipboardText ( ) ;
147- if ( parent ) {
148- const index = node . children ?. size || 0 ;
149-
150- if ( parent ) {
151- nodeSchema . forEach ( ( schema , schemaIndex ) => {
152- doc ?. insertNode ( node , schema , ( index ?? 0 ) + 1 + schemaIndex , true ) ;
153- } ) ;
154- }
188+ const index = node . children ?. size || 0 ;
189+ if ( nodeSchema . length === 0 ) {
190+ return ;
155191 }
192+ let canAddNodes = nodeSchema . filter ( ( nodeSchema : IPublicTypeNodeSchema ) => {
193+ const dragNodeObject : IPublicTypeDragNodeDataObject = {
194+ type : IPublicEnumDragObjectType . NodeData ,
195+ data : nodeSchema ,
196+ } ;
197+ return doc ?. checkNesting ( node , dragNodeObject ) ;
198+ } ) ;
199+ if ( canAddNodes . length === 0 ) {
200+ Notification . open ( {
201+ content : `${ nodeSchema . map ( d => getIntlStr ( d . title || d . componentName ) ) . join ( ',' ) } 等组件无法放置到${ getIntlStr ( node . title || node . componentName as any ) } 内` ,
202+ type : 'error' ,
203+ } ) ;
204+ return ;
205+ }
206+
207+ const nodes : IPublicModelNode [ ] = [ ] ;
208+ nodeSchema . forEach ( ( schema , schemaIndex ) => {
209+ const newNode = doc ?. insertNode ( node , schema , ( index ?? 0 ) + 1 + schemaIndex , true ) ;
210+ newNode && nodes . push ( newNode ) ;
211+ } ) ;
212+ doc ?. selection . selectAll ( nodes . map ( ( node ) => node ?. id ) ) ;
156213 } catch ( error ) {
157214 console . error ( error ) ;
158215 }
@@ -162,6 +219,9 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
162219 material . addContextMenuOption ( {
163220 name : 'delete' ,
164221 title : intl ( 'Delete' ) ,
222+ disabled ( nodes ) {
223+ return nodes ?. filter ( ( node ) => ! node ?. canPerformAction ( 'remove' ) ) . length > 0 ;
224+ } ,
165225 condition ( nodes ) {
166226 return nodes . length > 0 ;
167227 } ,
0 commit comments