Skip to content

Commit a9c4119

Browse files
committed
feat: attributes sync
1 parent e11b4d0 commit a9c4119

7 files changed

Lines changed: 129 additions & 10 deletions

File tree

packages/canvas/container/src/CanvasContainer.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ export default {
476476
updateStyleNode,
477477
updatePropsNode,
478478
updateMethodNode,
479+
updateAttributesNode,
479480
remoteStates
480481
} = useCollabSchema({
481482
roomId: 'schema-yjs',
@@ -491,6 +492,7 @@ export default {
491492
updateStyleNode,
492493
updatePropsNode,
493494
updateMethodNode,
495+
updateAttributesNode,
494496
remoteStates
495497
})
496498

packages/multi-person-collaboration/src/composables/useCollabSchema.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
type Node,
77
type PositionType,
88
type RootNode,
9+
type UpdateAttributesOperation,
910
type UpdateMethodsOperation,
1011
type UserAwareness
1112
} from '../type'
@@ -85,7 +86,7 @@ export function useCollabSchema(options: UseCollabSchemaOptions) {
8586
schemaModel.updatedNodeCss(styleStr, nodeId, className)
8687
}
8788

88-
// settings, 修改节点属性
89+
// settings, 修改节点设置
8990
const updatePropsNode = (newProps: Record<string, any>, nodeId: string, overwrite: boolean) => {
9091
schemaModel.updatedNodeProps(newProps, nodeId, overwrite)
9192
}
@@ -95,6 +96,11 @@ export function useCollabSchema(options: UseCollabSchemaOptions) {
9596
schemaModel.updatedNodeMethods(operation)
9697
}
9798

99+
// Attributes,修改节点属性
100+
const updateAttributesNode = (operation: UpdateAttributesOperation) => {
101+
schemaModel.updatedNodeAttributes(operation)
102+
}
103+
98104
// 用户信息同步 方法
99105
const updateUserSelection = (selectedNode: any) => {
100106
updateLocalStateField('selection', selectedNode)
@@ -130,6 +136,7 @@ export function useCollabSchema(options: UseCollabSchemaOptions) {
130136
moveDownSharedNode,
131137
updateStyleNode,
132138
updatePropsNode,
133-
updateMethodNode
139+
updateMethodNode,
140+
updateAttributesNode
134141
}
135142
}

packages/multi-person-collaboration/src/models/NodeSchemaModel.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import {
77
POSITION,
88
type InsertOptions,
99
type PageSchema,
10-
type UpdateMethodsOperation
10+
type UpdateMethodsOperation,
11+
type UpdateAttributesOperation
1112
} from '../type'
1213
import { OperationHandler } from '../operation/operationHandler '
1314

@@ -91,6 +92,11 @@ export class NodeSchemaModel {
9192
this.operationHandler.updatedMethods(operation)
9293
}
9394

95+
//
96+
public updatedNodeAttributes(operation: UpdateAttributesOperation) {
97+
this.operationHandler.updatedAttributes(operation)
98+
}
99+
94100
// insert 操作
95101
private insert(parentId: string, newNodeData: Node, position: string, referTargetNodeId?: string) {
96102
this.operationHandler.insert({

packages/multi-person-collaboration/src/operation/operationHandler .ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type {
44
Node,
55
NodeOperation,
66
PageSchema,
7+
UpdateAttributesOperation,
78
UpdateMethodsOperation,
89
UpdatePropsOperation,
910
UpdateStyleOperation
@@ -175,7 +176,7 @@ export class OperationHandler {
175176
Object.assign(this.rootSchema, { css: strStyle })
176177
}
177178

178-
// 修改节点属性
179+
// 修改节点 Props
179180
public updatedProps(operation: UpdatePropsOperation) {
180181
const { newProps, nodeId, overwrite } = operation
181182
let node = this.getYNode(nodeId)
@@ -235,6 +236,37 @@ export class OperationHandler {
235236
}
236237
}
237238

239+
// 更新节点属性
240+
public updatedAttributes(opertion: UpdateAttributesOperation) {
241+
const { type, nodeId } = opertion
242+
const targetNode = this.getYNode(nodeId)
243+
244+
switch (type) {
245+
case 'condition': {
246+
targetNode?.set('condition', opertion.value)
247+
break
248+
}
249+
case 'loop': {
250+
targetNode?.set('loop', opertion.value)
251+
break
252+
}
253+
case 'loopArgs': {
254+
targetNode?.set('loopArgs', opertion.value)
255+
break
256+
}
257+
case 'clean': {
258+
this.yDoc.transact(() => {
259+
// 合并为一次操作
260+
targetNode?.delete('loop')
261+
targetNode?.delete('loopArgs')
262+
})
263+
break
264+
}
265+
default:
266+
break
267+
}
268+
}
269+
238270
// 重建整个映射(刷新后可以手动调用)
239271
public rebuildYNodeMap(rootSchema: PageSchema) {
240272
this.yNodeMap.clear()

packages/multi-person-collaboration/src/services/schemaManager.ts

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useCanvas, useMessage } from '@opentiny/tiny-engine-meta-register'
22
import * as Y from 'yjs'
33
import { NodeSchemaModel } from '../models/NodeSchemaModel'
44
import { DocManager } from './docManager'
5-
import type { RootNode } from '../type'
5+
import type { RootNode, UpdateAttributesRole } from '../type'
66
import { fromYjs, sanitizeSchema, toYjs } from '../utils'
77
import { toRaw } from 'vue'
88
import type { YjsProvider } from './providerManager'
@@ -14,6 +14,10 @@ type DiffPatch =
1414
| { type: 'array-delete'; path: (string | number)[]; count: number; deletedIds: string[] }
1515
| { type: 'text-insert'; path: (string | number)[]; index: number; text: string }
1616
| { type: 'text-delete'; path: (string | number)[]; index: number; length: number }
17+
| { type: 'style-update'; path: (string | number)[]; css: string }
18+
| { type: 'class-add'; path: (string | number)[]; nodeId: string; className: string }
19+
| { type: 'props-update'; path: (string | number)[]; props: Record<any, any>; meta: Record<any, any> }
20+
| { type: 'methods-add-root'; path: (string | number)[]; methods: Record<string, any> }
1721
| {
1822
type: 'array-swap'
1923
direction: 'down' | 'up'
@@ -22,17 +26,20 @@ type DiffPatch =
2226
targetIndex: number
2327
swapIndex: number
2428
}
25-
| { type: 'style-update'; path: (string | number)[]; css: string }
26-
| { type: 'class-add'; path: (string | number)[]; nodeId: string; className: string }
27-
| { type: 'props-update'; path: (string | number)[]; props: Record<any, any>; meta: Record<any, any> }
28-
| { type: 'methods-add-root'; path: (string | number)[]; methods: Record<string, any> }
2929
| {
3030
type: 'methods-add-node'
3131
path: (string | number)[]
3232
methods: Record<string, any>
3333
methodsName: string
3434
nodeId: string
3535
}
36+
| {
37+
type: 'attributes-update'
38+
role: UpdateAttributesRole
39+
path: (string | number)[]
40+
value: boolean | Record<string, any> | undefined
41+
nodeId: string
42+
}
3643

3744
/**
3845
* SchemaManager 类,负责管理 Yjs 中的 NodeSchema 文档
@@ -253,6 +260,7 @@ export class SchemaManager {
253260
if (event.target instanceof Y.Map) {
254261
const yMapNode = event.target
255262
const regex = /^on[A-Z][A-Za-z]*$/
263+
const attributesKey = ['condition', 'loop', 'loopArgs', 'clean']
256264

257265
event.changes.keys.forEach((change, key) => {
258266
// 软删除
@@ -315,6 +323,29 @@ export class SchemaManager {
315323
methods: newMethods
316324
})
317325
}
326+
} else if (attributesKey.includes(key)) {
327+
if (key === 'condition' || key === 'loop' || key === 'loopArgs') {
328+
if (change.action === 'add' || change.action === 'update') {
329+
const targetNodeId = yMapNode.get('id')
330+
const value = yMapNode.get(key)
331+
patches.push({
332+
type: 'attributes-update',
333+
role: key,
334+
path: event.path,
335+
value,
336+
nodeId: targetNodeId
337+
})
338+
} else if (change.action === 'delete' && (key === 'loop' || key === 'loopArgs')) {
339+
const targetNodeId = yMapNode.get('id')
340+
patches.push({
341+
type: 'attributes-update',
342+
role: 'clean',
343+
path: event.path,
344+
value: undefined,
345+
nodeId: targetNodeId
346+
})
347+
}
348+
}
318349
} else if (regex.test(key)) {
319350
// 先判断非根节点 添加时间函数
320351
if (change.action === 'add' || change.action === 'update') {
@@ -478,6 +509,27 @@ export class SchemaManager {
478509
useMessage().publish({ topic: 'schemaChange', data: {} })
479510
break
480511
}
512+
case 'attributes-update': {
513+
const { role, value, nodeId } = patch
514+
const targetNode = useCanvas().getNode(nodeId, false)
515+
516+
if (role === 'condition') {
517+
if (!(value as boolean)) {
518+
useCanvas().operateNode({ type: 'updateAttributes', id: nodeId, value: { condition: value } })
519+
} else {
520+
const { condition: _schemaCondition, children, ...rest } = targetNode
521+
useCanvas().operateNode({ type: 'updateAttributes', id: nodeId, value: { ...rest }, overwrite: true })
522+
}
523+
} else if (role === 'loop') {
524+
useCanvas().operateNode({ type: 'updateAttributes', id: nodeId, value: { loop: value } })
525+
} else if (role === 'loopArgs') {
526+
useCanvas().operateNode({ type: 'updateAttributes', id: nodeId, value: { loopArgs: value } })
527+
} else if (role === 'clean') {
528+
const { loop: _loop, loopArgs: _loopArgs, children: _children, ...rest } = targetNode
529+
useCanvas().operateNode({ type: 'updateAttributes', id: nodeId, value: rest, overwrite: true })
530+
}
531+
break
532+
}
481533
default:
482534
break
483535
}

packages/multi-person-collaboration/src/type.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ export type UpdateMethodsOperation =
106106
| { type: 'root'; methods: Record<string, any> }
107107
| { type: 'node'; nodeId: string; methodsName: string; methods: Record<string, any>; params: any }
108108

109+
export type UpdateAttributesOperation =
110+
| { type: 'loop'; value: Record<string, any>; nodeId: string }
111+
| { type: 'loopArgs'; value: Record<string, any>; nodeId: string }
112+
| { type: 'condition'; value: boolean; nodeId: string }
113+
| { type: 'clean'; nodeId: string }
114+
115+
export type UpdateAttributesRole = 'loop' | 'loopArgs' | 'condition' | 'clean'
116+
109117
export interface UserAwareness {
110118
id?: string | number
111119
name: string

packages/settings/events/src/components/AdvanceConfig.vue

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ import {
8080
SwitchConfigurator,
8181
VariableConfigurator
8282
} from '@opentiny/tiny-engine-configurator'
83-
import { useProperties, useCanvas } from '@opentiny/tiny-engine-meta-register'
83+
import { useProperties, useCanvas, useRealtimeCollab } from '@opentiny/tiny-engine-meta-register'
8484
import { PROP_DATA_TYPE } from '@opentiny/tiny-engine-common/js/constants'
8585
import { constants, utils } from '@opentiny/tiny-engine-utils'
8686
import { Tooltip } from '@opentiny/vue'
@@ -185,9 +185,13 @@ export default {
185185
186186
if (value === false || value?.type) {
187187
operateNode({ type: 'updateAttributes', id: schema.id, value: { condition: value } })
188+
// 多人协同实现
189+
useRealtimeCollab().updateAttributesNode({ type: 'condition', value, nodeId: schema.id })
188190
} else {
189191
const { condition: _schemaCondition, children, ...rest } = schema
190192
operateNode({ type: 'updateAttributes', id: schema.id, value: { ...rest }, overwrite: true })
193+
// 多人协同实现
194+
useRealtimeCollab().updateAttributesNode({ type: 'condition', value, nodeId: schema.id })
191195
}
192196
193197
useCanvas().canvasApi.value.updateRect()
@@ -206,6 +210,8 @@ export default {
206210
}
207211
208212
operateNode({ type: 'updateAttributes', id: schema.id, value: { loopArgs } })
213+
// 多人协同实现
214+
useRealtimeCollab().updateAttributesNode({ type: 'loopArgs', value: loopArgs, nodeId: schema.id })
209215
}
210216
211217
const setLoop = (value) => {
@@ -217,12 +223,16 @@ export default {
217223
const newLoop = value?.type ? value : string2Obj(value)
218224
219225
operateNode({ type: 'updateAttributes', id: schema.id, value: { loop: newLoop } })
226+
// 多人协同实现
227+
useRealtimeCollab().updateAttributesNode({ type: 'loop', value: newLoop, nodeId: schema.id })
220228
setLoopIndex(DEFAULT_LOOP_NAME.INDEX)
221229
} else {
222230
setLoopKey()
223231
const { loop: _loop, loopArgs: _loopArgs, children: _children, ...rest } = schema
224232
225233
operateNode({ type: 'updateAttributes', id: schema.id, value: rest, overwrite: true })
234+
// 多人协同实现
235+
useRealtimeCollab().updateAttributesNode({ type: 'clean', nodeId: schema.id })
226236
}
227237
228238
// 触发更新state
@@ -241,6 +251,8 @@ export default {
241251
}
242252
243253
operateNode({ type: 'updateAttributes', id: schema.id, value: { loopArgs } })
254+
// 多人协同实现
255+
useRealtimeCollab().updateAttributesNode({ type: 'loopArgs', value: loopArgs, nodeId: schema.id })
244256
}
245257
246258
return {

0 commit comments

Comments
 (0)