import React, { useEffect, useState } from 'react'; import moment from 'moment'; import { Tag, Popover, Table, Drawer, Modal } from 'antd'; import Icon from '@/components/icons'; import get from 'lodash/get'; import isEmpty from 'lodash/isEmpty'; import findIndex from 'lodash/findIndex'; import { fields2columns } from '../SortableTable'; import ViewFactory from '..'; import './style.less'; import { getImageByUrl, testUrl } from '@/components/form.fields'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons'; import marked from 'marked'; import Lightbox from 'react-image-lightbox'; import 'react-image-lightbox/style.css'; marked.setOptions({ gfm: true, breaks: true, }); const InterfaceTypes = new Map(); 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, viewType } = props; if (!value) { return null; } if (typeof value === 'object') { return JSON.stringify(value); } if (viewType === 'table' && value.length > 20) { return ( { e.stopPropagation(); }} style={{maxWidth: 300}}>{value}}>{value.substring(0, 15)}... ); } return ( <>{value} ); } export function TextareaField(props: any) { const { value, viewType } = props; if (!value) { return null; } if (viewType !== 'table') { return
; } if (value.length > 20) { return ( e.stopPropagation()} className={'textarea-field-content'} style={{maxWidth: 300}} dangerouslySetInnerHTML={{__html: marked(value)}}/> )}>{value.substring(0, 15)}... ); } return ( <>{value} ); } export function BooleanField(props: any) { const { value } = props; return ( <>{value ? : } ); } export function NumberField(props: any) { const { schema: { precision = 0 }, value } = props; if (!isNumber(value)) { return null; } return (
{new Intl.NumberFormat().format(value)}
); } export function isNumber(num) { if (typeof num === 'number') { return num - num === 0; } if (typeof num === 'string' && num.trim() !== '') { return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); } return false; }; export function PercentField(props: any) { const { schema: { precision = 0 }, value } = props; if (!isNumber(value)) { return null; } return (
{new Intl.NumberFormat().format(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 ; } function toFlat(items = []): Array { 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 (isEmpty(value)) { return null; } if (Array.isArray(value)) { return value.map(val => { const item = items.find(item => item.value === val); return ( {item ? item.label : val} ) }); } const item = items.find(item => item.value === value); return ( {item ? item.label : value} ) } export function RealtionField(props: any) { const { schema: { labelField }, value } = props; if (!value) { return null; } const items = Array.isArray(value) ? value : [value]; return ( <> {items.map(item => ( {get(item, labelField)} ))} ); } export function SubTableField(props: any) { const { schema: { children }, value } = props; console.log(value); if (!Array.isArray(value)) { return null; } return (
); } export function LinkToField(props: any) { const { schema, value } = props; if (!value) { return null; } const values = Array.isArray(value) ? value : [value]; return (
{values.map(item => )}
); } export function LinkToFieldLink(props) { const { data, schema, schema: { title, labelField } } = props; const [visible, setVisible] = useState(false); // console.log(schema); return ( { e.stopPropagation(); setVisible(true); }}>{data[labelField]} { e.stopPropagation(); }} className={'noco-drawer'} bodyStyle={{padding: 0}} width={'40%'} title={`查看${title}详情`} visible={visible} onClose={() => setVisible(false)} > ); } function getImgUrls(value) { const values = Array.isArray(value) ? value : [value]; return values.filter(item => testUrl(item.url, { exclude: ['.png', '.jpg', '.jpeg', '.gif'] })).map(item => item); } export function AttachmentField(props: any) { const { value, schema } = props; const [imgIndex, setImgIndex] = useState(0); const [visible, setVisible] = useState(false); if (!value) { return null; } const values = Array.isArray(value) ? value : [value]; const images = getImgUrls(values); console.log(images); return (
{ e.stopPropagation(); }} className={'attachment-field'}> {values.map(item => { setVisible(true); const index = findIndex(images, img => item.id === img.id); setImgIndex(index); }} data={item} schema={schema}/>)} {visible && setVisible(false)} onMovePrevRequest={() => { setImgIndex((imgIndex + images.length - 1) % images.length); }} onMoveNextRequest={() => { setImgIndex((imgIndex + 1) % images.length); }} />}
); } export function AttachmentFieldItem(props: any) { const { title, url } = props.data || {}; const img = getImageByUrl(url, { exclude: ['.png', '.jpg', '.jpeg', '.gif'] }) // const [visible, setVisible] = useState(false); return ( <> { e.stopPropagation(); if (testUrl(url, { exclude: ['.png', '.jpg', '.jpeg', '.gif'] })) { props.onClick && props.onClick(); // setVisible(true); e.preventDefault(); } }} className={'attachment-field-item'} target={'_blank'} href={url}> {title} {/* { e.stopPropagation(); setVisible(false); }} // @ts-ignore onClick={(e) => { e.stopPropagation(); }} bodyStyle={{padding: 0}} footer={null} visible={visible}> { e.stopPropagation(); }} style={{height: 'auto', width: '100%'}} alt={title} title={title} src={url}/> */} ); } 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, createdBy: RealtionField, updatedBy: RealtionField, subTable: SubTableField, linkTo: LinkToField, attachment: AttachmentField, }); export default function Field(props: any) { const { schema = {} } = props; const Component = getFieldComponent(schema.interface); return ; }