diff --git a/packages/amis-editor/src/plugin/Form/InputDate.tsx b/packages/amis-editor/src/plugin/Form/InputDate.tsx index 1598d95ef..49c3e0286 100644 --- a/packages/amis-editor/src/plugin/Form/InputDate.tsx +++ b/packages/amis-editor/src/plugin/Form/InputDate.tsx @@ -4,6 +4,7 @@ import {BasePlugin, BaseEventContext, tipedLabel} from 'amis-editor-core'; import {ValidatorTag} from '../../validator'; import {getEventControlConfig} from '../../renderer/event-control/helper'; +import {FormulaDateType} from '../../renderer/FormulaControl'; import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; const formatX = [ @@ -135,8 +136,8 @@ const DateType: { } }; -const tipedLabelText = - '支持 now、+1day、-2weeks、+1hours、+2years这种相对值用法,同时支持变量如\\${start_date}'; +const dateTooltip = + '支持例如: now、+3days、-2weeks、+1hour、+2years 等(minute|min|hour|day|week|month|year|weekday|second|millisecond)这种相对值用法'; export class DateControlPlugin extends BasePlugin { // 关联渲染器名字 @@ -312,28 +313,31 @@ export class DateControlPlugin extends BasePlugin { }), getSchemaTpl('valueFormula', { rendererSchema: context?.schema, - label: tipedLabel( - '默认值', - '支持 now、+1day、-2weeks、+1hours、+2years等这种相对值用法' - ) + header: '表达式或相对值', + DateTimeType: FormulaDateType.IsDate, + label: tipedLabel('默认值', dateTooltip) }), getSchemaTpl('valueFormula', { name: 'minDate', + header: '表达式或相对值', + DateTimeType: FormulaDateType.IsDate, rendererSchema: { ...context?.schema, value: context?.schema.minDate }, needDeleteProps: ['minDate'], // 避免自我限制 - label: tipedLabel('最小值', tipedLabelText) + label: tipedLabel('最小值', dateTooltip) }), getSchemaTpl('valueFormula', { name: 'maxDate', + header: '表达式或相对值', + DateTimeType: FormulaDateType.IsDate, rendererSchema: { ...context?.schema, value: context?.schema.maxDate }, needDeleteProps: ['maxDate'], // 避免自我限制 - label: tipedLabel('最大值', tipedLabelText) + label: tipedLabel('最大值', dateTooltip) }), getSchemaTpl('placeholder', { pipeIn: defaultValue('请选择日期') diff --git a/packages/amis-editor/src/plugin/Form/InputDateRange.tsx b/packages/amis-editor/src/plugin/Form/InputDateRange.tsx index d2ab4e4b7..e427ab6ed 100644 --- a/packages/amis-editor/src/plugin/Form/InputDateRange.tsx +++ b/packages/amis-editor/src/plugin/Form/InputDateRange.tsx @@ -4,6 +4,7 @@ import {BasePlugin, BaseEventContext} from 'amis-editor-core'; import {ValidatorTag} from '../../validator'; import {getEventControlConfig} from '../../renderer/event-control/helper'; +import {FormulaDateType} from '../../renderer/FormulaControl'; import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; const DateType: { @@ -59,8 +60,10 @@ const DateType: { } }; -const tipedLabelText = - '支持 now、+1day、-2weeks、+1hours、+2years这种相对值用法,同时支持变量如\\${start_date}'; +const dateTooltip = + '支持例如: now、+3days、-2weeks、+1hour、+2years 等(minute|hour|day|week|month|year|weekday|second|millisecond)这种相对值用法'; +const rangTooltip = + '支持例如: 3days、2weeks、1hour、2years 等(minute|hour|day|week|month|year|weekday|second|millisecond)这种相对值用法'; export class DateRangeControlPlugin extends BasePlugin { // 关联渲染器名字 @@ -247,63 +250,65 @@ export class DateRangeControlPlugin extends BasePlugin { }), getSchemaTpl('valueFormula', { - /* 备注: 待 amis 日期组件优化 - rendererSchema: { - ...context?.schema, - size: 'full', // 备注:目前样式还有问题,需要在amis端进行优化 - mode: "inline" - }, - mode: 'vertical', - */ rendererSchema: { - type: 'input-date' + ...context?.schema, + size: 'full', + mode: 'inline' }, - label: tipedLabel( - '默认值', - '支持 now、+1day、-2weeks、+1hours、+2years等这种相对值用法' - ) + mode: 'vertical', + header: '表达式或相对值', + DateTimeType: FormulaDateType.IsDate, + label: tipedLabel('默认值', dateTooltip) }), getSchemaTpl('valueFormula', { name: 'minDate', + header: '表达式或相对值', + DateTimeType: FormulaDateType.IsDate, rendererSchema: { ...context?.schema, value: context?.schema.minDate, type: 'input-date' }, needDeleteProps: ['minDate'], // 避免自我限制 - label: tipedLabel('最小值', tipedLabelText) + label: tipedLabel('最小值', dateTooltip) }), getSchemaTpl('valueFormula', { name: 'maxDate', + header: '表达式或相对值', + DateTimeType: FormulaDateType.IsDate, rendererSchema: { ...context?.schema, value: context?.schema.maxDate, type: 'input-date' }, needDeleteProps: ['maxDate'], // 避免自我限制 - label: tipedLabel('最大值', tipedLabelText) + label: tipedLabel('最大值', dateTooltip) }), getSchemaTpl('valueFormula', { name: 'minDuration', + header: '表达式或相对值', + DateTimeType: FormulaDateType.IsRange, rendererSchema: { ...context?.schema, value: context?.schema.minDuration, type: 'input-text' }, needDeleteProps: ['minDuration'], // 避免自我限制 - label: tipedLabel('最小跨度', '例如 2days') + label: tipedLabel('最小跨度', rangTooltip) }), getSchemaTpl('valueFormula', { name: 'maxDuration', + header: '表达式或相对值', + DateTimeType: FormulaDateType.IsRange, rendererSchema: { ...context?.schema, value: context?.schema.maxDuration, type: 'input-text' }, needDeleteProps: ['maxDuration'], // 避免自我限制 - label: tipedLabel('最大跨度', '例如 1year') + label: tipedLabel('最大跨度', rangTooltip) }), getSchemaTpl('dateShortCutControl', { mode: 'normal', diff --git a/packages/amis-editor/src/renderer/FormulaControl.tsx b/packages/amis-editor/src/renderer/FormulaControl.tsx index 2c4591c5d..55b2b1de5 100644 --- a/packages/amis-editor/src/renderer/FormulaControl.tsx +++ b/packages/amis-editor/src/renderer/FormulaControl.tsx @@ -15,7 +15,7 @@ import omit from 'lodash/omit'; import cx from 'classnames'; import {FormItem, Button, InputBox, Icon, ResultBox} from 'amis'; import {FormulaExec, isExpression} from 'amis'; -import {PickerContainer} from 'amis'; +import {PickerContainer, relativeValueRe} from 'amis'; import {FormulaEditor} from 'amis-ui/lib/components/formula/Editor'; import {autobind} from 'amis-editor-core'; @@ -27,6 +27,13 @@ import type { import {dataMapping, FormControlProps} from 'amis-core'; import type {BaseEventContext} from 'amis-editor-core'; import {EditorManager} from 'amis-editor-core'; + +export enum FormulaDateType { + NotDate, // 不是时间类 + IsDate, // 日期时间类 + IsRange // 日期时间范围类 +} + export interface FormulaControlProps extends FormControlProps { manager?: EditorManager; @@ -95,6 +102,14 @@ export interface FormulaControlProps extends FormControlProps { * 是否使用外部的Form数据 */ useExternalFormData?: boolean; + + /** + * 是否是日期类组件使用formulaControl + * 日期类 值 使用表达式时,支持 now、+1day、-2weeks、+1hours、+2years等这种相对值写法,不会最外层包裹 ${} + * 日期类 跨度值 使用表达式时,支持 1day、2weeks、1hours、2years等这种相对值写法,不会最外层包裹 ${} + * 默认为 FormulaDateType.NotDate + */ + DateTimeType?: FormulaDateType; } interface FormulaControlState { @@ -109,7 +124,8 @@ export default class FormulaControl extends React.Component< FormulaControlState > { static defaultProps: Partial = { - simple: false + simple: false, + DateTimeType: FormulaDateType.NotDate }; isUnmount: boolean; @@ -261,6 +277,28 @@ export default class FormulaControl extends React.Component< } return []; } + // 日期类组件 & 是否存在快捷键判断 + @autobind + hasDateShortcutkey(str: string): boolean { + const {DateTimeType} = this.props; + + if (DateTimeType === FormulaDateType.IsDate) { + return ( + /^(\+|-)(\d+)(minute|min|hour|day|week|month|year|weekday|second|millisecond)s?$/i.test( + str + ) || /^(now|today)$/.test(str) + ); + } else if (DateTimeType === FormulaDateType.IsRange) { + return /^((?:\-|\+)?(?:\d*\.)?\d+)(minute|min|hour|day|week|month|quarter|year|weekday|second|millisecond)s?$/i.test( + str + ); + } + // 非日期类组件使用,也直接false + // if (DateTimeType === FormulaDateType.NotDate) { + // return false; + // } + return false; + } @autobind transExpr(str: string) { @@ -282,7 +320,7 @@ export default class FormulaControl extends React.Component< handleConfirm(value: any) { const val = !value ? undefined - : isExpression(value) + : isExpression(value) || this.hasDateShortcutkey(value) ? value : `\${${value}}`; this.props?.onChange?.(val); @@ -421,7 +459,6 @@ export default class FormulaControl extends React.Component< ...rest } = this.props; - const labelText = typeof label === 'string' ? label : ''; // 自身字段 const selfName = this.props?.data?.name; @@ -445,6 +482,13 @@ export default class FormulaControl extends React.Component< ? FormulaEditor.highlightValue(value, this.state.variables) : value; + // 公式表达式弹窗内容过滤 + const filterValue = isExpression(value) + ? this.transExpr(value) + : this.hasDateShortcutkey(value) + ? value + : undefined; + return (
- {/* 非简单模式 & 非表达式 & 无自定义渲染 */} - {!simple && !isExpr && !rendererSchema && ( - - )} - {/* 非简单模式 & 非表达式 & 自定义渲染 */} - {!simple && !isExpr && rendererSchema && ( -
- {render('inner', this.filterCustomRendererProps(rendererSchema), { - inputOnly: true, - value: value, - data: useExternalFormData - ? { - ...this.props.data - } - : {}, - onChange: this.handleSimpleInputChange, - manager: manager - })} -
- )} - {/* 非简单模式 & 表达式 */} - {!simple && isExpr && ( + {/* 非简单模式 & 非表达式 & 非日期快捷 & 无自定义渲染 */} + {!simple && + !isExpr && + !this.hasDateShortcutkey(value) && + !rendererSchema && ( + + )} + {/* 非简单模式 & 非表达式 & 非日期快捷 & 自定义渲染 */} + {!simple && + !isExpr && + !this.hasDateShortcutkey(value) && + rendererSchema && ( +
+ {render('inner', this.filterCustomRendererProps(rendererSchema), { + inputOnly: true, + value: value, + data: useExternalFormData + ? { + ...this.props.data + } + : {}, + onChange: this.handleSimpleInputChange, + manager: manager + })} +
+ )} + {/* 非简单模式 &(表达式 或 日期快捷)*/} + {!simple && (isExpr || this.hasDateShortcutkey(value)) && ( diff --git a/packages/amis-editor/src/tpl/common.tsx b/packages/amis-editor/src/tpl/common.tsx index fd982ab9c..ca685f00f 100644 --- a/packages/amis-editor/src/tpl/common.tsx +++ b/packages/amis-editor/src/tpl/common.tsx @@ -10,6 +10,7 @@ import {remarkTpl} from '../component/BaseControl'; import {SchemaObject} from 'amis/lib/Schema'; import flatten from 'lodash/flatten'; import {InputComponentName} from '../component/InputComponentName'; +import {FormulaDateType} from '../renderer/FormulaControl'; /** * @deprecated 兼容当前组件的switch @@ -355,12 +356,14 @@ setSchemaTpl( mode?: string; // 自定义展示默认值,上下展示: vertical, 左右展示: horizontal label?: string; // 表单项 label name?: string; // 表单项 name + header?: string; // 表达式弹窗标题 rendererSchema?: any; rendererWrapper?: boolean; // 自定义渲染器 是否需要浅色边框包裹 needDeleteValue?: boolean; // 是否需要剔除默认值 useSelectMode?: boolean; // 是否使用Select选择设置模式,需要确保 rendererSchema.options 不为 undefined valueType?: string; // 用于设置期望数值类型 visibleOn?: string; // 用于控制显示的表达式 + DateTimeType?: FormulaDateType; // 日期类组件要支持 表达式 & 相对值 }) => { let curRendererSchema = config?.rendererSchema; if ( @@ -389,7 +392,8 @@ setSchemaTpl( rendererWrapper: config?.rendererWrapper, needDeleteValue: config?.needDeleteValue, valueType: config?.valueType, - header: '表达式' + header: config.header ?? '表达式', + DateTimeType: config.DateTimeType ?? FormulaDateType.NotDate } ] }; @@ -404,7 +408,8 @@ setSchemaTpl( needDeleteValue: config?.needDeleteValue, valueType: config?.valueType, visibleOn: config?.visibleOn, - header: '表达式' + header: config?.header ?? '表达式', + DateTimeType: config?.DateTimeType ?? FormulaDateType.NotDate }; } }