diff --git a/apps/storybook/src/setting-form.stories.tsx b/apps/storybook/src/setting-form.stories.tsx index 8bf783a..48a7b90 100644 --- a/apps/storybook/src/setting-form.stories.tsx +++ b/apps/storybook/src/setting-form.stories.tsx @@ -44,6 +44,7 @@ function SettingFormDemo({ initValues, prototype }: SettingFormDemoProps) { prototype={prototype} showIdentifier={{ identifierKey: 'tid', + getIdentifier: () => `time${Date.now()}`, }} /> diff --git a/packages/designer/src/helpers/dom.ts b/packages/designer/src/helpers/dom.ts index 029a30c..12f4a04 100644 --- a/packages/designer/src/helpers/dom.ts +++ b/packages/designer/src/helpers/dom.ts @@ -75,7 +75,7 @@ export function getElementData( const display = getElementCSSDisplay(element); return { id: dnd.id, - codeId: dnd.index, + codeId: dnd.codeId, name: dnd.component || element.tagName.toLowerCase(), filename: dnd.filename, bounding, diff --git a/packages/designer/src/setting-panel.tsx b/packages/designer/src/setting-panel.tsx index 95df475..88f9e70 100644 --- a/packages/designer/src/setting-panel.tsx +++ b/packages/designer/src/setting-panel.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Box } from 'coral-system'; import { SettingForm, FormModel, SettingFormProps } from '@music163/tango-setting-form'; import { Panel } from '@music163/tango-ui'; -import { clone } from '@music163/tango-helpers'; +import { clone, parseDndId } from '@music163/tango-helpers'; import { observer, useDesigner, useWorkspace } from '@music163/tango-context'; import { registerBuiltinSetters } from './setters'; @@ -103,6 +103,11 @@ export const SettingPanel = observer((props: SettingPanelProps) => { prototype={prototype} showIdentifier={{ identifierKey: 'tid', + getIdentifier: () => { + // 直接拿当前的虚拟 id 作为 tid + const { codeId } = parseDndId(workspace.selectSource.first.id); + return codeId; + }, }} {...props} /> diff --git a/packages/designer/src/sidebar/outline-panel/components-tree.tsx b/packages/designer/src/sidebar/outline-panel/components-tree.tsx index d282758..5454c34 100644 --- a/packages/designer/src/sidebar/outline-panel/components-tree.tsx +++ b/packages/designer/src/sidebar/outline-panel/components-tree.tsx @@ -81,8 +81,8 @@ const OutlineTreeNode: React.FC<{ node: ITangoViewNodeData } & ComponentsTreePro const sandboxQuery = useSandboxQuery(); const [visible, setVisible] = useState(true); const nodeLabel = (() => { - const { index } = parseDndId(node.id); - return index; + const { codeId } = parseDndId(node.id); + return codeId; })(); const componentPrototype = workspace.componentPrototypes.get(node.component); const icon = componentPrototype?.icon || 'icon-placeholder'; diff --git a/packages/helpers/src/helpers/string.ts b/packages/helpers/src/helpers/string.ts index 91a1cfb..ece586d 100644 --- a/packages/helpers/src/helpers/string.ts +++ b/packages/helpers/src/helpers/string.ts @@ -75,9 +75,13 @@ export function parseDndTrackId(str: string) { interface DndIdParsedType { /** - * 完整的 ID + * full id */ id?: string; + /** + * 组件代码中的 id,一般对应组件的 tid 属性 + */ + codeId?: string; /** * 组件名 */ @@ -86,19 +90,11 @@ interface DndIdParsedType { * 文件名 */ filename?: string; - /** - * @deprecated 使用 filename 代替 - */ - module?: string; - /** - * 序号 - */ - index?: string; } /** * 解析 dnd id - * @example Button:123 -> { component: "Button", id: "Button:123" } + * @example Button:button123 -> { component: "Button", id: "Button:123" } * @example LocalBlock:Button:123 -> { filename: LocalBlock, component: "Button", id: "Button:123" } * @param str */ @@ -109,19 +105,20 @@ export function parseDndId(str: string): DndIdParsedType { const parts = str.split(':'); if (parts.length === 2) { + // e.g. Button:button123 return { - component: parts[0], - index: parts[1], id: str, + component: parts[0], + codeId: parts[1], }; } else if (parts.length >= 3) { + // e.g. LocalBlock:Button:button123 const filename = decodeURIComponent(parts[0]); return { - module: filename, + id: str, filename, component: parts[1], - index: parts[2], - id: str, + codeId: parts[2], }; } return { diff --git a/packages/helpers/tests/helpers.test.ts b/packages/helpers/tests/helpers.test.ts index 7d44a98..15017b1 100644 --- a/packages/helpers/tests/helpers.test.ts +++ b/packages/helpers/tests/helpers.test.ts @@ -58,22 +58,21 @@ describe('string', () => { it('parseDndId', () => { expect(parseDndId('123')).toEqual({ id: '123' }); - expect(parseDndId('Button:123')).toEqual({ + expect(parseDndId('Button:button123')).toEqual({ component: 'Button', - id: 'Button:123', - index: '123', + id: 'Button:button123', + codeId: 'button123', }); - expect(parseDndId('Button.Group:123')).toEqual({ + expect(parseDndId('Button.Group:buttonGroup123')).toEqual({ component: 'Button.Group', - id: 'Button.Group:123', - index: '123', + id: 'Button.Group:buttonGroup123', + codeId: 'buttonGroup123', }); - expect(parseDndId('LocalBlock:Button.Group:123')).toEqual({ + expect(parseDndId('LocalBlock:Button.Group:buttonGroup123')).toEqual({ + id: 'LocalBlock:Button.Group:buttonGroup123', filename: 'LocalBlock', - module: 'LocalBlock', component: 'Button.Group', - id: 'LocalBlock:Button.Group:123', - index: '123', + codeId: 'buttonGroup123', }); }); diff --git a/packages/setting-form/src/form.tsx b/packages/setting-form/src/form.tsx index a4813a4..806d72f 100644 --- a/packages/setting-form/src/form.tsx +++ b/packages/setting-form/src/form.tsx @@ -104,7 +104,8 @@ export interface SettingFormProps { showIdentifier?: | false | { - identifierKey: string; + identifierKey: string; // 唯一标识符属性key + getIdentifier?: () => string; // 获取唯一标识符的方法 }; /** * 是否显示搜索框 @@ -222,6 +223,9 @@ export function SettingForm({ } diff --git a/packages/setting-form/src/setters/id-setter.tsx b/packages/setting-form/src/setters/id-setter.tsx index 8b86709..4cb9b76 100644 --- a/packages/setting-form/src/setters/id-setter.tsx +++ b/packages/setting-form/src/setters/id-setter.tsx @@ -2,7 +2,8 @@ import React, { useEffect, useState } from 'react'; import { Input, InputProps, Tooltip } from 'antd'; import { css, Box } from 'coral-system'; import { FormItemComponentProps } from '../form-item'; -import { ExclamationCircleOutlined } from '@ant-design/icons'; +import { ExclamationCircleOutlined, ThunderboltOutlined } from '@ant-design/icons'; +import { Action } from '@music163/tango-ui'; const idInputStyle = css` > .ant-input-borderless { @@ -22,6 +23,7 @@ export function IdSetter({ defaultValue, onChange, placeholder = '输入唯一组件ID', + getId, ...rest }: FormItemComponentProps) { const [value, setValue] = useState(valueProp || defaultValue); @@ -60,6 +62,8 @@ export function IdSetter({ }, }; + const showQuickIdButton = !value || error; // 没有设置 id 或 id 不合法的时候显示快捷生成按钮 + return ( ) : null } + suffix={ + showQuickIdButton ? ( + } + tooltip="快捷设置组件ID" + onClick={() => { + const id = getId?.(); + if (id) { + setValue(id); + onChange?.(id); + } + }} + /> + ) : null + } /> );