mirror of
https://github.com/NetEase/tango.git
synced 2026-08-29 02:01:34 +08:00
fix: renderSetter with template (#202)
* fix: renderSetter with template * fix: update types
This commit is contained in:
@@ -48,7 +48,6 @@ const Snippet3ColumnLayout: IComponentPrototype = {
|
||||
icon: 'icon-column-3',
|
||||
type: 'snippet',
|
||||
package: '@music163/antd',
|
||||
// FIXME: Column 组件 需要更新为 defineComponent
|
||||
initChildren: `
|
||||
<Columns columns={12}>
|
||||
<Column colSpan={4}>
|
||||
@@ -169,6 +168,32 @@ const prototypes: Dict<IComponentPrototype> = {
|
||||
Snippet2ColumnLayout,
|
||||
Snippet3ColumnLayout,
|
||||
SnippetButtonGroup,
|
||||
Section: {
|
||||
...basePrototypes['Section'],
|
||||
props: [
|
||||
// ...(basePrototypes['Section'].props as any),
|
||||
{
|
||||
name: 'title',
|
||||
title: '标题',
|
||||
setter: 'textSetter',
|
||||
},
|
||||
{
|
||||
name: 'extra',
|
||||
title: '额外内容',
|
||||
setter: 'renderSetter',
|
||||
options: [
|
||||
{
|
||||
label: '按钮组',
|
||||
value: 'ButtonGroup',
|
||||
renderBody:
|
||||
'<ButtonGroup><Button>button1</Button><Button>button2</Button></ButtonGroup>',
|
||||
relatedImports: ['ButtonGroup', 'Button'],
|
||||
},
|
||||
],
|
||||
template: '(v) => {\n return {{content}};\n}',
|
||||
},
|
||||
],
|
||||
},
|
||||
Box: {
|
||||
name: 'Box',
|
||||
title: '盒子',
|
||||
@@ -207,6 +232,25 @@ const prototypes: Dict<IComponentPrototype> = {
|
||||
template: '(e) => {\n {{content}}\n}',
|
||||
tip: '回调参数说明:e 为事件对象',
|
||||
},
|
||||
{
|
||||
name: 'renderFoo',
|
||||
title: 'foo自定义渲染',
|
||||
setter: 'renderSetter',
|
||||
options: [
|
||||
{
|
||||
label: '占位空间',
|
||||
value: 'Box',
|
||||
render: '() => <Box>test</Box>',
|
||||
relatedImports: ['Box'],
|
||||
},
|
||||
{
|
||||
label: '占位文本',
|
||||
value: 'Text',
|
||||
render: '() => <Text>text</Text>',
|
||||
relatedImports: ['Text'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
Columns: {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { Radio, RadioProps, Tooltip } from 'antd';
|
||||
import type { OptionType } from '@music163/tango-helpers';
|
||||
import type { IOptionItem } from '@music163/tango-helpers';
|
||||
import { FormItemComponentProps } from '@music163/tango-setting-form';
|
||||
import { IconFont } from '@music163/tango-ui';
|
||||
|
||||
interface ChoiceSetterProps {
|
||||
options?: OptionType[];
|
||||
options?: IOptionItem[];
|
||||
}
|
||||
|
||||
export function ChoiceSetter({
|
||||
|
||||
+2
-2
@@ -58,7 +58,7 @@ const suffixStyle = css`
|
||||
}
|
||||
`;
|
||||
|
||||
export interface ExpressionSetterProps extends FormItemComponentProps<string> {
|
||||
export interface CodeSetterProps extends FormItemComponentProps<string> {
|
||||
modalTitle?: string;
|
||||
modalTip?: string;
|
||||
autoCompleteOptions?: string[];
|
||||
@@ -70,7 +70,7 @@ export interface ExpressionSetterProps extends FormItemComponentProps<string> {
|
||||
expressionType?: 'cssObject';
|
||||
}
|
||||
|
||||
export function ExpressionSetter(props: ExpressionSetterProps) {
|
||||
export function CodeSetter(props: CodeSetterProps) {
|
||||
const {
|
||||
onChange,
|
||||
modalTitle,
|
||||
@@ -5,7 +5,7 @@ import { ActionSelect } from '@music163/tango-ui';
|
||||
import { FormItemComponentProps } from '@music163/tango-setting-form';
|
||||
import { useWorkspace, useWorkspaceData } from '@music163/tango-context';
|
||||
import { Dict, wrapCode } from '@music163/tango-helpers';
|
||||
import { ExpressionPopover, getCallbackValue } from './expression-setter';
|
||||
import { ExpressionPopover, getCallbackValue } from './code-setter';
|
||||
import { value2code } from '@music163/tango-core';
|
||||
|
||||
enum EventAction {
|
||||
|
||||
@@ -5,14 +5,14 @@ import { CssSetter } from './css-setter';
|
||||
import { DateRangeSetter, DateSetter, TimeRangeSetter } from './date-setter';
|
||||
import { EnumSetter } from './enum-setter';
|
||||
import { EventSetter } from './event-setter';
|
||||
import { ExpressionSetter } from './expression-setter';
|
||||
import { CodeSetter } from './code-setter';
|
||||
import { JSONSetter } from './json-setter';
|
||||
import { JsxSetter } from './jsx-setter';
|
||||
import { ListSetter } from './list-setter';
|
||||
import { ModelSetter } from './model-setter';
|
||||
import { OptionSetter } from './option-setter';
|
||||
import { PickerSetter } from './picker-setter';
|
||||
import { RenderSetter, TableCellSetter, TableExpandableSetter } from './render-setter';
|
||||
import { RenderSetter } from './render-setter';
|
||||
import { RouterSetter } from './router-setter';
|
||||
import {
|
||||
SpacingSetter,
|
||||
@@ -49,7 +49,7 @@ export const BUILT_IN_SETTERS: IFormItemCreateOptions[] = [
|
||||
{
|
||||
name: 'codeSetter',
|
||||
alias: ['expSetter', 'expressionSetter'],
|
||||
component: ExpressionSetter,
|
||||
component: CodeSetter,
|
||||
type: 'code',
|
||||
validate: codeValidate,
|
||||
},
|
||||
@@ -126,22 +126,12 @@ export const BUILT_IN_SETTERS: IFormItemCreateOptions[] = [
|
||||
component: PickerSetter,
|
||||
},
|
||||
{
|
||||
name: 'renderPropsSetter',
|
||||
name: 'renderSetter',
|
||||
alias: ['renderPropsSetter'],
|
||||
component: RenderSetter,
|
||||
type: 'code',
|
||||
validate: codeValidate,
|
||||
},
|
||||
{
|
||||
name: 'tableCellSetter',
|
||||
component: TableCellSetter,
|
||||
type: 'code',
|
||||
},
|
||||
{
|
||||
name: 'tableExpandableSetter',
|
||||
component: TableExpandableSetter,
|
||||
type: 'code',
|
||||
validate: codeValidate,
|
||||
},
|
||||
{
|
||||
name: 'routerSetter',
|
||||
component: RouterSetter,
|
||||
|
||||
@@ -2,22 +2,16 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { ActionSelect, InputCode } from '@music163/tango-ui';
|
||||
import { FormItemComponentProps } from '@music163/tango-setting-form';
|
||||
import { Box } from 'coral-system';
|
||||
import { Dict } from '@music163/tango-helpers';
|
||||
|
||||
interface IRenderOption {
|
||||
label: string;
|
||||
value: string;
|
||||
render?: string;
|
||||
relatedImports?: string[];
|
||||
}
|
||||
import { Dict, IOptionItem } from '@music163/tango-helpers';
|
||||
import { getCallbackValue } from './code-setter';
|
||||
|
||||
export interface RenderSetterProps {
|
||||
text?: string;
|
||||
options?: IRenderOption[];
|
||||
fallbackOption?: IRenderOption;
|
||||
options?: IOptionItem[];
|
||||
fallbackOption?: IOptionItem;
|
||||
}
|
||||
|
||||
const defaultOptions: IRenderOption[] = [
|
||||
const defaultOptions: IOptionItem[] = [
|
||||
{ label: '取消自定义', value: '' },
|
||||
{ label: '自定义渲染', value: 'Box', render: '() => <Box></Box>' },
|
||||
];
|
||||
@@ -30,6 +24,7 @@ export function RenderSetter({
|
||||
onChange,
|
||||
text = '自定义渲染为',
|
||||
options = defaultOptions,
|
||||
template = `() => {{content}}`,
|
||||
fallbackOption,
|
||||
}: FormItemComponentProps & RenderSetterProps) {
|
||||
const [inputValue, setInputValue] = useState(value || '');
|
||||
@@ -47,13 +42,14 @@ export function RenderSetter({
|
||||
const onSelect = useCallback(
|
||||
(key: string) => {
|
||||
const option = optionsMap[key] || fallbackOption;
|
||||
if (option?.render) {
|
||||
onChange(option.render, { relatedImports: option.relatedImports });
|
||||
const next = option?.render || getCallbackValue(option.renderBody, template);
|
||||
if (next) {
|
||||
onChange(next, { relatedImports: option.relatedImports });
|
||||
} else {
|
||||
onChange(undefined);
|
||||
}
|
||||
},
|
||||
[optionsMap, fallbackOption, onChange],
|
||||
[optionsMap, fallbackOption, onChange, template],
|
||||
);
|
||||
return (
|
||||
<Box>
|
||||
@@ -68,69 +64,3 @@ export function RenderSetter({
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const getRender = (content: string, type?: 'tableCell' | 'tableExpandable') => {
|
||||
let code;
|
||||
switch (type) {
|
||||
case 'tableCell':
|
||||
code = `(value, record, index) => ${content}`;
|
||||
break;
|
||||
case 'tableExpandable':
|
||||
code = `{
|
||||
expandedRowRender: (record) => ${content},
|
||||
rowExpandable: (record) => true
|
||||
}`;
|
||||
break;
|
||||
default:
|
||||
code = `() => ${content}`;
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
};
|
||||
|
||||
const tableCellOptions: RenderSetterProps['options'] = [
|
||||
{ label: '取消自定义', value: '' },
|
||||
{
|
||||
label: '自定义区域',
|
||||
value: 'Box',
|
||||
render: getRender('<Box></Box>', 'tableCell'),
|
||||
relatedImports: ['Box'],
|
||||
},
|
||||
{
|
||||
label: '标签',
|
||||
value: 'Tag',
|
||||
render: getRender('<Tag>tag</Tag>', 'tableCell'),
|
||||
relatedImports: ['Tag'],
|
||||
},
|
||||
{
|
||||
label: '按钮',
|
||||
value: 'Button',
|
||||
render: getRender('<Button>button</Button>', 'tableCell'),
|
||||
relatedImports: ['Button'],
|
||||
},
|
||||
{
|
||||
label: '图片',
|
||||
value: 'Image',
|
||||
render: getRender('<Image width={150} src="https://picsum.photos/100" />', 'tableCell'),
|
||||
relatedImports: ['Image'],
|
||||
},
|
||||
];
|
||||
|
||||
const tableExpandableOptions: RenderSetterProps['options'] = [
|
||||
{
|
||||
label: '设置可展开行',
|
||||
value: 'Box',
|
||||
render: getRender('<Box></Box>', 'tableExpandable'),
|
||||
relatedImports: ['Box'],
|
||||
},
|
||||
{ label: '取消可展开行', value: '' },
|
||||
];
|
||||
|
||||
export function TableCellSetter(props: FormItemComponentProps) {
|
||||
return <RenderSetter options={tableCellOptions} {...props} />;
|
||||
}
|
||||
|
||||
// FIXME: 应该直接用 props 嵌套的模式
|
||||
export function TableExpandableSetter(props: FormItemComponentProps) {
|
||||
return <RenderSetter options={tableExpandableOptions} text="配置表格可展开行" {...props} />;
|
||||
}
|
||||
|
||||
@@ -10,11 +10,19 @@ export type MousePoint = {
|
||||
y: number;
|
||||
};
|
||||
|
||||
export type OptionType = {
|
||||
/**
|
||||
* @deprecated 使用 IOptionItem 代替
|
||||
*/
|
||||
export type OptionType = IOptionItem<any>;
|
||||
|
||||
/**
|
||||
* 列表项
|
||||
*/
|
||||
export interface IOptionItem<T = string> {
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
value: any;
|
||||
value: T;
|
||||
/**
|
||||
* 显示的文本
|
||||
*/
|
||||
@@ -28,10 +36,18 @@ export type OptionType = {
|
||||
*/
|
||||
tip?: string;
|
||||
/**
|
||||
* 关联的导入
|
||||
* 自定义渲染函数,仅用于 renderSetter
|
||||
*/
|
||||
render?: string;
|
||||
/**
|
||||
* 自定义渲染函数的 body(可以用来和 template 配合),仅用于 renderSetter
|
||||
*/
|
||||
renderBody?: string;
|
||||
/**
|
||||
* 关联的导入,仅用于 renderSetter
|
||||
*/
|
||||
relatedImports?: string[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 变量树节点类型
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* 物料描述类型
|
||||
*/
|
||||
|
||||
import { OptionType } from './advanced';
|
||||
import { IOptionItem } from './advanced';
|
||||
import { PartialRecord } from './base';
|
||||
|
||||
/**
|
||||
@@ -113,7 +113,7 @@ export interface IComponentProp<T = any> {
|
||||
/**
|
||||
* 配置项的可选值,setterProps.options 的简写
|
||||
*/
|
||||
options?: OptionType[];
|
||||
options?: IOptionItem[];
|
||||
/**
|
||||
* 是否禁用变量绑定
|
||||
*/
|
||||
|
||||
@@ -231,9 +231,14 @@ export function createFormItem(options: IFormItemCreateOptions) {
|
||||
|
||||
// FIXME: 重新考虑这段代码的位置,外置这个逻辑
|
||||
if (
|
||||
['codeSetter', 'expressionSetter', 'expSetter', 'actionSetter', 'eventSetter'].includes(
|
||||
setter,
|
||||
)
|
||||
[
|
||||
'codeSetter',
|
||||
'expressionSetter',
|
||||
'expSetter',
|
||||
'actionSetter',
|
||||
'eventSetter',
|
||||
'renderSetter',
|
||||
].includes(setter)
|
||||
) {
|
||||
expProps = {
|
||||
modalTitle: title,
|
||||
|
||||
Reference in New Issue
Block a user