feat: add field renderer

This commit is contained in:
chenos 2020-12-13 20:48:48 +08:00
parent ab90b15ffc
commit d45d37cabf
4 changed files with 148 additions and 6 deletions

View File

@ -4,6 +4,8 @@ import { Actions } from '@/components/actions';
import api from '@/api-client';
import { useRequest } from 'umi';
import { Spin } from '@nocobase/client';
import Field from './Field';
import get from 'lodash/get';
export function Details(props: any) {
const {
@ -38,7 +40,9 @@ export function Details(props: any) {
<Descriptions bordered column={1}>
{fields.map((field: any) => {
return (
<Descriptions.Item label={field.title||field.name}>{JSON.stringify(data[field.name])}</Descriptions.Item>
<Descriptions.Item label={field.title||field.name}>
<Field schema={field} value={get(data, field.name)}/>
</Descriptions.Item>
)
})}
</Descriptions>

View File

@ -0,0 +1,134 @@
import React, { useEffect, useState } from 'react';
import moment from 'moment';
import { Tag } from 'antd';
import Icon from '@/components/icons';
const InterfaceTypes = new Map<string, any>();
function registerFieldComponent(type, Component) {
InterfaceTypes.set(type, Component);
}
function registerFieldComponents(components) {
Object.keys(components).forEach(key => {
registerFieldComponent(key, components[key]);
});
}
function getFieldComponent(type) {
if (InterfaceTypes.has(type)) {
return InterfaceTypes.get(type);
}
return InterfaceTypes.get('string');
}
export function StringField(props: any) {
const { value } = props;
return (
<>{value}</>
);
}
export function TextareaField(props: any) {
const { value } = props;
return (
<>{value}</>
);
}
export function BooleanField(props: any) {
const { value } = props;
return (
<>{value ? '是' : '否'}</>
);
}
export function NumberField(props: any) {
const { schema: { precision }, value } = props;
return (
<>{value}</>
);
}
export function PercentField(props: any) {
const { schema: { precision }, value } = props;
return (
<>{value}%</>
);
}
export function DateTimeField(props: any) {
const { schema: { dateFormat, showTime, timeFormat }, value } = props;
const m = moment(value);
if (!m.isValid()) {
return null;
}
let format = dateFormat;
if (showTime) {
format += ` ${timeFormat}`;
}
return (
<>{m.format(`${format}`)}</>
);
}
export function IconField(props) {
const { value } = props;
return <Icon type={value}/>;
}
function toFlat(items = []): Array<any> {
let flat = [];
items.forEach(item => {
flat.push(item);
if (Array.isArray(item.children) && item.children.length) {
flat = flat.concat(toFlat(item.children));
}
});
return flat;
}
export function DataSourceField(props: any) {
const { schema: { dataSource = [] }, value } = props;
const items = toFlat(dataSource);
console.log(items);
if (Array.isArray(value)) {
return value.map(val => {
const item = items.find(item => item.value === val);
return (
<Tag>
{item ? item.label : val}
</Tag>
)
});
}
const item = items.find(item => item.value === value);
return (
<Tag>
{item ? item.label : value}
</Tag>
)
}
registerFieldComponents({
string: StringField,
textarea: TextareaField,
boolean: BooleanField,
select: DataSourceField,
multipleSelect: DataSourceField,
radio: DataSourceField,
checkboxes: DataSourceField,
number: NumberField,
percent: PercentField,
datetime: DateTimeField,
createdAt: DateTimeField,
updatedAt: DateTimeField,
icon: IconField,
});
export default function Field(props: any) {
const { schema = {} } = props;
const Component = getFieldComponent(schema.interface);
return <Component {...props}/>;
}

View File

@ -6,6 +6,7 @@ import arrayMove from 'array-move';
import findIndex from 'lodash/findIndex';
import get from 'lodash/get';
import './style.less';
import Field from '../Field';
export const SortableItem = sortableElement(props => <tr {...props} />);
export const SortableContainer = sortableContainer(props => <tbody {...props} />);
@ -55,10 +56,7 @@ export const components = ({data = {}, rowKey, mutate, onMoved}: Props) => {
export function fields2columns(fields) {
const columns: any[] = fields.map(field => {
const type = get(field, 'component.type');
if (type === 'sort') {
field.render = () => <DragHandle/>;
}
field.render = (value) => field.interface === 'sort' ? <DragHandle/> : <Field schema={field} value={value}/>;
return {
...field,
...(field.component||{}),

View File

@ -12,7 +12,7 @@ const transforms = {
arr.push({
...field.get(),
sorter: field.get('sortable'),
dataIndex: field.name,
dataIndex: field.name.split('.'),
});
}
return arr;
@ -72,6 +72,9 @@ const transforms = {
set(prop, 'x-component-props.children', prop.title);
delete prop.title;
}
if (interfaceType === 'multipleSelect') {
set(prop, 'x-component-props.mode', 'multiple');
}
if (['radio', 'select', 'multipleSelect', 'checkboxes'].includes(interfaceType)) {
prop.enum = get(field.options, 'dataSource', []);
}
@ -159,6 +162,9 @@ export default async (ctx, next) => {
});
view.setDataValue('defaultTabName', get(defaultTabs, [0, 'name']));
}
if (view.get('template') === 'SimpleTable') {
view.setDataValue('rowViewName', 'form');
}
if (view.get('updateViewName')) {
view.setDataValue('rowViewName', view.get('updateViewName'));
}