|
@@ -0,0 +1,484 @@
|
|
|
+
|
|
|
+
|
|
|
+import React, { useState, useEffect, useRef, useImperativeHandle } from 'react';
|
|
|
+import { Drawer, Form, Button, Input, Divider, Table, Popconfirm, Select,Alert } from 'antd';
|
|
|
+
|
|
|
+import {commitTemplateData,editTemplateData} from '@/api/generalSetting.js'
|
|
|
+import './style.less';
|
|
|
+
|
|
|
+const { TextArea } = Input;
|
|
|
+
|
|
|
+const { Option } = Select;
|
|
|
+
|
|
|
+const EditableContext = React.createContext();
|
|
|
+
|
|
|
+const EditableRow = ({ form, index, ...props }) => (
|
|
|
+ <EditableContext.Provider value={form}>
|
|
|
+ <tr {...props} />
|
|
|
+ </EditableContext.Provider>
|
|
|
+);
|
|
|
+
|
|
|
+const EditableFormRow = Form.create()(EditableRow);
|
|
|
+
|
|
|
+class EditableCell extends React.Component {
|
|
|
+
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+ const { editing } = props;
|
|
|
+ this.state = {
|
|
|
+ editing: editing == 'true',
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ static getDerivedStateFromProps(props, state) {
|
|
|
+ // console.log({ props, state });
|
|
|
+ const { editing } = props;
|
|
|
+ return {
|
|
|
+ ...state,
|
|
|
+ editing: editing == 'true',
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param {Object} form Form实例
|
|
|
+ * @returns tableCell ReactNode
|
|
|
+ */
|
|
|
+ renderCell = form => {
|
|
|
+ this.form = form;
|
|
|
+ const { children, dataIndex, record, title } = this.props;
|
|
|
+ const { editing } = this.state;
|
|
|
+
|
|
|
+ return editing ? (
|
|
|
+ <Form.Item style={{ margin: 0 }}>
|
|
|
+ {form.getFieldDecorator(dataIndex, {
|
|
|
+ rules: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: `${title} 是必填.`,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ initialValue: record[dataIndex],
|
|
|
+ })(
|
|
|
+ // <Input ref={node => (this.input = node)} onPressEnter={this.save} onBlur={this.save} />
|
|
|
+ (dataIndex != 'required'&&dataIndex != 'showFiled') ? <Input ref={node => (this.input = node)} /> :
|
|
|
+ (
|
|
|
+ <Select
|
|
|
+ ref={node => (this.selecter = node)}
|
|
|
+ style={{ width: '100%' }}
|
|
|
+ >
|
|
|
+ <Option value={0}>否</Option>
|
|
|
+ <Option value={1}>是</Option>
|
|
|
+ </Select>
|
|
|
+ )
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ ) : (
|
|
|
+ <div
|
|
|
+ className="editable-cell-value-wrap"
|
|
|
+ style={{ paddingRight: 24 }}
|
|
|
+ // onClick={this.toggleEdit}
|
|
|
+ >
|
|
|
+ {children}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ };
|
|
|
+
|
|
|
+ render() {
|
|
|
+ const {
|
|
|
+ editable,
|
|
|
+ dataIndex,
|
|
|
+ title,
|
|
|
+ record,
|
|
|
+ index,
|
|
|
+ children,
|
|
|
+ ...restProps
|
|
|
+ } = this.props;
|
|
|
+ return (
|
|
|
+ <td {...restProps}>
|
|
|
+ {editable ? (
|
|
|
+ <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
|
|
|
+ ) : (
|
|
|
+ children
|
|
|
+ )}
|
|
|
+ </td>
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const NormalForm = React.forwardRef((props, ref) => {
|
|
|
+
|
|
|
+ const { form,initialFormValue } = props;
|
|
|
+ const formRefs = React.createRef();
|
|
|
+ const {getFieldDecorator} = form;
|
|
|
+ const onSubmitFormhandle = () => {
|
|
|
+ return new Promise((resolve)=>{
|
|
|
+ form.validateFields((err, values) => {
|
|
|
+ if (!err) {
|
|
|
+ console.log('Received values of form: ', values);
|
|
|
+ resolve(values);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ useImperativeHandle(ref,()=>{
|
|
|
+ return {
|
|
|
+ ...formRefs.current,
|
|
|
+ form:form
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ useEffect(()=>{
|
|
|
+ form.setFieldsValue({name:initialFormValue.name,remark:initialFormValue.remark})
|
|
|
+ },[]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Form
|
|
|
+ labelCol={{ span: 3 }}
|
|
|
+ wrapperCol={{ span: 16 }}
|
|
|
+ ref={formRefs}
|
|
|
+ onSubmit={onSubmitFormhandle}
|
|
|
+ >
|
|
|
+ <Form.Item
|
|
|
+ label="模板名称"
|
|
|
+ rules={[{ required: true, message: '请输入模板名称!' }]}
|
|
|
+ >
|
|
|
+ {getFieldDecorator('name', {
|
|
|
+ rules: [{ required: true, message: '请输入模板名称!' }],
|
|
|
+ })(
|
|
|
+ <Input
|
|
|
+ placeholder="请输入模板名称,限制长度20字符"
|
|
|
+ maxLength={20}
|
|
|
+ />,
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item
|
|
|
+ label="备注说明"
|
|
|
+ rules={[{ required: false }]}
|
|
|
+ >
|
|
|
+ {getFieldDecorator('remark', {
|
|
|
+ rules: [{ required: false}],
|
|
|
+ })(
|
|
|
+ <TextArea rows={4} />
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ <Divider dashed />
|
|
|
+ </Form>
|
|
|
+ )
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+const WrappedForm = Form.create()(NormalForm);
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @param {Object} props
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+const DrawerForm = (props) => {
|
|
|
+
|
|
|
+ const defaultData = [
|
|
|
+ {
|
|
|
+ key: 1,
|
|
|
+ title: '姓名',
|
|
|
+ filedType: 'Text',
|
|
|
+ required: 1,
|
|
|
+ showFiled:1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 2,
|
|
|
+ title: '性别',
|
|
|
+ filedType: 'Text',
|
|
|
+ required: 1,
|
|
|
+ showFiled:1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 3,
|
|
|
+ title: '年龄',
|
|
|
+ filedType: 'Text',
|
|
|
+ required: 1,
|
|
|
+ showFiled:1,
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ const [dataSource, setDataSource] = useState(defaultData);
|
|
|
+ const { visible: asVisible, onVisibleChange, title,initData } = props;
|
|
|
+ const [visible, setVisible] = useState(false);
|
|
|
+ const [ifEdit, setIfEdit] = useState(false);
|
|
|
+ const [columns, setColumns] = useState([]);
|
|
|
+ const [currentEditKey, setCurrentEditKey] = useState(-1);
|
|
|
+ const formRef = useRef(null);
|
|
|
+ const [drawerInitData,setDrawerInitData] = useState(null);
|
|
|
+ const [showAlert,setShowAlert] = useState(false);
|
|
|
+
|
|
|
+ const tableColumns = [
|
|
|
+ {
|
|
|
+ title: '标题',
|
|
|
+ dataIndex: 'title',
|
|
|
+ width: '20%',
|
|
|
+ editable: true,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '类型',
|
|
|
+ dataIndex: 'filedType',
|
|
|
+ editable: false,
|
|
|
+ width: '10%',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '是否必填',
|
|
|
+ dataIndex: 'required',
|
|
|
+ editable: true,
|
|
|
+ width: '20%',
|
|
|
+ render: bool => (bool ? '是' : '否')
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '是否展示信息',
|
|
|
+ dataIndex: 'showFiled',
|
|
|
+ editable: true,
|
|
|
+ width: '20%',
|
|
|
+ render: bool => (bool ? '是' : '否')
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ width:'20%',
|
|
|
+ dataIndex: 'operation',
|
|
|
+ render: (text, record) => {
|
|
|
+ // console.log(record.key,currentEditKey);
|
|
|
+ if (true) {
|
|
|
+ if (record.key === currentEditKey) {
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <EditableContext.Consumer>
|
|
|
+ {
|
|
|
+ form => (
|
|
|
+ <a
|
|
|
+ onClick={() => handleSave(form, record.key)}
|
|
|
+ >保存</a>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </EditableContext.Consumer>
|
|
|
+ <Divider type="vertical" />
|
|
|
+ <a onClick={() => cancelUpdateTableHandle(record.key)}>取消</a>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <a onClick={() => editRowHandle(record.key)}>编辑</a>
|
|
|
+ <Divider type="vertical" />
|
|
|
+ <Popconfirm title="确定删除?" onConfirm={() => delTableRowHandle(record.key)}>
|
|
|
+ <a>删除</a>
|
|
|
+ </Popconfirm>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const showDrawer = () => {
|
|
|
+ setVisible(true);
|
|
|
+ onVisibleChange(true);
|
|
|
+ };
|
|
|
+
|
|
|
+ const onClose = () => {
|
|
|
+ setVisible(false);
|
|
|
+ onVisibleChange(false);
|
|
|
+ setDrawerInitData(null);
|
|
|
+ localStorage.removeItem('localDataSource');
|
|
|
+ setDataSource([...defaultData]);
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param {Number} key 当前选中的key
|
|
|
+ */
|
|
|
+ const editRowHandle = (key) => {
|
|
|
+ setIfEdit(true);
|
|
|
+ setCurrentEditKey(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ const delTableRowHandle = (key) => {
|
|
|
+ let _data = localStorage.getItem('localDataSource');
|
|
|
+ _data = JSON.parse(_data);
|
|
|
+ const filtedData = _data.filter(t => {
|
|
|
+ return t.key !== key
|
|
|
+ });
|
|
|
+ setDataSource([...filtedData]);
|
|
|
+ }
|
|
|
+
|
|
|
+ const cancelUpdateTableHandle = (key) => {
|
|
|
+ setIfEdit(false);
|
|
|
+ setCurrentEditKey(-1);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param {Object} form form实例对象参考antd Form
|
|
|
+ * @param {Number} key 当前选中的key
|
|
|
+ */
|
|
|
+ const handleSave = (form, key) => {
|
|
|
+ form.validateFields((error, row) => {
|
|
|
+ if (error) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const newData = [...dataSource];
|
|
|
+ const index = newData.findIndex(item => key === item.key);
|
|
|
+ if (index > -1) {
|
|
|
+ const item = newData[index];
|
|
|
+ newData.splice(index, 1, {
|
|
|
+ ...item,
|
|
|
+ ...row,
|
|
|
+ });
|
|
|
+ setDataSource(newData);
|
|
|
+ setIfEdit(false);
|
|
|
+ setCurrentEditKey(-1);
|
|
|
+ } else {
|
|
|
+ newData.push(row);
|
|
|
+ setDataSource(newData);
|
|
|
+ setIfEdit(false);
|
|
|
+ setCurrentEditKey(-1)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ const renderColumn = () => {
|
|
|
+
|
|
|
+ const columns = tableColumns.map(col => {
|
|
|
+ if (!col.editable) {
|
|
|
+ return col;
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ ...col,
|
|
|
+ onCell: record => ({
|
|
|
+ record,
|
|
|
+ editable: col.editable,
|
|
|
+ dataIndex: col.dataIndex,
|
|
|
+ title: col.title,
|
|
|
+ editing: `${record.key === currentEditKey}`,
|
|
|
+ }),
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ setColumns(columns);
|
|
|
+ }
|
|
|
+
|
|
|
+ const addHandle = () => {
|
|
|
+ const newData = {
|
|
|
+ key: dataSource.length + 1,
|
|
|
+ title: '字段名',
|
|
|
+ filedType: 'Text',
|
|
|
+ required: 0,
|
|
|
+ showFiled:0,
|
|
|
+ };
|
|
|
+ setDataSource([...dataSource, newData]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param {Object} formData ==> {name,remark}
|
|
|
+ */
|
|
|
+ const postDrawerData = async (formData)=>{
|
|
|
+ if(drawerInitData){
|
|
|
+ //编辑
|
|
|
+ const resp = await editTemplateData({
|
|
|
+ id:drawerInitData.id,
|
|
|
+ ...formData,
|
|
|
+ contentDTOs:dataSource.map(t=>({title:t.title,required:t.required,filedType:t.filedType,showFiled:t.showFiled}))
|
|
|
+ });
|
|
|
+ if(resp.data.status == 200){
|
|
|
+ onClose();
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ //新增
|
|
|
+ const resp = await commitTemplateData({
|
|
|
+ ...formData,
|
|
|
+ contentDTOs:dataSource.map(t=>({title:t.title,required:t.required,filedType:t.filedType,showFiled:t.showFiled}))
|
|
|
+ });
|
|
|
+ if(resp.data.status == 200){
|
|
|
+ onClose();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ const onCommitDrawerData = async () => {
|
|
|
+
|
|
|
+ const { props: { onSubmit } } = formRef.current;
|
|
|
+ onSubmit().then((formData)=>{
|
|
|
+ // console.log({formData});
|
|
|
+ if(dataSource.length > 0){
|
|
|
+ postDrawerData(formData);
|
|
|
+ }else{
|
|
|
+ setShowAlert(true);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ asVisible && showDrawer();
|
|
|
+ if(initData){
|
|
|
+ //设置编辑时的回显
|
|
|
+ const {dataSource:list} = initData;
|
|
|
+ const _list = list.map((t,index)=>({...t,key:index+1}));
|
|
|
+ setDataSource(_list);
|
|
|
+ setDrawerInitData(initData);
|
|
|
+ }
|
|
|
+ }, [props]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ //delTableRowHandle获取不到datasource,暂存localStorage
|
|
|
+ localStorage.setItem('localDataSource', JSON.stringify(dataSource));
|
|
|
+ }, [dataSource]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ renderColumn();
|
|
|
+ }, [ifEdit, currentEditKey]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ return () => {
|
|
|
+ //卸载时清空
|
|
|
+ localStorage.removeItem('localDataSource');
|
|
|
+ setDataSource([...defaultData]);
|
|
|
+ }
|
|
|
+ }, []);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Drawer title={title} width={800} placement="right" onClose={onClose} visible={visible} destroyOnClose={true} >
|
|
|
+ <div className='formContainer'>
|
|
|
+ <WrappedForm wrappedComponentRef={formRef} initialFormValue={{...drawerInitData}} />
|
|
|
+ <div className='multiFormWrap' >
|
|
|
+ <div className='blockTitle'>模板内容</div>
|
|
|
+ { showAlert && <Alert message="请添加模板内容!" type="error" closable onClose={()=>setShowAlert(false)} />}
|
|
|
+ <Table
|
|
|
+ components={{
|
|
|
+ body: {
|
|
|
+ row: EditableFormRow,
|
|
|
+ cell: EditableCell,
|
|
|
+ },
|
|
|
+ }}
|
|
|
+ rowClassName={() => 'editable-row'}
|
|
|
+ dataSource={dataSource}
|
|
|
+ columns={columns}
|
|
|
+ pagination={false}
|
|
|
+ rowKey='key'
|
|
|
+ footer={() => <div className='footerTail' onClick={addHandle}>添加</div>}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div className='drawerFooter'>
|
|
|
+ <Button className='sureBtn' type='primary' onClick={onCommitDrawerData} >确定</Button>
|
|
|
+ <Button onClick={onClose}>取消</Button>
|
|
|
+ </div>
|
|
|
+ </Drawer>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+export default DrawerForm;
|