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

fix: 增加批量操作一些属性

parent b94a57d2
{
"name": "panda-xform",
"version": "4.1.9",
"description": "4.1.9 选项筛选表头优化",
"version": "4.2.0",
"description": "4.2.0 增加批量操作一些属性",
"keywords": [
"panda-xform"
],
......@@ -39,6 +39,7 @@
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-file-viewer": "^1.2.1",
"react-resizable": "^3.0.5",
"react-sign2": "^0.0.3",
"react-svg": "15.1.9",
"viewerjs": "^1.11.3",
......@@ -129,4 +130,4 @@
"publishConfig": {
"registry": "https://g.civnet.cn:4873"
}
}
\ No newline at end of file
}
......@@ -252,6 +252,14 @@ export function EditTableDataInfo(data) {
});
}
export function BatchEditTableDataInfo(data) {
return request({
url: `${BASEURL}/BatchEditTableDataInfo`,
method: 'post',
data,
});
}
export function DeleteTableDataInfo(data) {
return request({
url: `${BASEURL}/DeleteTableDataInfo`,
......
import React, { useState, useImperativeHandle, forwardRef, useMemo, useRef } from 'react'
import { Select, message } from 'antd'
import Drag from '../../../components/Drag'
import FormRender from '../../../FormRender'
import { isJson, isObject } from '../../../../utils/index'
import { BatchEditTableDataInfo } from '../../../../apis/process'
const BatchEdit = (props, ref) => {
useImperativeHandle(ref, () => ({
open,
}))
const { config } = props
const { editFieldGroup, formJson } = config
const [value, setValue] = useState('')
const [params, setParams] = useState({ accountTable: '', id: '' })
const [visible, setVisible] = useState(false)
const [confirmLoading, setConfirmLoading] = useState(false)
const formRenderRef = useRef()
const filedArr = useMemo(() => {
let array = editFieldGroup ? editFieldGroup.split(',').filter(v => v) : []
setValue(array.length ? array[0] : '')
return array
}, [editFieldGroup])
const schemaValues = useMemo(() => {
let properties = {}
let schema = formJson.properties
if (isObject(schema)) {
Object.keys(schema).forEach(v => {
if (isObject(schema[v]?.properties)) {
Object.keys(schema[v].properties).forEach(s => {
if (s === value) {
properties = {
[v]: {
...schema[v],
properties: {
[s]: schema[v].properties[s]
}
}
}
}
})
}
})
}
return {
formJson: {
...formJson,
column: 1,
properties: properties
},
values: []
}
}, [editFieldGroup, formJson, value])
const onSelect = (value) => {
setValue(value)
}
const open = (values) => {
setParams(values)
setVisible(true)
}
const onOk = async () => {
setConfirmLoading(true)
const { formValue, errors } = await formRenderRef.current.getValues()
if (errors.length) {
return message.error('请完善表单内容')
}
const { code, data, msg } = await BatchEditTableDataInfo({ ...params, values: formValue })
if (code === 0) {
message.success('批量修改成功!')
setVisible(false)
props.onOk && props.onOk()
} else {
message.error(msg)
}
setConfirmLoading(false)
}
return (
<Drag
width={700}
title='批量修改'
visible={visible}
bodyStyle={{ height: '300px', overflow: 'auto' }}
onOk={onOk}
onCancel={() => setVisible(false)}
confirmLoading={confirmLoading}
getContainer={false}
destroyOnClose
>
<div style={{ display: 'flex', alignItems: 'center' }}>
列字段选择:
<Select
style={{ minWidth: '250px' }}
placeholder='请选择字段'
showArrow
showSearch
value={value}
onSelect={onSelect}
>
{filedArr.map(v => <Select.Option key={v} value={v}>{v}</Select.Option>)}
</Select>
</div>
<div style={{ marginTop: '10px' }}>
<FormRender schemaValues={schemaValues} ref={formRenderRef} />
</div>
</Drag>
)
}
export default forwardRef(BatchEdit)
\ No newline at end of file
import React, { useCallback, useEffect, useMemo, useRef, useState, forwardRef, useImperativeHandle } from 'react';
import { AudioOutlined } from '@ant-design/icons';
import {
Row,
DatePicker,
......@@ -19,10 +18,8 @@ import {
Popover,
Form,
} from 'antd';
import 'dayjs/locale/zh-cn';
import locale from 'antd/es/date-picker/locale/zh_CN';
import {
SnippetsOutlined,
PlusOutlined,
......@@ -41,6 +38,7 @@ import {
} from '@ant-design/icons';
import styles from './search.less';
import moment from 'moment';
const { Search } = Input;
const { RangePicker } = DatePicker;
const { Option } = Select;
......@@ -51,22 +49,13 @@ const SearchGroup = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
getQueryInfo,
}));
const { readOnly } = props
const [form] = Form.useForm();
const [showPicker, setShowPicker] = useState(true);
const [dateArray, setDateArray] = useState([
// moment(moment().format('YYYY-MM-DD 00:00:00')).subtract(1, 'years'),
// moment(moment().format('YYYY-MM-DD 23:59:59')),
]);
const [formatterStr, setFormatterStr] = useState('YYYY-MM-DD HH:mm:ss');
const [searchValues, setSearchValues] = useState('');
// const [queryWheres, setQueryWheres] = useState([
// props.params.tempQueryWhere || {},
// ])
const [queryWheres, setQueryWheres] = useState([{}]);
const [searchKey, setSearchKey] = useState(''); // 快速搜索字段名称
const [queryInfo, setQueryInfo] = useState({ info: '', timeFrom: '', timeTo: '' });
const { readOnly } = props
const [form] = Form.useForm()
const [showPicker, setShowPicker] = useState(true)
const [dateArray, setDateArray] = useState([])
const [formatterStr, setFormatterStr] = useState('YYYY-MM-DD HH:mm:ss')
const [queryInfo, setQueryInfo] = useState({ info: '', timeFrom: '', timeTo: '' })
const rangerOptions = useMemo(() => {
const todayRanger = [
......@@ -163,34 +152,49 @@ const SearchGroup = forwardRef((props, ref) => {
30: last30DaysRanger,
近一年: lastOneYearRanger,
};
}, []);
const dateChange = (dateObj, dateString) => {
setDateArray(dateObj || ['', '']);
setQueryInfo({
...queryInfo,
timeFrom: dateObj[0].format('YYYY-MM-DD HH:mm:ss') || '',
timeTo: dateObj[1].format('YYYY-MM-DD HH:mm:ss') || '',
});
};
}, [])
const batchMenu = [
{
label: (
<Button
style={{ width: '100%', textAlign: 'left' }}
size='middle'
type='text'
onClick={() => btnsClick('批量删除')}
icon={<DeleteOutlined />}
>
批量删除
</Button>
),
key: '批量删除',
},
{
label: (
<Button
style={{ width: '100%', textAlign: 'left' }}
size='middle'
type='text'
onClick={() => btnsClick('批量修改')}
icon={<EditOutlined />}
>
批量修改
</Button>
),
key: '批量修改',
}
];
const onSearch = e => {
// if (fieldSearch) {
// setQueryWheres([{
// "field": searchKey,
// "value": e,
// "type": "模糊查询"
// }])
// } else {
// getAccountData();
// }
setQueryInfo({ ...queryInfo, info: e });
getQueryInfo(form.getFieldsValue());
};
}
const onValuesChange = values => {
let keys = Object.keys(values);
if (keys.includes('info')) return;
getQueryInfo(form.getFieldsValue());
};
}
const getQueryInfo = data => {
let params = {};
......@@ -251,6 +255,17 @@ const SearchGroup = forwardRef((props, ref) => {
{/* 按钮区域 */}
<div className={styles.controlRowRight}>
<div className={styles.controlBtns}>
{
!readOnly ? (
<Dropdown.Button
style={{ marginLeft: '20px' }}
icon={<DownOutlined />}
overlay={<Menu items={batchMenu} />}
>
批量操作
</Dropdown.Button>
) : null
}
{
!readOnly ? (
<Button
......
import React, { useState } from 'react'
import { Resizable } from 'react-resizable'
import './index.less'
import classnames from 'classnames'
const ResizeableTitle = (props) => {
const { onResize, width, onClick, ...restProps } = props
const [resizing, setResizing] = useState(true)
const [offset, setOffset] = useState(0)
return (
<Resizable
width={width + offset}
height={0}
handle={
<span
// 有偏移量显示竖线
className={classnames(['react-resizable-handle', offset && 'active'])}
// 拖拽层偏移
style={{ transform: `translateX(${offset}px)` }}
onClick={(e) => {
// 取消冒泡,不取消貌似容易触发排序事件
e.stopPropagation()
e.preventDefault()
}}
/>
}
onResize={(e, { size }) => {
// 这里只更新偏移量,数据列表其实并没有伸缩
setOffset(size.width - width)
}}
onResizeStart={() => setResizing(true)}
onResizeStop={(...arg) => {
setTimeout(() => {
setResizing(false)
}, 0)
// 拖拽结束以后偏移量归零
setOffset(0)
// 这里是props传进来的事件,在外部是列数据中的onHeaderCell方法提供的事件,请自行研究官方提供的案例
onResize(...arg)
}}
draggableOpts={{ enableUserSelectHack: false }}
>
<th
onClick={(...args) => {
if (!resizing && onClick) {
onClick(...args)
}
}}
{...restProps}
/>
</Resizable>
)
}
export default ResizeableTitle
\ No newline at end of file
.react-resizable {
position: relative;
background-clip: padding-box;
}
.react-resizable-handle {
position: absolute;
width: 5px;
height: 100%;
bottom: 0;
right: -2.5px;
cursor: col-resize;
z-index: 1;
&:hover {
width: 10px;
right: -5px;
background: #0e98ed;
z-index: 999;
}
}
\ No newline at end of file
import React, { useMemo, useState, useRef, forwardRef, useImperativeHandle } from 'react'
import { Table, Tooltip, Button, Popconfirm, Input, Space, useTable } from 'antd'
import { SearchOutlined } from '@ant-design/icons'
import ResizeableTitle from './components/ResizeableTitle'
import FileView from './components/FileView'
import CoordView from './components/CoordView'
import SelectView from './components/SelectView'
......@@ -31,6 +32,7 @@ const TablePack = (props, ref) => {
}))
const { parent, readOnly, config, fieldList, loading, dataSource, rowSelection, onRow, tableChange, btnsClick } = props
const [fieldResize, setFieldResize] = useState({})
const [filteredInfo, setFilteredInfo] = useState({})
const [sortedInfo, setSortedInfo] = useState({})
const inputRef = useRef()
......@@ -138,17 +140,24 @@ const TablePack = (props, ref) => {
}
let json = getFileInfo(formJson)
let array = []
showField.forEach(v => {
const { widget } = json[v]
showField.forEach((v, i) => {
const { widget } = json?.[v] || {}
console.log('json', json, v)
array.push({
title: json[v]?.title || v,
dataIndex: v,
width: 120,
width: fieldResize[v] || 120,
ellipsis: true,
sorter: true,
sortOrder: sortedInfo.columnKey === v ? sortedInfo.order : null,
filteredValue: filteredInfo[v] || null,
...getColumnSearchProps(json[v], v),
onHeaderCell: (column) => ({
width: column.width,
onResize: (e, props) => {
setFieldResize({ ...fieldResize, [v]: props?.size?.width })
},
}),
render: (value, r) => {
let props = { ...json[v], value }
if (widget === 'FileUpload') {
......@@ -167,7 +176,7 @@ const TablePack = (props, ref) => {
})
})
return array
}, [config, fieldList, filteredInfo, sortedInfo])
}, [config, fieldList, fieldResize, filteredInfo, sortedInfo])
const columns = useMemo(() => {
let columns = [
......@@ -233,7 +242,6 @@ const TablePack = (props, ref) => {
}, [parent, btns, fileColumns])
const onChange = (page, filters, sorter) => {
console.log('filters', filters)
setFilteredInfo(filters)
setSortedInfo({ order: sorter.order, columnKey: sorter.field })
tableChange(page, filters, sorter)
......@@ -250,8 +258,13 @@ const TablePack = (props, ref) => {
rowSelection={rowSelection}
onRow={onRow}
pagination={false}
scroll={{ y: 'calc(100% - 40px)' }}
scroll={{ x: '100%', y: 'calc(100% - 40px)' }}
onChange={onChange}
components={{
header: {
cell: ResizeableTitle
}
}}
/>
)
......
import React, { useEffect, useMemo, useRef, useState } from 'react'
import styles from './index.less'
import { Table, Tooltip, message, Button, Pagination, Popconfirm, Space, Input } from 'antd'
import { message, Button, Pagination, Modal } from 'antd'
import { ExclamationCircleOutlined } from '@ant-design/icons'
import SearchGroup from './components/SearchGroup'
import TablePack from './components/TablePack'
import BatchEdit from './components/BatchEdit'
import {
GetAccountConfigInfo,
GetAccountPageList,
getStationListByUserID,
GetTableJson,
GetTableDataInfo,
EditTableDataInfo,
SaveTableDataInfo,
......@@ -38,8 +39,10 @@ const Account = (props) => {
const [schemaValues, setSchemaValues] = useState({ formJson: {}, values: [] })
const [submitLoading, setSubmitLoading] = useState(false)
const [operation, setOperation] = useState({ id: null, state: '添加' })
const [keys, setKeys] = useState([])
const formRenderRef = useRef()
const tablePackRef = useRef()
const batchEditRef = useRef()
const btnsClick = async (type, id) => {
const { addFieldGroup, editFieldGroup, formJson } = config
......@@ -72,6 +75,36 @@ const Account = (props) => {
message.error(msg)
}
}
if (type === '批量删除') {
if (!keys.length) {
return message.info('请勾选要删除的数据!')
}
Modal.confirm({
icon: <ExclamationCircleOutlined />,
content: '确定要批量删除数据吗?',
okText: '确认',
cancelText: '取消',
onOk: async () => {
return await new Promise(async (resolve, reject) => {
const { code, data, msg } = await DeleteTableDataInfo({ accountTable: accountName, ids: keys.join(',') })
if (code === 0) {
message.success('批量删除成功!')
getDataSource()
resolve()
} else {
message.error(msg)
reject()
}
})
},
})
}
if (type === '批量修改') {
if (!keys.length) {
return message.info('请勾选要修改的数据!')
}
batchEditRef.current.open({ accountTable: accountName, id: keys.join(','), })
}
}
const saveClick = (addField, formJson, values, type) => {
......@@ -114,7 +147,8 @@ const Account = (props) => {
const { type, id } = operation
setSubmitLoading(true)
if (type === '添加') {
const { code, data } = await SaveTableDataInfo({ accountTable: accountName, id: operation.id, values: formValue })
let params = { accountTable: accountName, id: operation.id, values: formValue, relationForm }
const { code, data } = await SaveTableDataInfo(params)
if (code === 0) {
message.success('保存成功!')
setSubmitLoading(false)
......@@ -123,7 +157,8 @@ const Account = (props) => {
}
}
if (type === '编辑') {
const { code, data } = await EditTableDataInfo({ accountTable: accountName, id: operation.id, values: formValue })
let params = { accountTable: accountName, id: operation.id, values: formValue, relationForm }
const { code, data } = await EditTableDataInfo(params)
if (code === 0) {
message.success('修改成功!')
setSubmitLoading(false)
......@@ -148,7 +183,6 @@ const Account = (props) => {
setLoading(true)
const { code, data, msg } = await GetAccountPageList({ ...params, ...param })
if (code === 0) {
console.log(1, isJson(data.jsonData) ? JSON.parse(data.jsonData) : [])
setDataSource(isJson(data.jsonData) ? JSON.parse(data.jsonData) : [])
setParams({ ...params, ...param, total: data.totalCount, pageIndex: data.pageIndex, pageSize: data.pageSize })
} else {
......@@ -183,6 +217,11 @@ const Account = (props) => {
getDataSource(param)
}
const batchEditOk = () => {
setKeys([])
getDataSource()
}
useEffect(() => {
getData()
}, [])
......@@ -204,6 +243,12 @@ const Account = (props) => {
readOnly={readOnly}
config={config}
dataSource={dataSource}
rowSelection={{
type: 'checkbox',
selectedRowKeys: keys,
fixed: 'left',
onChange: (keys) => setKeys(keys)
}}
btnsClick={btnsClick}
tableChange={tableChange}
ref={tablePackRef}
......@@ -222,6 +267,7 @@ const Account = (props) => {
/>
</div>
</div>
<BatchEdit config={config} ref={batchEditRef} onOk={batchEditOk} />
</div>
{
detailShow ? (
......
......@@ -41,6 +41,17 @@
.@{ant-prefix}-table-thead>tr {
height: 40px;
th {
overflow: inherit;
user-select: none;
/* Chrome and Opera */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
border-right: 1px solid #dbe7fb!important;
border-bottom: 1px solid #dbe7fb;
background: white;
......
......@@ -18,7 +18,7 @@ const AccountSelector = (props) => {
const [params, setParams] = useState(initParams)
const [loading, setLoading] = useState(false)
const [dataSource, setDataSource] = useState([])
const [config, setConfig] = useState({ webShowFieldGroup: '' })
const [config, setConfig] = useState({ webShowFieldGroup: '', addFieldGroup: '', formJson: {} })
const [visible, setVisible] = useState(false)
const [keys, setKeys] = useState([])
const tablePackRef = useRef(null)
......@@ -26,16 +26,13 @@ const AccountSelector = (props) => {
const iconClick = () => {
if (addons) {
if (!accountName) {
return message.info('请配置台账名称!');
return message.info('请配置台账名称!')
}
if (!fieldshine.length) {
return message.info('请配置映射字段!');
return message.info('请配置映射字段!')
}
setVisible(true);
if (!config.webShowFieldGroup) {
getConfig();
}
getDataSource();
setVisible(true)
getDataSource()
}
}
......@@ -163,9 +160,10 @@ const AccountSelector = (props) => {
useEffect(() => {
if (addons) {
addons.setValue(addons.dataPath, presetValue);
addons.setValue(addons.dataPath, presetValue)
getConfig()
} else {
onChange(presetValue);
onChange(presetValue)
}
}, [presetValue])
......
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