Commit 6905ba0b authored by 田翔's avatar 田翔

统一表单配置信息

parent 3b2245b9
......@@ -3518,7 +3518,7 @@ const Test = (props) => {
<div style={{ width: '100%' }}>
<Tabs>
<Tabs.TabPane tab="编辑" key="item-1">
<FormDesigner setSchema={changeSchema} />
<FormDesigner setSchema={changeSchema} tableName='' />
</Tabs.TabPane>
<Tabs.TabPane tab="渲染" key="item-2">
<FormRender schema={schema} />
......
......@@ -73,23 +73,17 @@ module.exports = {
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 (context.resourcePath.includes('wisdom-map')) {
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 `pandaXform-${arr.join('-')}-${localName}`.replace(/--/g, '-');
}
}
return localName;
},
......
{
"name": "panda-xform",
"version": "1.3.0",
"description": "1.3.0: 支持附件各种形态",
"version": "1.4.0",
"description": "1.4.0: 统一表单配置信息",
"keywords": [
"panda-xform"
],
......
const baseSettings = {
title: {
title: '标题',
type: 'string',
// widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
// title: {
// title: '标题',
// type: 'string',
// // widget: 'htmlInput',
// displayType: 'row',
// labelWidth: 80,
// },
}
const commonSettings = {
......@@ -29,8 +29,10 @@ const commonSettings = {
placeholder: {
title: '提示语',
type: 'string',
widget: 'Placeholder',
displayType: 'row',
labelWidth: 80,
dependencies: ['title']
},
// description: {
// title: '说明',
......@@ -41,7 +43,6 @@ const commonSettings = {
type: 'string',
displayType: 'row',
labelWidth: 80,
// default: ''
},
}
......@@ -49,36 +50,39 @@ const switchSettings = {
disabled: {
title: '只读',
type: 'boolean',
widget: 'BooleanSwitch',
displayType: 'row',
labelWidth: 80,
default: false
widget: 'checkbox',
// displayType: 'row',
// labelWidth: 80,
default: false,
width: '33%',
},
required: {
title: '必填',
type: 'boolean',
widget: 'BooleanSwitch',
displayType: 'row',
labelWidth: 80,
default: false
widget: 'checkbox',
// displayType: 'row',
// labelWidth: 80,
default: false,
width: '33%',
},
hidden: {
title: '隐藏',
type: 'boolean',
widget: 'BooleanSwitch',
widget: 'checkbox',
default: false,
displayType: 'row',
labelWidth: 80,
width: '33%',
// displayType: 'row',
// labelWidth: 80,
},
}
const elementSettings = {
width: {
title: '元素宽度',
type: 'string',
widget: 'percentSlider',
// default: '33%',
},
// width: {
// title: '元素宽度',
// type: 'string',
// widget: 'percentSlider',
// // default: '33%',
// },
labelWidth: {
title: '标签宽度',
description: '默认值110',
......@@ -95,12 +99,46 @@ const elementSettings = {
const globalSettings = {
type: 'object',
properties: {
groupBase: {
title: '基础信息',
type: 'object',
properties: {},
},
tableName: {
title: '表名',
type: 'string',
widget: 'select',
required: true,
displayType: 'row',
labelWidth: 70,
default: '我是表名',
},
tableAlias: {
title: '别名',
type: 'string',
widget: 'htmlInput',
displayType: 'row',
labelWidth: 70,
},
interfaceText: {
title: '接口',
type: 'string',
widget: 'htmlInput',
displayType: 'row',
labelWidth: 70,
default: '我是接口'
},
groupStyle: {
title: '表单样式',
type: 'object',
properties: {},
},
column: {
title: '整体布局',
type: 'number',
enum: [1],
enum: [1, 2, 3],
default: 1,
enumNames: ['一行一列'],
enumNames: ['一行一列', '一行两列', '一行三列'],
widget: 'select',
props: {
placeholder: '默认一行一列',
......@@ -129,6 +167,8 @@ const globalSettings = {
},
},
},
}
export {
......
......@@ -6,10 +6,7 @@ const allSetting = {
...elementSettings
}
const settings = [
{
title: '布局控件',
widgets: [
const layoutWidgets = [
{
text: '分组名称',
name: '分组名称',
......@@ -18,22 +15,186 @@ const settings = [
type: 'object',
properties: {}
},
setting: {},
setting: {
groupBase: {
title: '基础信息',
type: 'object',
properties: {}
},
],
title: {
title: '标题',
type: 'string',
widget: 'FieldNames',
required: true,
displayType: 'row',
labelWidth: 80,
},
{
title: '文本控件',
widgets: [
// groupStyle: {
// title: '控件样式',
// type: 'object',
// properties: {
// color: {
// title: '颜色',
// type: 'string',
// }
// }
// }
},
},
]
const textWidgets = [
{
text: '文本',
name: '文本',
schema: {
title: '文本',
type: 'string',
widget: 'TextInput',
props: {
style: {
color: 'pink'
}
}
},
setting: {
...allSetting
groupBase: {
title: '基础信息',
type: 'object',
collapsed: true,
properties: {}
},
fieldName: {
title: '字段名称',
type: 'string',
widget: 'FieldNames',
required: true,
displayType: 'row',
labelWidth: 80,
},
title: {
title: '标题',
required: true,
type: 'string',
widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
placeholder: {
title: '提示语',
type: 'string',
widget: 'Placeholder',
displayType: 'row',
labelWidth: 80,
dependencies: ['title']
},
presetValue: {
title: '默认值',
type: 'string',
widget: 'InputDefault',
displayType: 'row',
labelWidth: 80,
},
// groupSource: {
// title: '数据来源',
// type: 'object',
// properties: {}
// },
// source: {
// title: '数据来源',
// name: '数据来源',
// type: 'string',
// widget: 'select',
// displayType: 'row',
// labelWidth: 80,
// enum: [1, 2, 3],
// enumNames: ['一行一列', '一行两列', '一行三列'],
// },
groupVerify: {
title: '数据校验',
type: 'object',
properties: {}
},
required: {
title: '必填',
type: 'boolean',
widget: 'BooleanSwitch',
default: false,
displayType: 'row',
labelWidth: 100,
},
maxLength: {
title: '字节最大长度',
type: 'number',
widget: 'number',
default: 200,
displayType: 'row',
labelWidth: 100,
},
rules: {
title: '正则校验',
type: 'array',
default: [],
widget: 'VerifyTextInput',
displayType: 'row',
labelWidth: 100,
},
groupSetting: {
title: '控件设置',
type: 'object',
properties: {}
},
disabled: {
title: '只读',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '33%',
},
hidden: {
title: '隐藏',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '33%',
},
emphasis: {
title: '强调',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '33%',
},
groupStyle: {
title: '控件样式',
type: 'object',
properties: {}
},
prefix: {
title: '前缀',
type: 'string',
widget: 'InputAddon',
displayType: 'row',
labelWidth: 80,
},
suffix: {
title: '后缀',
type: 'string',
widget: 'InputAddon',
displayType: 'row',
labelWidth: 80,
},
labelWidth: {
title: '标签宽度',
description: '默认值110',
default: 110,
type: 'number',
widget: 'slider',
max: 400,
props: {
hideNumber: true,
},
},
},
},
{
......@@ -45,7 +206,7 @@ const settings = [
widget: 'UniqueValue'
},
setting: {
...allSetting
// ...allSetting
},
},
{
......@@ -69,7 +230,30 @@ const settings = [
widget: 'number'
},
setting: {
...allSetting
fieldName: {
title: '字段名称',
type: 'string',
widget: 'FieldNames',
required: true,
displayType: 'row',
labelWidth: 80,
},
title: {
title: '标题',
required: true,
type: 'string',
widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
placeholder: {
title: '提示语',
type: 'string',
widget: 'Placeholder',
displayType: 'row',
labelWidth: 80,
dependencies: ['title']
},
},
},
{
......@@ -121,14 +305,19 @@ const settings = [
widget: 'RichText'
},
setting: {
...allSetting
...allSetting,
width: {
title: '元素宽度',
type: 'string',
hidden: true,
widget: 'percentSlider',
default: '100%',
},
},
],
},
{
title: '选择器控件',
widgets: [
]
const selectWidgets = [
{
text: '值选择器',
name: '值选择器',
......@@ -140,23 +329,159 @@ const settings = [
require: true,
},
setting: {
...commonSettings,
dataSource: {
groupBase: {
title: '基础信息',
type: 'object',
collapsed: true,
properties: {}
},
fieldName: {
title: '字段名称',
type: 'string',
widget: 'FieldNames',
required: true,
displayType: 'row',
labelWidth: 80,
},
title: {
title: '标题',
required: true,
type: 'string',
widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
placeholder: {
title: '提示语',
type: 'string',
displayType: 'row',
labelWidth: 80,
default: '123'
},
presetValue: {
title: '默认值',
type: 'string',
displayType: 'row',
labelWidth: 80,
},
'数据来源': {
title: '数据来源',
type: 'object',
properties: {}
},
options: {
title: '选项',
name: '选项',
type: 'array',
default: [],
widget: 'simpleList',
default: [
{ value: '选项一', },
],
items: {
type: 'object',
properties: {
value: {
title: '选项值',
type: 'string',
widget: 'DataSource',
displayType: 'row',
labelWidth: 75,
required: true,
default: '',
props: {
style: {
width: '120px',
color: 'blue'
}
}
},
},
},
props: {
// hideMove: true,
hideCopy: true,
},
displayType: 'row',
labelWidth: 80,
},
'数据校验': {
title: '数据校验',
type: 'object',
properties: {}
},
required: {
title: '必填',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '33%',
},
'控件设置': {
title: '控件设置',
type: 'object',
properties: {}
},
disabled: {
title: '只读',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '25%',
},
hidden: {
title: '隐藏',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '25%',
},
emphasis: {
title: '强调',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '25%',
},
isMultiple: {
title: '是否多选',
title: '多选',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '25%',
},
isEdit: {
title: '是否可编辑',
type: 'boolean',
widget: 'BooleanSwitch',
displayType: 'row',
labelWidth: 120,
description: '勾选后可直接输入选项'
},
'控件样式': {
title: '控件样式',
type: 'object',
properties: {}
},
showType: {
title: '显示方式',
type: 'string',
enum: ['下拉', '平铺'],
default: '下拉',
enumNames: ['下拉', '平铺'],
displayType: 'row',
labelWidth: 80,
},
...switchSettings,
...elementSettings,
labelWidth: {
title: '标签宽度',
description: '默认值110',
default: 110,
type: 'number',
widget: 'slider',
max: 400,
props: {
hideNumber: true,
},
},
}
},
{
......@@ -170,24 +495,37 @@ const settings = [
require: true,
},
setting: {
...commonSettings,
options: {
title: '可选值',
fieldName: {
title: '字段名称',
type: 'string',
widget: 'EnumOptions',
widget: 'FieldNames',
required: true,
displayType: 'row',
labelWidth: 80,
},
isMultiple: {
title: '是否多选',
name: '是否多选',
type: 'boolean',
widget: 'BooleanSwitch',
base: {
title: '基础信息',
type: 'object',
properties: {
fieldName: {
title: '字段名称',
type: 'string',
widget: 'FieldNames',
required: true,
displayType: 'row',
labelWidth: 80,
},
title: {
title: '标题',
required: true,
type: 'string',
widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
...switchSettings,
...elementSettings,
}
},
// ...commonSettings,
}
},
{
......@@ -281,7 +619,21 @@ const settings = [
...elementSettings,
}
},
],
]
const settings = [
{
title: '布局控件',
widgets: layoutWidgets
},
{
title: '文本控件',
widgets: textWidgets
},
{
title: '选择器控件',
widgets: selectWidgets,
},
{
title: '时间控件',
......@@ -382,6 +734,12 @@ const settings = [
labelWidth: 80,
},
...switchSettings,
width: {
title: '元素宽度',
type: 'string',
widget: 'percentSlider',
default: '100%',
},
...elementSettings,
},
},
......@@ -416,7 +774,7 @@ const settings = [
widget: 'RelationForm',
},
setting: {
$id: {
fieldName: {
title: '字段名称',
type: 'string',
widget: 'FieldNames',
......@@ -447,6 +805,12 @@ const settings = [
labelWidth: 80,
default: false
},
width: {
title: '元素宽度',
type: 'string',
widget: 'percentSlider',
default: '100%',
},
...elementSettings,
},
},
......
import React, { useRef, useMemo, useState, useContext } from 'react'
import React, { useRef, useMemo, useEffect, useState, useContext, createContext } from 'react'
import { ConfigProvider, message } from 'antd'
import Generator from 'fr-generator'
import { settings, baseSettings, globalSettings } from './config'
import widgets from '../widgets'
export const GlobalStore = createContext(null)
const FormDesigner = (props) => {
const { tableName } = props
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext)
const prefixCls = getPrefixCls('parse-form')
const prefixClsWithoutParseForm = getPrefixCls()
const prefixCls = getPrefixCls('pandaXform')
const pandaXform = getPrefixCls()
const [table, setTable] = useState()
const ref = useRef(null)
const getTableField = () => {
}
const getTableInfo = () => {
}
const getTable = () => {
}
useEffect(() => {
if (tableName) {
getTable()
}
}, [tableName])
const extraButtons = [
{
text: '提交',
......@@ -19,6 +43,7 @@ const FormDesigner = (props) => {
if (errors.length) {
return message.error('请按照提示完善表单内容')
}
console.log('ref.current', ref.current)
props.setSchema && props.setSchema(ref.current.getValue())
}
}
......@@ -44,9 +69,12 @@ const FormDesigner = (props) => {
}
return (
<GlobalStore.Provider
value={{}}
>
<div className={prefixCls}>
<Generator
configProvider={{ prefixCls: prefixClsWithoutParseForm }}
configProvider={{ prefixCls: pandaXform }}
mapping={{
object: 'Header',
}}
......@@ -62,6 +90,7 @@ const FormDesigner = (props) => {
globalSettings={globalSettings}
/>
</div>
</GlobalStore.Provider>
)
}
......
......@@ -55,7 +55,7 @@ const schema = {
},
},
"required": [],
"className": "ant-parse-form-group"
"className": "ant-pandaXform-group"
},
},
"required": [],
......
......@@ -2,7 +2,6 @@ import React, { useState, useEffect, useRef, useContext, createContext, forwardR
import FormRender, { useForm } from 'form-render'
import { ConfigProvider } from 'antd'
import widgets from '../widgets'
// import schema from './data'
export const GlobalStore = createContext(null)
......@@ -17,14 +16,18 @@ const XRender = (props, ref) => {
const { schema } = props
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext)
const prefixCls = getPrefixCls('parse-form')
const prefixClsWithoutParseForm = getPrefixCls()
const prefixCls = getPrefixCls('pandaXform')
const pandaXform = getPrefixCls()
const [extraData, setExtraData] = useState({})
const [parseFormData, setParseFormData] = useState({})
const [listData, setListData] = useState([])
const form = useForm()
const onClick = () => {
console.log('form', form)
}
return (
<GlobalStore.Provider
value={{
......@@ -35,9 +38,9 @@ const XRender = (props, ref) => {
listData,
setParseFormData,
}}>
<div className={prefixCls}>
<div className={prefixCls} onClick={() => onClick()}>
<FormRender
configProvider={{ prefixCls: prefixClsWithoutParseForm }}
configProvider={{ prefixCls: pandaXform }}
form={form}
schema={schema}
// onChange={form.setValues}
......
......@@ -5,9 +5,9 @@ import './index.less'
const Header = (props) => {
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext)
const prefixCls = getPrefixCls('parse-form')
const prefixCls = getPrefixCls('pandaXform')
const { title } = props
const { title, value } = props
return (
<div>
......
@import '~antd/es/style/themes/default.less';
@parse-form-prefix-cls: ~'@{ant-prefix}-parse-form';
.@{parse-form-prefix-cls} {
.@{parse-form-prefix-cls}-title {
@pandaXform: ~'@{ant-prefix}-pandaXform';
.@{pandaXform} {
.@{pandaXform}-title {
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
}
.@{parse-form-prefix-cls}-bg {
.@{pandaXform}-bg {
width: 3px;
height: 16px;
margin-right: 10px;
......
......@@ -8,11 +8,46 @@ import { downloadFunc, filenameVerification } from '../../../../utils/utils'
const accepts = {
'图片': ['.bmp', '.gif', '.jpeg', 'tiff', '.png', '.svg', '.jpg'],
'文档': ['.docx', '.xlsx', '.pdf'],
// '文档': ['.docx', '.xlsx', '.pdf'],
'文档': [],
'视频': ['.mp4'],
'音频': ['.mp3'],
}
const getFileType = (fileName) => {
if (fileName) {
//图片
if (fileName.includes('jpg')) {
return 'jpg'
}
if (fileName.includes('png')) {
return 'png'
}
if (fileName.includes('svg')) {
return 'svg'
}
//文档
if (fileName.includes('docx')) {
return 'docx'
}
if (fileName.includes('xlsx')) {
return 'xlsx'
}
if (fileName.includes('pdf')) {
return 'pdf'
}
//音频
if (fileName.includes('mp3')) {
return 'mp3'
}
//视频
if (fileName.includes('mp4')) {
return 'mp4'
}
}
return null
}
const FileUpload = (props) => {
const { value, schema, onChange } = props
......@@ -69,14 +104,7 @@ const FileUpload = (props) => {
}
},
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'
}
let fileType = getFileType(file.name)
if (fileType) {
setShowFile({ name: file.name, fileType: fileType, filePath: file.url })
setVisible(true)
......@@ -86,10 +114,11 @@ const FileUpload = (props) => {
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>
let fileType = getFileType(file.name)
if (fileType) {
return <div className={styles.iconImg} type={fileType}></div>
} else {
return <div className={styles.iconImg} type={'通用'}></div>
}
}
return <FileOutlined />
......@@ -135,7 +164,7 @@ const FileUpload = (props) => {
{listType !== 'picture-card' ? <Button icon={<UploadOutlined />}>{placeholder || '上传'}</Button> : (disabled ? null : (placeholder || '+ 上传'))}
</Upload>
<Modal
width={'80%'}
width={'70%'}
title={showFile.name}
visible={visible}
onCancel={() => setVisible(false)}
......
@imgSrc: '../../../../assets/images';
.uploadBox {
.iconImg {
width:45px;
width: 45px;
height: 45px;
margin: 0 auto;
&[type='通用'] {
background: url('@{imgSrc}/通用.png');
background-size: 100% 100%;
}
&[type='jpg'] {
background: url('@{imgSrc}/JPG.png');
background-size: 100% 100%;
}
&[type='png'] {
background: url('@{imgSrc}/PNG.png');
background-size: 100% 100%;
}
&[type="mp3"] {
background: url('@{imgSrc}/音乐.png');
background-size: 100% 100%;
}
&[type="mp4"] {
background: url('@{imgSrc}/视频.png');
background-size: 100% 100%;
}
&[type='docx'] {
background: url('@{imgSrc}/Word.png');
background-size: 100% 100%;
......@@ -12,5 +32,9 @@
background: url('@{imgSrc}/Excel.png');
background-size: 100% 100%;
}
&[type='PDF'] {
background: url('@{imgSrc}/PDF.png');
background-size: 100% 100%;
}
}
}
\ No newline at end of file
......@@ -2,42 +2,13 @@ import React, { useEffect, useMemo } from 'react'
import { Radio, Checkbox } from 'antd'
import './index.less'
const TileSelect = ({ value, onChange, schema }) => {
const TileSelect = (props) => {
const { presetValue, isMultiple, options, isDisable } = schema
console.log('isDisable', schema)
const enums = useMemo(() => {
return options ? options.split(',') : []
}, [options])
const showValue = useMemo(() => {
if (value) {
if (isMultiple) {
return value.split(',')
}
return value
}
return presetValue
}, [value, presetValue, isMultiple])
console.log('props', props)
return (
<div className='tileSelect' disabled={isDisable}>
{
isMultiple ?
<Checkbox.Group
disabled={isDisable}
onChange={value => onChange(value.join(','))}
value={showValue}
>
{enums.map(v => <Checkbox key={v} value={v}>{v}</Checkbox>)}
</Checkbox.Group>
:
<Radio.Group onChange={e => onChange(e.target.value)} value={showValue} disabled={isDisable}>
{enums.map(v => <Radio key={v} value={v}>{v}</Radio>)}
</Radio.Group>
}
<div className='tileSelect'>
123
</div>
)
......
// 选择器,值选择器
import React, { useState, useMemo } from 'react'
import { Select } from 'antd'
import style from '../../style'
import { Select, Checkbox, Radio } from 'antd'
import styels from './index.less'
const { Option } = Select
const ValueSelect = ({ value, onChange, schema }) => {
const { config, placeholder, disabled, options, presetValue } = schema
const { placeholder, disabled, options, presetValue, showType, isMultiple, isEdit } = schema
const mode = useMemo(() => {
if (config && config.includes('n')) {
return 'multiple'
}
return null
}, [config])
console.log('options', options)
const valueShow = useMemo(() => {
if (mode) {
return (value || presetValue) ? (value || presetValue).split(',') : null
if (isMultiple) {
return (value || presetValue) ? (value || presetValue).split(',') : []
} else {
return value || presetValue || null
}
}, [presetValue, value])
const enums = useMemo(() => {
return Array.isArray(options) ? options.map(v => v.value) : []
// if (options) {
// return options.split(',')
// }
}, [options])
const handleChange = value => {
if (mode) {
if (isEdit) {
} else {
if (isMultiple) {
onChange(value.join(','))
} else {
onChange(value)
}
}
}
// console.log('valueShow', valueShow, disabled)
if (showType === '下拉') {
return (
<Select
style={style}
mode={mode}
style={{ width: '100%' }}
mode={isMultiple ? 'multiple' : ''}
disabled={disabled}
showArrow={!disabled}
optionFilterProp="children"
// optionFilterProp="children"
value={valueShow}
placeholder={placeholder}
onChange={handleChange}
>
{options && options.split(',').map(v => <Option value={v} key={v}>{v}</Option>)}
{enums.map(v => <Option value={v} key={v}>{v}</Option>)}
</Select>
)
}
if (showType === '平铺') {
return (
<div className={styels.tileSelect} type={disabled ? 'disabled' : ''}>
{
isMultiple ?
<Checkbox.Group
disabled={disabled}
onChange={value => onChange(value.join(','))}
value={valueShow}
>
{enums.map(v => <Checkbox key={v} value={v}>{v}</Checkbox>)}
</Checkbox.Group>
:
<Radio.Group onChange={e => onChange(e.target.value)} value={valueShow} disabled={disabled}>
{enums.map(v => <Radio key={v} value={v}>{v}</Radio>)}
</Radio.Group>
}
</div>
)
}
return null
}
export default ValueSelect
@import '~antd/es/style/themes/default.less';
.tileSelect {
width: 100%;
min-height: 30px;
&[type='disabled'] {
background: #f8fafc;
}
padding: 0 5px;
.@{ant-prefix}-checkbox-wrapper {
margin-top: 4px;
}
.@{ant-prefix}-radio-wrapper {
margin-top: 4px;
}
}
\ No newline at end of file
......@@ -8,6 +8,8 @@ const BooleanSwitch = (props) => {
return (
<Switch
checked={value}
checkedChildren='是'
unCheckedChildren='否'
onChange={(checked) => onChange(checked)}
/>
)
......
......@@ -91,7 +91,7 @@ const FieldNames = (props) => {
}
return (
<Select onChange={change} style={style} value={valueShow}>
<Select onChange={change} style={{ ...style, maxWidth: '208px' }} value={valueShow}>
{
field.map(v => <Select.Option key={v} value={v}>{v}</Select.Option>)
}
......
import React, { useMemo, useState, useContext } from 'react'
import { Input, Modal, ConfigProvider } from 'antd'
import Icon, { EllipsisOutlined } from '@ant-design/icons'
import * as icons from '@ant-design/icons'
import './index.less'
const iconList = Object.keys(icons).filter((item) => typeof icons[item] === 'object')
const InputAddon = (props) => {
const { value, onChange } = props
const [visible, setVisible] = useState(false)
const [icon, setIcon] = useState()
// const valueShow = useMemo(() => {
// return value ? value : ''
// }, [value])
const inputChange = (e) => {
onChange(e.target.value)
}
const onOk = () => {
setVisible(false)
onChange(icon)
}
const iconClick = () => {
setVisible(true)
}
const onCancel = () => {
setVisible(false)
}
return (
<div className={`inputAddon`}>
<Input value={value} onChange={inputChange} addonAfter={<EllipsisOutlined onClick={iconClick} />} />
<Modal
width={'50%'}
getContainer={false}
title='图标选择'
visible={visible}
onOk={onOk}
onCancel={onCancel}
bodyStyle={{ height: '450px', overflow: 'auto' }}
>
<div className={`iconBox`}>
{
iconList.map((v, i) => {
if (i === 0) return null
return (
<div key={v} className={`iconItem`} active={JSON.stringify(icon === v)} onClick={() => setIcon(v)}>
<Icon component={icons[v]} />
</div>
)
})
}
</div>
</Modal>
</div>
)
}
export default InputAddon
\ No newline at end of file
@import '~antd/es/style/themes/default.less';
@pandaXform: ~'@{ant-prefix}-pandaXform';
.@{pandaXform} {
.inputAddon {
.iconBox {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
.iconItem {
display: flex;
align-items: center;
justify-content: center;
width: 70px;
height: 70px;
font-size: 50px;
&:hover {
cursor: pointer;
}
&[active='true'] {
transition: all 0.3s ease;
background: #4096ff;
border-radius: 5px;
color: white;
transform: scale(1.2);
}
}
}
}
}
\ No newline at end of file
import React, { useMemo, useEffect, useState } from 'react'
import { Input } from 'antd'
const Placeholder = (props) => {
const { value, addons, onChange } = props
const { title } = addons.formData
const inputChange = (e) => {
onChange(e.target.value)
}
useEffect(() => {
if (!value) {
onChange(`请输入${title}`)
}
}, [title, value])
return (
<Input value={value} onChange={inputChange} />
)
}
export default Placeholder
\ No newline at end of file
import React, { useMemo } from 'react'
import { Select } from 'antd'
const options = [
{
label: '邮箱(email)',
value: '^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$',
message: '邮箱校验未通过'
},
{
label: '身份证号(identity)',
value: '(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)',
message: '手机号校验未通过'
},
{
label: '手机号(mobile)',
value: '/^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/',
message: '手机号校验未通过',
},
{
label: '银行卡号(bankAccount)',
value: '^(\\d{16}|\\d{19})$',
message: '银行卡号校验未通过'
},
]
const VerifyTextInput = (props) => {
const { value, onChange } = props
const valueShow = useMemo(() => {
return Array.isArray(value) && value.length ? value[0].pattern : null
}, [value])
const selectChange = (value) => {
const item = options.find(v => v.value === value)
onChange([{
pattern: value,
message: item.message,
}])
}
return (
<Select
allowClear
value={valueShow}
options={options}
onChange={selectChange}
/>
)
}
export default VerifyTextInput
\ No newline at end of file
import React, { useMemo, useState } from 'react'
import { Input, Modal, Popover, Select } from 'antd'
import { EllipsisOutlined } from '@ant-design/icons'
const options = [
{ label: '本人姓名', value: '【本人姓名】' },
{ label: '本人部门', value: '【本人部门】' },
]
const InputDefault = (props) => {
console.log('props', props)
const { value, onChange } = props
const [visible, setVisible] = useState(false)
const style = useMemo(() => {
},)
const iconClick = () => {
setVisible(true)
}
const onOk = () => {
}
const onCancel = () => {
setVisible(false)
}
const selectChange = (value) => {
onChange(value)
}
const content = (
<Select
style={{ width: '100%' }}
options={options}
onChange={selectChange}
>
</Select>
)
return (
<div className='InputDefault'>
<Input
value={value}
onChange={(e) => onChange(e.target.value)}
style={style}
addonAfter={
<Popover
placement="topRight"
content={content}
title="数据将从环境变量读取"
trigger="click"
>
<EllipsisOutlined />
</Popover>
}
/>
</div>
)
}
export default InputDefault
\ No newline at end of file
import InputDefault from "./InputDefault"
const base = {
InputDefault,
}
export default base
\ No newline at end of file
import base from './base'
import BooleanSwitch from './BooleanSwitch'
import EnumOptions from './EnumOptions'
import FieldNames from './FieldNames'
import InputAddon from './InputAddon'
import Placeholder from './Placeholder'
import CascadeField from './CascadeField'
import DateSelect from './DateSelect'
import DataSource from './DataSource'
import VerifyTextInput from './VerifyTextInput'
const settings = {
...base,
BooleanSwitch,
EnumOptions,
FieldNames,
InputAddon,
Placeholder,
CascadeField,
DateSelect,
DataSource,
VerifyTextInput,
}
export default settings
\ No newline at end of file
import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef, useMemo } from 'react'
import './index.less'
import styles from './index.less'
import { request } from '@wisdom-utils/utils'
import { Editor, Toolbar } from '@wangeditor/editor-for-react'
import { DomEditor } from '@wangeditor/editor'
......@@ -68,7 +68,7 @@ const RichText = forwardRef(({ schema, onChange, value }, ref) => {
return (
<div className='richText' disabled={disabled}>
<div className={styles.richText} disabled={disabled}>
{
!disabled ?
<Toolbar
......
@import '~antd/es/style/themes/default.less';
@parse-form-prefix-cls: ~'@{ant-prefix}-parse-form';
@pandaXform-prefix-cls: ~'@{ant-prefix}-pandaXform';
.richText {
border: 1px solid #ccc;
z-index: 100;
......
import React, { useState, useEffect, useMemo } from 'react'
import { Input } from 'antd'
import Icon, { EllipsisOutlined } from '@ant-design/icons'
import * as icons from '@ant-design/icons'
const TextInput = ({ value, onChange, schema }) => {
const iconList = Object.keys(icons).filter((item) => typeof icons[item] === 'object')
console.log('文本输入框', schema)
const TextInput = (props) => {
const { disabled, placeholder, presetValue } = schema
const { value, onChange, schema } = props
const { disabled, placeholder, presetValue, prefix, suffix, maxLength, rules } = schema
const valueShow = useMemo(() => {
return presetValue || value
......@@ -15,13 +18,18 @@ const TextInput = ({ value, onChange, schema }) => {
onChange(e.target.value)
}
console.log('rules', rules)
return (
<Input
rules={rules}
disabled={disabled}
value={valueShow}
rows={5}
placeholder={placeholder}
maxLength={maxLength}
placeholder={disabled ? null : placeholder}
onChange={handleChange}
addonBefore={iconList.includes(prefix) ? <Icon component={icons[prefix]} /> : prefix}
addonAfter={iconList.includes(suffix) ? <Icon component={icons[suffix]} /> : suffix}
/>
)
......
......@@ -2,10 +2,8 @@
@disabledBgColor: rgb(248 ,250, 252);
@disabledColor: rgba(0, 0, 0, 0.7);
@parse-form-prefix-cls: ~'@{ant-prefix}-parse-form';
//@parse-form-prefix-cls: ~'ant-parse-form';
.@{parse-form-prefix-cls} {
@pandaXform-prefix-cls: ~'@{ant-prefix}-pandaXform';
.@{pandaXform-prefix-cls} {
.dnd-container {
height: 700px;
......@@ -179,17 +177,17 @@
justify-content: flex-end;
padding: 10px 10px;
.@{parse-form-prefix-cls}-operate-reset {
.@{pandaXform-prefix-cls}-operate-reset {
margin-right: 10px;
}
.parse-form-text-area {
.pandaXform-text-area {
width: 100% !important;
}
}
&-group {
.@{parse-form-prefix-cls}-title {
.@{pandaXform-prefix-cls}-title {
display: flex;
align-items: center;
justify-content: center;
......@@ -230,7 +228,7 @@
}
}
.@{parse-form-prefix-cls}-divider-horizontal {
.@{pandaXform-prefix-cls}-divider-horizontal {
margin: 10px;
&:first-child {
......@@ -238,7 +236,7 @@
}
}
.@{parse-form-prefix-cls}-input[disabled] {
.@{pandaXform-prefix-cls}-input[disabled] {
background-color: #ffffff60 !important;
}
......
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