mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-30 02:48:55 +08:00
fix: PageMaker315专项问题修复 (#6570)
Co-authored-by: wutong25 <wutong25@baidu.com>
This commit is contained in:
parent
ec2fca5dda
commit
17662f5337
@ -5,6 +5,9 @@ $category-2-height: px2rem(32px);
|
||||
$tooltip-bottom: '[data-tooltip][data-position=' bottom ']:hover:after';
|
||||
|
||||
.editor-right-panel {
|
||||
--select-base-default-fontSize: 12px;
|
||||
--fonts-size-7: 12px;
|
||||
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
width: $right-panel-width;
|
||||
@ -222,7 +225,6 @@ $tooltip-bottom: '[data-tooltip][data-position=' bottom ']:hover:after';
|
||||
height: 100%;
|
||||
max-width: calc(100% - 48px); // 避免被内容元素撑开
|
||||
border-left: none;
|
||||
transform: scale(1); // 内部元素fixed定位需要
|
||||
|
||||
.editorPanel-tabs-pane {
|
||||
position: relative;
|
||||
@ -274,13 +276,16 @@ $tooltip-bottom: '[data-tooltip][data-position=' bottom ']:hover:after';
|
||||
overflow: hidden;
|
||||
margin: calc(0rem - (var(--gap-base)));
|
||||
|
||||
// 老动作入口
|
||||
.old-action-btn {
|
||||
.old-action-tooltip-warpper {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
top: px2rem(15px);
|
||||
width: 91%;
|
||||
z-index: 9999;
|
||||
// 老动作入口
|
||||
.old-action-btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// tab导航
|
||||
|
@ -120,3 +120,40 @@
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
.ae-AdaptorControl {
|
||||
&-func {
|
||||
&-header,
|
||||
&-footer {
|
||||
padding-left: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
&-header {
|
||||
margin-bottom: -20px;
|
||||
}
|
||||
&-footer {
|
||||
margin-top: -20px;
|
||||
}
|
||||
&-arg {
|
||||
padding: 0;
|
||||
height: auto;
|
||||
font-size: 12px;
|
||||
vertical-align: baseline;
|
||||
color: var(--primary);
|
||||
}
|
||||
&-editor {
|
||||
margin-bottom: 0;
|
||||
.cxd-EditorControl {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.cxd-MonacoEditor-placeholder {
|
||||
line-height: 18px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-desc-tooltip {
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
@ -70,7 +70,7 @@
|
||||
}
|
||||
|
||||
&-EditLabel {
|
||||
width: px2rem(36px);
|
||||
flex: 0 0 2.25rem;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
|
@ -100,3 +100,9 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ae-ValidationControl-label-code {
|
||||
background-color: #666;
|
||||
padding: 0 4px;
|
||||
border-radius: 2px;
|
||||
}
|
@ -69,7 +69,8 @@ export class PopOverForm extends React.Component<PopOverFormProps> {
|
||||
render(
|
||||
this.buildSchema(),
|
||||
{
|
||||
data: createObject(store.ctx, popOverFormContext?.value)
|
||||
data: createObject(store.ctx, popOverFormContext?.value),
|
||||
manager
|
||||
},
|
||||
{
|
||||
...manager.env,
|
||||
|
@ -461,7 +461,7 @@ export class BasicToolbarPlugin extends BasePlugin {
|
||||
onSelect: () => store.redo()
|
||||
});
|
||||
|
||||
// menus.push('|');
|
||||
menus.push('|');
|
||||
|
||||
/** 可使用「点选(默认向后插入)」替代 */
|
||||
/*
|
||||
@ -519,10 +519,8 @@ export class BasicToolbarPlugin extends BasePlugin {
|
||||
}
|
||||
}
|
||||
|
||||
/** 「点选(默认向后插入)」+ 「删除」可以替换 「更改类型」 */
|
||||
/*
|
||||
menus.push({
|
||||
label: '更改类型',
|
||||
label: '替换组件',
|
||||
disabled:
|
||||
!node.host ||
|
||||
node.info?.typeMutable === false ||
|
||||
@ -531,7 +529,6 @@ export class BasicToolbarPlugin extends BasePlugin {
|
||||
!node.replaceable,
|
||||
onSelect: () => manager.showReplacePanel(id)
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -21,14 +21,15 @@ export class UnkownRendererPlugin extends BasePlugin {
|
||||
return;
|
||||
} else if (
|
||||
renderer.name === 'card-item' ||
|
||||
renderer.name === 'list-item-field'
|
||||
renderer.name === 'list-item-field' ||
|
||||
renderer.name === 'card-item-field'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 复制部分信息出去
|
||||
return {
|
||||
name: 'Unkown',
|
||||
name: 'Unknown',
|
||||
$schema: '/schemas/UnkownSchema.json'
|
||||
};
|
||||
}
|
||||
|
@ -118,6 +118,7 @@ import picker from './form/picker.svg';
|
||||
|
||||
import quarter from './form/quarter.svg';
|
||||
import radios from './form/radios.svg';
|
||||
import searchBox from './form/select.svg';
|
||||
import select from './form/select.svg';
|
||||
import staticIcon from './form/static.svg';
|
||||
import subForm from './form/sub-form.svg';
|
||||
@ -282,6 +283,7 @@ registerIcon('nested-select-plugin', nestedSelect);
|
||||
registerIcon('picker-plugin', picker);
|
||||
registerIcon('quarter-plugin', quarter);
|
||||
registerIcon('radios-plugin', radios);
|
||||
registerIcon('search-box-plugin', searchBox);
|
||||
registerIcon('select-plugin', select);
|
||||
registerIcon('static-plugin', staticIcon);
|
||||
registerIcon('sub-form-plugin', subForm);
|
||||
|
@ -1,6 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg t="1614838454815" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12115" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16">
|
||||
<path d="M904 1024H120c-66.168 0-120-53.832-120-120V120C0 53.832 53.832 0 120 0h784c66.168 0 120 53.832 120 120v784c0 66.168-53.832 120-120 120zM120 4C56.038 4 4 56.038 4 120v784c0 63.962 52.038 116 116 116h784c63.962 0 116-52.038 116-116V120c0-63.962-52.038-116-116-116H120z" fill="currentColor" p-id="12116"></path>
|
||||
<path d="M402 832h-130c-44.112 0-80-35.888-80-80V272c0-44.112 35.888-80 80-80h130c44.112 0 80 35.888 80 80v480c0 44.112-35.888 80-80 80z m-130-580c-11.028 0-20 8.972-20 20v480c0 11.028 8.972 20 20 20h130c11.028 0 20-8.972 20-20V272c0-11.028-8.972-20-20-20h-130z" fill="currentColor" p-id="12117"></path>
|
||||
<path d="M752 482h-130c-44.112 0-80-35.888-80-80v-130c0-44.112 35.888-80 80-80h130c44.112 0 80 35.888 80 80v130c0 44.112-35.888 80-80 80z m-130-230c-11.028 0-20 8.972-20 20v130c0 11.028 8.972 20 20 20h130c11.028 0 20-8.972 20-20v-130c0-11.028-8.972-20-20-20h-130z" fill="currentColor" p-id="12118"></path>
|
||||
<path d="M752 832h-130c-44.112 0-80-35.888-80-80v-130c0-44.112 35.888-80 80-80h130c44.112 0 80 35.888 80 80v130c0 44.112-35.888 80-80 80z m-130-230c-11.028 0-20 8.972-20 20v130c0 11.028 8.972 20 20 20h130c11.028 0 20-8.972 20-20v-130c0-11.028-8.972-20-20-20h-130z" fill="#205dd9" p-id="12119"></path></svg>
|
||||
<svg width="17px" height="16px" viewBox="0 0 17 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="布局容器交互稿" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="图标" transform="translate(-63.000000, -251.000000)">
|
||||
<g id="常见布局备份-3" transform="translate(63.500000, 251.000000)">
|
||||
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
|
||||
<rect id="矩形" stroke="currentColor" stroke-linejoin="round" x="10.5" y="10" width="4" height="4"></rect>
|
||||
<polyline id="路径" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" points="8.52861305 14 1.5 14 1.5 2 14.5 2 14.5 8"></polyline>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 856 B |
@ -108,6 +108,7 @@ import './plugin/Markdown';
|
||||
import './plugin/Nav';
|
||||
import './plugin/Operation';
|
||||
import './plugin/Page';
|
||||
import './plugin/Icon';
|
||||
import './plugin/Pagination';
|
||||
import './plugin/Panel';
|
||||
import './plugin/Plain';
|
||||
@ -115,6 +116,7 @@ import './plugin/Progress';
|
||||
import './plugin/Property';
|
||||
import './plugin/QRCode';
|
||||
import './plugin/Reset';
|
||||
import './plugin/SearchBox';
|
||||
import './plugin/Service';
|
||||
import './plugin/Status';
|
||||
import './plugin/Steps';
|
||||
@ -154,6 +156,7 @@ import './renderer/NavDefaultActive';
|
||||
import './renderer/MapSourceControl';
|
||||
import './renderer/TimelineItemControl';
|
||||
import './renderer/APIControl';
|
||||
import './renderer/APIAdaptorControl';
|
||||
import './renderer/ValidationControl';
|
||||
import './renderer/ValidationItem';
|
||||
import './renderer/SwitchMoreControl';
|
||||
|
@ -1843,8 +1843,6 @@ extendLocale('en-US', {
|
||||
'348097cc50579e489f0bcb5433637d3a':
|
||||
'With this option enabled, you can sort them according to the current column sequence (backend sequence).',
|
||||
'9db64f772c11c614ee00bb3cc066f46f': 'Column group name',
|
||||
'fea0f3f456153564218a9eefb78d8cec':
|
||||
'When the group name of multiple column groups keeps consistent, the table displays the super table header at the top layer of the table header displayed.<a href="https://baidu.github.io/amis/crud/header-group" target="_blank">Example</a>',
|
||||
'19c4f5e98ad302574202de30dddbaf66': 'Enable quick edit',
|
||||
'15c3796e07e33afc7252df751f610c5d': 'Whether to save immediately',
|
||||
'ba5a0a1ff2c438ae7719ca48b0ce3af7': 'Enable “View more display options”',
|
||||
@ -3773,6 +3771,14 @@ extendLocale('en-US', {
|
||||
'8985ea173dce8f9bee667b3cdf0b7bdf':
|
||||
'This configuration item only applies to the "Add" button in the table operation bar',
|
||||
'3f64a567662a24714768237a3a6d0de7': 'New button below the table',
|
||||
'9dd651411c1cb25e19249bb4ea8878c3': 'Animation interval (ms)',
|
||||
'46bc66b19c2b589ebd24d1c583325080': 'Animation duration (ms)',
|
||||
'9cb33a16b57ef10b79ae76a66379d66f': 'Arrows are always displayed',
|
||||
'0bf60b32f9db93b87e08763b1c815469': 'quantity',
|
||||
'98e04bf7cb91497e4225d272e3a331c8': 'Custom Arrows',
|
||||
'7076ef56f5c4f13d3c9bf87d3536352f': 'left arrow',
|
||||
'fce3880b7a24a47f02a16331a294b255': 'Right arrow',
|
||||
'f4f965513462fcc9fe6fe896a9c249d8': 'Multi-picture display',
|
||||
'522cddc343d72db3db80cf3d71f99210':
|
||||
'The API return format is incorrect. Please click the example on the right side of the interface address to view the CRUD data interface structure requirements',
|
||||
'5323ab3e5c12066101244f0577c30e22': 'Custom container area',
|
||||
@ -3842,5 +3848,7 @@ extendLocale('en-US', {
|
||||
'<div>When the value is__ When undefined, it means to delete the corresponding field. You can combine {"&": " $$"} to achieve the blacklist effect</ div>',
|
||||
'cb65841ea7dec5ae0af20b3f5e52abfc': 'Raw data leveling',
|
||||
'6922790f45faf064e063069816e4d2ec':
|
||||
'After opening, all the original data will be flattened and set in the data, and customized on this basis'
|
||||
'After opening, all the original data will be flattened and set in the data, and customized on this basis',
|
||||
'9791b05a4df9d72f1a01b81fa695fbc6':
|
||||
'When the grouping names of multiple columns are consistent, the table will display the super header on the upper layer of the display header.<a href=“ https://baidu.github.io/amis/zh-CN/components/table#%E8%B6%85%E7%BA%A7%E8%A1%A8%E5%A4%B4 " target="_ Blank ">Example</a>'
|
||||
});
|
||||
|
@ -2840,8 +2840,6 @@ extendLocale('zh-CN', {
|
||||
'<span class="label label-warning">四</span>',
|
||||
'ce3fd44456123f571e9d083b98da9fcb':
|
||||
'<span class="label label-primary">五</span>',
|
||||
'fea0f3f456153564218a9eefb78d8cec':
|
||||
'当多列的分组名称设置一致时,表格会在显示表头的上层显示超级表头,<a href="https://baidu.github.io/amis/crud/header-group" target="_blank">示例</a>',
|
||||
'f8fc21a9fd40881e8fd3d7f15919465c':
|
||||
'如果当前字段有值,请不要设置,否则覆盖。支持使用 <code>\\${xxx}</code> 来获取变量,或者用 lodash.template 语法来写模板逻辑。<a target="_blank" href="/amis/zh-CN/docs/concepts/template">详情</a>',
|
||||
'2c8a99d35cb5704994cabcc61a4c3a4a':
|
||||
@ -3348,7 +3346,7 @@ extendLocale('zh-CN', {
|
||||
'9e1bafbb00018beacc8f579c8ddfaa36': '设置组件「',
|
||||
'6c6e12c54723170f214527bedaf81f7d': '动作类型',
|
||||
'1b7e6b2dbf3b7f4b1baf2c42e49a995d': '组件变量',
|
||||
'2eb4c7ac45befad0f1f9c750bda57166': '内存变量',
|
||||
'2eb4c7ac45befad0f1f9c750bda57166': '应用临时变量',
|
||||
'844a7a7aacc5be82d0fd6225edc6bf63': '请选择变量',
|
||||
'85451d2eb59327a23e8f745161066d4a': '请输入变量值',
|
||||
'3d4d83f05a12364e2522fcfb265d8ce8':
|
||||
@ -3357,6 +3355,14 @@ extendLocale('zh-CN', {
|
||||
'5720057e62e80f7a04489dc4c035b4f1': '取消按钮图标',
|
||||
'8985ea173dce8f9bee667b3cdf0b7bdf': '此配置项只作用于表格操作栏的“新增”按钮',
|
||||
'3f64a567662a24714768237a3a6d0de7': '表格下方新增按钮',
|
||||
'9dd651411c1cb25e19249bb4ea8878c3': '动画间隔(ms)',
|
||||
'46bc66b19c2b589ebd24d1c583325080': '动画时长(ms)',
|
||||
'9cb33a16b57ef10b79ae76a66379d66f': '箭头一直显示',
|
||||
'0bf60b32f9db93b87e08763b1c815469': '数量',
|
||||
'98e04bf7cb91497e4225d272e3a331c8': '自定义箭头',
|
||||
'7076ef56f5c4f13d3c9bf87d3536352f': '左箭头',
|
||||
'fce3880b7a24a47f02a16331a294b255': '右箭头',
|
||||
'f4f965513462fcc9fe6fe896a9c249d8': '多图展示',
|
||||
'522cddc343d72db3db80cf3d71f99210':
|
||||
'API返回格式不正确,请点击接口地址右侧示例查看CRUD数据接口结构要求',
|
||||
'9b39126b20e519bb1c6e9054f4b55784':
|
||||
@ -3423,5 +3429,7 @@ extendLocale('zh-CN', {
|
||||
'<div>当值为 __undefined时,表示删除对应的字段,可以结合{"&": "\\$$"}来达到黑名单效果。</div>',
|
||||
'cb65841ea7dec5ae0af20b3f5e52abfc': '原始数据打平',
|
||||
'6922790f45faf064e063069816e4d2ec':
|
||||
'开启后,会将所有原始数据打平设置到 data 中,并在此基础上定制'
|
||||
'开启后,会将所有原始数据打平设置到 data 中,并在此基础上定制',
|
||||
'9791b05a4df9d72f1a01b81fa695fbc6':
|
||||
'当多列的分组名称设置一致时,表格会在显示表头的上层显示超级表头,<a href="https://baidu.github.io/amis/zh-CN/components/table#%E8%B6%85%E7%BA%A7%E8%A1%A8%E5%A4%B4" target="_blank">示例</a>'
|
||||
});
|
||||
|
@ -295,7 +295,8 @@ export class ButtonPlugin extends BasePlugin {
|
||||
getSchemaTpl('icon', {
|
||||
name: 'rightIcon',
|
||||
label: '右侧图标'
|
||||
})
|
||||
}),
|
||||
getSchemaTpl('badge')
|
||||
]
|
||||
},
|
||||
getSchemaTpl('status', {
|
||||
|
@ -209,26 +209,26 @@ export class CarouselPlugin extends BasePlugin {
|
||||
label: '自动轮播',
|
||||
pipeIn: defaultValue(true)
|
||||
},
|
||||
{
|
||||
getSchemaTpl('valueFormula', {
|
||||
rendererSchema: {
|
||||
type: 'input-number'
|
||||
},
|
||||
mode: 'vertical',
|
||||
name: 'interval',
|
||||
type: 'input-range',
|
||||
label: '动画间隔',
|
||||
min: 1,
|
||||
max: 100,
|
||||
step: 1,
|
||||
unit: 's',
|
||||
pipeIn: (value: any) => (value ?? 3000) / 1000,
|
||||
pipeOut: (value: any, originValue: any, data: any) => value * 1000
|
||||
},
|
||||
label: '动画间隔(ms)',
|
||||
valueType: 'number',
|
||||
pipeIn: defaultValue(5000)
|
||||
}),
|
||||
{
|
||||
name: 'duration',
|
||||
type: 'input-range',
|
||||
label: '动画时长',
|
||||
type: 'input-number',
|
||||
label: '动画时长(ms)',
|
||||
mode: 'inline',
|
||||
className: 'w-full',
|
||||
min: 100,
|
||||
max: 2000,
|
||||
step: 10,
|
||||
pipeIn: defaultValue(500),
|
||||
unit: 'ms'
|
||||
size: 'sm',
|
||||
pipeIn: defaultValue(500)
|
||||
},
|
||||
{
|
||||
name: 'animation',
|
||||
@ -288,6 +288,34 @@ export class CarouselPlugin extends BasePlugin {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'alwaysShowArrow',
|
||||
type: 'switch',
|
||||
mode: 'inline',
|
||||
className: 'w-full',
|
||||
label: '箭头一直显示',
|
||||
hiddenOn: '!~this.controls.indexOf("arrows")',
|
||||
pipeIn: defaultValue(false)
|
||||
},
|
||||
{
|
||||
type: 'ae-switch-more',
|
||||
bulk: true,
|
||||
mode: 'normal',
|
||||
name: 'multiple',
|
||||
label: '多图展示',
|
||||
formType: 'extend',
|
||||
form: {
|
||||
body: [
|
||||
{
|
||||
name: 'multiple.count',
|
||||
label: '数量',
|
||||
type: 'input-number',
|
||||
min: 2,
|
||||
step: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'width',
|
||||
type: 'input-text',
|
||||
|
@ -1,7 +1,35 @@
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {registerEditorPlugin, tipedLabel} from 'amis-editor-core';
|
||||
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
const dateFormatOptions = [
|
||||
{
|
||||
label: 'X(时间戳)',
|
||||
value: 'X'
|
||||
},
|
||||
{
|
||||
label: 'x(毫秒时间戳)',
|
||||
value: 'x'
|
||||
},
|
||||
{
|
||||
label: 'YYYY-MM-DD',
|
||||
value: 'YYYY-MM-DD'
|
||||
},
|
||||
{
|
||||
label: 'YYYY/MM/DD',
|
||||
value: 'YYYY/MM/DD'
|
||||
},
|
||||
{
|
||||
label: 'YYYY年MM月DD日',
|
||||
value: 'YYYY年MM月DD日'
|
||||
}
|
||||
];
|
||||
const valueDateFormatOptions = [
|
||||
{
|
||||
label: 'X(时间戳)',
|
||||
value: 'X'
|
||||
}
|
||||
];
|
||||
export class DatePlugin extends BasePlugin {
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
@ -40,20 +68,28 @@ export class DatePlugin extends BasePlugin {
|
||||
{
|
||||
type: 'input-date',
|
||||
name: 'value',
|
||||
label: '日期数值'
|
||||
label: '日期值'
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'format',
|
||||
label: '显示日期格式',
|
||||
description: '请参考 moment 中的格式用法。',
|
||||
label: tipedLabel(
|
||||
'显示格式',
|
||||
'请参考 <a href="https://momentjs.com/" target="_blank">moment</a> 中的格式用法。'
|
||||
),
|
||||
clearable: true,
|
||||
options: dateFormatOptions,
|
||||
pipeIn: defaultValue('YYYY-MM-DD')
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'valueFormat',
|
||||
label: '数据日期格式',
|
||||
description: '请参考 moment 中的格式用法。',
|
||||
label: tipedLabel(
|
||||
'值格式',
|
||||
'请参考 <a href="https://momentjs.com/" target="_blank">moment</a> 中的格式用法。'
|
||||
),
|
||||
clearable: true,
|
||||
options: valueDateFormatOptions,
|
||||
pipeIn: defaultValue('X')
|
||||
},
|
||||
getSchemaTpl('placeholder', {
|
||||
|
@ -1,8 +1,36 @@
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {registerEditorPlugin, tipedLabel} from 'amis-editor-core';
|
||||
import {BaseEventContext} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {DatePlugin} from './Date';
|
||||
|
||||
const dateFormatOptions = [
|
||||
{
|
||||
label: 'X(时间戳)',
|
||||
value: 'X'
|
||||
},
|
||||
{
|
||||
label: 'x(毫秒时间戳)',
|
||||
value: 'x'
|
||||
},
|
||||
{
|
||||
label: 'YYYY-MM-DD HH:mm:ss',
|
||||
value: 'YYYY-MM-DD HH:mm:ss'
|
||||
},
|
||||
{
|
||||
label: 'YYYY/MM/DD HH:mm:ss',
|
||||
value: 'YYYY/MM/DD HH:mm:ss'
|
||||
},
|
||||
{
|
||||
label: 'YYYY年MM月DD日 HH时mm分ss秒',
|
||||
value: 'YYYY年MM月DD日 HH时mm分ss秒'
|
||||
}
|
||||
];
|
||||
const valueDateFormatOptions = [
|
||||
{
|
||||
label: 'X(时间戳)',
|
||||
value: 'X'
|
||||
}
|
||||
];
|
||||
export class DatetimePlugin extends DatePlugin {
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
@ -35,20 +63,28 @@ export class DatetimePlugin extends DatePlugin {
|
||||
{
|
||||
type: 'input-datetime',
|
||||
name: 'value',
|
||||
label: '日期时间数值'
|
||||
label: '日期时间值'
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'format',
|
||||
label: '显示日期时间格式',
|
||||
description: '请参考 moment 中的格式用法。',
|
||||
label: tipedLabel(
|
||||
'显示格式',
|
||||
'请参考 <a href="https://momentjs.com/" target="_blank">moment</a> 中的格式用法。'
|
||||
),
|
||||
clearable: true,
|
||||
options: dateFormatOptions,
|
||||
pipeIn: defaultValue('YYYY-MM-DD HH:mm:ss')
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'valueFormat',
|
||||
label: '数据日期格式',
|
||||
description: '请参考 moment 中的格式用法。',
|
||||
label: tipedLabel(
|
||||
'值格式',
|
||||
'请参考 <a href="https://momentjs.com/" target="_blank">moment</a> 中的格式用法。'
|
||||
),
|
||||
clearable: true,
|
||||
options: valueDateFormatOptions,
|
||||
pipeIn: defaultValue('X')
|
||||
},
|
||||
getSchemaTpl('placeholder', {
|
||||
|
@ -163,7 +163,8 @@ export class ButtonGroupControlPlugin extends BasePlugin {
|
||||
}),
|
||||
getSchemaTpl('buttonLevel', {
|
||||
label: '按钮选中样式',
|
||||
name: 'btnActiveLevel'
|
||||
name: 'btnActiveLevel',
|
||||
pipeIn: defaultValue('primary')
|
||||
})
|
||||
]
|
||||
},
|
||||
|
@ -294,7 +294,32 @@ export class DateControlPlugin extends BasePlugin {
|
||||
'值格式',
|
||||
'提交数据前将根据设定格式化数据,请参考 <a href="https://momentjs.com/" target="_blank">moment</a> 中的格式用法。'
|
||||
),
|
||||
pipeIn: defaultValue('X')
|
||||
pipeIn: defaultValue('YYYY-MM-DD'),
|
||||
clearable: true,
|
||||
onChange: (
|
||||
value: string,
|
||||
oldValue: any,
|
||||
model: any,
|
||||
form: any
|
||||
) => {
|
||||
const type = form.data.type.split('-')[1];
|
||||
model.setOptions(DateType[type].formatOptions);
|
||||
// 时间日期类组件 input-time 需要更加关注 timeFormat 和 inputFormat 属性区别
|
||||
// inputFormat 表示输入框内的显示格式; timeFormat表示选择下拉弹窗中展示"HH、mm、ss"的组合
|
||||
if (type === 'time') {
|
||||
const timeFormatObj = DateType[type].formatOptions.find(
|
||||
item => item.value === value
|
||||
);
|
||||
const timeFormat = timeFormatObj
|
||||
? (timeFormatObj as any).timeFormat
|
||||
: 'HH:mm:ss';
|
||||
form.setValues({
|
||||
timeFormat: timeFormat
|
||||
});
|
||||
}
|
||||
},
|
||||
options:
|
||||
DateType[this.scaffold.type.split('-')[1]].formatOptions
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
|
@ -8,6 +8,16 @@ import {FormulaDateType} from '../../renderer/FormulaControl';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import {getRendererByName} from 'amis-core';
|
||||
|
||||
const formatX = [
|
||||
{
|
||||
label: 'X(时间戳)',
|
||||
value: 'X'
|
||||
},
|
||||
{
|
||||
label: 'x(毫秒时间戳)',
|
||||
value: 'x'
|
||||
}
|
||||
];
|
||||
const DateType: {
|
||||
[key: string]: {
|
||||
format: string;
|
||||
@ -15,6 +25,8 @@ const DateType: {
|
||||
ranges: string[];
|
||||
sizeMutable?: boolean;
|
||||
type?: string;
|
||||
timeFormat?: string;
|
||||
formatOptions: Array<{label: string; value: string; timeFormat?: string}>;
|
||||
};
|
||||
} = {
|
||||
date: {
|
||||
@ -28,11 +40,27 @@ const DateType: {
|
||||
'thismonth',
|
||||
'prevmonth',
|
||||
'prevquarter'
|
||||
],
|
||||
formatOptions: [
|
||||
...formatX,
|
||||
{
|
||||
label: 'YYYY-MM-DD',
|
||||
value: 'YYYY-MM-DD'
|
||||
},
|
||||
{
|
||||
label: 'YYYY/MM/DD',
|
||||
value: 'YYYY/MM/DD'
|
||||
},
|
||||
{
|
||||
label: 'YYYY年MM月DD日',
|
||||
value: 'YYYY年MM月DD日'
|
||||
}
|
||||
]
|
||||
},
|
||||
datetime: {
|
||||
...getRendererByName('input-datetime-range'),
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
timeFormat: 'HH:mm:ss',
|
||||
placeholder: '请选择日期时间范围',
|
||||
ranges: [
|
||||
'yesterday',
|
||||
@ -41,31 +69,102 @@ const DateType: {
|
||||
'thismonth',
|
||||
'prevmonth',
|
||||
'prevquarter'
|
||||
],
|
||||
formatOptions: [
|
||||
...formatX,
|
||||
{
|
||||
label: 'YYYY-MM-DD HH:mm:ss',
|
||||
value: 'YYYY-MM-DD HH:mm:ss'
|
||||
},
|
||||
{
|
||||
label: 'YYYY/MM/DD HH:mm:ss',
|
||||
value: 'YYYY/MM/DD HH:mm:ss'
|
||||
},
|
||||
{
|
||||
label: 'YYYY年MM月DD日 HH时mm分ss秒',
|
||||
value: 'YYYY年MM月DD日 HH时mm分ss秒'
|
||||
}
|
||||
]
|
||||
},
|
||||
time: {
|
||||
...getRendererByName('input-time-range'),
|
||||
format: 'HH:mm',
|
||||
timeFormat: 'HH:mm:ss',
|
||||
placeholder: '请选择时间范围',
|
||||
ranges: []
|
||||
ranges: [],
|
||||
formatOptions: [
|
||||
{
|
||||
label: 'HH:mm',
|
||||
value: 'HH:mm',
|
||||
timeFormat: 'HH:mm'
|
||||
},
|
||||
{
|
||||
label: 'HH:mm:ss',
|
||||
value: 'HH:mm:ss',
|
||||
timeFormat: 'HH:mm:ss'
|
||||
},
|
||||
{
|
||||
label: 'HH时mm分',
|
||||
value: 'HH时mm分',
|
||||
timeFormat: 'HH:mm'
|
||||
},
|
||||
{
|
||||
label: 'HH时mm分ss秒',
|
||||
value: 'HH时mm分ss秒',
|
||||
timeFormat: 'HH:mm:ss'
|
||||
}
|
||||
]
|
||||
},
|
||||
month: {
|
||||
...getRendererByName('input-month-range'),
|
||||
format: 'YYYY-MM',
|
||||
placeholder: '请选择月份范围',
|
||||
ranges: []
|
||||
ranges: [],
|
||||
formatOptions: [
|
||||
...formatX,
|
||||
{
|
||||
label: 'YYYY-MM',
|
||||
value: 'YYYY-MM'
|
||||
},
|
||||
{
|
||||
label: 'MM',
|
||||
value: 'MM'
|
||||
},
|
||||
{
|
||||
label: 'M',
|
||||
value: 'M'
|
||||
}
|
||||
]
|
||||
},
|
||||
quarter: {
|
||||
...getRendererByName('input-quarter-range'),
|
||||
format: 'YYYY [Q]Q',
|
||||
placeholder: '请选择季度范围',
|
||||
ranges: ['thisquarter', 'prevquarter']
|
||||
ranges: ['thisquarter', 'prevquarter'],
|
||||
formatOptions: [
|
||||
...formatX,
|
||||
{
|
||||
label: 'YYYY-[Q]Q',
|
||||
value: 'YYYY-[Q]Q'
|
||||
},
|
||||
{
|
||||
label: 'Q',
|
||||
value: 'Q'
|
||||
}
|
||||
]
|
||||
},
|
||||
year: {
|
||||
...getRendererByName('input-year-range'),
|
||||
format: 'YYYY',
|
||||
placeholder: '请选择年范围',
|
||||
ranges: ['thisyear', 'lastYear']
|
||||
ranges: ['thisyear', 'lastYear'],
|
||||
formatOptions: [
|
||||
...formatX,
|
||||
{
|
||||
label: 'YYYY',
|
||||
value: 'YYYY'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
@ -218,6 +317,7 @@ export class DateRangeControlPlugin extends BasePlugin {
|
||||
const type: string = value.split('-')[1];
|
||||
form.setValues({
|
||||
inputFormat: DateType[type]?.format,
|
||||
timeFormat: DateType[type]?.timeFormat,
|
||||
placeholder: DateType[type]?.placeholder,
|
||||
format: type === 'time' ? 'HH:mm' : 'X',
|
||||
minDate: '',
|
||||
@ -238,7 +338,20 @@ export class DateRangeControlPlugin extends BasePlugin {
|
||||
'值格式',
|
||||
'提交数据前将根据设定格式化数据,请参考 <a href="https://momentjs.com/" target="_blank">moment</a> 中的格式用法。'
|
||||
),
|
||||
pipeIn: defaultValue('X')
|
||||
pipeIn: defaultValue('X'),
|
||||
clearable: true,
|
||||
onChange: (
|
||||
value: string,
|
||||
oldValue: any,
|
||||
model: any,
|
||||
form: any
|
||||
) => {
|
||||
model.setOptions(
|
||||
DateType[form.data.type.split('-')[1]].formatOptions
|
||||
);
|
||||
},
|
||||
options:
|
||||
DateType[this.scaffold.type.split('-')[1]].formatOptions
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
@ -248,19 +361,19 @@ export class DateRangeControlPlugin extends BasePlugin {
|
||||
'请参考 <a href="https://momentjs.com/" target="_blank">moment</a> 中的格式用法。'
|
||||
),
|
||||
pipeIn: defaultValue('YYYY-MM-DD'),
|
||||
clearable: true
|
||||
// onChange: (
|
||||
// value: string,
|
||||
// oldValue: any,
|
||||
// model: any,
|
||||
// form: any
|
||||
// ) => {
|
||||
// model.setOptions(
|
||||
// DateType[form.data.type.split('-')[1]].formatOptions
|
||||
// );
|
||||
// },
|
||||
// options:
|
||||
// DateType[this.scaffold.type.split('-')[1]].formatOptions
|
||||
clearable: true,
|
||||
onChange: (
|
||||
value: string,
|
||||
oldValue: any,
|
||||
model: any,
|
||||
form: any
|
||||
) => {
|
||||
model.setOptions(
|
||||
DateType[form.data.type.split('-')[1]].formatOptions
|
||||
);
|
||||
},
|
||||
options:
|
||||
DateType[this.scaffold.type.split('-')[1]].formatOptions
|
||||
},
|
||||
getSchemaTpl('utc'),
|
||||
getSchemaTpl('clearable', {
|
||||
|
@ -15,9 +15,10 @@ import {
|
||||
tipedLabel,
|
||||
getI18nEnabled,
|
||||
repeatArray,
|
||||
mockValue
|
||||
mockValue,
|
||||
EditorNodeType
|
||||
} from 'amis-editor-core';
|
||||
import {setVariable} from 'amis-core';
|
||||
import {setVariable, someTree} from 'amis-core';
|
||||
import {ValidatorTag} from '../../validator';
|
||||
import {
|
||||
getEventControlConfig,
|
||||
@ -833,6 +834,41 @@ export class TableControlPlugin extends BasePlugin {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async buildDataSchemas(node: EditorNodeType, region?: EditorNodeType) {
|
||||
const itemsSchema: any = {
|
||||
$id: 'inputTableRow',
|
||||
type: 'object',
|
||||
properties: {}
|
||||
};
|
||||
|
||||
const columns: EditorNodeType = node.children.find(
|
||||
item => item.isRegion && item.region === 'columns'
|
||||
);
|
||||
for (let current of columns?.children) {
|
||||
const schema = current.schema;
|
||||
if (schema.name) {
|
||||
itemsSchema.properties[schema.name] = current.info?.plugin
|
||||
?.buildDataSchemas
|
||||
? await current.info.plugin.buildDataSchemas(current, region)
|
||||
: {
|
||||
type: 'string',
|
||||
title: schema.label || schema.name
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (region?.region === 'columns') {
|
||||
return itemsSchema;
|
||||
}
|
||||
|
||||
return {
|
||||
$id: 'inputTable',
|
||||
type: 'array',
|
||||
title: '表格表单数据',
|
||||
items: itemsSchema
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
registerEditorPlugin(TableControlPlugin);
|
||||
|
@ -124,8 +124,7 @@ export class RadiosControlPlugin extends BasePlugin {
|
||||
getSchemaTpl('valueFormula', {
|
||||
rendererSchema: context?.schema,
|
||||
useSelectMode: true, // 改用 Select 设置模式
|
||||
visibleOn:
|
||||
'this.options && this.options.length > 0 && this.selectFirst !== true'
|
||||
visibleOn: 'this.options && this.options.length > 0'
|
||||
}),
|
||||
// getSchemaTpl('autoFill')
|
||||
getSchemaTpl('labelRemark'),
|
||||
@ -135,15 +134,7 @@ export class RadiosControlPlugin extends BasePlugin {
|
||||
},
|
||||
{
|
||||
title: '选项',
|
||||
body: [
|
||||
getSchemaTpl('optionControlV2'),
|
||||
getSchemaTpl('switch', {
|
||||
label: '默认选择第一个',
|
||||
name: 'selectFirst',
|
||||
horizontal: {justify: true, left: 5},
|
||||
visibleOn: '!this.options'
|
||||
})
|
||||
]
|
||||
body: [getSchemaTpl('optionControlV2'), getSchemaTpl('selectFirst')]
|
||||
},
|
||||
getSchemaTpl('status', {isFormItem: true}),
|
||||
getSchemaTpl('validation', {tag: ValidatorTag.MultiSelect})
|
||||
|
@ -253,6 +253,7 @@ export class SelectControlPlugin extends BasePlugin {
|
||||
title: '选项',
|
||||
body: [
|
||||
getSchemaTpl('optionControlV2'),
|
||||
getSchemaTpl('selectFirst'),
|
||||
getSchemaTpl(
|
||||
'loadingConfig',
|
||||
{
|
||||
|
@ -12,7 +12,7 @@ import {EditorNodeType} from 'amis-editor-core';
|
||||
import {mockValue} from 'amis-editor-core';
|
||||
|
||||
// 快速编辑
|
||||
setSchemaTpl('quickEdit', {
|
||||
setSchemaTpl('quickEdit', (patch: any, manager: any) => ({
|
||||
type: 'ae-switch-more',
|
||||
mode: 'normal',
|
||||
name: 'quickEdit',
|
||||
@ -84,7 +84,7 @@ setSchemaTpl('quickEdit', {
|
||||
block
|
||||
level="primary"
|
||||
onClick={() => {
|
||||
this.manager.openSubEditor({
|
||||
manager.openSubEditor({
|
||||
title: '配置快速编辑类型',
|
||||
value: value,
|
||||
slot: {
|
||||
@ -93,7 +93,7 @@ setSchemaTpl('quickEdit', {
|
||||
body: ['$$'],
|
||||
wrapWithPanel: false
|
||||
},
|
||||
onChange: value =>
|
||||
onChange: (value: any) =>
|
||||
onChange(
|
||||
{
|
||||
...value,
|
||||
@ -111,10 +111,10 @@ setSchemaTpl('quickEdit', {
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
// 查看更多
|
||||
setSchemaTpl('morePopOver', {
|
||||
setSchemaTpl('morePopOver', (patch: any, manager: any) => ({
|
||||
type: 'ae-switch-more',
|
||||
mode: 'normal',
|
||||
name: 'popOver',
|
||||
@ -212,10 +212,10 @@ setSchemaTpl('morePopOver', {
|
||||
block
|
||||
level="primary"
|
||||
onClick={() => {
|
||||
this.manager.openSubEditor({
|
||||
manager.openSubEditor({
|
||||
title: '配置查看更多展示内容',
|
||||
value: value,
|
||||
onChange: value => onChange(value, 'quickEdit')
|
||||
onChange: (value: any) => onChange(value, 'quickEdit')
|
||||
});
|
||||
}}
|
||||
>
|
||||
@ -226,7 +226,7 @@ setSchemaTpl('morePopOver', {
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
// 可复制
|
||||
setSchemaTpl('copyable', {
|
||||
@ -310,19 +310,18 @@ export class StaticControlPlugin extends BasePlugin {
|
||||
getSchemaTpl('formItemName', {
|
||||
required: false
|
||||
}),
|
||||
getSchemaTpl('label')
|
||||
getSchemaTpl('label'),
|
||||
// getSchemaTpl('value'),
|
||||
/*
|
||||
getSchemaTpl('valueFormula', {
|
||||
name: 'tpl',
|
||||
name: 'tpl'
|
||||
// rendererSchema: {
|
||||
// ...context?.schema,
|
||||
// type: 'textarea', // 改用多行文本编辑
|
||||
// value: context?.schema.tpl // 避免默认值丢失
|
||||
// }
|
||||
}),
|
||||
getSchemaTpl('quickEdit'),
|
||||
getSchemaTpl('morePopOver'),
|
||||
getSchemaTpl('quickEdit', {}, this.manager),
|
||||
getSchemaTpl('morePopOver', {}, this.manager),
|
||||
getSchemaTpl('copyable'),
|
||||
getSchemaTpl('labelRemark'),
|
||||
getSchemaTpl('remark'),
|
||||
|
144
packages/amis-editor/src/plugin/Icon.tsx
Normal file
144
packages/amis-editor/src/plugin/Icon.tsx
Normal file
@ -0,0 +1,144 @@
|
||||
import {registerEditorPlugin, RendererPluginEvent} from 'amis-editor-core';
|
||||
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../renderer/event-control';
|
||||
|
||||
export class IconPlugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
rendererName = 'icon';
|
||||
$schema = '/schemas/Icon.json';
|
||||
|
||||
// 组件名称
|
||||
name = '图标';
|
||||
isBaseComponent = true;
|
||||
icon = 'fa fa-calendar';
|
||||
|
||||
panelTitle = '图标';
|
||||
|
||||
description = '用来展示一个图标,你可以配置不同的图标样式。';
|
||||
docLink = '/amis/zh-CN/components/icon';
|
||||
tags = ['展示'];
|
||||
|
||||
pluginIcon = 'button-plugin';
|
||||
|
||||
scaffold = {
|
||||
type: 'icon',
|
||||
icon: 'fa fa-spotify',
|
||||
vendor: ''
|
||||
};
|
||||
previewSchema: any = {
|
||||
type: 'icon',
|
||||
icon: 'fa fa-spotify',
|
||||
vendor: ''
|
||||
};
|
||||
|
||||
// 事件定义
|
||||
events: RendererPluginEvent[] = [
|
||||
{
|
||||
eventName: 'click',
|
||||
eventLabel: '点击',
|
||||
description: '点击时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'mouseenter',
|
||||
eventLabel: '鼠标移入',
|
||||
description: '鼠标移入时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'mouseleave',
|
||||
eventLabel: '鼠标移出',
|
||||
description: '鼠标移出时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
panelJustify = true;
|
||||
panelBodyCreator = (context: BaseEventContext) => {
|
||||
return [
|
||||
getSchemaTpl('tabs', [
|
||||
{
|
||||
title: '属性',
|
||||
body: getSchemaTpl('collapseGroup', [
|
||||
{
|
||||
title: '基本',
|
||||
body: [
|
||||
getSchemaTpl('icon', {
|
||||
label: '图标'
|
||||
})
|
||||
]
|
||||
},
|
||||
getSchemaTpl('status')
|
||||
])
|
||||
},
|
||||
|
||||
{
|
||||
title: '外观',
|
||||
body: getSchemaTpl('collapseGroup', [
|
||||
{
|
||||
title: '自定义样式',
|
||||
body: [
|
||||
getSchemaTpl('theme:size', {
|
||||
label: '尺寸',
|
||||
name: 'css.className.font.fontSize'
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
label: '颜色',
|
||||
name: `css.className.font.color`,
|
||||
labelMode: 'input'
|
||||
}),
|
||||
getSchemaTpl('theme:paddingAndMargin', {
|
||||
label: '边距'
|
||||
})
|
||||
]
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
// {
|
||||
// title: '事件',
|
||||
// className: 'p-none',
|
||||
// body: [
|
||||
// getSchemaTpl('eventControl', {
|
||||
// name: 'onEvent',
|
||||
// ...getEventControlConfig(this.manager, context)
|
||||
// })
|
||||
// ]
|
||||
// }
|
||||
])
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
registerEditorPlugin(IconPlugin);
|
@ -13,9 +13,9 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {diff, JSONPipeOut, repeatArray} from 'amis-editor-core';
|
||||
import {schemaArrayFormat, schemaToArray} from '../util';
|
||||
|
||||
export class ListPlugin extends BasePlugin {
|
||||
static scene = ['layout'];
|
||||
// 关联渲染器名字
|
||||
rendererName = 'list';
|
||||
$schema = '/schemas/ListSchema.json';
|
||||
@ -240,13 +240,13 @@ export class ListPlugin extends BasePlugin {
|
||||
value &&
|
||||
this.manager.openSubEditor({
|
||||
title: '配置头部',
|
||||
value: value.header ?? defaultHeader,
|
||||
value: schemaToArray(value.header ?? defaultHeader),
|
||||
slot: {
|
||||
type: 'container',
|
||||
body: '$$'
|
||||
},
|
||||
onChange: newValue => {
|
||||
newValue = {...value, header: newValue};
|
||||
newValue = {...value, header: schemaArrayFormat(newValue)};
|
||||
manager.panelChangeValue(newValue, diff(value, newValue));
|
||||
}
|
||||
});
|
||||
@ -268,13 +268,13 @@ export class ListPlugin extends BasePlugin {
|
||||
value &&
|
||||
this.manager.openSubEditor({
|
||||
title: '配置底部',
|
||||
value: value.footer ?? defaultFooter,
|
||||
value: schemaToArray(value.footer ?? defaultFooter),
|
||||
slot: {
|
||||
type: 'container',
|
||||
body: '$$'
|
||||
},
|
||||
onChange: newValue => {
|
||||
newValue = {...value, footer: newValue};
|
||||
newValue = {...value, footer: schemaArrayFormat(newValue)};
|
||||
manager.panelChangeValue(newValue, diff(value, newValue));
|
||||
}
|
||||
});
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
ContextMenuEventContext,
|
||||
ContextMenuItem
|
||||
} from 'amis-editor-core';
|
||||
import {schemaArrayFormat, schemaToArray} from '../util';
|
||||
|
||||
export class MappingPlugin extends BasePlugin {
|
||||
static scene = ['layout'];
|
||||
@ -184,21 +185,22 @@ export class MappingPlugin extends BasePlugin {
|
||||
const store = manager.store;
|
||||
const node = store.getNodeById(id);
|
||||
const value = store.getValueOf(id);
|
||||
const defaultItemSchema = {
|
||||
type: 'tag',
|
||||
label: `\${${this.getDisplayField(value)}}`
|
||||
};
|
||||
|
||||
node &&
|
||||
value &&
|
||||
this.manager.openSubEditor({
|
||||
title: '配置显示模板',
|
||||
value: value.itemSchema || {
|
||||
type: 'tag',
|
||||
label: `\${${this.getDisplayField(value)}}`
|
||||
},
|
||||
value: schemaToArray(value.itemSchema ?? defaultItemSchema),
|
||||
slot: {
|
||||
type: 'container',
|
||||
body: '$$'
|
||||
},
|
||||
onChange: (newValue: any) => {
|
||||
newValue = {...value, itemSchema: newValue};
|
||||
newValue = {...value, itemSchema: schemaArrayFormat(newValue)};
|
||||
manager.panelChangeValue(newValue, diff(value, newValue));
|
||||
},
|
||||
data: {
|
||||
|
@ -14,6 +14,10 @@ import {SchemaCollection} from 'amis/lib/Schema';
|
||||
|
||||
export class ActionPlugin extends BasePlugin {
|
||||
panelTitle = '按钮';
|
||||
rendererName = 'action';
|
||||
name = '行为按钮';
|
||||
$schema = '/schemas/ActionSchema.json';
|
||||
|
||||
panelBodyCreator = (context: BaseEventContext) => {
|
||||
const isInDialog = /(?:\/|^)dialog\/.+$/.test(context.path);
|
||||
const isInDropdown = /(?:\/|^)dropdown-button\/.+$/.test(context.path);
|
||||
@ -365,35 +369,18 @@ export class ActionPlugin extends BasePlugin {
|
||||
if (context.selections.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
~['action', 'button', 'submit', 'reset', 'sparkline'].indexOf(
|
||||
context.info!.renderer.name!
|
||||
)
|
||||
) {
|
||||
if (context.info!.renderer.name === 'action') {
|
||||
let body: any = this.panelBodyCreator(context);
|
||||
|
||||
// sparkline 的 action 配置是放 clickAction 参数下的,所以需要加一层
|
||||
if (context.info.renderer.name === 'sparkline') {
|
||||
body = {
|
||||
name: 'clickAction',
|
||||
type: 'combo',
|
||||
label: '',
|
||||
noBorder: true,
|
||||
multiLine: true,
|
||||
items: body
|
||||
};
|
||||
}
|
||||
|
||||
// panels.push({
|
||||
// key: 'action',
|
||||
// icon: 'fa fa-gavel',
|
||||
// title: '动作',
|
||||
// render: this.manager.makeSchemaFormRender({
|
||||
// body: body
|
||||
// }),
|
||||
// order: 100
|
||||
// });
|
||||
panels.push({
|
||||
key: 'action',
|
||||
icon: 'fa fa-gavel',
|
||||
title: '动作',
|
||||
render: this.manager.makeSchemaFormRender({
|
||||
body: body
|
||||
}),
|
||||
order: 100
|
||||
});
|
||||
} else {
|
||||
super.buildEditorPanel(context, panels);
|
||||
}
|
||||
|
172
packages/amis-editor/src/plugin/SearchBox.tsx
Normal file
172
packages/amis-editor/src/plugin/SearchBox.tsx
Normal file
@ -0,0 +1,172 @@
|
||||
import React from 'react';
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {
|
||||
BaseEventContext,
|
||||
BasePlugin,
|
||||
RendererPluginEvent
|
||||
} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../renderer/event-control/helper';
|
||||
|
||||
import {SchemaObject} from 'amis/lib/Schema';
|
||||
|
||||
export class SearchBoxPlugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
rendererName = 'search-box';
|
||||
$schema = '/schemas/SearchBoxSchema.json';
|
||||
|
||||
// 组件名称
|
||||
name = '搜索框';
|
||||
isBaseComponent = true;
|
||||
description =
|
||||
'用于展示一个简单搜索框,通常需要搭配其他组件使用。比如 page 配置 initApi 后,可以用来实现简单数据过滤查找,name keywords 会作为参数传递给 page 的 initApi。';
|
||||
docLink = '/amis/zh-CN/components/search-box';
|
||||
icon = 'fa fa-search';
|
||||
pluginIcon = 'search-box-plugin';
|
||||
|
||||
scaffold: SchemaObject = {
|
||||
type: 'search-box',
|
||||
body: {
|
||||
type: 'tpl',
|
||||
tpl: '搜索框',
|
||||
wrapperComponent: '',
|
||||
inline: false
|
||||
},
|
||||
level: 'info'
|
||||
};
|
||||
|
||||
previewSchema: any = {
|
||||
...this.scaffold,
|
||||
className: 'text-left',
|
||||
showCloseButton: true
|
||||
};
|
||||
|
||||
regions = [{key: 'body', label: '内容区', placeholder: '搜索框内容'}];
|
||||
|
||||
// 事件定义
|
||||
events: RendererPluginEvent[] = [
|
||||
{
|
||||
eventName: 'search',
|
||||
eventLabel: '点击搜索',
|
||||
description: '点击搜索图标时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
'event.data.keywords': {
|
||||
type: 'string',
|
||||
title: '搜索内容'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'change',
|
||||
eventLabel: '值变化',
|
||||
description: '输入框值变化时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
'event.data.keywords': {
|
||||
type: 'string',
|
||||
title: '搜索内容'
|
||||
},
|
||||
'event.data.value': {
|
||||
type: 'string',
|
||||
title: '搜索内容' // 和keywords值相同
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'focus',
|
||||
eventLabel: '获取焦点',
|
||||
description: '输入框获取焦点时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
'event.data.keywords': {
|
||||
type: 'string',
|
||||
title: '搜索内容'
|
||||
},
|
||||
'event.data.value': {
|
||||
type: 'string',
|
||||
title: '搜索内容' // 和keywords值相同
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'blur',
|
||||
eventLabel: '失去焦点',
|
||||
description: '输入框失去焦点时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
'event.data.keywords': {
|
||||
type: 'string',
|
||||
title: '搜索内容'
|
||||
},
|
||||
'event.data.value': {
|
||||
type: 'string',
|
||||
title: '搜索内容' // 和keywords值相同
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
notRenderFormZone = true;
|
||||
panelTitle = '搜索框';
|
||||
panelJustify = true;
|
||||
panelBodyCreator = (context: BaseEventContext) => {
|
||||
return getSchemaTpl('tabs', [
|
||||
{
|
||||
title: '属性',
|
||||
body: getSchemaTpl('collapseGroup', [
|
||||
{
|
||||
title: '基础',
|
||||
body: [
|
||||
getSchemaTpl('formItemName', {
|
||||
required: true
|
||||
}),
|
||||
getSchemaTpl('switch', {
|
||||
label: '可清除',
|
||||
name: 'clearable'
|
||||
}),
|
||||
getSchemaTpl('switch', {
|
||||
label: '清除后立即搜索',
|
||||
name: 'clearAndSubmit'
|
||||
}),
|
||||
getSchemaTpl('switch', {
|
||||
label: '立即搜索',
|
||||
name: 'searchImediately'
|
||||
}),
|
||||
getSchemaTpl('switch', {
|
||||
label: 'mini版本',
|
||||
name: 'mini'
|
||||
}),
|
||||
getSchemaTpl('switch', {
|
||||
label: '加强样式',
|
||||
name: 'enhance',
|
||||
visibleOn: '!data.mini'
|
||||
}),
|
||||
getSchemaTpl('placeholder')
|
||||
]
|
||||
},
|
||||
getSchemaTpl('status')
|
||||
])
|
||||
},
|
||||
{
|
||||
title: '外观',
|
||||
body: getSchemaTpl('collapseGroup', [
|
||||
getSchemaTpl('style:classNames', {isFormItem: false})
|
||||
])
|
||||
},
|
||||
{
|
||||
title: '事件',
|
||||
className: 'p-none',
|
||||
body: getSchemaTpl('eventControl', {
|
||||
name: 'onEvent',
|
||||
...getEventControlConfig(this.manager, context)
|
||||
})
|
||||
}
|
||||
]);
|
||||
};
|
||||
}
|
||||
registerEditorPlugin(SearchBoxPlugin);
|
@ -27,6 +27,7 @@ import {
|
||||
getEventControlConfig,
|
||||
getArgsWrapper
|
||||
} from '../renderer/event-control/helper';
|
||||
import {schemaArrayFormat, schemaToArray} from '../util';
|
||||
|
||||
export class TablePlugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
@ -744,13 +745,13 @@ export class TablePlugin extends BasePlugin {
|
||||
value &&
|
||||
this.manager.openSubEditor({
|
||||
title: '配置头部',
|
||||
value: value.header ?? defaultHeader,
|
||||
value: schemaToArray(value.header ?? defaultHeader),
|
||||
slot: {
|
||||
type: 'container',
|
||||
body: '$$'
|
||||
},
|
||||
onChange: newValue => {
|
||||
newValue = {...value, header: newValue};
|
||||
newValue = {...value, header: schemaArrayFormat(newValue)};
|
||||
manager.panelChangeValue(newValue, diff(value, newValue));
|
||||
}
|
||||
});
|
||||
@ -772,13 +773,13 @@ export class TablePlugin extends BasePlugin {
|
||||
value &&
|
||||
this.manager.openSubEditor({
|
||||
title: '配置底部',
|
||||
value: value.footer ?? defaultFooter,
|
||||
value: schemaToArray(value.footer ?? defaultFooter),
|
||||
slot: {
|
||||
type: 'container',
|
||||
body: '$$'
|
||||
},
|
||||
onChange: newValue => {
|
||||
newValue = {...value, footer: newValue};
|
||||
newValue = {...value, footer: schemaArrayFormat(newValue)};
|
||||
manager.panelChangeValue(newValue, diff(value, newValue));
|
||||
}
|
||||
});
|
||||
|
@ -58,6 +58,10 @@ export class TagPlugin extends BasePlugin {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
},
|
||||
label: {
|
||||
type: 'string',
|
||||
title: '标签名称'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,6 +78,10 @@ export class TagPlugin extends BasePlugin {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
},
|
||||
label: {
|
||||
type: 'string',
|
||||
title: '标签名称'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -90,6 +98,30 @@ export class TagPlugin extends BasePlugin {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
},
|
||||
label: {
|
||||
type: 'string',
|
||||
title: '标签名称'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
eventName: 'close',
|
||||
eventLabel: '点击关闭',
|
||||
description: '点击关闭时触发',
|
||||
dataSchema: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
nativeEvent: {
|
||||
type: 'object',
|
||||
title: '鼠标事件对象'
|
||||
},
|
||||
label: {
|
||||
type: 'string',
|
||||
title: '标签名称'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,6 +165,10 @@ export class TagPlugin extends BasePlugin {
|
||||
getSchemaTpl('icon', {
|
||||
visibleOn: 'data.displayMode === "status"',
|
||||
label: '前置图标'
|
||||
}),
|
||||
getSchemaTpl('switch', {
|
||||
label: '可关闭',
|
||||
name: 'closable'
|
||||
})
|
||||
]
|
||||
},
|
||||
|
@ -1,8 +1,37 @@
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {registerEditorPlugin, tipedLabel} from 'amis-editor-core';
|
||||
import {BaseEventContext} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {DatePlugin} from './Date';
|
||||
|
||||
const timeFormatOptions = [
|
||||
{
|
||||
label: 'HH:mm',
|
||||
value: 'HH:mm',
|
||||
timeFormat: 'HH:mm'
|
||||
},
|
||||
{
|
||||
label: 'HH:mm:ss',
|
||||
value: 'HH:mm:ss',
|
||||
timeFormat: 'HH:mm:ss'
|
||||
},
|
||||
{
|
||||
label: 'HH时mm分',
|
||||
value: 'HH时mm分',
|
||||
timeFormat: 'HH:mm'
|
||||
},
|
||||
{
|
||||
label: 'HH时mm分ss秒',
|
||||
value: 'HH时mm分ss秒',
|
||||
timeFormat: 'HH:mm:ss'
|
||||
}
|
||||
];
|
||||
// 暂仅提示时间戳,待input-time的timeFormat支持表达式后增加其他类型
|
||||
const dateFormatOptions = [
|
||||
{
|
||||
label: 'X(时间戳)',
|
||||
value: 'X'
|
||||
}
|
||||
];
|
||||
export class TimePlugin extends DatePlugin {
|
||||
// 关联渲染器名字
|
||||
rendererName = 'time';
|
||||
@ -37,20 +66,28 @@ export class TimePlugin extends DatePlugin {
|
||||
name: 'value',
|
||||
inputFormat: 'HH:mm:ss',
|
||||
timeFormat: 'HH:mm:ss',
|
||||
label: '时间数值'
|
||||
label: '时间值'
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'format',
|
||||
label: '显示时间格式',
|
||||
description: '请参考 moment 中的格式用法。',
|
||||
label: tipedLabel(
|
||||
'显示格式',
|
||||
'请参考 <a href="https://momentjs.com/" target="_blank">moment</a> 中的格式用法。'
|
||||
),
|
||||
clearable: true,
|
||||
options: timeFormatOptions,
|
||||
pipeIn: defaultValue('HH:mm:ss')
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
name: 'valueFormat',
|
||||
label: '数据日期格式',
|
||||
description: '请参考 moment 中的格式用法。',
|
||||
label: tipedLabel(
|
||||
'值格式',
|
||||
'请参考 <a href="https://momentjs.com/" target="_blank">moment</a> 中的格式用法。'
|
||||
),
|
||||
clearable: true,
|
||||
options: dateFormatOptions,
|
||||
pipeIn: defaultValue('X')
|
||||
},
|
||||
getSchemaTpl('placeholder', {
|
||||
|
451
packages/amis-editor/src/renderer/APIAdaptorControl.tsx
Normal file
451
packages/amis-editor/src/renderer/APIAdaptorControl.tsx
Normal file
@ -0,0 +1,451 @@
|
||||
/**
|
||||
* @file API 适配器
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import cx from 'classnames';
|
||||
import {autobind, getSchemaTpl, setSchemaTpl} from 'amis-editor-core';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
import {FormControlProps, render} from 'amis-core';
|
||||
import {FormItem, Icon, TooltipWrapper} from 'amis';
|
||||
import {TooltipObject} from 'amis-ui/lib/components/TooltipWrapper';
|
||||
interface AdaptorFuncParam {
|
||||
label: string;
|
||||
tip?: string | TooltipObject;
|
||||
}
|
||||
|
||||
export interface APIAdaptorControlProps extends FormControlProps {
|
||||
/**
|
||||
* 适配器函数参数
|
||||
*/
|
||||
params?: AdaptorFuncParam[];
|
||||
/**
|
||||
* 复用适配器 函数参数提示
|
||||
*/
|
||||
mergeParams?: (params: AdaptorFuncParam[]) => AdaptorFuncParam[];
|
||||
/**
|
||||
* 代码编辑器底部的 description
|
||||
*/
|
||||
editorDesc?: any;
|
||||
/**
|
||||
* 代码编辑器开启时 需要预置的代码
|
||||
*/
|
||||
defaultCode?: string;
|
||||
/**
|
||||
* 代码编辑器开启 的 placeHolder
|
||||
*/
|
||||
editorPlaceholder?: string;
|
||||
/**
|
||||
* 开关右侧旁边的提示
|
||||
*/
|
||||
switchTip?: string | React.ReactNode;
|
||||
/**
|
||||
* 自定义提示参数
|
||||
*/
|
||||
tooltipProps?: TooltipObject;
|
||||
}
|
||||
|
||||
export interface APIAdaptorControlState {
|
||||
switch: boolean;
|
||||
}
|
||||
|
||||
export default class APIAdaptorControl extends React.Component<
|
||||
APIAdaptorControlProps,
|
||||
APIAdaptorControlState
|
||||
> {
|
||||
|
||||
static defaultProps: Pick<APIAdaptorControlProps, 'params'> = {
|
||||
params: []
|
||||
};
|
||||
|
||||
constructor(props: APIAdaptorControlProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
switch: !!this.props.value
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Readonly<APIAdaptorControlProps>): void {
|
||||
if (this.props.value !== prevProps.value) {
|
||||
this.setState({
|
||||
switch: !!this.props.value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
onChange(value: any = '') {
|
||||
this.props.onChange?.(value);
|
||||
}
|
||||
|
||||
// 生成tooltip 的参数
|
||||
genTooltipProps(content: any, othersProps?: TooltipObject) {
|
||||
return {
|
||||
tooltipTheme: 'light',
|
||||
trigger: 'hover',
|
||||
rootClose: true,
|
||||
placement: 'top',
|
||||
tooltipClassName: 'ae-AdaptorControl-desc-tooltip',
|
||||
...(typeof content === 'string'
|
||||
? {content}
|
||||
: {
|
||||
content: ' ', // amis缺陷,必须有这个字段,否则显示不出来
|
||||
children: () => content
|
||||
}
|
||||
),
|
||||
...this.props.tooltipProps || {},
|
||||
...othersProps || {}
|
||||
}
|
||||
}
|
||||
|
||||
renderEditor() {
|
||||
if (!this.state.switch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
render,
|
||||
params = [],
|
||||
allowFullscreen,
|
||||
value,
|
||||
name,
|
||||
editorPlaceholder,
|
||||
editorDesc,
|
||||
mergeParams
|
||||
} = this.props;
|
||||
|
||||
const lastParams = typeof mergeParams === 'function'
|
||||
? mergeParams(params) : params;
|
||||
|
||||
return render('api-adaptor-control-editor', [
|
||||
{
|
||||
type: 'container',
|
||||
className: 'ae-AdaptorControl-func-header',
|
||||
body: [
|
||||
'<span class="mtk6">function </span>',
|
||||
'<span class="mtk1 bracket-highlighting-0">(</span>',
|
||||
...lastParams.map(({label, tip}, index) => {
|
||||
return [
|
||||
{
|
||||
type: 'button',
|
||||
level: 'link',
|
||||
label,
|
||||
className: 'ae-AdaptorControl-func-arg',
|
||||
...tip ? {tooltip: this.genTooltipProps(tip)} : {}
|
||||
},
|
||||
...(index === lastParams.length - 1
|
||||
? [] : ['<span class="mtk1">, </span>']
|
||||
)
|
||||
]
|
||||
}).flat(),
|
||||
'<span class="mtk1 bracket-highlighting-0">) {</span>'
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
mode: 'normal',
|
||||
name: '__editor_' + name,
|
||||
type: 'js-editor',
|
||||
className: 'ae-AdaptorControl-func-editor',
|
||||
allowFullscreen,
|
||||
value,
|
||||
placeholder: editorPlaceholder || '',
|
||||
onChange: (value: any) => {
|
||||
this.onChange(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'container',
|
||||
body: '<span class="mtk1 bracket-highlighting-0">}</span>',
|
||||
className: 'ae-AdaptorControl-func-footer'
|
||||
},
|
||||
{
|
||||
type: 'container',
|
||||
className: 'cxd-Form-description',
|
||||
body: editorDesc
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
renderSwitch() {
|
||||
const {render, defaultCode = '', switchTip, name, value} = this.props;
|
||||
return render('api-adaptor-control-switch', {
|
||||
type: 'flex',
|
||||
className: 'mb-2',
|
||||
alignItems: 'center',
|
||||
direction: 'row',
|
||||
justify: 'flex-start',
|
||||
items: [
|
||||
{
|
||||
type: 'switch',
|
||||
label: '',
|
||||
mode: 'inline',
|
||||
name: '__editorSwitch_' + name,
|
||||
key: 'switch',
|
||||
className: 'mb-1',
|
||||
value: this.state.switch,
|
||||
onChange: (checked: any) => {
|
||||
this.setState({switch: checked}, () => {
|
||||
this.onChange(!checked ? '' : value || defaultCode);
|
||||
});
|
||||
}
|
||||
},
|
||||
...switchTip ? [
|
||||
<TooltipWrapper
|
||||
key="TooltipWrapper"
|
||||
tooltip={this.genTooltipProps(switchTip, {
|
||||
placement: 'right'
|
||||
})}
|
||||
>
|
||||
<Icon
|
||||
icon="editor-help"
|
||||
className="icon"
|
||||
color="#84868c"
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
] : []
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {className} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx('ae-ApiAdaptorControl', className)}>
|
||||
{this.renderSwitch()}
|
||||
{this.renderEditor()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@FormItem({
|
||||
type: 'ae-apiAdaptorControl'
|
||||
})
|
||||
export class APIAdaptorControlRenderer extends APIAdaptorControl {}
|
||||
|
||||
/**
|
||||
* 渲染 代码高亮 节点
|
||||
* @param code 代码字符串
|
||||
* @param size 渲染区域的width, height, 代码区域是异步渲染,tooltip时计算会偏移
|
||||
* @returns
|
||||
*/
|
||||
const genCodeSchema = (code: string, size?: string[]) => ({
|
||||
type: 'container',
|
||||
...!size ? {}
|
||||
: {style: {
|
||||
width: size[0],
|
||||
height: size[1]
|
||||
}},
|
||||
body: {
|
||||
type: 'code',
|
||||
language: 'typescript',
|
||||
className: 'bg-white text-xs m-0',
|
||||
value: code
|
||||
}
|
||||
});
|
||||
|
||||
// 请求适配器 示例代码
|
||||
export const requestAdaptorDefaultCode =
|
||||
`api.data.count = api.data.count + 1;
|
||||
return api;`;
|
||||
|
||||
// 适配器 适配器 api 参数说明
|
||||
export const adaptorApiStruct = `{
|
||||
url: string; // 当前接口地址
|
||||
method: 'get' | 'post' | 'put' | 'delete';
|
||||
data?: Object; // 请求体
|
||||
headers?: Object; // 请求头
|
||||
...
|
||||
}`;
|
||||
|
||||
export const adaptorApiStructTooltip =
|
||||
render(genCodeSchema(adaptorApiStruct, ['350px', '128px']))
|
||||
;
|
||||
|
||||
// 适配器 response 参数说明
|
||||
export const adaptorResponseStruct = `{
|
||||
data: Object; // 接口返回数据,
|
||||
request: XMLHttpRequest;
|
||||
headers?: Object; // 请求头
|
||||
status: number; // 状态码 200, 404, 500..
|
||||
statusText: string; // 状态信息
|
||||
...
|
||||
}`;
|
||||
|
||||
export const adaptorResponseStructTooltip =
|
||||
render(genCodeSchema(adaptorResponseStruct, ['345px', '144px']))
|
||||
;
|
||||
|
||||
// 接收适配器 示例代码
|
||||
export const adaptorDefaultCode =
|
||||
`// API响应或自定义处理后需要符合以下格式
|
||||
return {
|
||||
status: 0, // 0 表示请求成功,否则按错误处理
|
||||
msg: '请求成功',
|
||||
data: {
|
||||
text: 'world',
|
||||
items: [
|
||||
{label: '张三', value: 1}
|
||||
]
|
||||
}
|
||||
}`;
|
||||
|
||||
export const validateApiAdaptorDefaultCode =
|
||||
`// 校验成功
|
||||
return {
|
||||
status: 0
|
||||
};
|
||||
|
||||
// 校验失败
|
||||
return {
|
||||
status: 422,
|
||||
errors: '当前用户已存在'
|
||||
}`;
|
||||
|
||||
// 接收适配器 正确返回格式 示例
|
||||
export const adaptorReturnStruct = `{
|
||||
"status": 0,
|
||||
"msg": "",
|
||||
"data": {
|
||||
// ...其他字段
|
||||
}
|
||||
}`;
|
||||
|
||||
// 接收适配器 正确返回格式说明
|
||||
export const adaptorEditorDescSchema = {
|
||||
type: 'container',
|
||||
className: 'text-xs',
|
||||
style: {
|
||||
width: '458px',
|
||||
height: '315px'
|
||||
},
|
||||
body: [
|
||||
'接口返回数据需要符合以下格式, status、msg、data 为必要字段',
|
||||
genCodeSchema(adaptorReturnStruct),
|
||||
{
|
||||
type: 'table',
|
||||
className: 'mt-1 mb-0',
|
||||
data: {
|
||||
items: [
|
||||
{
|
||||
label: 'status',
|
||||
desc: '返回 0 表示当前接口正确返回,否则按错误请求处理'
|
||||
},
|
||||
{
|
||||
label: 'msg',
|
||||
desc: '返回接口处理信息,主要用于表单提交或请求失败时的 toast 显示'
|
||||
},
|
||||
{
|
||||
label: 'data',
|
||||
desc: '必须返回一个具有 key-value 结构的对象'
|
||||
}
|
||||
]
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
name: 'label',
|
||||
label: '字段'
|
||||
},
|
||||
{
|
||||
name: 'desc',
|
||||
label: '说明'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// 表单项校验接收适配器 正确返回格式说明
|
||||
export const validateApiAdaptorEditorDescSchema = {
|
||||
type: 'container',
|
||||
className: 'text-xs',
|
||||
body: [
|
||||
'校验接口返回格式字段说明:',
|
||||
{
|
||||
type: 'table',
|
||||
className: 'mt-1 mb-0',
|
||||
data: {
|
||||
items: [
|
||||
{
|
||||
label: 'status',
|
||||
desc: '返回 0 表示校验成功,422 表示校验失败'
|
||||
},
|
||||
{
|
||||
label: 'errors',
|
||||
desc: '返回 status 为 422 时,显示的校验失败信息'
|
||||
}
|
||||
]
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
name: 'label',
|
||||
label: '字段'
|
||||
},
|
||||
{
|
||||
name: 'desc',
|
||||
label: '说明'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
setSchemaTpl('apiRequestAdaptor', {
|
||||
label: tipedLabel(
|
||||
'发送适配器',
|
||||
`可基于 JavaScript 语言直接录入发送适配器的函数体,在该函数体内,您可以对 <span style="color: #108CEE">api</span> 进行处理或者返回新的内容,最后需要 <span style="color: #108CEE">return</span> <span style="color: #108CEE">api</span>。<br><br/>
|
||||
函数体内可访问的变量如下:<br/>
|
||||
1. <span style="color: #108CEE">api</span>:接口的schema配置对象<br/>
|
||||
2. <span style="color: #108CEE">api.data</span>:请求数据<br/>
|
||||
3. <span style="color: #108CEE">api.query</span>:请求查询参数<br/>
|
||||
4. <span style="color: #108CEE">api.body</span>:请求体(针对POST/PUT/PATCH)<br/>
|
||||
5. <span style="color: #108CEE">api.headers</span>:请求头<br/>
|
||||
6. <span style="color: #108CEE">api.url</span>:请求地址<br/>`
|
||||
),
|
||||
name: 'requestAdaptor',
|
||||
type: 'ae-apiAdaptorControl',
|
||||
editorDesc: '必须将修改好的 api 对象 return 出去。',
|
||||
editorPlaceholder: requestAdaptorDefaultCode,
|
||||
params: [
|
||||
{
|
||||
label: 'api',
|
||||
tip: adaptorApiStructTooltip
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
setSchemaTpl('apiAdaptor', {
|
||||
label: tipedLabel(
|
||||
'返回适配器',
|
||||
`可基于 JavaScript 语言直接录入返回适配器的函数体,在函数体内,您可以对 <span style="color: #108CEE">payload</span> 进行处理或者返回新的内容,最后需要 <span style="color: #108CEE">return</span> 接口最终的返回结果。<br><br/>
|
||||
函数体内可访问的变量如下:<br/>
|
||||
1. <span style="color: #108CEE">payload</span>:接口的返回结果<br/>
|
||||
2. <span style="color: #108CEE">response</span>:接口的response对象<br/>
|
||||
3. <span style="color: #108CEE">api</span>:接口的schema配置对象<br/>`
|
||||
),
|
||||
type: 'ae-apiAdaptorControl',
|
||||
name: 'adaptor',
|
||||
params: [
|
||||
{
|
||||
label: 'payload',
|
||||
tip: '当前请求的响应 payload,即 response.data'
|
||||
},
|
||||
{
|
||||
label: 'response',
|
||||
tip: adaptorResponseStructTooltip
|
||||
},
|
||||
{
|
||||
label: 'api',
|
||||
tip: adaptorApiStructTooltip
|
||||
}
|
||||
],
|
||||
editorPlaceholder: adaptorDefaultCode,
|
||||
switchTip: render(adaptorEditorDescSchema)
|
||||
});
|
||||
|
||||
setSchemaTpl('validateApiAdaptor', {
|
||||
...getSchemaTpl('apiAdaptor'),
|
||||
editorPlaceholder: validateApiAdaptorDefaultCode,
|
||||
switchTip: render(validateApiAdaptorEditorDescSchema)
|
||||
});
|
@ -523,7 +523,7 @@ export default class APIControl extends React.Component<
|
||||
}
|
||||
|
||||
renderApiConfigTabs(submitOnChange: boolean = false) {
|
||||
const {messageDesc, debug = false} = this.props;
|
||||
const {messageDesc, debug = false, name} = this.props;
|
||||
|
||||
return {
|
||||
type: 'form',
|
||||
@ -840,17 +840,7 @@ export default class APIControl extends React.Component<
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '发送适配器',
|
||||
name: 'requestAdaptor',
|
||||
type: 'js-editor',
|
||||
mode: 'horizontal',
|
||||
horizontal: {justify: true},
|
||||
clasName: 'm-t-sm',
|
||||
allowFullscreen: true,
|
||||
description:
|
||||
'函数签名:(api) => api, 数据在 api.data 中,修改后返回 api 对象。'
|
||||
},
|
||||
getSchemaTpl('apiRequestAdaptor'),
|
||||
{
|
||||
type: 'switch',
|
||||
label: tipedLabel(
|
||||
@ -922,16 +912,11 @@ export default class APIControl extends React.Component<
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '接收适配器',
|
||||
name: 'adaptor',
|
||||
type: 'js-editor',
|
||||
mode: 'horizontal',
|
||||
horizontal: {justify: true},
|
||||
clasName: 'm-t-sm',
|
||||
allowFullscreen: true,
|
||||
description: '函数签名: (payload, response, api) => payload'
|
||||
}
|
||||
getSchemaTpl(
|
||||
name === 'validateApi'
|
||||
? 'validateApiAdaptor'
|
||||
: 'apiAdaptor'
|
||||
)
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -8,7 +8,7 @@ import {PickerContainer} from 'amis-ui';
|
||||
import {getEnv} from 'mobx-state-tree';
|
||||
import {normalizeApi, isEffectiveApi, isApiOutdated} from 'amis-core';
|
||||
|
||||
import {autobind, isObject, anyChanged, createObject} from 'amis-editor-core';
|
||||
import {autobind, isObject, anyChanged, createObject, getSchemaTpl} from 'amis-editor-core';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
|
||||
import type {SchemaObject, SchemaCollection, SchemaApi} from 'amis/lib/Schema';
|
||||
@ -753,28 +753,8 @@ export default class APIControl extends React.Component<
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '发送适配器',
|
||||
name: 'requestAdaptor',
|
||||
type: 'js-editor',
|
||||
mode: 'horizontal',
|
||||
horizontal: {justify: true},
|
||||
clasName: 'm-t-sm',
|
||||
allowFullscreen: true,
|
||||
description:
|
||||
'函数签名:(api) => api, 数据在 api.data 中,修改后返回 api 对象。'
|
||||
},
|
||||
{
|
||||
label: '接收适配器',
|
||||
name: 'adaptor',
|
||||
type: 'js-editor',
|
||||
mode: 'horizontal',
|
||||
horizontal: {justify: true},
|
||||
clasName: 'm-t-sm',
|
||||
allowFullscreen: true,
|
||||
description:
|
||||
'函数签名: (payload, response, api) => payload'
|
||||
}
|
||||
getSchemaTpl('apiRequestAdaptor'),
|
||||
getSchemaTpl('apiAdaptor'),
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -72,6 +72,11 @@ export interface BadgeControlProps extends FormControlProps {
|
||||
* 提示类型
|
||||
*/
|
||||
level?: 'info' | 'warning' | 'success' | 'danger' | SchemaExpression;
|
||||
|
||||
/**
|
||||
* 作为option属性时,角标配置变化绑定事件
|
||||
*/
|
||||
onOptionChange?: (value: boolean | BadgeForm) => void
|
||||
}
|
||||
|
||||
interface BadgeControlState {
|
||||
@ -142,10 +147,14 @@ export default class BadgeControl extends React.Component<
|
||||
}
|
||||
|
||||
transformBadgeValue(): BadgeForm {
|
||||
const {data: ctx} = this.props;
|
||||
const badge = ctx?.badge ?? {};
|
||||
const {data: ctx, node} = this.props;
|
||||
let badge = ctx?.badge ?? {};
|
||||
// 避免获取到上层的size
|
||||
const size = ctx?.badge?.size;
|
||||
let size = ctx?.badge?.size;
|
||||
if (node.type === 'button-group-select') {
|
||||
badge = ctx?.option?.badge ?? {};
|
||||
size = badge?.size;
|
||||
}
|
||||
const offset = [0, 0];
|
||||
|
||||
// 转换成combo可以识别的格式
|
||||
@ -171,20 +180,25 @@ export default class BadgeControl extends React.Component<
|
||||
|
||||
@autobind
|
||||
handleSwitchChange(checked: boolean): void {
|
||||
const {onChange, disabled} = this.props;
|
||||
|
||||
const {onChange,onOptionChange, disabled} = this.props;
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({checked});
|
||||
if (onOptionChange) {
|
||||
return onOptionChange(checked);
|
||||
}
|
||||
onChange?.(checked ? {mode: 'dot'} : undefined);
|
||||
}
|
||||
|
||||
handleSubmit(form: BadgeForm, action: any): void {
|
||||
const {onBulkChange} = this.props;
|
||||
const {onBulkChange, onOptionChange} = this.props;
|
||||
|
||||
if (action?.type === 'submit') {
|
||||
if (onOptionChange) {
|
||||
return onOptionChange(this.normalizeBadgeValue(form));
|
||||
}
|
||||
onBulkChange?.({badge: this.normalizeBadgeValue(form)});
|
||||
}
|
||||
}
|
||||
|
@ -105,11 +105,9 @@ export default class ExpressionFormulaControl extends React.Component<
|
||||
|
||||
@autobind
|
||||
initFormulaPickerValue(value: string) {
|
||||
let formulaPickerValue = value;
|
||||
if (this.props.evalMode) {
|
||||
formulaPickerValue =
|
||||
value?.replace(/^\$\{(.*)\}$/, (match: string, p1: string) => p1) || '';
|
||||
}
|
||||
let formulaPickerValue =
|
||||
value?.replace(/^\$\{(.*)\}$/, (match: string, p1: string) => p1) || '';
|
||||
|
||||
this.setState({
|
||||
formulaPickerValue
|
||||
});
|
||||
@ -124,9 +122,9 @@ export default class ExpressionFormulaControl extends React.Component<
|
||||
|
||||
@autobind
|
||||
handleConfirm(value = '') {
|
||||
if (this.props.evalMode) {
|
||||
value = value.replace(/^\$\{(.*)\}$/, (match: string, p1: string) => p1);
|
||||
value = value ? `\${${value}}` : '';
|
||||
const expressionReg = /^\$\{(.*)\}$/;
|
||||
if (value && !expressionReg.test(value)) {
|
||||
value = `\${${value}}`;
|
||||
}
|
||||
this.props?.onChange?.(value);
|
||||
}
|
||||
|
@ -388,6 +388,8 @@ export default class FormulaControl extends React.Component<
|
||||
'size',
|
||||
'remark',
|
||||
'labelRemark',
|
||||
'static',
|
||||
'staticOn',
|
||||
'hidden',
|
||||
'hiddenOn',
|
||||
'visible',
|
||||
@ -409,6 +411,8 @@ export default class FormulaControl extends React.Component<
|
||||
'kilobitSeparator',
|
||||
'value',
|
||||
'inputControlClassName',
|
||||
'css',
|
||||
'validateApi',
|
||||
'themeCss'
|
||||
];
|
||||
|
||||
|
@ -7,6 +7,7 @@ import {findDOMNode} from 'react-dom';
|
||||
import cx from 'classnames';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import omit from 'lodash/omit';
|
||||
import get from 'lodash/get';
|
||||
import Sortable from 'sortablejs';
|
||||
import {
|
||||
FormItem,
|
||||
@ -23,7 +24,7 @@ import {getSchemaTpl} from 'amis-editor-core';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
|
||||
import type {Option} from 'amis';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import {createObject, FormControlProps} from 'amis-core';
|
||||
import type {TextControlSchema} from 'amis/lib/renderers/Form/inputText';
|
||||
import type {OptionValue} from 'amis-core';
|
||||
import {SchemaApi} from 'amis/lib/Schema';
|
||||
@ -87,6 +88,27 @@ export default class OptionControl extends React.Component<
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据更新
|
||||
*/
|
||||
componentWillReceiveProps(nextProps: OptionControlProps) {
|
||||
const options = get(nextProps, 'data.options')
|
||||
? this.transformOptions(nextProps)
|
||||
: [];
|
||||
if (
|
||||
JSON.stringify(
|
||||
this.state.options.map(item => ({
|
||||
...item,
|
||||
editing: undefined
|
||||
}))
|
||||
) !== JSON.stringify(options)
|
||||
) {
|
||||
this.setState({
|
||||
options
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前选项值的类型
|
||||
*/
|
||||
@ -147,7 +169,10 @@ export default class OptionControl extends React.Component<
|
||||
label: item.label,
|
||||
// 为了使用户编写label时同时生效到value
|
||||
value: item.label === item.value ? null : item.value,
|
||||
checked: !!~valueArray.indexOf(item[ctx?.valueField ?? 'value'])
|
||||
checked: !!~valueArray.indexOf(item[ctx?.valueField ?? 'value']),
|
||||
...(item?.badge ? {badge: item.badge} : {}),
|
||||
...(item.hidden !== undefined ? {hidden: item.hidden} : {}),
|
||||
...(item.hiddenOn !== undefined ? {hiddenOn: item.hiddenOn} : {})
|
||||
}))
|
||||
: [];
|
||||
}
|
||||
@ -165,7 +190,7 @@ export default class OptionControl extends React.Component<
|
||||
valueField
|
||||
} = ctx;
|
||||
const checkedOptions = this.state.options
|
||||
.filter(item => item.checked)
|
||||
.filter(item => item.checked && item?.hidden !== true)
|
||||
.map(item => omit(item, this.internalProps));
|
||||
let value: Array<OptionValue> | OptionValue;
|
||||
|
||||
@ -217,10 +242,13 @@ export default class OptionControl extends React.Component<
|
||||
if (source === 'custom') {
|
||||
const {options} = this.state;
|
||||
data.options = options.map(item => ({
|
||||
...(item?.badge ? {badge: item.badge} : {}),
|
||||
label: item.label,
|
||||
value: item.value == null || item.value === '' ? item.label : item.value
|
||||
value:
|
||||
item.value == null || item.value === '' ? item.label : item.value,
|
||||
...(item.hiddenOn !== undefined ? {hiddenOn: item.hiddenOn} : {})
|
||||
}));
|
||||
data.value = defaultValue || undefined;
|
||||
data.value = defaultValue;
|
||||
}
|
||||
|
||||
if (source === 'api' || source === 'apicenter') {
|
||||
@ -352,14 +380,44 @@ export default class OptionControl extends React.Component<
|
||||
this.setState({options});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑角标
|
||||
*/
|
||||
toggleBadge(index: number, value: boolean | {}) {
|
||||
const {options} = this.state;
|
||||
// visible
|
||||
if (typeof value === 'boolean') {
|
||||
if (value) {
|
||||
options[index].badge = {mode: 'dot'};
|
||||
} else {
|
||||
delete options[index].badge;
|
||||
}
|
||||
} else {
|
||||
// 角标配置
|
||||
options[index].badge = value;
|
||||
}
|
||||
|
||||
this.setState({options}, () => this.onChange());
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleEditLabel(index: number, value: string) {
|
||||
const options = this.state.options.concat();
|
||||
|
||||
options.splice(index, 1, {...options[index], label: value});
|
||||
this.setState({options}, () => this.onChange());
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleHiddenValueChange(index: number, value: string) {
|
||||
const options = this.state.options.concat();
|
||||
const {hiddenOn, ...option} = options[index];
|
||||
options.splice(index, 1, {
|
||||
...option,
|
||||
...(!value ? {} : {hiddenOn: value})
|
||||
});
|
||||
this.setState({options}, () => this.onChange());
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleAdd() {
|
||||
const {options} = this.state;
|
||||
@ -392,9 +450,9 @@ export default class OptionControl extends React.Component<
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleBatchAdd(values: {batchOption: string}, action: any) {
|
||||
handleBatchAdd(values: {batchOption: string}[], action: any) {
|
||||
const options = this.state.options.concat();
|
||||
const addedOptions: Array<OptionControlItem> = values.batchOption
|
||||
const addedOptions: Array<OptionControlItem> = values[0].batchOption
|
||||
.split('\n')
|
||||
.map(option => {
|
||||
const item = option.trim();
|
||||
@ -492,92 +550,110 @@ export default class OptionControl extends React.Component<
|
||||
|
||||
renderOption(props: any) {
|
||||
const {checked, index, editing, multipleProps, closeDefaultCheck} = props;
|
||||
const render = this.props.render;
|
||||
const ctx: Partial<TextControlSchema> = this.props.data;
|
||||
const {render, data: ctx, node} = this.props;
|
||||
const isMultiple = ctx?.multiple === true || multipleProps;
|
||||
const i18nEnabled = getI18nEnabled();
|
||||
|
||||
const label = this.transformOptionValue(props.label);
|
||||
const value = this.transformOptionValue(props.value);
|
||||
const valueType = this.getOptionValueType(props.value);
|
||||
const showBadge = node.type === 'button-group-select';
|
||||
|
||||
const editDom = editing ? (
|
||||
<div className="ae-OptionControlItem-extendMore">
|
||||
{render('option', {
|
||||
type: 'container',
|
||||
className: 'ae-ExtendMore right mb-2',
|
||||
body: [
|
||||
{
|
||||
type: 'button',
|
||||
className: 'ae-OptionControlItem-closeBtn',
|
||||
label: '×',
|
||||
level: 'link',
|
||||
onClick: () => this.toggleEdit(index)
|
||||
},
|
||||
{
|
||||
type: i18nEnabled ? 'input-text-i18n' : 'input-text',
|
||||
placeholder: '请输入显示文本',
|
||||
label: '文本',
|
||||
mode: 'horizontal',
|
||||
value: label,
|
||||
labelClassName: 'ae-OptionControlItem-EditLabel',
|
||||
valueClassName: 'ae-OptionControlItem-EditValue',
|
||||
onChange: (v: string) => this.handleEditLabel(index, v)
|
||||
},
|
||||
{
|
||||
type: 'input-group',
|
||||
name: 'input-group',
|
||||
label: '值',
|
||||
labelClassName: 'ae-OptionControlItem-EditLabel',
|
||||
valueClassName: 'ae-OptionControlItem-EditValue',
|
||||
mode: 'horizontal',
|
||||
body: [
|
||||
{
|
||||
type: 'select',
|
||||
name: 'valueType',
|
||||
value: valueType,
|
||||
options: [
|
||||
{
|
||||
label: '文本',
|
||||
value: 'text'
|
||||
},
|
||||
{
|
||||
label: '数字',
|
||||
value: 'number'
|
||||
},
|
||||
{
|
||||
label: '布尔',
|
||||
value: 'boolean'
|
||||
}
|
||||
],
|
||||
checkAll: false,
|
||||
onChange: (v: valueType) =>
|
||||
this.handleValueTypeChange(index, v)
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
placeholder: '默认与文本一致',
|
||||
name: 'value',
|
||||
value,
|
||||
visibleOn: "this.optionValueType !== 'boolean'",
|
||||
onChange: (v: string) => this.handleValueChange(index, v)
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
placeholder: '默认与文本一致',
|
||||
name: 'value',
|
||||
value,
|
||||
visibleOn: "this.optionValueType === 'boolean'",
|
||||
onChange: (v: string) => this.handleValueChange(index, v),
|
||||
options: [
|
||||
{label: 'true', value: true},
|
||||
{label: 'false', value: false}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})}
|
||||
{render(
|
||||
'option',
|
||||
{
|
||||
type: 'container',
|
||||
className: 'ae-ExtendMore right mb-2',
|
||||
body: [
|
||||
{
|
||||
type: 'button',
|
||||
className: 'ae-OptionControlItem-closeBtn',
|
||||
label: '×',
|
||||
level: 'link',
|
||||
onClick: () => this.toggleEdit(index)
|
||||
},
|
||||
{
|
||||
type: i18nEnabled ? 'input-text-i18n' : 'input-text',
|
||||
placeholder: '请输入显示文本',
|
||||
label: '文本',
|
||||
mode: 'horizontal',
|
||||
value: label,
|
||||
name: 'optionLabel',
|
||||
labelClassName: 'ae-OptionControlItem-EditLabel',
|
||||
valueClassName: 'ae-OptionControlItem-EditValue',
|
||||
onChange: (v: string) => this.handleEditLabel(index, v)
|
||||
},
|
||||
{
|
||||
type: 'input-group',
|
||||
name: 'input-group',
|
||||
label: '值',
|
||||
labelClassName: 'ae-OptionControlItem-EditLabel',
|
||||
valueClassName: 'ae-OptionControlItem-EditValue',
|
||||
mode: 'horizontal',
|
||||
body: [
|
||||
{
|
||||
type: 'select',
|
||||
name: 'optionValueType',
|
||||
value: valueType,
|
||||
options: [
|
||||
{
|
||||
label: '文本',
|
||||
value: 'text'
|
||||
},
|
||||
{
|
||||
label: '数字',
|
||||
value: 'number'
|
||||
},
|
||||
{
|
||||
label: '布尔',
|
||||
value: 'boolean'
|
||||
}
|
||||
],
|
||||
checkAll: false,
|
||||
onChange: (v: valueType) =>
|
||||
this.handleValueTypeChange(index, v)
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
placeholder: '默认与文本一致',
|
||||
name: 'optionValue',
|
||||
value,
|
||||
visibleOn: "this.optionValueType !== 'boolean'",
|
||||
onChange: (v: string) => this.handleValueChange(index, v)
|
||||
},
|
||||
{
|
||||
type: 'input-text',
|
||||
placeholder: '默认与文本一致',
|
||||
name: 'optionValue',
|
||||
value,
|
||||
visibleOn: "this.optionValueType === 'boolean'",
|
||||
onChange: (v: string) => this.handleValueChange(index, v),
|
||||
options: [
|
||||
{label: 'true', value: true},
|
||||
{label: 'false', value: false}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'ae-expressionFormulaControl',
|
||||
name: 'optionHiddenOn',
|
||||
label: '隐藏',
|
||||
labelClassName: 'ae-OptionControlItem-EditLabel',
|
||||
valueClassName: 'ae-OptionControlItem-EditValue',
|
||||
onChange: (v: string) => this.handleHiddenValueChange(index, v)
|
||||
},
|
||||
{
|
||||
type: 'ae-badge',
|
||||
visible: showBadge,
|
||||
value: props?.badge,
|
||||
onOptionChange: v => this.toggleBadge(index, v)
|
||||
}
|
||||
]
|
||||
},
|
||||
{data: createObject(ctx, {option: props})}
|
||||
)}
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
@ -606,6 +682,9 @@ export default class OptionControl extends React.Component<
|
||||
});
|
||||
}
|
||||
|
||||
const disabled = props?.hidden === true;
|
||||
const tooltip = disabled ? '隐藏选项不能设为默认值' : '默认选中此项';
|
||||
|
||||
return (
|
||||
<li className="ae-OptionControlItem" key={index}>
|
||||
<div className="ae-OptionControlItem-Main">
|
||||
@ -614,10 +693,11 @@ export default class OptionControl extends React.Component<
|
||||
</a>
|
||||
{!this.props.closeDefaultCheck &&
|
||||
this.props.data.defaultCheckAll !== true && (
|
||||
<span className="inline-flex" data-tooltip="默认选中此项">
|
||||
<span className="inline-flex" data-tooltip={tooltip}>
|
||||
<Checkbox
|
||||
className="ae-OptionControlItem-checkbox"
|
||||
checked={checked}
|
||||
disabled={disabled}
|
||||
type={isMultiple ? 'checkbox' : 'radio'}
|
||||
onChange={(newChecked: any, shift?: boolean) =>
|
||||
this.handleToggleDefaultValue(index, newChecked, shift)
|
||||
@ -676,6 +756,7 @@ export default class OptionControl extends React.Component<
|
||||
closeOnEsc: true,
|
||||
closeOnOutside: false,
|
||||
showCloseButton: true,
|
||||
onConfirm: this.handleBatchAdd,
|
||||
body: [
|
||||
{
|
||||
type: 'alert',
|
||||
@ -805,9 +886,7 @@ export default class OptionControl extends React.Component<
|
||||
添加选项
|
||||
</Button>
|
||||
{/* {render('option-control-batchAdd', this.buildBatchAddSchema())} */}
|
||||
{render('inner', this.buildBatchAddSchema(), {
|
||||
onSubmit: this.handleBatchAdd
|
||||
})}
|
||||
{render('inner', this.buildBatchAddSchema())}
|
||||
</div>
|
||||
|
||||
{/* {this.renderPopover()} */}
|
||||
|
@ -21,6 +21,10 @@ export interface StatusControlProps extends FormControlProps {
|
||||
options?: Option[];
|
||||
children?: SchemaCollection;
|
||||
messages?: Pick<FormSchema, 'messages'>;
|
||||
// 应用于不需要 bulkChange 的场景,如
|
||||
noBulkChange?: boolean;
|
||||
noBulkChangeData?: any;
|
||||
onDataChange?: (value: any) => void;
|
||||
}
|
||||
|
||||
type StatusFormData = {
|
||||
@ -48,11 +52,19 @@ export class StatusControl extends React.Component<
|
||||
}
|
||||
|
||||
initState() {
|
||||
const {data: ctx = {}, expressionName, name, trueValue} = this.props;
|
||||
const {data = {}, noBulkChange, noBulkChangeData, expressionName, name, trueValue} = this.props;
|
||||
|
||||
const formData: StatusFormData = {
|
||||
statusType: 1,
|
||||
expression: ''
|
||||
};
|
||||
|
||||
let ctx = data;
|
||||
|
||||
if (noBulkChange && noBulkChangeData) {
|
||||
ctx = noBulkChangeData
|
||||
}
|
||||
|
||||
if (ctx[expressionName] || ctx[expressionName] === '') {
|
||||
formData.statusType = 2;
|
||||
formData.expression = ctx[expressionName];
|
||||
@ -75,18 +87,19 @@ export class StatusControl extends React.Component<
|
||||
handleSwitch(value: boolean) {
|
||||
const {trueValue, falseValue} = this.props;
|
||||
this.setState({checked: value == trueValue ? true : false}, () => {
|
||||
const {onBulkChange, expressionName, name} = this.props;
|
||||
onBulkChange &&
|
||||
onBulkChange({
|
||||
[name]: value == trueValue ? trueValue : falseValue,
|
||||
[expressionName]: undefined
|
||||
});
|
||||
const {onBulkChange, noBulkChange, onDataChange, expressionName, name} = this.props;
|
||||
const newData = {
|
||||
[name]: value == trueValue ? trueValue : falseValue,
|
||||
[expressionName]: undefined
|
||||
};
|
||||
!noBulkChange && onBulkChange && onBulkChange(newData);
|
||||
onDataChange && onDataChange(newData);
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleFormSubmit(values: StatusFormData) {
|
||||
const {onBulkChange, name, expressionName} = this.props;
|
||||
const {onBulkChange, noBulkChange, onDataChange, name, expressionName} = this.props;
|
||||
const data: Record<string, any> = {
|
||||
[name]: undefined,
|
||||
[expressionName]: undefined
|
||||
@ -102,7 +115,8 @@ export class StatusControl extends React.Component<
|
||||
data[expressionName] = values.expression;
|
||||
break;
|
||||
}
|
||||
onBulkChange && onBulkChange(data);
|
||||
!noBulkChange && onBulkChange && onBulkChange(data);
|
||||
onDataChange && onDataChange(data);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -8,7 +8,7 @@ import remove from 'lodash/remove';
|
||||
import cx from 'classnames';
|
||||
import {FormItem} from 'amis';
|
||||
|
||||
import {autobind} from 'amis-editor-core';
|
||||
import {autobind, getSchemaTpl, tipedLabel} from 'amis-editor-core';
|
||||
import ValidationItem, {ValidatorData} from './ValidationItem';
|
||||
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
@ -323,10 +323,65 @@ export default class ValidationControl extends React.Component<
|
||||
return (
|
||||
<div className="ae-ValidationControl-rules" key="rules">
|
||||
{rules}
|
||||
{this.renderValidateApiControl()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderValidateApiControl() {
|
||||
const {onBulkChange, render} = this.props;
|
||||
return <div className='ae-ValidationControl-item'>
|
||||
{render('validate-api-control', {
|
||||
type: 'form',
|
||||
wrapWithPanel: false,
|
||||
className: 'w-full mb-2',
|
||||
bodyClassName: 'p-none',
|
||||
wrapperComponent: 'div',
|
||||
mode: 'horizontal',
|
||||
data: {
|
||||
validateApi: this.props.data.validateApi,
|
||||
switchStatus: this.props.data.validateApi !== undefined
|
||||
},
|
||||
preventEnterSubmit: true,
|
||||
submitOnChange: true,
|
||||
onSubmit: ({switchStatus, validateApi}: any) => {
|
||||
onBulkChange && onBulkChange({
|
||||
validateApi: !switchStatus ? undefined : validateApi
|
||||
});
|
||||
},
|
||||
body: [
|
||||
getSchemaTpl('switch', {
|
||||
label: tipedLabel(
|
||||
'接口校验',
|
||||
`配置校验接口,对表单项进行远程校验,配置方式与普通接口一致<br />
|
||||
1. 接口返回 <span class="ae-ValidationControl-label-code">{status: 0}</span> 表示校验通过<br />
|
||||
2. 接口返回 <span class="ae-ValidationControl-label-code">{status: 422}</span> 表示校验不通过<br />
|
||||
3. 若校验失败时需要显示错误提示信息,还需返回 errors 字段,示例<br />
|
||||
<span class="ae-ValidationControl-label-code">{status: 422, errors: '错误提示消息'}</span>
|
||||
`
|
||||
),
|
||||
name: 'switchStatus'
|
||||
}),
|
||||
{
|
||||
type: 'container',
|
||||
className: 'ae-ExtendMore ae-ValidationControl-item-input',
|
||||
bodyClassName: 'w-full',
|
||||
visibleOn: 'this.switchStatus',
|
||||
body: [
|
||||
getSchemaTpl('apiControl', {
|
||||
name: 'validateApi',
|
||||
renderLabel: true,
|
||||
label: '',
|
||||
mode: 'normal',
|
||||
className: 'w-full'
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
})}
|
||||
</div>
|
||||
}
|
||||
|
||||
render() {
|
||||
const {className} = this.props;
|
||||
|
||||
|
@ -40,12 +40,7 @@ export default class ActionConfigPanel extends React.Component<RendererProps> {
|
||||
|
||||
return schema ? (
|
||||
render('inner', schema as Schema, {
|
||||
data,
|
||||
onChange: (value: any, field: any) => {
|
||||
onBulkChange({
|
||||
[field]: value
|
||||
});
|
||||
}
|
||||
data
|
||||
})
|
||||
) : data.__subActions ? (
|
||||
<></>
|
||||
|
@ -334,6 +334,9 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
},
|
||||
{
|
||||
actionType: 'drawer'
|
||||
},
|
||||
{
|
||||
actionType: 'confirmDialog'
|
||||
}
|
||||
],
|
||||
schema: [
|
||||
@ -354,6 +357,10 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
{
|
||||
label: '抽屉',
|
||||
value: 'drawer'
|
||||
},
|
||||
{
|
||||
label: '确认对话框',
|
||||
value: 'confirmDialog'
|
||||
}
|
||||
],
|
||||
visibleOn: 'data.actionType === "openDialog"'
|
||||
@ -397,7 +404,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
mode: 'horizontal',
|
||||
required: true,
|
||||
pipeIn: defaultValue({
|
||||
title: '弹框标题',
|
||||
title: '抽屉标题',
|
||||
body: '对,你刚刚点击了'
|
||||
}),
|
||||
asFormItem: true,
|
||||
@ -419,6 +426,36 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
{_i18n('a532be3ad5f3fda70d228b8542e81835')}
|
||||
</Button>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'confirmDialog',
|
||||
type: 'container',
|
||||
visibleOn: 'data.groupType === "confirmDialog"',
|
||||
body: [
|
||||
getArgsWrapper({
|
||||
type: 'wrapper',
|
||||
className: 'p-none',
|
||||
body: [
|
||||
{
|
||||
name: 'msg',
|
||||
label: '消息内容',
|
||||
type: 'ae-textareaFormulaControl',
|
||||
mode: 'horizontal',
|
||||
variables: '${variables}',
|
||||
size: 'lg',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
label: '标题内容',
|
||||
type: 'ae-textareaFormulaControl',
|
||||
variables: '${variables}',
|
||||
mode: 'horizontal',
|
||||
size: 'lg'
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -1075,7 +1112,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
offText: '否',
|
||||
mode: 'horizontal',
|
||||
pipeIn: defaultValue(true),
|
||||
visibleOn: `data.actionType === "reload" && ${IS_DATA_CONTAINER}`
|
||||
visibleOn: `data.actionType === "reload" && data.__isScopeContainer`
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
@ -1088,7 +1125,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
offText: '否',
|
||||
mode: 'horizontal',
|
||||
pipeIn: defaultValue(true),
|
||||
visibleOn: `data.__addParam && data.actionType === "reload" && ${IS_DATA_CONTAINER}`,
|
||||
visibleOn: `data.__addParam && data.actionType === "reload" && data.__isScopeContainer`,
|
||||
onChange: (value: string, oldVal: any, data: any, form: any) => {
|
||||
form.setValueByName('__containerType', 'all');
|
||||
}
|
||||
@ -1099,7 +1136,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
mode: 'horizontal',
|
||||
label: '',
|
||||
pipeIn: defaultValue('all'),
|
||||
visibleOn: `data.__addParam && data.__customData && data.actionType === "reload" && ${IS_DATA_CONTAINER}`,
|
||||
visibleOn: `data.__addParam && data.__customData && data.actionType === "reload" && data.__isScopeContainer`,
|
||||
options: [
|
||||
{
|
||||
label: '直接赋值',
|
||||
@ -1127,7 +1164,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
label: '',
|
||||
size: 'lg',
|
||||
mode: 'horizontal',
|
||||
visibleOn: `data.__addParam && data.__customData && data.__containerType === "all" && data.actionType === "reload" && ${IS_DATA_CONTAINER}`
|
||||
visibleOn: `data.__addParam && data.__customData && data.__containerType === "all" && data.actionType === "reload" && data.__isScopeContainer`
|
||||
},
|
||||
*/
|
||||
getSchemaTpl('formulaControl', {
|
||||
@ -1137,7 +1174,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
size: 'lg',
|
||||
mode: 'horizontal',
|
||||
required: true,
|
||||
visibleOn: `data.__addParam && data.__customData && data.__containerType === "all" && data.actionType === "reload" && ${IS_DATA_CONTAINER}`
|
||||
visibleOn: `data.__addParam && data.__customData && data.__containerType === "all" && data.actionType === "reload" && data.__isScopeContainer`
|
||||
}),
|
||||
{
|
||||
type: 'combo',
|
||||
@ -1176,7 +1213,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
placeholder: '参数值'
|
||||
})
|
||||
],
|
||||
visibleOn: `data.__addParam && data.__customData && data.__containerType === "appoint" && data.actionType === "reload" && ${IS_DATA_CONTAINER}`
|
||||
visibleOn: `data.__addParam && data.__customData && data.__containerType === "appoint" && data.actionType === "reload" && data.__isScopeContainer`
|
||||
},
|
||||
{
|
||||
type: 'radios',
|
||||
@ -1187,7 +1224,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
'选择“合并”时,会将数据合并到目标组件的数据域。<br/>选择“覆盖”时,数据会直接覆盖目标组件的数据域。'
|
||||
),
|
||||
pipeIn: defaultValue('merge'),
|
||||
visibleOn: `data.__addParam && data.actionType === "reload" && ${IS_DATA_CONTAINER}`,
|
||||
visibleOn: `data.__addParam && data.actionType === "reload" && data.__isScopeContainer`,
|
||||
options: [
|
||||
{
|
||||
label: '合并',
|
||||
@ -1296,7 +1333,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
mode: 'horizontal',
|
||||
label: '数据设置',
|
||||
pipeIn: defaultValue('all'),
|
||||
visibleOn: `${IS_DATA_CONTAINER}`,
|
||||
visibleOn: 'data.__isScopeContainer',
|
||||
options: [
|
||||
{
|
||||
label: '直接赋值',
|
||||
@ -1396,7 +1433,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
placeholder: '字段值'
|
||||
})
|
||||
],
|
||||
visibleOn: `${IS_DATA_CONTAINER} && data.__containerType === 'appoint' || data.__comboType === 'appoint'`
|
||||
visibleOn: `data.__isScopeContainer && data.__containerType === 'appoint' || data.__comboType === 'appoint'`
|
||||
},
|
||||
{
|
||||
type: 'combo',
|
||||
@ -1466,7 +1503,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
label: '',
|
||||
size: 'lg',
|
||||
mode: 'horizontal',
|
||||
visibleOn: `(${IS_DATA_CONTAINER} || ${SHOW_SELECT_PROP}) && data.__containerType === 'all'`,
|
||||
visibleOn: `(data.__isScopeContainer || ${SHOW_SELECT_PROP}) && data.__containerType === 'all'`,
|
||||
required: true
|
||||
},
|
||||
*/
|
||||
@ -1476,7 +1513,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
variables: '${variables}',
|
||||
size: 'lg',
|
||||
mode: 'horizontal',
|
||||
visibleOn: `(${IS_DATA_CONTAINER} || ${SHOW_SELECT_PROP}) && data.__containerType === 'all'`,
|
||||
visibleOn: `(data.__isScopeContainer || ${SHOW_SELECT_PROP}) && data.__containerType === 'all'`,
|
||||
required: true
|
||||
}),
|
||||
/*
|
||||
@ -1490,7 +1527,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
label: '数据设置',
|
||||
size: 'lg',
|
||||
mode: 'horizontal',
|
||||
visibleOn: `data.__rendererName && !${IS_DATA_CONTAINER} && data.__rendererName !== 'combo'`,
|
||||
visibleOn: `data.__rendererName && !data.__isScopeContainer && data.__rendererName !== 'combo'`,
|
||||
required: true
|
||||
}
|
||||
*/
|
||||
@ -1500,7 +1537,7 @@ export const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
variables: '${variables}',
|
||||
size: 'lg',
|
||||
mode: 'horizontal',
|
||||
visibleOn: `data.__rendererName && !${IS_DATA_CONTAINER} && data.__rendererName !== 'combo' && data.__rendererName !== 'input-table'`,
|
||||
visibleOn: `data.__rendererName && !data.__isScopeContainer && data.__rendererName !== 'combo' && data.__rendererName !== 'input-table'`,
|
||||
required: true
|
||||
})
|
||||
]
|
||||
@ -1842,7 +1879,8 @@ export const renderCmptSelect = (
|
||||
__rendererLabel: '${label}',
|
||||
__rendererName: '${type}',
|
||||
__nodeId: '${id}',
|
||||
__nodeSchema: '${schema}'
|
||||
__nodeSchema: '${schema}',
|
||||
__isScopeContainer: '${isScopeContainer}'
|
||||
},
|
||||
onChange: async (value: string, oldVal: any, data: any, form: any) => {
|
||||
onChange?.(value, oldVal, data, form);
|
||||
@ -1987,7 +2025,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
placeholder: '变量值'
|
||||
})
|
||||
],
|
||||
visibleOn: `${IS_DATA_CONTAINER}`
|
||||
visibleOn: 'data.__isScopeContainer'
|
||||
},
|
||||
{
|
||||
type: 'combo',
|
||||
@ -2050,7 +2088,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
label: '变量赋值',
|
||||
size: 'lg',
|
||||
mode: 'horizontal',
|
||||
visibleOn: `!${IS_DATA_CONTAINER} && data.__rendererName !== 'combo'`,
|
||||
visibleOn: `!data.__isScopeContainer && data.__rendererName !== 'combo'`,
|
||||
required: true
|
||||
}
|
||||
*/
|
||||
@ -2060,7 +2098,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
variables: '${variables}',
|
||||
size: 'lg',
|
||||
mode: 'horizontal',
|
||||
visibleOn: `!${IS_DATA_CONTAINER} && data.__rendererName !== 'combo' && data.__rendererName !== 'input-table'`,
|
||||
visibleOn: `!data.__isScopeContainer && data.__rendererName !== 'combo' && data.__rendererName !== 'input-table'`,
|
||||
required: true
|
||||
})
|
||||
]
|
||||
@ -2308,10 +2346,12 @@ export const getOldActionSchema = (
|
||||
const isInDialog = /(?:\/|^)dialog\/.+$/.test(context.path);
|
||||
return {
|
||||
type: 'tooltip-wrapper',
|
||||
className: 'old-action-tooltip-warpper',
|
||||
content:
|
||||
'温馨提示:添加下方事件动作后,下方事件动作将先于旧版动作执行,建议统一迁移至事件动作机制,帮助您实现更灵活的交互设计',
|
||||
inline: true,
|
||||
tooltipTheme: 'dark',
|
||||
placement: 'bottom',
|
||||
body: [
|
||||
{
|
||||
type: 'button',
|
||||
@ -2477,7 +2517,7 @@ export const getOldActionSchema = (
|
||||
visibleOn: 'data.actionType == "drawer"',
|
||||
name: 'drawer',
|
||||
pipeIn: defaultValue({
|
||||
title: '弹框标题',
|
||||
title: '抽屉标题',
|
||||
body: '对,你刚刚点击了'
|
||||
}),
|
||||
asFormItem: true,
|
||||
@ -2713,18 +2753,20 @@ export const getEventControlConfig = (
|
||||
// 内置逻辑
|
||||
if (action.supportComponents === 'byComponent') {
|
||||
isSupport = hasActionType(actionType, actions);
|
||||
node.scoped = isSupport;
|
||||
}
|
||||
} else if (Array.isArray(action.supportComponents)) {
|
||||
isSupport = action.supportComponents.includes(node.type);
|
||||
}
|
||||
|
||||
node.isScopeContainer = !!manager.dataSchema.getScope(
|
||||
`${node.id}-${node.type}`
|
||||
);
|
||||
if (actionType === 'component' && !actions?.length) {
|
||||
node.disabled = true;
|
||||
}
|
||||
if (isSupport) {
|
||||
return true;
|
||||
} else if (haveChild) {
|
||||
node.disabled = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -130,6 +130,14 @@ export class TextareaFormulaControl extends React.Component<
|
||||
variables: variablesArr
|
||||
});
|
||||
}
|
||||
if (this.state.value !== this.props.value) {
|
||||
this.setState(
|
||||
{
|
||||
value: this.props.value
|
||||
},
|
||||
this.editorAutoMark
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -10,8 +10,10 @@ import type {VariableItem} from 'amis-ui/lib/components/formula/Editor';
|
||||
*/
|
||||
export async function resolveVariablesFromScope(node: any, manager: any) {
|
||||
await manager?.getContextSchemas(node);
|
||||
// 获取当前组件内相关变量,如表单、增删改查
|
||||
const dataPropsAsOptions: VariableItem[] =
|
||||
manager?.dataSchema?.getDataPropsAsOptions();
|
||||
await manager?.dataSchema?.getDataPropsAsOptions();
|
||||
|
||||
const variables: VariableItem[] =
|
||||
manager?.variableManager?.getVariableFormulaOptions() || [];
|
||||
|
||||
|
@ -281,8 +281,14 @@ setSchemaTpl('ref', () => {
|
||||
|
||||
setSchemaTpl('selectFirst', {
|
||||
type: 'switch',
|
||||
label: '是否默认选择第一个',
|
||||
name: 'selectFirst'
|
||||
label: '默认选择第一项',
|
||||
name: 'selectFirst',
|
||||
mode: 'horizontal',
|
||||
horizontal: {
|
||||
justify: true,
|
||||
left: 8
|
||||
},
|
||||
inputClassName: 'is-inline '
|
||||
});
|
||||
|
||||
setSchemaTpl('hideNodePathLabel', {
|
||||
@ -321,7 +327,7 @@ setSchemaTpl('optionControlV2', {
|
||||
mode: 'normal',
|
||||
name: 'options',
|
||||
type: 'ae-optionControl',
|
||||
closeDefaultCheck: true // 关闭默认值设置
|
||||
closeDefaultCheck: false // 关闭默认值设置
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -565,6 +565,16 @@ setSchemaTpl('theme:shadow', (option: any = {}) => {
|
||||
};
|
||||
});
|
||||
|
||||
// 尺寸选择器
|
||||
setSchemaTpl('theme:size', (option: any = {}) => {
|
||||
return {
|
||||
type: 'amis-theme-select',
|
||||
label: false,
|
||||
name: `css.className.size`,
|
||||
...option
|
||||
};
|
||||
});
|
||||
|
||||
setSchemaTpl(
|
||||
'theme:common',
|
||||
(exclude: string[] | string, include: string[]) => {
|
||||
|
@ -279,3 +279,11 @@ export const isAuto = (value: any) => {
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export const schemaToArray = (value: any) => {
|
||||
return value && Array.isArray(value)? value : [value];
|
||||
};
|
||||
|
||||
export const schemaArrayFormat = (value: any) => {
|
||||
return value && Array.isArray(value) && value.length === 1 ? value[0] : value;
|
||||
};
|
Loading…
Reference in New Issue
Block a user