Commit 3b85970e authored by 田翔's avatar 田翔

增加表单渲染组件

parent d91680b2
import React, { useState, useEffect, useRef } from 'react';
import { FormRender, FormDesigner } from '../../src/index';
import { options1, options2 } from './data';
import { Button } from 'antd';
import { Button, Tabs } from 'antd';
window.globalConfig = {
"env": "daily",
......@@ -3506,36 +3506,27 @@ window.globalConfig = {
"apiGatewayDomain": "http://127.0.0.1:8080"
}
export default (props) => {
const [editState, setEditState] = useState('edit');
const [trigger, setTrigger] = useState(false);
const [readOnly, setReadOnly] = useState(false)
const testRef = useRef();
const Test = (props) => {
const [schema, setSchema] = useState({})
const changeSchema = (value) => {
setSchema(value)
}
return (
<div>
<FormDesigner
style={{ margin: '0' }}
loading={props.loading}
key={editState}
handleType={editState}
// isReadOnly={1}
tablesSchema={options1}
onSubmit={(formData, formInstance) => {
console.log('formData', formData)
// setEditState('scan')
// setReadOnly(true)
}}
// codes={{ '工单编号': 'RYWX00000269', '事件编号': 'RYWXTB220000320' }}
// ref={testRef}
customerSubmitTrigger={{
trigger: trigger,
}}
onBack={() => {
// setEditState('edit')
// setReadOnly(false)
}}
/>
<div style={{ width: '100%' }}>
<Tabs>
<Tabs.TabPane tab="编辑" key="item-1">
<FormDesigner setSchema={changeSchema} />
</Tabs.TabPane>
<Tabs.TabPane tab="渲染" key="item-2">
<FormRender schema={schema} />
</Tabs.TabPane>
</Tabs>
</div>
);
};
)
}
export default Test
......@@ -29,7 +29,7 @@ app.use(webpackHotMiddleware(compiler));
app.use(express.static(__dirname));
// app.use('/', createProxyMiddleware('/', { target: 'http://127.0.0.1:8880', changeOrigin: true }));
app.use('/', createProxyMiddleware('/', { target: 'http://192.168.10.167:8088', changeOrigin: true }));
const port = process.env.PORT || 8383;
const port = process.env.PORT || 8888;
module.exports = app.listen(port, () => {
console.log(`Server listening on http://localhost:${port}, Ctrl+C to stop`);
});
......@@ -64,13 +64,37 @@ module.exports = {
},
{
test: /\.less$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
modules: {
getLocalIdent: (context, _, localName) => {
if (
context.resourcePath.includes('node_modules') ||
context.resourcePath.includes('ant.design.pro.less') ||
context.resourcePath.includes('main.less')
) {
return localName;
}
const match = context.resourcePath.match(/src(.*)/);
const matchAntd = /^ant/.test(localName);
if (match && match[1] && !matchAntd) {
const antdProPath = match[1].replace('.less', '');
const arr = slash(antdProPath)
.split('/')
.map(a => a.replace(/([A-Z])/g, '-$1'))
.map(a => a.toLowerCase());
return `parse-form-${arr.join('-')}-${localName}`.replace(/--/g, '-');
}
return localName;
},
},
},
},
{
loader: 'less-loader',
......
{
"name": "panda-xform",
"version": "1.1.0",
"description": "1.1.0: 项目初始化",
"version": "1.2.0",
"description": "1.2.0: 增加渲染表单组件",
"keywords": [
"panda-xform"
],
......@@ -37,6 +37,7 @@
"moment": "^2.29.1",
"qrcode.react": "^1.0.1",
"react": "17.0.2",
"react-file-viewer": "^1.2.1",
"react-svg": "15.1.9",
"yarn": "^1.22.17"
},
......@@ -124,4 +125,4 @@
"publishConfig": {
"registry": "https://g.civnet.cn:4873"
}
}
\ No newline at end of file
}
import settings from './settings'
import {
baseSettings,
commonSettings,
switchSettings,
elementSettings,
globalSettings,
} from './otherSettings'
export {
settings,
baseSettings,
commonSettings,
switchSettings,
elementSettings,
globalSettings,
}
\ No newline at end of file
const baseSettings = {
title: {
title: '标题',
type: 'string',
// widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
}
const commonSettings = {
$id: {
title: '字段名称',
type: 'string',
widget: 'FieldNames',
required: true,
displayType: 'row',
labelWidth: 80,
// width: '70%',
},
title: {
title: '标题',
required: true,
type: 'string',
widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
placeholder: {
title: '提示语',
type: 'string',
displayType: 'row',
labelWidth: 80,
},
// description: {
// title: '说明',
// type: 'string',
// },
presetValue: {
title: '默认值',
type: 'string',
displayType: 'row',
labelWidth: 80,
// default: ''
},
}
const switchSettings = {
disabled: {
title: '只读',
type: 'boolean',
widget: 'BooleanSwitch',
displayType: 'row',
labelWidth: 80,
default: false
},
required: {
title: '必填',
type: 'boolean',
widget: 'BooleanSwitch',
displayType: 'row',
labelWidth: 80,
default: false
},
hidden: {
title: '隐藏',
type: 'boolean',
widget: 'BooleanSwitch',
default: false,
displayType: 'row',
labelWidth: 80,
},
}
const elementSettings = {
width: {
title: '元素宽度',
type: 'string',
widget: 'percentSlider',
// default: '33%',
},
labelWidth: {
title: '标签宽度',
description: '默认值110',
default: 110,
type: 'number',
widget: 'slider',
max: 400,
props: {
hideNumber: true,
},
},
}
const globalSettings = {
type: 'object',
properties: {
column: {
title: '整体布局',
type: 'number',
enum: [1],
default: 1,
enumNames: ['一行一列'],
widget: 'select',
props: {
placeholder: '默认一行一列',
},
displayType: 'row',
labelWidth: 100,
},
displayType: {
title: '标签展示模式',
type: 'string',
default: 'row',
enum: ['row', 'column'],
enumNames: ['同行', '单独一行'],
widget: 'select',
displayType: 'row',
labelWidth: 100,
},
labelWidth: {
title: '标签宽度',
type: 'number',
widget: 'slider',
max: 300,
default: 120,
props: {
hideNumber: true,
},
},
},
}
export {
baseSettings,
commonSettings,
switchSettings,
elementSettings,
globalSettings
}
\ No newline at end of file
const baseSettings = {
title: {
title: '标题',
type: 'string',
// widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
}
const commonSettings = {
$id: {
title: '字段名称',
type: 'string',
widget: 'FieldNames',
required: true,
displayType: 'row',
labelWidth: 80,
// width: '70%',
},
title: {
title: '标题',
required: true,
type: 'string',
widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
placeholder: {
title: '提示语',
type: 'string',
displayType: 'row',
labelWidth: 80,
},
// description: {
// title: '说明',
// type: 'string',
// },
presetValue: {
title: '默认值',
type: 'string',
displayType: 'row',
labelWidth: 80,
// default: ''
},
}
const switchSettings = {
disabled: {
title: '只读',
type: 'boolean',
widget: 'BooleanSwitch',
displayType: 'row',
labelWidth: 80,
default: false
},
required: {
title: '必填',
type: 'boolean',
widget: 'BooleanSwitch',
displayType: 'row',
labelWidth: 80,
default: false
},
hidden: {
title: '隐藏',
type: 'boolean',
widget: 'BooleanSwitch',
default: false,
displayType: 'row',
labelWidth: 80,
},
}
const elementSettings = {
width: {
title: '元素宽度',
type: 'string',
widget: 'percentSlider',
// default: '33%',
},
labelWidth: {
title: '标签宽度',
description: '默认值110',
default: 110,
type: 'number',
widget: 'slider',
max: 400,
props: {
hideNumber: true,
},
},
}
import { commonSettings, switchSettings, elementSettings } from './otherSettings'
const allSetting = {
...commonSettings,
......@@ -110,16 +18,7 @@ const settings = [
type: 'object',
properties: {}
},
setting: {
hidden: {
title: '隐藏',
type: 'boolean',
widget: 'BooleanSwitch',
default: false,
displayType: 'row',
labelWidth: 80,
},
},
setting: {},
},
],
},
......@@ -132,7 +31,6 @@ const settings = [
schema: {
title: '文本',
type: 'string',
widget: 'TextInput',
},
setting: {
...allSetting
......@@ -168,7 +66,7 @@ const settings = [
schema: {
title: '数值',
type: 'number',
widget: 'NumberInput'
widget: 'number'
},
setting: {
...allSetting
......@@ -243,10 +141,10 @@ const settings = [
},
setting: {
...commonSettings,
options: {
title: '可选值',
dataSource: {
title: '数据来源',
type: 'string',
widget: 'EnumOptions',
widget: 'DataSource',
displayType: 'row',
labelWidth: 80,
},
......@@ -365,32 +263,20 @@ const settings = [
},
setting: {
...commonSettings,
interaction: {
title: '交互方式',
type: 'string',
enum: ['下拉框', '分组模态', '树形模态'],
default: '下拉框',
enumNames: ['下拉框', '分组模态', '树形模态'],
displayType: 'row',
labelWidth: 80,
},
role: {
title: '机构角色',
type: 'string',
required: true,
// enum: ['下拉框', '分组模态', '树形模态'],
// default: '下拉框',
// enumNames: ['下拉框', '分组模态', '树形模态'],
displayType: 'row',
labelWidth: 80,
},
isMultiple: {
title: '是否多选',
type: 'boolean',
widget: 'BooleanSwitch',
displayType: 'row',
labelWidth: 80,
},
// dependencies: {
// title: '关联字段',
// type: 'array',
// widget: 'CascadeField',
// displayType: 'row',
// labelWidth: 80,
// },
// isMultiple: {
// title: '是否多选',
// type: 'boolean',
// widget: 'BooleanSwitch',
// displayType: 'row',
// labelWidth: 80,
// },
...switchSettings,
...elementSettings,
}
......@@ -417,14 +303,16 @@ const settings = [
type: 'string',
displayType: 'row',
labelWidth: 80,
widget: 'date',
widget: 'DateSelect',
dependencies: ['format']
},
format: {
title: '日期格式',
type: 'string',
enum: ['date', 'dateTime', 'year', 'month', 'quarter', 'week'],
// enum: ['date', 'dateTime', 'year', 'month', 'quarter', 'week'],
enum: ['date', 'dateTime', 'year', 'month'],
default: 'date',
enumNames: ['日期', '日期时间', '日期年份', '日期月份', '日期季度', '日期周'],
enumNames: ['日期', '日期时间', '日期年份', '日期月份'],
displayType: 'row',
labelWidth: 80,
},
......@@ -470,32 +358,31 @@ const settings = [
type: 'string',
widget: 'FileUpload',
},
},
{
text: '图片',
name: '图片',
schema: {
title: '图片',
type: 'string',
widget: 'FileUpload',
},
},
{
text: '录音',
name: '录音',
schema: {
title: '录音',
type: 'string',
widget: 'FileUpload',
},
},
{
text: '视频',
name: '视频',
schema: {
title: '视频',
type: 'string',
widget: 'FileUpload',
setting: {
...commonSettings,
presetValue: {},
fileType: {
title: '文件类型',
type: 'string',
required: true,
widget: 'select',
enum: ['图片', '文档', '音频', '视频'],
enumNames: ['图片', '文档', '音频', '视频'],
default: '图片',
displayType: 'row',
labelWidth: 80,
},
listType: {
title: '显示样式',
type: 'string',
default: 'picture',
enum: ['picture', 'text', 'picture-card'],
enumNames: ['列表', '文本', '卡片'],
displayType: 'row',
labelWidth: 80,
},
...switchSettings,
...elementSettings,
},
},
],
......@@ -511,55 +398,11 @@ const settings = [
schema: {
title: '坐标控件',
type: 'string',
widget: 'DateSelect',
widget: 'Coordinate',
},
},
],
},
]
const globalSettings = {
type: 'object',
properties: {
column: {
title: '整体布局',
type: 'number',
enum: [1],
default: 1,
enumNames: ['一行一列'],
widget: 'select',
props: {
placeholder: '默认一行一列',
},
displayType: 'row',
labelWidth: 100,
},
displayType: {
title: '标签展示模式',
type: 'string',
default: 'row',
enum: ['row', 'column'],
enumNames: ['同行', '单独一行'],
widget: 'select',
displayType: 'row',
labelWidth: 100,
},
labelWidth: {
title: '标签宽度',
type: 'number',
widget: 'slider',
max: 300,
default: 120,
props: {
hideNumber: true,
},
},
},
}
export {
settings,
baseSettings,
commonSettings,
globalSettings
}
\ No newline at end of file
export default settings
\ No newline at end of file
......@@ -19,6 +19,7 @@ const FormDesigner = (props) => {
if (errors.length) {
return message.error('请按照提示完善表单内容')
}
props.setSchema && props.setSchema(ref.current.getValue())
}
}
]
......@@ -46,7 +47,6 @@ const FormDesigner = (props) => {
<div className={prefixCls}>
<Generator
configProvider={{ prefixCls: prefixClsWithoutParseForm }}
// getId={name => name ? `${name}_${count++}` : null}
mapping={{
object: 'Header',
}}
......
const schema = {
"type": "object",
"properties": {
"formGroup_1": {
"type": "object",
"title": "文本类",
"properties": {
"多行文本": {
"title": "多行文本",
"type": "string",
"format": "textarea",
"default": "",
"min": 0,
"max": 254,
"className": "",
"showDescIcon": true,
"column": 1,
"required": false,
"widget": "textArea",
"rules": [
{
"patterns": false,
"message": ""
}
],
"disabled": false,
"placeholder": "请输入多行文本",
"width": "100%",
"pathKey": "formGroup_1"
},
"富文本": {
"title": "富文本",
"widget": "RichText",
"type": "string",
"config": "",
"format": "text",
"className": "",
"default": "富文本默认值",
"content": "富文本默认值",
"min": 0,
"max": 254,
"disabled": false,
"showDescIcon": true,
"required": false,
"widget": "RichText",
"rules": [
{},
{
"pattern": false,
"message": ""
}
],
"width": "100%",
"pathKey": "formGroup_1"
},
},
"required": [],
"className": "ant-parse-form-group"
},
},
"required": [],
"column": 4,
"displayType": "row",
"showDescIcon": true,
"labelWidth": 120
}
export default schema
\ No newline at end of file
import React, { useState, useEffect, useRef, useContext, createContext, forwardRef, useImperativeHandle, useMemo } from 'react'
import FormRender, { useForm } from 'form-render'
import { ConfigProvider } from 'antd'
import widgets from '../widgets'
// import schema from './data'
// console.log('FormRender', widgets)
export const GlobalStore = createContext(null)
const XRender = (props, ref) => {
// useImperativeHandle(ref, () => ({
// form,
// getFormValues,
// setListData
// }))
const { schema } = props
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext)
const prefixCls = getPrefixCls('parse-form')
const prefixClsWithoutParseForm = getPrefixCls()
const [extraData, setExtraData] = useState({})
const form = useForm()
return (
<GlobalStore.Provider
value={{
extraData,
setExtraData
}}>
<div className={prefixCls}>
<FormRender
configProvider={{ prefixCls: prefixClsWithoutParseForm }}
form={form}
schema={schema}
// onChange={form.setValues}
mapping={{
object: 'Header',
}}
widgets={widgets}
/>
</div>
</GlobalStore.Provider>
);
}
export default forwardRef(XRender)
/*
* 地图中,显示的是墨卡托坐标,使用在地图上来做交互是用的经纬度坐标
* */
import React, { useState, useEffect, useContext, useRef } from 'react';
import { Input, Modal, Spin, Button } from 'antd';
import { CompassOutlined } from '@ant-design/icons';
import { AMapScene, AMapDrawTool, VectorLayer, PointLayer } from '@wisdom-map/amap';
import {
ArcGISSceneMap,
AutoCompleteSearch,
Drawtool as drawTool,
Graphic,
GraphicsLayer,
Point
} from '@wisdom-map/arcgismap';
import { mktlng } from '@wisdom-map/basemap/es/utils/coordTransformation';
import { GlobalStore } from '../../../../FormRender'
import React, { useState, useEffect, useContext, useRef } from 'react'
import { Input, Modal, Spin, Button } from 'antd'
import { CompassOutlined } from '@ant-design/icons'
import { AMapScene, AMapDrawTool, VectorLayer, PointLayer } from '@wisdom-map/amap'
import { ArcGISSceneMap, AutoCompleteSearch, Drawtool as drawTool, Graphic, GraphicsLayer, Point } from '@wisdom-map/arcgismap'
import { mktlng } from '@wisdom-map/basemap/es/utils/coordTransformation'
import { GlobalStore } from '../../../FormRender'
const CoordinatePicker = ({ value, onChange, name, schema }) => {
......
/*
* 地图中,显示的是墨卡托坐标,使用在地图上来做交互是用的经纬度坐标
* */
import React, {useState, useEffect, useContext} from 'react';
const CoordinatePicker = ({value}) => {
return <div>{value || '地图组件暂不可用'}</div>
};
export default CoordinatePicker;
import React, { useState, useEffect, useContext } from 'react'
import { Input, message } from 'antd';
import { GlobalStore } from '../../../../FormRender'
import { GlobalStore } from '../../../FormRender'
import { AMap } from '@wisdom-map/amap'
const SearchLocation = ({ value, onChange, name, schema }) => {
......
// 自定义时间组件
import React, { useState, useEffect, useMemo } from 'react';
import { DatePicker, Input } from 'antd';
import { dateType, dateFormat } from '../../../../constant/constant';
import moment from 'moment';
import locale from 'antd/lib/date-picker/locale/zh_CN';
import React, { useState, useEffect, useMemo } from 'react'
import { DatePicker, Input } from 'antd'
import style from '../../style'
import moment from 'moment'
import locale from 'antd/lib/date-picker/locale/zh_CN'
const DateTime = ({ value, onChange, schema }) => {
const DateTime = (props) => {
console.log('schema', schema)
const { value, onChange, schema } = props
const { disabled, format, presetValue, placeholder } = schema
// console.log('schema', schema)
// const dateTime = value || schema.default;
// const format = schema.shape != '日期周' ? dateFormat[schema.shape] : 'YYYY-wo';
const valueShow = useMemo(() => {
return moment(value || presetValue)
console.log('value+presetValue', value, presetValue)
return (value || presetValue) ? moment(value || presetValue) : null
}, [presetValue, value])
const disabledDate = (current) => {
......@@ -24,45 +22,30 @@ const DateTime = ({ value, onChange, schema }) => {
} else {
return false
}
};
// 不超过当前时间这个配置没有意义,在moment的工具中,已经囊括了未到时间这步
const disabledTime = (current) => {
if (schema.config === '不超过当前时间') {
return {
disabledHours: () => [],
disabledMinutes: () => [],
disabledSeconds: () => [55, 56],
};
} else {
return {}
}
};
}
const dateChange = (date, dateStr) => {
// console.log(val, dateVal)
// onChange(schema.shape != '日期周' ? dateVal : (val ? moment(val).format('YYYY-MM-DD') : null))
// onChange(moment(date._d).format('YYYY-MM-DD HH:mm:ss'))
console.log(date, dateStr)
onChange(date)
onChange(dateStr)
}
const onOk = (value) => {
console.log('value', value)
}
// useEffect(() => {
// onChange(dateTime);
// }, []);
// console.log('valueShow', valueShow)
return (
<DatePicker
mode={format}
picker={format}
disabled={disabled}
placeholder={placeholder}
value={valueShow}
onChange={dateChange}
picker={dateType[schema.shape]}
showNow
showTime={format === 'dateTime'}
style={{ width: '100%' }}
style={style}
locale={locale}
disabledDate={disabledDate}
onOk={onOk}
/>
);
......
import React, { useMemo } from 'react'
import { TimePicker } from 'antd'
import moment from 'moment'
const format = 'HH:mm:ss'
import style from '../../style'
const Time = ({ value, onChange, schema }) => {
// console.log(value, onChange, schema)
const { presetValue } = schema
const valueShow = useMemo(() => {
// console.log('时间改变', moment(value || presetValue))
// return (value || presetValue) ? moment(value || presetValue) : null
return (value || presetValue) ? moment(value || presetValue) : null
return (value || presetValue) ? moment(value || presetValue, 'HH:mm:ss') : null
}, [presetValue, value])
const timeChange = (time, timeStr) => {
console.log(time, timeStr)
onChange(timeStr)
}
console.log('valueShow', valueShow)
return (
<TimePicker value={valueShow} onChange={timeChange} format={format} />
<TimePicker style={style} value={valueShow} onChange={timeChange} />
)
}
......
import React, { useEffect, useMemo, useState } from 'react'
import styles from './index.less'
import { Upload, Button, message, Modal } from 'antd'
import { UploadOutlined, FileOutlined } from '@ant-design/icons'
import FileViewer from 'react-file-viewer'
import { uploadFileUrl, downloadFileUrl, downloadFile } from '../../../../apis/process'
import { downloadFunc, filenameVerification } from '../../../../utils/utils'
const accepts = {
'图片': ['.bmp', '.gif', '.jpeg', 'tiff', '.png', '.svg', '.jpg'],
'文档': ['.docx', '.xlsx', '.pdf'],
'视频': ['.mp4'],
'音频': ['.mp3'],
}
const FileUpload = (props) => {
const { value, schema, onChange } = props
const { disabled, fileType, listType, presetValue, placeholder } = schema
const [showList, setShowList] = useState('')
const [visible, setVisible] = useState(false)
const [showFile, setShowFile] = useState({ fileType: '', filePath: '' })
const option = {
name: 'file',
action: `${window.location.origin}${uploadFileUrl}`,
listType: listType,
withCredentials: true,
beforeUpload(file, fileList) {
/** @Tips: 解决提交文件中存在特殊字符的问题 */
let _continueUpload = true;
let _msg = {
type: 'success',
content: '上传成功!',
};
fileList.forEach(item => {
let _msgObject = filenameVerification(item);
if (_msgObject.type === 'error') {
_continueUpload = false;
_msg = {
type: 'error',
content: '上传失败!文件名不符合规则!',
};
}
});
_msg.type === 'error' ? message[_msg.type](_msg.content) : ''
return _continueUpload;
},
onChange: ({ file, fileList, event }) => {
// 检验名字,名字不通过不允许显示
if (filenameVerification(file).type === 'error') return false;
// 返回的链接在file.response内;不设置url,预览图表不可点击
if (file.status === 'done' && file.response.code === 0) {
file.url = `${downloadFileUrl}?filePath=${file.response.data}`
file.sourcePath = file.response.data;
message.success('上传成功!')
} else if (file.status === 'done' && file.response.code !== 0) {
file.status = 'error';
message.error('上传失败!')
}
if (Array.isArray(fileList)) {
let list = fileList.map(v => v.sourcePath || v.value)
onChange(list.join(','))
setShowList(JSON.stringify(fileList))
} else {
onChange('')
setShowList()
}
},
onPreview: (file) => {
let fileType = null
if (file.name.includes('docx')) {
fileType = 'docx'
} else if (file.name.includes('xlsx')) {
fileType = 'xlsx'
} else if (file.name.includes('jpg')) {
fileType = 'jpg'
}
if (fileType) {
setShowFile({ name: file.name, fileType: fileType, filePath: file.url })
setVisible(true)
}
}
}
const iconRender = (file, listType) => {
if (listType !== 'text') {
if (file.name.includes('docx')) {
return <div className={styles.iconImg} type='docx'></div>
} else if (file.name.includes('xlsx')) {
return <div className={styles.iconImg} type='xlsx'></div>
}
}
return <FileOutlined />
}
useEffect(() => {
if (value || presetValue) {
let fileList = [];
let list = (value || presetValue) && !(value || presetValue).includes('拍照相册') ? (value || presetValue).split(',') : []
list.forEach((item, index) => {
if (item) { // @Tips: 直接过滤掉名字中有异常字符的文件
let uid = index + '_' + Math.random()
let _obj = {
uid: uid,
value: item,
name: item.split('\\').reverse()[0],
type: fileType === '图片' ? 'image/jpeg' : 'file',
status: 'done',
url: `${downloadFileUrl}?filePath=${item}`,
sourcePath: item.url,
originFileObj: { "uid": uid },
"response": { "code": 0, "msg": "Ok", "data": item, "stackTrace": null },
"xhr": {},
};
if (schema.renderTo === 'Image') _obj.thumbUrl = `${downloadFileUrl}?filePath=${item}`;
fileList.push(_obj);
}
})
setShowList(JSON.stringify(fileList))
}
}, [value, presetValue])
return (
<div className={styles.uploadBox}>
<Upload
disabled={disabled}
accept={accepts[fileType]}
fileList={showList ? JSON.parse(showList) : []}
className="upload-list-inline"
iconRender={iconRender}
{...option}
>
{listType !== 'picture-card' ? <Button icon={<UploadOutlined />}>{placeholder || '上传'}</Button> : (disabled ? null : (placeholder || '+ 上传'))}
</Upload>
<Modal
width={'80%'}
title={showFile.name}
visible={visible}
onCancel={() => setVisible(false)}
bodyStyle={{ height: 650, overflowY: showFile.fileType.includes('xlsx') ? 'none' : "auto" }}
>
<FileViewer
title='123'
fileType={showFile.fileType}
filePath={window.location.origin + showFile.filePath}
/>
</Modal>
</div>
)
}
export default FileUpload
\ No newline at end of file
@imgSrc: '../../../../assets/images';
.uploadBox {
.iconImg {
width:45px;
height: 45px;
margin: 0 auto;
&[type='docx'] {
background: url('@{imgSrc}/Word.png');
background-size: 100% 100%;
}
&[type='xlsx'] {
background: url('@{imgSrc}/Excel.png');
background-size: 100% 100%;
}
}
}
\ No newline at end of file
import FileUpload from './FileUpload'
const file = {
FileUpload,
}
export default file
\ No newline at end of file
......@@ -3,15 +3,17 @@ import setting from './settings'
import text from './text'
import date from './date'
import select from './select'
// import file from './file'
// import coord from './coord'
import file from './file'
import coord from './coord'
export default {
const widgets = {
Header,
...setting,
...text,
...date,
...select,
// ...file,
// ...coord,
}
\ No newline at end of file
...file,
...coord,
}
export default widgets
\ No newline at end of file
// 选择器,值选择器
import React, { useState, useMemo } from 'react'
import { Select } from 'antd'
import style from '../../style'
const { Option } = Select
......@@ -33,7 +34,7 @@ const ValueSelect = ({ value, onChange, schema }) => {
return (
<Select
style={{ minWidth: 150 }}
style={style}
mode={mode}
disabled={disabled}
showArrow={!disabled}
......
import React, { useState } from 'react'
import { Button, Form, Input, Select, Space, Modal } from 'antd'
import style from '../../style'
const options = [
{ label: '手动输入', value: '手动输入' },
{ label: '数据字典', value: '数据字典' },
]
const DataSource = (props) => {
console.log('props', props)
const { formData } = props.addons
const [visible, setVisible] = useState(false)
const [form] = Form.useForm()
const onFocus = () => {
setVisible(true)
}
const inputChange = (e) => {
console.log('e', e)
}
return (
<>
<Modal
title={`【${formData.$id}】数据来源`}
width='500px'
visible={visible}
onOk={() => setVisible(false)}
onCancel={() => setVisible(false)}
>
<Form
form={form}
>
<Form.Item
name="area"
label="数据来源"
rules={[
{
required: true,
message: 'Missing area',
},
]}
>
<Select options={options} />
</Form.Item>
</Form>
</Modal>
<Input value={valueShow} onChange={inputChange} style={style} onClick={onFocus} />
</>
)
}
export default DataSource
\ No newline at end of file
import React, { useState, useEffect, useMemo } from 'react'
import { DatePicker, Input } from 'antd'
import { DatePicker, TimePicker, Input } from 'antd'
import moment from 'moment'
import locale from 'antd/lib/date-picker/locale/zh_CN'
......@@ -13,12 +13,33 @@ const DateSelect = (props) => {
onChange(dateStr)
}
const onOk = (value) => {
console.log('value', value)
}
console.log('format', format)
if (format === 'dateTime') {
return (
<DatePicker
picker={format}
// value={valueShow}
onChange={dateChange}
onOk={onOk}
showNow
showTime
style={{ width: '100%' }}
locale={locale}
/>
)
}
return (
<DatePicker
picker={format}
// value={valueShow}
onChange={dateChange}
showTime={format === 'dateTime'}
onOk={onOk}
style={{ width: '100%' }}
locale={locale}
/>
......
import React, { useMemo } from 'react'
import { Input, Select } from 'antd'
import style from '../../style'
const field = [
"处理站点",
......@@ -90,7 +91,7 @@ const FieldNames = (props) => {
}
return (
<Select onChange={change} style={{ minWidth: '143px' }} value={valueShow}>
<Select onChange={change} style={style} value={valueShow}>
{
field.map(v => <Select.Option key={v} value={v}>{v}</Select.Option>)
}
......
......@@ -3,6 +3,7 @@ import EnumOptions from './EnumOptions'
import FieldNames from './FieldNames'
import CascadeField from './CascadeField'
import DateSelect from './DateSelect'
import DataSource from './DataSource'
const settings = {
BooleanSwitch,
......@@ -10,6 +11,7 @@ const settings = {
FieldNames,
CascadeField,
DateSelect,
DataSource,
}
export default settings
\ No newline at end of file
const style = {
width: '100%'
}
export default style
\ No newline at end of file
import React, { useMemo } from 'react'
import { InputNumber } from 'antd'
const style = {
width: '100%'
}
import style from '../../style'
const NumberInput = ({ value, onChange, schema }) => {
console.log('数字输入框', schema)
const { disabled, presetValue } = schema
const valueShow = useMemo(() => {
return presetValue || value
}, [presetValue, value])
return (
<InputNumber
disabled={disabled}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -15,9 +15,6 @@ const TextArea = ({ value, onChange, schema }) => {
onChange(e.target.value)
}
// useEffect(() => {
// onChange(val)
// }, [])
return (
<Input.TextArea
......
......@@ -3,6 +3,8 @@ import { Input } from 'antd'
const TextInput = ({ value, onChange, schema }) => {
console.log('文本输入框', schema)
const { disabled, placeholder, presetValue } = schema
const valueShow = useMemo(() => {
......@@ -13,10 +15,6 @@ const TextInput = ({ value, onChange, schema }) => {
onChange(e.target.value)
}
// useEffect(() => {
// onChange(val)
// }, [])
return (
<Input
disabled={disabled}
......
import FormRender from './core/FormRender'
import FormDesigner from './core/FormDesigner'
import './main.less'
export {
FormDesigner
FormRender,
FormDesigner,
}
\ No newline at end of file
......@@ -6,6 +6,11 @@
//@parse-form-prefix-cls: ~'ant-parse-form';
.@{parse-form-prefix-cls} {
.dnd-container {
height: 700px;
}
.fr-generator-container .right-layout {
width: 20rem;
}
......@@ -132,10 +137,13 @@
}
// 上传组件的图片类型按钮的disabled样式
.@{ant-prefix}-upload.@{ant-prefix}-upload-disabled {
.@{ant-prefix}-upload-disabled {
color: @disabledColor;
cursor: default;
border: none;
.@{ant-prefix}-btn-default {
display: none;
}
}
// 多选下的tag的disabled样式
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment