Commit 5cd150f7 authored by 田翔's avatar 田翔

fix: 配置表名字段名支持下拉框,下拉框配置数据来源必填信息校验,时间配置改为支持单选,可编辑配置根据数据来源进行控制,下拉框增加搜索选项

parent a9f4e41a
{
"name": "panda-xform",
"version": "1.6.2",
"description": "1.6.2: 防止出现死循环",
"version": "1.6.3",
"description": "1.6.3: 配置表名字段名支持下拉框,下拉框配置数据来源必填信息校验,时间配置改为支持单选,可编辑配置根据数据来源进行控制,下拉框增加搜索选项",
"keywords": [
"panda-xform"
],
......@@ -126,4 +126,4 @@
"publishConfig": {
"registry": "https://g.civnet.cn:4873"
}
}
}
\ No newline at end of file
......@@ -202,7 +202,15 @@ export function GetSelectItemList({ nodeName }) {
})
}
//获取表
//获取所有表
export function LoadTableV2() {
return request({
url: `PandaOMS/OMS/CaseManage/LoadTableV2`,
method: 'get'
})
}
//获取台账表
export function LoadLedgers() {
return request({
url: `PandaOMS/OMS/WorkOrderCenter/GetCM_Ledger_LoadLedgers`,
......
......@@ -707,7 +707,7 @@ const textWidgets = [
title: '只读',
type: 'boolean',
widget: 'checkbox',
default: false,
default: true,
width: '30%',
},
hidden: {
......@@ -797,10 +797,11 @@ const selectWidgets = [
title: '来源方式',
name: '来源方式',
type: 'string',
widget: 'select',
// widget: 'select',
widget: 'SoruceType',
default: '手动输入',
enum: ['手动输入', '数据字典', '表数据', '站点'],
enumNames: ['手动输入', '数据字典', '表数据', '站点'],
// enum: ['手动输入', '数据字典', '表数据', '站点'],
// enumNames: ['手动输入', '数据字典', '表数据', '站点'],
displayType: 'row',
labelWidth: 80,
},
......@@ -808,6 +809,7 @@ const selectWidgets = [
title: '',
name: '选项',
type: 'array',
required: '{{formData.soruceType === "手动输入"}}',
hidden: '{{formData.soruceType !== "手动输入"}}',
default: [],
widget: 'simpleList',
......@@ -819,7 +821,7 @@ const selectWidgets = [
type: 'string',
displayType: 'row',
labelWidth: 75,
// required: true,
required: true,
default: '',
props: {
style: {
......@@ -836,37 +838,42 @@ const selectWidgets = [
},
displayType: 'row',
labelWidth: 80,
dependencies: ['soruceType']
},
dictionary: {
title: '{{formData.soruceType}}',
name: '{{formData.soruceType}}',
// required: true,
required: '{{formData.soruceType === "数据字典"}}',
hidden: '{{formData.soruceType !== "数据字典"}}',
type: 'string',
widget: 'Dictionary',
value: '{{formData.soruceType !== "数据字典" ? null : ""}}',
displayType: 'row',
labelWidth: 80,
dependencies: ['soruceType']
},
tableName: {
title: '表名',
name: '表名',
required: true,
required: '{{formData.soruceType === "表数据"}}',
hidden: '{{formData.soruceType !== "表数据"}}',
type: 'string',
// widget: 'TableName',
widget: 'TableName',
displayType: 'row',
labelWidth: 80,
dependencies: ['soruceType'],
},
fieldName: {
title: '字段名',
name: '字段名',
required: true,
required: '{{formData.soruceType === "表数据"}}',
hidden: '{{formData.soruceType !== "表数据"}}',
type: 'string',
// widget: 'TableName',
widget: 'FieldName',
displayType: 'row',
labelWidth: 80,
dependencies: ['soruceType', 'tableName'],
},
isMySite: {
title: '仅显示本人所属的站点',
......@@ -915,13 +922,22 @@ const selectWidgets = [
default: false,
width: '25%',
},
isSearch: {
title: '搜索',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '25%',
default: true
},
isEdit: {
title: '是否可编辑',
type: 'boolean',
widget: 'BooleanSwitch',
displayType: 'row',
labelWidth: 120,
description: '勾选后可直接输入选项,可编辑选择仅支持多选'
description: '勾选后可直接输入选项,可编辑选择仅支持多选',
hidden: '{{formData.soruceType !== "手动输入"}}'
},
description: {
title: '说明',
......@@ -1281,7 +1297,7 @@ const selectWidgets = [
schema: {
title: '开关',
name: '开关',
type: 'boolean',
type: 'number',
widget: 'SwitchSelector',
},
setting: {
......@@ -1339,11 +1355,23 @@ const selectWidgets = [
default: false,
width: '25%',
},
showText: {
title: '显示文字',
type: 'string',
widget: 'select',
enum: ['开/关', '是/否', '明/暗'],
enumNames: ['开/关', '是/否', '明/暗'],
displayType: 'row',
labelWidth: 80,
props: {
allowClear: true
}
},
description: {
title: '说明',
type: 'string',
displayType: 'row',
labelWidth: 55,
labelWidth: 80,
},
groupStyle: {
title: '控件样式',
......@@ -2023,29 +2051,20 @@ const dateWidgets = [
labelWidth: 80,
default: '请选择日期',
},
presetValue: {
title: '默认值',
type: 'string',
widget: 'DateDefault',
dateFormat: '{{formData.format}}',
displayType: 'row',
labelWidth: 80,
description: '勾选默认当前日期此处配置无效'
},
// presetValue: {
// title: '默认值',
// type: 'string',
// widget: 'DateDefault',
// dateFormat: '{{formData.format}}',
// displayType: 'row',
// labelWidth: 80,
// description: '勾选默认当前日期此处配置无效'
// },
groupSetting: {
title: '控件设置',
type: 'object',
properties: {}
},
format: {
title: '日期格式',
type: 'string',
enum: ['date', 'dateTime', 'year', 'month', 'week', 'quarter'],
default: 'date',
enumNames: ['日期', '日期时间', '日期年份', '日期月份', '日期周', '日期季度'],
displayType: 'row',
labelWidth: 80,
},
required: {
title: '必填',
type: 'boolean',
......@@ -2072,30 +2091,52 @@ const dateWidgets = [
default: false,
width: '30%',
},
defaultCurrent: {
title: '默认当前日期',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '50%',
props: {
style: {
marginLeft: '10px',
}
}
format: {
title: '日期格式',
type: 'string',
enum: ['date', 'dateTime', 'year', 'month', 'week', 'quarter'],
default: 'date',
enumNames: ['日期', '日期时间', '日期年份', '日期月份', '日期周', '日期季度'],
displayType: 'row',
labelWidth: 80,
},
currentDate: {
title: '不超过当前日期',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '50%',
props: {
style: {
marginLeft: '10px',
}
}
options: {
title: '选项',
type: 'string',
widget: 'select',
enum: ['默认为空', '默认为当前时间', '不超过当前时间'],
default: '默认为空',
enumNames: ['默认为空', '默认为当前时间', '不超过当前时间'],
displayType: 'row',
labelWidth: 80,
// props: {
// allowClear: true
// }
},
// defaultCurrent: {
// title: '默认当前日期',
// type: 'boolean',
// widget: 'checkbox',
// default: false,
// width: '50%',
// props: {
// style: {
// marginLeft: '10px',
// }
// }
// },
// currentDate: {
// title: '不超过当前日期',
// type: 'boolean',
// widget: 'checkbox',
// default: false,
// width: '50%',
// props: {
// style: {
// marginLeft: '10px',
// }
// }
// },
groupStyle: {
title: '控件样式',
type: 'object',
......@@ -2181,6 +2222,16 @@ const dateWidgets = [
displayType: 'row',
labelWidth: 80,
},
options: {
title: '选项',
type: 'string',
widget: 'select',
enum: ['默认为空', '默认为当前时间', '不超过当前时间'],
default: '默认为空',
enumNames: ['默认为空', '默认为当前时间', '不超过当前时间'],
displayType: 'row',
labelWidth: 80,
},
description: {
title: '说明',
type: 'string',
......@@ -2214,25 +2265,25 @@ const dateWidgets = [
default: false,
width: '30%',
},
defaultCurrent: {
title: '默认当前时间',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '50%',
props: {
style: {
marginLeft: '10px',
}
}
},
currentDate: {
title: '不超过当前时间',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '50%',
},
// defaultCurrent: {
// title: '默认当前时间',
// type: 'boolean',
// widget: 'checkbox',
// default: false,
// width: '50%',
// props: {
// style: {
// marginLeft: '10px',
// }
// }
// },
// currentDate: {
// title: '不超过当前时间',
// type: 'boolean',
// widget: 'checkbox',
// default: false,
// width: '50%',
// },
groupStyle: {
title: '控件样式',
type: 'object',
......
import React, { useRef, useEffect, useState, useContext, forwardRef, createContext, useMemo, useLayoutEffect } from 'react'
import { ConfigProvider, message, Modal, Button } from 'antd'
import { ExclamationCircleOutlined } from '@ant-design/icons'
import Generator, { defaultSettings } from 'fr-generator'
import { settings, baseSettings, globalSettings } from './config'
import widgets from '../widgets'
......@@ -51,10 +52,35 @@ const FormDesigner = (props, ref) => {
}, [tableName])
const extraButtons = [
false,
false,
true,
true,
true,
{
text: '清空',
onClick: (e) => {
Modal.confirm({
title: '确定要清空该表单配置吗?',
icon: <ExclamationCircleOutlined />,
centered: true,
cancelText: '取消',
okText: '确定',
onCancel: () => {
console.log('取消清空')
},
onOk: () => {
const schema = designerRef.current.getValue()
let newschema = {}
for (let key in schema) {
if (key !== 'properties') {
newschema[key] = schema[key]
}
}
designerRef.current.setValue(newschema)
}
})
},
},
{
text: '预览',
onClick: (e) => {
......
......@@ -7,17 +7,17 @@ import locale from 'antd/lib/date-picker/locale/zh_CN'
const DateTime = (props) => {
const { value, onChange, schema } = props
const { disabled, format, presetValue, placeholder, currentDate, defaultCurrent } = schema
const { disabled, format, presetValue, placeholder, options, currentDate, defaultCurrent } = schema
const valueShow = useMemo(() => {
if (defaultCurrent) {
if (options === '默认为当前时间') {
return (value || new Date()) ? moment(value || new Date()) : null
}
return (value || presetValue) ? moment(value || presetValue) : null
}, [presetValue, defaultCurrent, value])
const disabledDate = (current) => {
if (currentDate) {
if (options === '不超过当前时间') {
return current && current > moment()
} else {
return false
......
......@@ -5,17 +5,17 @@ import moment from 'moment'
const Time = (props) => {
const { value, onChange, schema, addons } = props
const { presetValue, currentDate, defaultCurrent } = schema
const { presetValue, currentDate, defaultCurrent, options } = schema
const valueShow = useMemo(() => {
if (defaultCurrent) {
if (options === '默认为当前时间') {
return (value || new Date()) ? moment(value || new Date(), 'HH:mm:ss') : null
}
return (value || presetValue) ? moment(value || presetValue, 'HH:mm:ss') : null
}, [presetValue, value, defaultCurrent])
const disabledDate = (current) => {
if (currentDate) {
if (options === '不超过当前时间') {
return current && current.format('HH:mm:ss') > moment().format('HH:mm:ss')
} else {
return false
......@@ -35,7 +35,6 @@ const Time = (props) => {
/>
)
}
export default Time
\ No newline at end of file
......@@ -8,7 +8,7 @@ const ComboBox = (props) => {
const userID = window?.globalConfig?.userInfo?.OID || 1
const { value, onChange, schema, addons } = props
const { placeholder, disabled, soruceType, options, dictionary, tableName, fieldName, presetValue, isMultiple, isEdit, isMySite } = schema
const { placeholder, disabled, soruceType, options, dictionary, tableName, fieldName, presetValue, isMultiple, isEdit, isMySite, isSearch } = schema
const [dictionaryList, setDictionaryList] = useState([])
const [tableData, setTableData] = useState([])
const [site, setSite] = useState([])
......@@ -113,7 +113,7 @@ const ComboBox = (props) => {
mode={isEdit ? 'tags' : (isMultiple ? 'multiple' : '')}
disabled={disabled}
showArrow={!disabled}
showSearch
showSearch={isSearch}
value={valueShow}
placeholder={placeholder}
onChange={handleChange}
......
......@@ -4,9 +4,8 @@ import { Switch } from 'antd'
const SwitchSelector = (props) => {
const { value, onChange, schema, addons } = props
const { disabled, presetValue } = schema
console.log('props', props)
const { disabled, presetValue, showText } = schema
const text = showText ? showText.split('/') : ['', '']
useEffect(() => {
if (addons) {
......@@ -18,16 +17,16 @@ const SwitchSelector = (props) => {
const switchChange = (checked) => {
if (addons) {
onChange(checked)
onChange(checked ? 1 : 0)
}
}
return (
<Switch
checked={value}
checked={Boolean(value)}
disabled={disabled}
checkedChildren={'开启'}
unCheckedChildren="关闭"
checkedChildren={Array.isArray(text) ? text[0] : ''}
unCheckedChildren={Array.isArray(text) ? text[1] : ''}
onChange={switchChange}
>
......
......@@ -61,7 +61,7 @@ const Dictionary = (props) => {
onChange={selectChange}
onFocus={() => getDictionary()}
showSearch
allowClear
// allowClear
>
{
options.map(v => {
......
import React, { useState } from 'react'
import { Select, message } from 'antd'
import { LoadTableV2, LoadTableFields } from '../../../../../apis/process'
const FieldName = (props) => {
const { value, onChange, addons } = props
const { tableName } = addons.formData
const [options, setOptions] = useState([])
const onFocus = async () => {
if (!tableName) {
return message.info('请选择表名!')
}
const { code, data, msg } = await LoadTableFields({ tableName: tableName })
if (code === 0) {
let result = data.root.map(v => { return { label: v.fieldName, value: v.fieldName } })
setOptions(result)
} else {
message.error(msg)
}
}
const selectChange = (value) => {
onChange(value)
}
return (
<Select
options={options}
value={value}
onFocus={onFocus}
onChange={selectChange}
>
</Select>
)
}
export default FieldName
\ No newline at end of file
import React, { useMemo } from 'react'
import { Select } from 'antd'
const options = [
{ label: '手动输入', value: '手动输入' },
{ label: '数据字典', value: '数据字典' },
{ label: '表数据', value: '表数据' },
{ label: '站点', value: '站点' }
]
const SoruceType = (props) => {
const { value, onChange, schema, addons } = props
const selectChange = (e) => {
if (value === '手动输入') {
addons.removeErrorField('options')
} else if (value === '数据字典') {
addons.removeErrorField('dictionary')
} else if (value === '表数据') {
addons.removeErrorField('tableName')
addons.removeErrorField('fieldName')
}
if (e !== '手动输入') {
addons.setValueByPath('isEdit', false)
}
onChange(e)
}
return (
<Select
value={value}
style={{ width: '100%' }}
options={options}
onChange={selectChange}
/>
)
}
export default SoruceType
\ No newline at end of file
import React from 'react'
import { Input, Select } from 'antd'
import Form from 'antd/es/form/Form'
const TableAndField = (props) => {
const { value, onChange } = props
const selectChange = (value) => {
onChange(value)
}
const inputChange = (e) => {
onChange(e.target.value)
}
return (
<Form
labelCol={{
span: 8,
}}
wrapperCol={{
span: 16,
}}
>
<Form.Item
label='表名'
name='tableName'
rules={[
{
required: true,
message: '请输入表名',
}
]}
>
<Input style={{ width: '100%' }} />
</Form.Item>
<Form.Item
label='字段名'
name='fieldName'
rules={[
{
required: true,
message: '请输入字段名',
}
]}
>
<Input />
</Form.Item>
</Form>
)
}
export default TableAndField
\ No newline at end of file
import React, { useMemo, useState } from 'react'
import { Select } from 'antd'
import { LoadTableV2, LoadLedgers } from '../../../../../apis/process'
const TableName = (props) => {
const { value, onChange } = props
const [groupNames, setGroupNames] = useState([])
const [data, setData] = useState([])
const options = useMemo(() => {
let array = []
if (Array.isArray(groupNames)) {
groupNames.forEach(v => {
let options = Array.isArray(data) ? data.filter(s => s.groupNames === v.groupName) : []
array.push({
label: v,
options: options.map(s => { return { label: s.tableName, value: s.tableName } })
})
})
}
return array
}, [groupNames, data])
const onFocus = async () => {
const { code, data } = await LoadTableV2()
if (code === 0) {
setGroupNames(data.groupNames)
setData(data.root)
} else {
message.error('请求错误!')
}
}
const selectChange = (value) => {
onChange(value)
}
return (
<Select
value={value}
options={options}
onFocus={onFocus}
onChange={selectChange}
showSearch
>
</Select>
)
}
export default TableName
\ No newline at end of file
import Dictionary from './Dictionary'
import TableAndField from './TableAndField'
import AccountName from './AccountName'
import Fieldshine from './Fieldshine'
import MappedField from './MappedField'
import ControlShow from './ControlShow'
import SoruceType from './SoruceType'
import TableName from './TableName'
import FieldName from './FieldName'
const groupSource = {
Dictionary,
TableAndField,
AccountName,
Fieldshine,
MappedField,
ControlShow,
SoruceType,
TableName,
FieldName,
}
export default groupSource
\ No newline at end of file
import React from 'react'
import { Input, Popover } from 'antd'
import React, { useEffect, useContext } from 'react'
import { Input, Popover, ConfigProvider } from 'antd'
import { QrcodeOutlined } from '@ant-design/icons'
import QRcode from 'qrcode.react'
import './index.less'
const Coding = (props) => {
const { value, onChange } = props
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext)
const prefixCls = getPrefixCls('pandaXform')
const { value, onChange, schema, addons } = props
const { disabled } = schema
const inputChange = (e) => {
if (addons) {
onChange(e.target.value)
}
}
const content = (
<div>
{/* <QRcode value={<div style={{ color: 'red' }}>123</div>} /> */}
<QRcode src='https://www.runoob.com/w3cnote/javascript-qrcodejs-library.html' />
<QRcode value={value} />
</div>
)
return (
<div>
<div className={`${prefixCls}-input`} isdisabled={JSON.stringify(disabled)}>
<Input
onChange={inputChange}
disabled={disabled}
addonAfter={
<Popover content={content}>
<QrcodeOutlined />
</Popover>
}
onChange={e => onChange(e.target.value)}
/>
</div>
)
......
@import '~antd/es/style/themes/default.less';
@pandaXform: ~'@{ant-prefix}-pandaXform';
.@{pandaXform} {
.@{pandaXform}-input[isdisabled='true'] {
.@{ant-prefix}-input-group-addon {
border: 1px solid #e9e9e9;
}
}
}
\ No newline at end of file
/**
* @Description: QRCode 使用传入的值生成二维码
* @Params: 参数描述
* @Date: 2021/12/3
* @Author: ChenLong
* */
import React, { useState } from 'react';
import { Input } from 'antd';
import QR from 'qrcode.react';
import './index.less'
const QRCode = ({ schema }) => {
const [show, setShow] = useState(false)
return (
<div className='QRCode'>
<Input
disabled={schema.disabled}
value={schema.default}
onFocus={() => setShow(true)}
onBlur={() => setShow(false)}
/>
<div className='QRCode-img' style={{ display: show ? 'block' : 'none' }}>
{
schema.default ? <QR value={schema.default} /> : null
}
</div>
</div>
);
};
export default QRCode;
.QRCode {
position: relative;
.QRCode-img {
position: absolute;
z-index: 99;
}
}
\ No newline at end of file
import React, { useState, useEffect, useMemo } from 'react'
import { Input, message } from 'antd'
import React, { useState, useEffect, useMemo, useContext } from 'react'
import { Input, message, ConfigProvider } from 'antd'
import Icon, { EllipsisOutlined } from '@ant-design/icons'
import * as icons from '@ant-design/icons'
import { GetFieldValueFromTable } from '../../../../apis/process'
import './index.less'
const iconList = Object.keys(icons).filter((item) => typeof icons[item] === 'object')
......@@ -23,7 +24,8 @@ const debounce = (fn) => {
const TextInput = (props) => {
const userInfo = window?.globalConfig?.userInfo || { fullName: '【本人姓名】', depart: { name: '【本人部门】' } }
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext)
const prefixCls = getPrefixCls('pandaXform')
const { value, onChange, schema, addons } = props
const { title, disabled, placeholder, presetValue, addonBefore, addonAfter, maxLength, rules, uniqueVerify, tableName, fieldName } = schema
......@@ -73,15 +75,17 @@ const TextInput = (props) => {
}, [uniqueVerify, tableName, fieldName])
return (
<Input
disabled={disabled}
value={value}
maxLength={maxLength}
placeholder={disabled ? null : placeholder}
onChange={handleChange}
addonBefore={iconList.includes(addonBefore) ? <Icon component={icons[addonBefore]} /> : addonBefore}
addonAfter={iconList.includes(addonAfter) ? <Icon component={icons[addonAfter]} /> : addonAfter}
/>
<div className={`${prefixCls}-input`} isdisabled={JSON.stringify(disabled)}>
<Input
disabled={disabled}
value={value}
maxLength={maxLength}
placeholder={disabled ? null : placeholder}
onChange={handleChange}
addonBefore={iconList.includes(addonBefore) ? <Icon style={{ color: 'pink' }} component={icons[addonBefore]} /> : addonBefore}
addonAfter={iconList.includes(addonAfter) ? <Icon component={icons[addonAfter]} /> : addonAfter}
/>
</div>
)
}
......
@import '~antd/es/style/themes/default.less';
@pandaXform: ~'@{ant-prefix}-pandaXform';
.@{pandaXform} {
.@{pandaXform}-input[isdisabled='true'] {
.@{ant-prefix}-input-group-addon {
border: 1px solid #e9e9e9;
}
}
}
\ No newline at end of file
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