tsg-web/src/views/fxzb/qxdw/gc/form.js

642 lines
19 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import React,{useEffect,useState,useMemo,useRef} from 'react';
import { Form, Button, Input, Row,Upload, Col, Table, DatePicker, InputNumber,message,Image,Modal,Typography ,Popconfirm } from 'antd';
import { DeleteOutlined,FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps';
import { getDictService } from '../../../../service/SelectValue'
import { validlgtd , validlttd } from '../../../../utils/validators';
import apiurl from '../../../../service/apiurl';
import {mobile} from '../../../../utils/validators'
import AdcdTreeSelect from '../../../../components/Form/AdcdTreeSelect'
import NormalSelect from '../../../../components/Form/NormalSelect';
import { config } from '../../../../config';
import "./index.less"
import moment from 'moment';
import { createCrudService } from '../../../../components/crud/_';
const { RangePicker } = DatePicker
const { Dragger } = Upload;
const url = "http://223.75.53.141:9100/gs-tsg"
const EditableCell = ({
editing,
dataIndex,
title,
inputType,
record,
index,
children,
...restProps
}) => {
const inputNode = inputType === 'number' ?
<InputNumber style={{ textAlign: "center", flex: 1 }} /> :
inputType === 'select' ? <NormalSelect style={{ textAlign: "center", flex: 1 }} options={[{label:"男",value:"男"},{label:"女",value:"女"}]} />:
<Input style={{ textAlign: "center" }} />;
return (
<td {...restProps}>
{editing ? (
<Form.Item
name={dataIndex}
wrapperCol={[24]}
style={{
margin: 0,
}}
// rules={[
// {
// required: true,
// message: `Please Input ${title}!`,
// },
// ]}
>
{inputNode}
</Form.Item>
) : (
children
)}
</td>
);
};
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const [editingKey, setEditingKey] = useState('');
const [disabled, setDisabled] = useState(false)
const [details, setDetails] = useState([])
const detailsRef = useRef(null)
detailsRef.current = details
const isEditing = (record) => {
return record.key === editingKey;
}
const columns = [
{
title: "序号",
dataIndex: "index",
width: 60,
render: (text, record, index) => <span>{ index + 1}</span>,
align: "center"
},
{
title: '姓名',
key: 'name',
dataIndex: 'name',
width: 150
, align: "center",
editable: true,
},
{
title: '性别',
key: 'sex',
dataIndex: 'sex',
width: 100,
align: "center",
render: (rec, record) => <span>{rec == "F" ? "女" : rec == "M" ? "男" : ''}</span>,
editable: true,
},
{
title: '年龄',
key: 'age',
dataIndex: 'age',
width: 100,
align: "center",
editable: true,
},
{
title: '工作单位',
key: 'workUnit',
dataIndex: 'workUnit',
width: 150,
align: "center",
editable: true,
},
{
title: '职务',
key: 'duty',
dataIndex: 'duty',
width: 150,
align: "center",
editable: true,
},
{
title: '联系方式',
key: 'phone',
dataIndex: 'phone',
width: 150,
align: "center",
editable: true,
},
{
title: '操作', key: 'operation', width: 240, fixed: 'right',align: 'center',
render: (_, record) => {
const editable = isEditing(record);
return editable ? (
<span>
<Typography.Link
onClick={() => save(record.key)}
style={{
marginRight: 8,
}}
>
完成
</Typography.Link>
</span>
) : (
<div style={{display:"flex",justifyContent:"center",columnGap:10}}>
<Typography.Link disabled={editingKey !== ''} onClick={() => edit1(record)}>
编辑
</Typography.Link>
<Popconfirm title="确定要删除?" onConfirm={()=>handleDelete(record.key)}>
<a>删除</a>
</Popconfirm>
</div>
);
},
},
]
const newColumns = useMemo(() => {
let data = columns;
if (mode == "view") {
data.pop();
return data
} else {
return data;
}
}, [mode,editingKey])
const [form1] = Form.useForm()
const edit1 = (record) => {
setDisabled(true)
form1.setFieldsValue({
name: '',
sex:"",
age: '',
workUnit:'',
duty: '',
phone:'',
...record,
sex:record.sex == "F" ? "女" : record.sex == "M" ? "男" : ''
});
setEditingKey(record.key);
};
const save = async (key) => {
setDisabled(false)
try {
const row = await form1.validateFields();
if (row.sex) {
row.sex = row.sex == "男" ? "M" : row.sex == "女" ? "F" :''
}
const newData = [...details];
const index = newData.findIndex((item) => key === item.key);
if (index > -1) {
const item = newData[index];
newData.splice(index, 1, {
...item,
...row,
});
setDetails(newData);
setEditingKey('');
} else {
newData.push(row);
setDetails(newData);
setEditingKey('');
}
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
}
};
const mergedColumns = newColumns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record) => ({
record,
inputType: col.dataIndex === 'age' ? 'number' :
col.dataIndex === 'sex' ? 'select' : "text",
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record),
}),
};
});
const handleAddRow = () => {
setDisabled(true)
const newData = {
key: (details.length + 1).toString(),
name: '',
sex: '',
age: '',
workUnit: '',
duty: '',
phone:""
};
form1.setFieldsValue(newData)
setDetails([...details, newData]);
setEditingKey(newData.key);
};
const [form] = Form.useForm();
const [fileList, setFileList] = useState([]) //上传文件列表
const [fileIds, setFileIds] = useState([])
const [iframeSrc, setIframeSrc] = useState('')
const [pdfViewOPen, setPdfViewOPen] = useState(false)
const [loading, setLoading] = useState(false)
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
/**
* @description 获取查看时文件
* @param {*} type
* @returns
*/
const getFileInfo = (params) => {
createCrudService(apiurl.fxzb.qsdw.zq.getFile).delGet({ teamId: params.teamId }).then(res => {
if (res.code === 200) {
let fileArr = res.data?.files.map(item => {
return {
name: item.fileName,
response: {
data: {
filePath: item.filePath,
fileId:item.fileId
}
},
}
})
setFileList(fileArr)
const result = res.data?.details.map(item => ({ ...item, key: item.detailId }))
console.log("resss",result);
setDetails(result)
}
})
}
/**
* @description 文件下载
* @param {String} params 文件fileId
*/
const download = (params) => {
let downloadLink = document.createElement("a");
downloadLink.href = `${process.env.REACT_APP_API_URL}/gunshiApp/tsg/rescue/team/file/download/${params}`;
downloadLink.download = `${params.fileName}`;
downloadLink.style.display = "none";
// 将链接添加到页面中
document.body.appendChild(downloadLink);
// 模拟点击事件,开始下载
downloadLink.click();
}
/**
* @description 上传图片
* @param {string} file 上传的文件
*/
const fileChange = (info) => {
if (info.file.status === "done") {
setLoading(false);
}
if (info.file.status === "uploading") {
setLoading(true);
}
if (info.file.status === "error") {
message.error("文件上传失败")
setLoading(false);
}
let fileIds = info.fileList.map(file => {
return file.response?.data?.fileId
})
setFileIds(fileIds)
setFileList(info.fileList)
}
/**
* @description pdf文件预览
* @param {String} params 文件预览url
*/
const viewPdf = (params) => {
setIframeSrc(params)
setPdfViewOPen(true)
}
const handleDelete = (key) => {
const newData = detailsRef.current.filter((item) => item.key !== key);
setDetails(newData);
};
const onfinish = () => {
let values = form.getFieldsValue();
values.details = details;
values.validStartDate = values.dateRangeSo&&moment(values.dateRangeSo[0]).format("YYYY-MM-DD")
values.validEndDate = values.dateRangeSo&&moment(values.dateRangeSo[1]).format("YYYY-MM-DD")
if (mode === 'edit') {
let oldFiles = fileList.map(item => item.response?.data?.fileId )
values.fileIds = oldFiles;
values.teamId = record.teamId;
onEdit(apiurl.fxzb.qsdw.zq.edit,values)
}
if (mode === 'save') {
values.fileIds = fileIds
onSave(apiurl.fxzb.qsdw.zq.save,values)
}
}
/**
* @description 删除上传的图片
* @param {string} id 删除的id
*/
const deleteFile = (fileId) => {
console.log(fileId);
let filterFile = fileList.filter(item => item.response?.data?.fileId !== fileId);
setFileList(filterFile)
}
useEffect(()=>{
if (record.teamId ) {
getFileInfo(record)
}
}, [record])
useEffect(() => {
if (mode !== "save") {
let dateSo = [
record.validStartDate? moment(record.validStartDate):'',
record.validEndDate? moment(record.validEndDate): ''
]
form.setFieldsValue({...record,dateRangeSo:dateSo})
}
}, [record,mode])
return (
<>
<div className='basic-info'>基本信息</div>
{/* <Divider /> */}
<Form
form={form}
{...formItemLayout}
// initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="队伍名称"
name="teamName"
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="登记日期"
name="registerDate"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
rules={[
{
required: true,
message: `登记日期不能为空`,
},
]}
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="有效期限"
name="dateRangeSo"
rules={[
{
required: true,
message: `有效期限不能为空`,
},
]}
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => {
return {
value: value ? [value[0]&&moment(value[0]),value[1]&&moment(value[1])] : undefined
};
}}
>
<RangePicker
allowClear
showTime
disabled={mode==='view'}
// style={{ width: "300px" }}
format="YYYY-MM-DD"
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="管理单位"
name="managementUnit"
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="地址"
name="address"
rules={[{ required: true }]}
>
<Input type='text' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item
label="经度"
name="lgtd"
labelCol={{ span: 12 }}
wrapperCol={{ span: 10 }}
>
<Input type='text' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item
label="纬度"
name="lttd"
labelCol={{ span: 6 }}
wrapperCol={{ span: 10 }}
>
<Input type='text' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="队伍负责人"
name="teamLeader"
>
<Input type='num' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="联系电话"
name="phone"
>
<Input type='num' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="附件"
name="fieldId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
{mode !== "view" &&
<Dragger
name='file'
// multiple
action="/gunshiApp/tsg/rescue/team/file/upload/singleSimple"
onChange={fileChange}
onDrop={(info) => { console.log(info.dataTransfer.files); }}
fileList={fileList}
disabled={loading}
// onSuccess={handleSuccess}
>
<p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
<p className="ant-upload-hint">
支持扩展名.rar .zip .doc .docx .pdf .jpg .png .ppt
</p>
</Dragger>
}
<Row gutter={[16]}>
{
fileList.length > 0 && fileList.map(file => {
return (
<Col span={12}>
<div className="file-item" style={{width:"75%"}}>
<div className='file-description'>
{file.name.indexOf('.docx') > -1 ?
<div
onClick={() => { download(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileWordOutlined
style={{ fontSize: 40 }}
/>
</div>
:
file.name.indexOf('.pdf') > -1 ?
<div
onClick={() => { viewPdf(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FilePdfOutlined style={{ fontSize: 40 }} />
</div>
:
file.name.indexOf('.zip') > -1 ?
<div
onClick={() => { download(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileZipOutlined style={{ fontSize: 40 }} />
</div>
:
file.name.indexOf('.xlsx') > -1 ?
<div
onClick={() => { download(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileExcelOutlined style={{ fontSize: 40 }} />
</div>
:
<Image width={60} src={url +file.response?.data?.filePath} alt='' />
}
<span>{file.name}</span>
</div>
<div className={mode == "view" ? 'delete-icon disable-icon' : 'delete-icon'} onClick={() => deleteFile(file.response?.data?.fileId)}>
<DeleteOutlined />
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
</Form>
<div className='basic-info' style={{display:"flex",justifyContent:"space-between"}}>
<span>队伍明细共计{details?.length}</span>
{mode != "view" ?<div style={{display:"flex",columnGap:10,marginBottom:10}}>
<Button onClick={handleAddRow} type='primary' disabled={disabled}>添加</Button>
{/* <Button onClick={() => {}} >导入</Button> */}
</div>:null}
</div>
<Form form={form1} component={false}>
<Table
rowKey="index"
components={{
body: {
// row: EditableRow,
cell: EditableCell,
},
}}
columns={mergedColumns}
dataSource={details}
scroll={{ x: width}}
pagination={false}
/>
{
mode==='view'?null:(
<div style={{marginTop:20}}>
<Form.Item wrapperCol={{span:2,offset:22}}>
<Button type="primary" onClick={onfinish} disabled={disabled}>
{mode === 'save' ? '保存' :
'修改'}
</Button>
</Form.Item>
</div>
)
}
</Form>
<Modal
open={pdfViewOPen}
width={1000}
title=""
footer={null}
style={{marginTop:"-5%"}}
onCancel={() => {
setPdfViewOPen(false)
}}
>
<iframe
style={{
height: '80vh',
width: '100%',
border: 0,
marginTop: 20,
}}
src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(`/gunshiApp/tsg/rescue/goods/file/download/${iframeSrc}`)}`}
/>
</Modal>
</>
);
}
export default ModalForm;