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

fix: 关联表单增加可编辑状态与台账导入

parent bcc1f503
{
"name": "panda-xform",
"version": "5.0.6",
"description": "5.0.6 详情状态下只读取值不读取配置",
"version": "5.0.7",
"description": "5.0.7 关联表单增加可编辑状态与台账导入",
"keywords": [
"panda-xform"
],
......
import React, { useMemo, useState, forwardRef, useImperativeHandle, useRef } from 'react'
import { Table, Button, Popconfirm, Input, Space, Tag, Popover, Checkbox } from 'antd'
import { Table, Button, Popconfirm, Input, Space, Tag, Popover, Checkbox, Form } from 'antd'
import { TweenOneGroup } from 'rc-tween-one'
import styles from './index.less'
import { SearchOutlined, FormOutlined } from '@ant-design/icons'
......@@ -19,7 +19,7 @@ const TablePack = (props, ref) => {
fileColumns,
}))
const { notUse, config, fieldList, loading, dataSource, rowSelection, onRow, tableChange, btnsClick } = props
const { notUse, config, fieldList, loading, dataSource, sourceChange, rowSelection, onRow, tableChange, btnsClick, isEdit } = props
const { accountFieids, webShowFieldGroup, formJson, parent } = config
const [fieldResize, setFieldResize] = useState({})
const [filteredInfo, setFilteredInfo] = useState({})
......@@ -27,6 +27,7 @@ const TablePack = (props, ref) => {
const [open, setOpen] = useState(false)
const [checks, setChecks] = useState([])
const searchInput = useRef(null)
const [form] = Form.useForm()
const filtered = useMemo(() => {
let array = []
......@@ -126,7 +127,7 @@ const TablePack = (props, ref) => {
setFieldResize({ ...fieldResize, [fieldName]: props?.size?.width })
},
}),
render: (value, r) => {
render: (value, record) => {
let props = { ...json[fieldName], value }
if (widget === 'FileUpload') {
return <FileView {...props} />
......@@ -143,7 +144,7 @@ const TablePack = (props, ref) => {
}
//关联表单表头
const getRelevanceColumnProps = (json, field) => {
const getRelevanceColumnProps = (json, field, isEdit = false) => {
const { fieldName, columnWidth, isSort, accurateSearch } = field
const { widget } = json?.[fieldName] || {}
let searchProps = {}
......@@ -226,19 +227,25 @@ const TablePack = (props, ref) => {
setFieldResize({ ...fieldResize, [fieldName]: props?.size?.width })
},
}),
render: (value, r) => {
let props = { ...json[fieldName], value }
if (widget === 'FileUpload') {
return <FileView {...props} />
}
if (['Coordinate', 'Device', 'DrawPath', 'DrawArea'].includes(widget)) {
return <CoordView {...props} />
}
if (['RadioButton', 'CheckBox'].includes(widget)) {
return <SelectView {...props} />
render: (value, record) => {
if (isEdit) {
return (
<Input onChange={(e) => btnsClick({ type: '变化', row: { ...record, [fieldName]: e.target.value } })} value={value} />
)
} else {
let props = { ...json[fieldName], value }
if (widget === 'FileUpload') {
return <FileView {...props} />
}
if (['Coordinate', 'Device', 'DrawPath', 'DrawArea'].includes(widget)) {
return <CoordView {...props} />
}
if (['RadioButton', 'CheckBox'].includes(widget)) {
return <SelectView {...props} />
}
return <Text text={value} />
}
return <Text text={value} />
}
},
}
}
......@@ -282,13 +289,13 @@ const TablePack = (props, ref) => {
let array = []
showField.forEach((v, i) => {
if (parent === '关联表单') {
array.push(getRelevanceColumnProps(json, v))
array.push(getRelevanceColumnProps(json, v, isEdit))
} else {
array.push(getColumnProps(json, v))
}
})
return array
}, [parent, formJson, showField, fieldResize, filteredInfo, sortedInfo])
}, [parent, formJson, showField, fieldResize, filteredInfo, sortedInfo, isEdit, dataSource])
const showColumns = useMemo(() => {
return fileColumns.filter(v => checks.includes(v.dataIndex))
......@@ -328,7 +335,7 @@ const TablePack = (props, ref) => {
if (btns.length) {
columns.push(
{
title: (
title: isEdit ? '操作' : (
<div className={styles.operation}>
<span>操作</span>
<span className={styles.operationSpan}>
......@@ -355,7 +362,7 @@ const TablePack = (props, ref) => {
</span>
</div>
),
width: btns.length * 35 + 30,
width: isEdit ? 75 : btns.length * 35 + 30,
align: 'center',
filteredValue: null,
fixed: 'right',
......@@ -363,7 +370,7 @@ const TablePack = (props, ref) => {
return (
<div style={{ display: 'flex', justifyContent: 'center' }}>
{
btns.map(v => {
(isEdit ? [{ title: '删除', icon: <IconPack.ShanChu /> }] : btns).map(v => {
if (v.title === '删除') {
return (
<Popconfirm
......@@ -405,7 +412,7 @@ const TablePack = (props, ref) => {
return fileColumns
}
return columns
}, [parent, btns, dataSource, fileColumns, checks, open])
}, [parent, btns, dataSource, fileColumns, checks, open, isEdit])
const onChange = (page, filters, sorter) => {
setFilteredInfo(filters)
......@@ -476,24 +483,26 @@ const TablePack = (props, ref) => {
</div>
) : null
}
<Table
size='small'
rowKey='ID'
bordered
loading={loading}
columns={columns}
dataSource={dataSource}
rowSelection={rowSelection}
onRow={onRow}
pagination={parent === '关联表单' ? { total: dataSource.length, showTotal: (value) => `总计 ${value} 条` } : false}
scroll={{ x: '100%', y: 'calc(100% - 40px)' }}
onChange={onChange}
components={{
header: {
cell: ResizeableTitle
}
}}
/>
<Form form={form} component={false}>
<Table
size='small'
rowKey='ID'
bordered
loading={loading}
columns={columns}
dataSource={dataSource}
rowSelection={rowSelection}
onRow={onRow}
pagination={parent === '关联表单' ? { total: dataSource.length, showTotal: (value) => `总计 ${value} 条` } : false}
scroll={{ x: '100%', y: 'calc(100% - 40px)' }}
onChange={onChange}
components={{
header: {
cell: ResizeableTitle
},
}}
/>
</Form>
</div>
)
......
......@@ -2583,11 +2583,19 @@ const advancedWidgets = [
displayType: 'row',
labelWidth: 80,
},
// otherAccount: {
// title: '数据来源',
// type: 'string',
// widget: 'OtherAccount',
// },
isEdit: {
title: '表格可编辑',
description: '表格字段变为可编辑与添加字段集',
type: 'boolean',
widget: 'BooleanSwitch',
default: false,
},
otherSource: {
title: '数据来源',
type: 'object',
widget: 'OtherSource',
dependencies: ['台账名称']
},
disabled: {
title: '只读',
type: 'boolean',
......
......@@ -6,11 +6,52 @@
height: 45px;
line-height: 45px;
position: relative;
text-align: center;
.headerBtn {
.text {
text-align: center;
}
.btns {
position: absolute;
top: 0;
right: 0;
top: 7px;
}
}
.content {
width: 100%;
height: 100%;
position: relative;
padding-bottom: 40px;
.top {
width: 100%;
height: 50px;
}
.bottom {
width: 100%;
height: calc(100% - 50px);
.@{ant-prefix}-table-wrapper {
height: 100%;
.@{ant-prefix}-spin-nested-loading {
height: 100%;
}
.@{ant-prefix}-spin-container {
height: 100%;
}
.@{ant-prefix}-table {
height: 100%;
.@{ant-prefix}-table-container {
height: 100%;
}
}
}
}
.footer {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
}
}
}
\ No newline at end of file
......@@ -22,10 +22,22 @@ const initConfig = {
const AccountSelector = (props) => {
const userID = window?.globalConfig?.userInfo?.OID || 1
const codes = window?.pandaXform?.codes || { 工单编号: '', 事件编号: '', }
const { value, onChange, schema, addons } = props
const { disabled, accountName, fieldshine, siteFilter, sql, isMultiple, presetValue, placeholder, fieldList } = schema
const initParams = { user: userID, accountName, sortFields: '录入时间', direction: 'desc', total: 0, pageIndex: 1, pageSize: 100, siteFilter }
const initParams = {
user: userID,
accountName,
extendQuery: {
caseNo: codes['工单编号']
},
sortFields: '录入时间',
direction: 'desc',
total: 0,
pageIndex: 1,
pageSize: 100,
siteFilter
}
const [params, setParams] = useState(initParams)
const [loading, setLoading] = useState(false)
const [dataSource, setDataSource] = useState([])
......
import React, { useState } from 'react'
import { Form, Input, Select, Space, Button, TreeSelect } from 'antd'
import styles from './index.less'
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'
import Drag from '../../../../components/Drag'
import { LoadLedgers, QueryFields, ReloadTableFields } from '../../../../../apis/process'
const { TreeNode } = TreeSelect
const OtherSource = (props) => {
const { addons, onChange, value } = props
const { '台账名称': accountName } = addons?.formData || {}
const [visible, setVisible] = useState(false)
const [options, setOptions] = useState([])
const [fromField, setFromField] = useState([])
const [toField, setToField] = useState([])
const [form] = Form.useForm()
const toFieldFocus = async () => {
const { code, data } = await QueryFields(accountName)
if (code === 0) {
setToField(data)
}
}
const fromFieldFocus = async () => {
const { accountName } = form.getFieldsValue()
const { code, data } = await QueryFields(accountName)
if (code === 0) {
setFromField(data)
}
}
const focusSelect = async () => {
const { code, data, msg } = await LoadLedgers()
if (code === 0) {
if (Array.isArray(data.root)) {
setOptions(data.root)
} else {
setOptions([])
}
} else {
message.error(msg)
}
}
const onOk = () => {
setVisible(true)
const values = form.getFieldsValue()
onChange(values)
setVisible(false)
}
const inputClick = () => {
setVisible(true)
form.setFieldsValue(value)
}
return (
<div className={styles.otherSource}>
<Input value={value ? JSON.stringify(value) : ''} onClick={inputClick} />
<Drag
onOk={onOk}
onCancel={() => setVisible(false)}
title={'数据来源'}
visible={visible}
>
<Form form={form} autoComplete='off'>
<Form.Item
label={'台账名称'}
name={'accountName'}
>
<Select showSearch allowClear onFocus={focusSelect} onChange={() => form.setFieldsValue({ ...form.getFieldsValue(), field: [] })}>
{
options.map(v => {
return (
<Select.Option key={v.name} value={v.name}>{v.name}</Select.Option>
)
})
}
</Select>
</Form.Item>
<Form.List name="field" label='字段映射'>
{(value, { add, remove }) => (
<>
{value.map(({ key, name, ...restField }, index) => (
<Space
key={key}
style={{
display: 'flex',
marginBottom: '5px',
justifyContent: 'center',
position: 'relative',
left: index === 0 ? '-11px' : '',
}}
align='baseline'
>
<Form.Item
{...restField}
name={[name, 'fromField']}
rules={[
{
required: true,
message: '来源字段必填',
}
]}
>
<TreeSelect
showSearch
style={{ width: '180px' }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
placeholder="请选择字段名 "
allowClear
treeDefaultExpandAll
showCheckedStrategy
onFocus={fromFieldFocus}
>
{fromField.map(s => <TreeNode value={s} title={s} key={s} />)}
</TreeSelect>
</Form.Item>
<div className={styles.centerImg}></div>
<Form.Item
{...restField}
name={[name, 'toField']}
rules={[
{
required: true,
message: '目标字段必填',
},
{
validator: (rules, value, callback) => {
const { field } = form.getFieldsValue()
let toFields = Array.from(new Set([...field.map(v => v.toField)]))
if (toFields.length !== field.length) {
return Promise.reject('目标字段不能重复!')
}
return Promise.resolve()
}
}
]}
>
<TreeSelect
showSearch
style={{ width: '180px' }}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
placeholder="请选择字段名 "
allowClear
treeDefaultExpandAll
showCheckedStrategy
onFocus={toFieldFocus}
>
{toField.map(s => <TreeNode value={s} title={s} key={s} />)}
</TreeSelect>
</Form.Item>
<Form.Item
hidden={true}
{...restField}
name={[name, 'layerName']}
>
<Input />
</Form.Item>
<MinusCircleOutlined onClick={() => remove(name)} />
</Space>
))}
<Form.Item style={{ padding: '0 10px' }}>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
添加映射
</Button>
</Form.Item>
</>
)}
</Form.List>
</Form>
</Drag>
</div>
)
}
export default OtherSource
\ No newline at end of file
@imgSrc: '../../../../../assets/images/settting';
.otherSource {
.centerImg {
width: 24px;
height: 24px;
background: url('@{imgSrc}/值映射.png');
background-size: 100% 100%;
position: relative;
top: 7px;
}
}
\ No newline at end of file
......@@ -8,6 +8,7 @@ const fnList = [
{ label: '本人ID', value: '$本人ID' },
{ label: '本人部门', value: '$本人部门' },
{ label: '本人部门ID', value: '$本人部门ID' },
{ label: '本表单工单编号', value: '$本表单工单编号' },
]
const SqlFilter = (props) => {
......
......@@ -14,6 +14,7 @@ import AddressSync from './AddressSync'
import CoordSync from './CoordSync'
import SimpleList from './SimpleList'
import SqlFilter from './SqlFilter'
import OtherSource from './OtherSource'
const groupSource = {
Dictionary,
......@@ -32,6 +33,7 @@ const groupSource = {
CoordSync,
SimpleList,
SqlFilter,
OtherSource,
}
export default groupSource
\ 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