feat: 同步pagemaker以下功能: inputNumber单位选项支持key/value; inputTable增加是否展示列开关配置项;增加部分组件searchKeywords字段

This commit is contained in:
yinchunyu 2023-10-23 15:33:23 +08:00
parent 7c739a152f
commit 88fefedde7
33 changed files with 424 additions and 41 deletions

View File

@ -0,0 +1,42 @@
.ae-KeyValMapControl-wrapper {
.ae-KeyValMapControlItem-Main {
width: 100%;
display: flex;
justify-content: space-between;
}
.ae-KeyValMapControlItem-input {
flex: 1;
margin-right: 10px;
}
.ae-ExtendMore {
position: relative;
.cxd-Container-body {
margin-top: 20px;
}
}
.ae-KeyValMapControlItem-closeBtn {
position: absolute;
top: 0;
right: 0;
font-size: 18px;
color: #151b26;
padding-right: 0.625rem;
z-index: 1;
}
.ae-KeyValMapControlItem-EditLabel {
margin-top: 10px;
}
.ae-KeyValMapControl-footer > * {
width: calc(50% - 0.375rem);
}
.ae-KeyValMapControl-footer > *:first-child {
margin-right: 0.75rem;
}
}

View File

@ -38,6 +38,7 @@
@import './control/tree_option_control';
@import './control/_inpupt-file';
@import './control/_nav-control';
@import './control/_key-value-map-control';
@import './control/_status';
@import './control/_icon-button-group-control';
@import './control/_flex-setting-control';

View File

@ -6,6 +6,7 @@ export * from './plugin';
import './renderer/OptionControl';
import './renderer/NavSourceControl';
import './renderer/KeyValueMapControl';
import './renderer/NavBadgeControl';
import './renderer/NavDefaultActive';
import './renderer/MapSourceControl';

View File

@ -30,6 +30,7 @@ export class CardsPlugin extends BasePlugin {
isBaseComponent = true;
description =
'功能类似于表格,但是用一个个小卡片来展示数据。当前组件需要配置数据源,不自带数据拉取,请优先使用 「CRUD」 组件。';
searchKeywords = '卡片组';
docLink = '/amis/zh-CN/components/cards';
tags = ['展示'];
icon = 'fa fa-window-maximize';

View File

@ -24,6 +24,7 @@ export class DropDownButtonPlugin extends BasePlugin {
name = '下拉按钮';
isBaseComponent = true;
description = '下拉按钮,更多的按钮通过点击后展示开来。';
searchKeywords = '下拉菜单';
tags = ['表单项'];
icon = 'fa fa-chevron-down';
pluginIcon = 'dropdown-btn-plugin';

View File

@ -23,6 +23,7 @@ export class EachPlugin extends BasePlugin {
name = '循环 Each';
isBaseComponent = true;
description = '功能渲染器,可以基于现有变量循环输出渲染器。';
searchKeywords = '循环渲染器';
tags = ['功能'];
icon = 'fa fa-repeat';
pluginIcon = 'each-plugin';

View File

@ -27,6 +27,7 @@ export class DiffEditorControlPlugin extends BasePlugin {
description = `左右两边的代码做对比,支持的语言包括:${availableLanguages
.slice(0, 10)
.join('')}`;
searchKeywords = '对比编辑器';
docLink = '/amis/zh-CN/components/form/diff-editor';
tags = ['表单项'];
scaffold = {

View File

@ -15,6 +15,7 @@ export class FieldSetControlPlugin extends BasePlugin {
isBaseComponent = true;
icon = 'fa fa-toggle-down';
description = '多个表单项的组合,可配置是否折叠';
searchKeywords = '表单项集合';
docLink = '/amis/zh-CN/components/form/fieldset';
tags = ['表单项'];
scaffold = {

View File

@ -14,6 +14,7 @@ export class HiddenControlPlugin extends BasePlugin {
icon = 'fa fa-eye-slash';
pluginIcon = 'hidden-plugin';
description = '隐藏表单项';
searchKeywords = '隐藏字段';
docLink = '/amis/zh-CN/components/form/hidden';
tags = ['表单项'];
scaffold = {

View File

@ -32,6 +32,7 @@ export class CityControlPlugin extends BasePlugin {
icon = 'fa fa-building-o';
pluginIcon = 'input-city-plugin';
description = '可配置是否选择区域或者城市';
searchKeywords = '城市选择器';
docLink = '/amis/zh-CN/components/form/input-city';
tags = ['表单项'];
scaffold = {

View File

@ -68,6 +68,7 @@ export class ColorControlPlugin extends BasePlugin {
pluginIcon = 'input-color-plugin';
description =
'支持<code>hex、hls、rgb、rgba</code>格式,默认为<code>hex</code>格式';
searchKeywords = '颜色选择器';
docLink = '/amis/zh-CN/components/form/input-color';
tags = ['表单项'];
scaffold = {

View File

@ -148,7 +148,7 @@ export class DateControlPlugin extends BasePlugin {
isBaseComponent = true;
// 添加源对应组件中文名称 & type字段
searchKeywords =
'日期框、input-datetime、日期时间框、input-time、时间框、input-month、月份框、input-quarter、季度框、input-year、年框';
'日期框、input-datetime、日期时间框、input-time、时间框、input-month、月份框、input-quarter、季度框、input-year、年框、年份框、年份选择';
description = '年月日选择,支持相对值设定,如<code>+2days</code>两天后';
docLink = '/amis/zh-CN/components/form/input-date';
tags = ['表单项'];

View File

@ -193,7 +193,7 @@ export class DateRangeControlPlugin extends BasePlugin {
isBaseComponent = true;
// 添加源对应组件中文名称 & type字段
searchKeywords =
'日期范围框、input-datetime-range、日期时间范围、input-time-range、时间范围、input-month-range、月份范围、input-quarter-range、季度范围、input-year-range、年范围';
'日期范围框、input-datetime-range、日期时间范围、input-time-range、时间范围、input-month-range、月份范围、input-quarter-range、季度范围、input-year-range、年范围、年份范围';
description =
'日期范围选择,可通过<code>minDate</code>、<code>maxDate</code>设定最小、最大日期';
docLink = '/amis/zh-CN/components/form/input-date-range';

View File

@ -22,6 +22,7 @@ export class InputGroupControlPlugin extends BasePlugin {
icon = 'fa fa-object-group';
pluginIcon = 'input-group-plugin';
description = '输入组合,支持多种类型的控件组合';
searchKeywords = '输入框组合';
docLink = '/amis/zh-CN/components/form/input-group';
tags = ['表单项'];
scaffold = {

View File

@ -32,6 +32,7 @@ export class NumberControlPlugin extends BasePlugin {
icon = 'fa fa-sort-numeric-asc';
pluginIcon = 'input-number-plugin';
description = '支持设定最大值和最小值,以及步长与精度';
searchKeywords = '数字输入框';
docLink = '/amis/zh-CN/components/form/input-number';
tags = ['表单项'];
scaffold = {
@ -222,35 +223,7 @@ export class NumberControlPlugin extends BasePlugin {
},
getSchemaTpl('prefix'),
getSchemaTpl('suffix'),
getSchemaTpl('combo-container', {
type: 'combo',
label: '单位选项',
mode: 'normal',
name: 'unitOptions',
flat: true,
items: [
{
placeholder: '单位选项',
type: i18nEnabled ? 'input-text-i18n' : 'input-text',
name: 'text'
}
],
draggable: false,
multiple: true,
pipeIn: (value: any) => {
if (!isObject(value)) {
return Array.isArray(value) ? value : [];
}
const res = value.map((item: any) => item.value);
return res;
},
pipeOut: (value: any[]) => {
if (!value.length) {
return undefined;
}
return value;
}
}),
getSchemaTpl('keyValueMapControl'),
getSchemaTpl('labelRemark'),
getSchemaTpl('remark'),
getSchemaTpl('placeholder'),

View File

@ -14,6 +14,7 @@ export class RepeatControlPlugin extends BasePlugin {
icon = 'fa fa-repeat';
pluginIcon = 'input-repeat-plugin';
description = '选择重复的频率,如每时、每天、每周等';
searchKeywords = '重复频率选择器';
docLink = '/amis/zh-CN/components/form/input-repeat';
tags = ['表单项'];
scaffold = {

View File

@ -1004,7 +1004,34 @@ export class TableControlPlugin extends BasePlugin {
},
getSchemaTpl('description'),
getSchemaTpl('placeholder'),
getSchemaTpl('labelRemark')
getSchemaTpl('labelRemark'),
{
name: 'columnsTogglable',
label: tipedLabel(
'列显示开关',
'是否展示表格列的显隐控件“自动”即列数量大于5时自动开启'
),
type: 'button-group-select',
pipeIn: defaultValue('auto'),
size: 'sm',
labelAlign: 'left',
options: [
{
label: '自动',
value: 'auto'
},
{
label: '开启',
value: true
},
{
label: '关闭',
value: false
}
]
}
]
},
{

View File

@ -25,6 +25,7 @@ export class TagControlPlugin extends BasePlugin {
icon = 'fa fa-tag';
pluginIcon = 'input-tag-plugin';
description = '配置 options 可以实现选择选项';
searchKeywords = '标签选择器';
docLink = '/amis/zh-CN/components/form/input-tag';
tags = ['表单项'];
scaffold = {

View File

@ -31,7 +31,7 @@ export class TextControlPlugin extends BasePlugin {
order = -600;
// 添加源对应组件中文名称 & type字段
searchKeywords =
'文本框、邮箱框、input-email、URL框、input-url、密码框、input-password';
'文本框、邮箱框、input-email、URL框、input-url、密码框、input-password、密码输入框';
// 组件名称
name = '文本框';

View File

@ -29,7 +29,8 @@ export class TreeControlPlugin extends BasePlugin {
icon = 'fa fa-list-alt';
pluginIcon = 'input-tree-plugin';
description = '树型结构选择,支持 [内嵌模式] 与 [浮层模式] 的外观切换';
searchKeywords = 'tree、树下拉、树下拉框、tree-select';
searchKeywords =
'tree、树下拉、树下拉框、tree-select、树形选择框、树形选择器';
docLink = '/amis/zh-CN/components/form/input-tree';
tags = ['表单项'];
scaffold = {

View File

@ -32,6 +32,7 @@ export class PickerControlPlugin extends BasePlugin {
pluginIcon = 'picker-plugin';
description =
'通过 pickerSchema 配置可供选取的数据源进行选择需要的数据,支持多选';
searchKeywords = '列表选择器';
docLink = '/amis/zh-CN/components/form/picker';
tags = ['表单项'];
scaffold = {

View File

@ -21,6 +21,9 @@ export class SelectControlPlugin extends BasePlugin {
icon = 'fa fa-th-list';
pluginIcon = 'select-plugin';
description = '支持多选,输入提示,可使用 source 获取选项';
searchKeywords = '选择器';
docLink = '/amis/zh-CN/components/form/select';
tags = ['表单项'];
scaffold = {

View File

@ -19,6 +19,7 @@ export class TextareaControlPlugin extends BasePlugin {
icon = 'fa fa-paragraph';
pluginIcon = 'textarea-plugin';
description = '支持换行输入';
searchKeywords = '多行文本输入框';
docLink = '/amis/zh-CN/components/form/textarea';
tags = ['表单项'];
scaffold = {

View File

@ -19,6 +19,7 @@ export class UUIDControlPlugin extends BasePlugin {
icon = 'fa fa-eye-slash';
pluginIcon = 'uuid-plugin';
description = '自动生成的 UUID';
searchKeywords = 'uuid字段';
docLink = '/amis/zh-CN/components/form/uuid';
tags = ['表单项'];
scaffold = {

View File

@ -30,6 +30,7 @@ export class GridPlugin extends BasePlugin {
name = '分栏';
isBaseComponent = true;
description = '分栏布局';
searchKeywords = '水平分栏';
docLink = '/amis/zh-CN/components/grid';
tags = ['布局容器'];
order = -2;

View File

@ -17,6 +17,7 @@ export class LogPlugin extends BasePlugin {
icon = 'fa fa-file-text-o';
pluginIcon = 'log-plugin';
description = '用来实时显示日志';
searchKeywords = '实时日志';
docLink = '/amis/zh-CN/components/log';
tags = ['展示'];
previewSchema = {

View File

@ -23,6 +23,9 @@ export class ServicePlugin extends BasePlugin {
isBaseComponent = true;
description =
'功能性容器,可以用来加载数据或者加载渲染器配置。加载到的数据在容器可以使用。';
searchKeywords = '功能型容器';
docLink = '/amis/zh-CN/components/service';
tags = ['数据容器'];
icon = 'fa fa-server';

View File

@ -560,15 +560,14 @@ export class TablePlugin extends BasePlugin {
body: [
{
name: 'columnsTogglable',
label: '展示列显示开关',
label: tipedLabel(
'列显示开关',
'是否展示表格列的显隐控件“自动”即列数量大于5时自动开启'
),
type: 'button-group-select',
pipeIn: defaultValue('auto'),
size: 'sm',
labelAlign: 'left',
horizontal: {
left: 5,
right: 7
},
options: [
{
label: '自动',
@ -584,8 +583,7 @@ export class TablePlugin extends BasePlugin {
label: '关闭',
value: false
}
],
description: '自动即列数量大于5个时自动开启'
]
},
getSchemaTpl('switch', {

View File

@ -96,6 +96,7 @@ export class TableViewPlugin extends BasePlugin {
icon = 'fa fa-columns';
pluginIcon = 'table-view-plugin';
description = '表格类型的展现';
searchKeywords = '表格展现';
docLink = '/amis/zh-CN/components/table-view';
tags = ['功能'];
scaffold = {

View File

@ -16,6 +16,7 @@ export class TasksPlugin extends BasePlugin {
name = '异步任务';
isBaseComponent = true;
description = '用来做异步任务呈现或者操作。';
searchKeywords = '任务操作集合';
docLink = '/amis/zh-CN/components/tasks';
tags = ['功能'];
icon = '';

View File

@ -17,6 +17,7 @@ export class TooltipWrapperPlugin extends BasePlugin {
name = '文字提示';
description =
'类似容器,可以将多个渲染器放置在一起,当用户鼠标悬停或者点击容器时,显示文字提示浮层';
searchKeywords = '文字提示容器';
docLink = '/amis/zh-CN/components/tooltip';
tags = ['功能'];
icon = 'fa fa-comment-alt';

View File

@ -0,0 +1,306 @@
import React from 'react';
import {FormItem, Button, render as amisRender} from 'amis';
import {autobind, getI18nEnabled} from 'amis-editor-core';
import type {FormControlProps} from 'amis-core';
import uniqBy from 'lodash/uniqBy';
export interface KeyValueControlProps extends FormControlProps {}
export interface KeyValueControlState {
unitOptions: Array<{label: string; value: string; editing?: boolean}>;
}
@FormItem({
type: 'ae-keyValueMapControl'
})
export class KeyValueMapControl extends React.Component<
KeyValueControlProps,
KeyValueControlState
> {
constructor(props: KeyValueControlProps) {
super(props);
this.state = {
unitOptions: this.transformOptions(props)
};
}
transformOptions(props: KeyValueControlProps) {
const {value} = props;
if (Array.isArray(value)) {
return value.map(item =>
typeof item === 'string'
? {
label: item,
value: item
}
: item
);
} else {
return [];
}
}
/**
*
*/
@autobind
handleAdd() {
const {unitOptions} = this.state;
unitOptions.push({
label: '',
value: '',
editing: false
});
this.setState({unitOptions}, () => {
this.onChange();
});
}
/**
*
*/
@autobind
handleBatchAdd(values: {batchOption: string}[], action: any) {
const unitOptions = this.state.unitOptions.concat();
const addedOptions: Array<{label: string; value: string}> =
values[0].batchOption.split('\n').map(option => {
const item = option.trim();
if (~item.indexOf(' ')) {
let [label, value] = item.split(' ');
return {label: label.trim(), value: value.trim()};
}
return {label: item, value: item};
});
const newOptionsUniqByLabel = uniqBy(
[...unitOptions, ...addedOptions],
'label'
);
const newOptions = uniqBy(newOptionsUniqByLabel, 'value');
this.setState({unitOptions: newOptions}, () => this.onChange());
}
/**
*
*/
@autobind
handleEditLabel(index: number, value: string) {
const unitOptions = this.state.unitOptions.concat();
unitOptions.splice(index, 1, {...unitOptions[index], label: value});
this.setState({unitOptions}, () => this.onChange());
}
/**
*
*/
@autobind
handleValueChange(index: number, value: string) {
const unitOptions = this.state.unitOptions.concat();
unitOptions.splice(index, 1, {...unitOptions[index], value: value});
this.setState({unitOptions}, () => this.onChange());
}
/**
*
*/
toggleEdit(index: number) {
const {unitOptions} = this.state;
unitOptions[index].editing = !unitOptions[index].editing;
this.setState({unitOptions});
}
/**
*
*/
handleDelete(index: number) {
const unitOptions = this.state.unitOptions.concat();
unitOptions.splice(index, 1);
this.setState({unitOptions}, () => this.onChange());
}
/**
* unitOptions字段的统一出口
*/
onChange() {
const {onBulkChange} = this.props;
const {unitOptions} = this.state;
const options = unitOptions.map(item => ({
label: item.label,
value: item.value
}));
onBulkChange && onBulkChange({unitOptions: options});
return;
}
renderOption(props: any, index: number) {
const {label, value, editing} = props;
const {render} = this.props;
const i18nEnabled = getI18nEnabled();
const editDom = editing ? (
<div className="ae-KeyValMapControlItem-extendMore">
{render('option', {
type: 'container',
className: 'ae-ExtendMore right mb-2',
body: [
{
type: 'button',
className: 'ae-KeyValMapControlItem-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-KeyValMapControlItem-EditLabel',
valueClassName: 'ae-KeyValMapControlItem-EditValue',
onChange: (v: string) => this.handleEditLabel(index, v)
},
{
type: i18nEnabled ? 'input-text-i18n' : 'input-text',
placeholder: '值内容',
label: '值',
mode: 'horizontal',
value: value,
name: 'optionValue',
labelClassName: 'ae-KeyValMapControlItem-EditLabel',
valueClassName: 'ae-KeyValMapControlItem-EditValue',
onChange: (v: string) => this.handleValueChange(index, v)
}
]
})}
</div>
) : null;
const operationBtn = [
{
type: 'button',
className: 'ae-KeyValMapControlItem-action',
label: '编辑',
onClick: () => this.toggleEdit(index)
},
{
type: 'button',
className: 'ae-KeyValMapControlItem-action',
label: '删除',
onClick: () => this.handleDelete(index)
}
];
return (
<div className="ae-KeyValMapControlItem">
<div className="ae-KeyValMapControlItem-Main">
{amisRender({
type: i18nEnabled ? 'input-text-i18n' : 'input-text',
className: 'ae-KeyValMapControlItem-input',
value: label,
placeholder: '请输入文本/值',
clearable: false,
onChange: (value: string) => {
this.handleEditLabel(index, value);
}
})}
{render(
'dropdown',
{
type: 'dropdown-button',
className: 'ae-KeyValMapControlItem-dropdown',
btnClassName: 'px-2',
icon: 'fa fa-ellipsis-h',
hideCaret: true,
closeOnClick: true,
align: 'right',
menuClassName: 'ae-KeyValMapControlItem-ulmenu',
buttons: operationBtn
},
{
popOverContainer: null // amis 渲染挂载节点会使用 this.target
}
)}
</div>
{editDom}
</div>
);
}
buildBatchAddSchema() {
return {
type: 'action',
actionType: 'dialog',
label: '批量添加',
dialog: {
title: '批量添加选项',
headerClassName: 'font-bold',
closeOnEsc: true,
closeOnOutside: false,
showCloseButton: true,
onConfirm: this.handleBatchAdd,
body: [
{
type: 'alert',
level: 'warning',
body: [
{
type: 'tpl',
tpl: '每个选项单列一行,将所有值不重复的项加为新的选项;<br/>每行可通过空格来分别设置label和value,例:"张三 zhangsan"'
}
],
showIcon: true,
className: 'mb-2.5'
},
{
type: 'form',
wrapWithPanel: false,
mode: 'normal',
wrapperComponent: 'div',
resetAfterSubmit: true,
autoFocus: true,
preventEnterSubmit: true,
horizontal: {
left: 0,
right: 12
},
body: [
{
name: 'batchOption',
type: 'textarea',
label: '',
placeholder: '请输入选项内容',
trimContents: true,
minRows: 10,
maxRows: 50,
required: true
}
]
}
]
}
};
}
render() {
const {unitOptions} = this.state;
const {render} = this.props;
return (
<div className="ae-KeyValMapControl-wrapper">
{unitOptions.length && (
<div>
{unitOptions.map((item, index) => this.renderOption(item, index))}
</div>
)}
<div className="ae-KeyValMapControl-footer">
<Button level="enhance" onClick={this.handleAdd}>
</Button>
{render('inner', this.buildBatchAddSchema())}
</div>
</div>
);
}
}

View File

@ -446,3 +446,12 @@ setSchemaTpl('dataMap', {
})
]
});
/**
* key value映射类组件
*/
setSchemaTpl('keyValueMapControl', {
type: 'ae-keyValueMapControl',
label: '单位选项',
name: 'unitOptions',
mode: 'normal'
});