+
{
onFocus={this.onFocus}
mobileUI={mobileUI}
/>
+ {unit && showInputUnit && (
+
+ {unit}
+
+ )}
);
}
@@ -512,6 +529,7 @@ export default class RangeControl extends React.PureComponent<
clearable: true,
disabled: false,
showInput: false,
+ showInputUnit: false,
multiple: false,
joinValues: true,
delimiter: ',',
diff --git a/packages/amis/src/renderers/Progress.tsx b/packages/amis/src/renderers/Progress.tsx
index d333617e341e..f7dc681baa5f 100644
--- a/packages/amis/src/renderers/Progress.tsx
+++ b/packages/amis/src/renderers/Progress.tsx
@@ -1,5 +1,15 @@
import React from 'react';
-import {Renderer, RendererProps, filter} from 'amis-core';
+import {
+ Renderer,
+ RendererProps,
+ filter,
+ ActionObject,
+ ScopedContext,
+ IScopedContext,
+ ScopedComponentType
+} from 'amis-core';
+import isEqual from 'lodash/isEqual';
+import pick from 'lodash/pick';
import cx from 'classnames';
import {BaseSchema, SchemaClassName, SchemaTpl} from '../Schema';
import {autobind, getPropValue, createObject} from 'amis-core';
@@ -96,7 +106,16 @@ export interface ProgressProps
extends RendererProps,
Omit
{}
-export class ProgressField extends React.Component {
+interface ProgressState {
+ value: number;
+}
+
+const COMPARE_KEYS = ['name', 'value', 'data', 'defaultValue'];
+
+export class ProgressField extends React.Component<
+ ProgressProps,
+ ProgressState
+> {
static defaultProps = {
placeholder: '-',
progressClassName: '',
@@ -108,6 +127,32 @@ export class ProgressField extends React.Component {
animate: false
};
+ constructor(props: ProgressProps) {
+ super(props);
+
+ this.state = {
+ value: this.getValue()
+ };
+ }
+
+ componentDidUpdate(prevProps: Readonly): void {
+ if (
+ !isEqual(pick(prevProps, COMPARE_KEYS), pick(this.props, COMPARE_KEYS))
+ ) {
+ this.setState({value: this.getValue()});
+ }
+ }
+
+ getValue() {
+ let value = getPropValue(this.props);
+ value = typeof value === 'number' ? value : filter(value, this.props.data);
+
+ if (/^\d*\.?\d+$/.test(value)) {
+ value = parseFloat(value);
+ }
+ return value;
+ }
+
@autobind
format(value: number) {
const {valueTpl, render, data} = this.props;
@@ -135,13 +180,7 @@ export class ProgressField extends React.Component {
threshold,
showThresholdText
} = this.props;
-
- let value = getPropValue(this.props);
- value = typeof value === 'number' ? value : filter(value, data);
-
- if (/^\d*\.?\d+$/.test(value)) {
- value = parseFloat(value);
- }
+ const {value} = this.state;
if (threshold) {
if (Array.isArray(threshold)) {
@@ -184,4 +223,32 @@ export class ProgressField extends React.Component {
@Renderer({
type: 'progress'
})
-export class ProgressFieldRenderer extends ProgressField {}
+export class ProgressFieldRenderer extends ProgressField {
+ static contextType = ScopedContext;
+
+ constructor(props: ProgressProps, context: IScopedContext) {
+ super(props);
+ const scoped = context;
+ scoped.registerComponent(this as unknown as ScopedComponentType);
+ }
+
+ componentWillUnmount() {
+ super.componentWillUnmount?.();
+ const scoped = this.context as IScopedContext;
+ scoped.unRegisterComponent(this as unknown as ScopedComponentType);
+ }
+
+ doAction(action: ActionObject, args: any, throwErrors: boolean): any {
+ const actionType = action?.actionType as string;
+
+ if (actionType === 'reset') {
+ this.setState({value: 0});
+ }
+ }
+
+ setData(value: number) {
+ if (typeof value === 'number' || typeof +value === 'number') {
+ this.setState({value: +value});
+ }
+ }
+}
diff --git a/packages/amis/src/renderers/Table/exportExcel.ts b/packages/amis/src/renderers/Table/exportExcel.ts
index e01c4dd8d3c3..cd9d4c32fdf4 100644
--- a/packages/amis/src/renderers/Table/exportExcel.ts
+++ b/packages/amis/src/renderers/Table/exportExcel.ts
@@ -2,7 +2,7 @@
* 导出 Excel 功能
*/
-import {filter, isEffectiveApi, arraySlice} from 'amis-core';
+import {filter, isEffectiveApi, arraySlice, isObject} from 'amis-core';
import './ColumnToggler';
import {TableStore} from 'amis-core';
import {saveAs} from 'file-saver';
@@ -425,6 +425,7 @@ export async function exportExcel(
}
} else if (type == 'link' || (type as any) === 'static-link') {
const href = column.pristine.href;
+
const linkURL =
(typeof href === 'string' && href
? filter(href, rowData, '| raw')
@@ -443,6 +444,8 @@ export async function exportExcel(
};
} else if (type === 'mapping' || (type as any) === 'static-mapping') {
let map = column.pristine.map;
+ const valueField = column.pristine.valueField || 'value';
+ const labelField = column.pristine.labelField || 'label';
const source = column.pristine.source;
if (source) {
let sourceValue = source;
@@ -462,6 +465,29 @@ export async function exportExcel(
}
}
+ if (Array.isArray(map)) {
+ map = map.reduce((res, now) => {
+ if (now == null) {
+ return res;
+ } else if (isObject(now)) {
+ let keys = Object.keys(now);
+ if (
+ keys.length === 1 ||
+ (keys.length == 2 && keys.includes('$$id'))
+ ) {
+ // 针对amis-editor的特殊处理
+ keys = keys.filter(key => key !== '$$id');
+ // 单key 数组对象
+ res[keys[0]] = now[keys[0]];
+ } else if (keys.length > 1) {
+ // 多key 数组对象
+ res[now[valueField]] = now;
+ }
+ }
+ return res;
+ }, {});
+ }
+
if (typeof value !== 'undefined' && map && (map[value] ?? map['*'])) {
const viewValue =
map[value] ??
@@ -470,7 +496,23 @@ export async function exportExcel(
: value === false && map['0']
? map['0']
: map['*']); // 兼容平台旧用法:即 value 为 true 时映射 1 ,为 false 时映射 0
- let text = removeHTMLTag(viewValue);
+
+ let label = viewValue;
+ if (isObject(viewValue)) {
+ if (labelField === undefined || labelField === '') {
+ if (!viewValue.hasOwnProperty('type')) {
+ // 映射值是object
+ // 没配置labelField
+ // object 也没有 type,不能作为schema渲染
+ // 默认取 label 字段
+ label = viewValue['label'];
+ }
+ } else {
+ label = viewValue[labelField || 'label'];
+ }
+ }
+
+ let text = removeHTMLTag(label);
/** map可能会使用比较复杂的html结构,富文本也无法完全支持,直接把里面的变量解析出来即可 */
if (isPureVariable(text)) {