tsg-web/src/views/rcgl/jdkh/khrwgl/PfDetail.js

709 lines
23 KiB
JavaScript
Raw Normal View History

2024-09-20 15:02:50 +08:00
import React,{useState,useEffect,useRef,useContext,useMemo} from 'react'
import { Table, Radio,Switch,Button,Form,message, InputNumber,DatePicker,Upload,Row,Col,Image,Modal,Input} from "antd"
import { EditOutlined,DeleteOutlined,EyeOutlined } from '@ant-design/icons';
import { httpget2, httppost2 } from '../../../../utils/request'
import { handleData } from "../../../../utils/tools"
import apiurl from '../../../../service/apiurl'
import PfViewModal from "./pfViewModal"
import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps';
import moment from 'moment'
const { Dragger } = Upload;
export default function PfDetail({ record, Item, refresh, onCancel,tabs }) {
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const EditableContext = React.createContext(null);
const EditableRow = ({ index, ...props }) => {
const [form] = Form.useForm();
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
);
};
const EditableCell = ({
title,
editable,
children,
dataIndex,
record,
handleSave,
...restProps
}) => {
const [editing, setEditing] = useState(false);
const inputRef = useRef(null);
const form = useContext(EditableContext);
useEffect(() => {
if (editing) {
inputRef.current.focus();
}
}, [editing]);
const toggleEdit = () => {
if(Item.view) return
setEditing(!editing);
form.setFieldsValue({
[dataIndex]: record[dataIndex],
});
};
const save = async () => {
try {
const values = await form.validateFields();
toggleEdit();
handleSave({
...record,
...values,
});
} catch (errInfo) {
console.log('Save failed:', errInfo);
}
};
let childNode = children;
if (editable) {
childNode = editing ? (
<Form form={form}>
<Form.Item
style={{
margin: 0,
}}
name={dataIndex}
>
<InputNumber min={0} max={record?.standardScore} ref={inputRef} onPressEnter={save} onBlur={save} />
</Form.Item>
</Form>
) : (
<div
className="editable-cell-value-wrap"
style={{
paddingRight: 24,
}}
onClick={toggleEdit}
>
{children}
</div>
);
}
return <td {...restProps}>{childNode}</td>;
};
// 总分
const [tableData, setTableData] = useState([])
const score = useMemo(() => tableData?.reduce((total, cur) => total + (cur?.assessScore ?? 0), 0), [tableData]);
const columns = [
{
title: "考核类目",
dataIndex: "name",
key:"name",
width: 150,
align: "center",
onCell: (row) => ({ rowSpan: row.rowSpan || 0 })
},
{
title: '指标名称',
key: 'indicatorName',
dataIndex: 'indicatorName',
width: 200,
align: "center",
},
{
title: '标准分数',
key: 'standardScore',
dataIndex: 'standardScore',
2024-09-29 17:42:30 +08:00
width: 70,
2024-09-20 15:02:50 +08:00
align: "center",
},
{
title: `考核得分(${score ?? ''})`,
key: 'assessScore',
dataIndex: 'assessScore',
width: 80,
align: "center",
editable: true,
},
{
title: '是否需要整改',
key: 'isNeedRectify1',
dataIndex: 'isNeedRectify1',
width: 150,
align: "center",
render: (text, row) => {
const checked = compareScore(row)
return (
<>
<Switch
checkedChildren="是"
unCheckedChildren="否"
checked={checked}
/>
{(checked && !Item.view) ? <EditOutlined
title='编辑'
style={{ marginLeft: 10, cursor: 'pointer' }}
onClick={() => { zgCallback(row) }}
/> : (checked && Item.view) ?
<EyeOutlined
title='查看'
style={{ marginLeft: 10, cursor: 'pointer' }}
onClick={() => { zgView(row) }}
/> : null
}
</>
)
}
},
]
const components = {
body: {
row: EditableRow,
cell: EditableCell,
},
};
const newcolumns = columns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record) => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
title: col.title,
handleSave,
}),
};
});
const handleSave = (row) => {
const newData = [...tableData];
const index = newData.findIndex((item) => row.id === item.id);
const item = newData[index];
newData.splice(index, 1, {
...item,
...row,
});
setTableData(newData);
tableDataRef.current = newData
};
const tableDataRef = useRef(null)
const getZbTableData = async (id, type) => {
const url = type == 1 ? apiurl.rcgl.jdkh.khmbgl.info :
apiurl.rcgl.jdkh.khrwgl.pfDetail
try {
const res = await httpget2(url + `/${id}`)
if (res.code == 200) {
res.data.forEach(item => {
if (item.rowSpan) delete item.rowSpan;
})
const result = handleData(res.data, "name")
setTableData(result)
tableDataRef.current = result;
}
} catch (error) {
console.log(error);
}
}
// 分数进行比较
const compareScore = (row) => {
let isBelowStandard = false;
if (Item.tabs != 2) {
isBelowStandard = row.standardScore > row.assessScore ? true : false;
return isBelowStandard;
} else {
for (let i = 0; row[`assessScore${i}`] !== undefined; i++) {
if (row[`assessScore${i}`] < row.standardScore) {
isBelowStandard = true;
break;
}
}
}
return isBelowStandard
}
// 处理清单任务查看详情
const handleTableData = (obj) => {
let rrlts = {};
const arr = Object.values(obj).map(item => {
item.map((it, index) => {
it['teamUserName' + index] = it.teamUserName;
it['assessScore' + index] = it.assessScore;
it['problemDesc' + index] = it.problemDesc;
it['rectifyRequirement' + index] = it.rectifyRequirement;
it['rectifyLastDate' + index] = it.rectifyLastDate;
it['files' + index] = it.files;
it["count"] = index +1;
rrlts = { ...rrlts, ...it }
})
return rrlts
})
return arr
}
2024-10-15 16:11:21 +08:00
const handleTableData2 = (obj) => {
const names = Object.values(obj)?.[0]?.map(o=>o.teamUserName)
const obj2 = {}
for(let key in obj){
const arr = []
names?.map((name)=>{
obj?.[key]?.map((item)=>{
if(name===item.teamUserName){
arr.push(item)
}
})
})
obj2[key] = arr
}
return obj2
}
2024-09-20 15:02:50 +08:00
// 获取清单查看数据
const [qdColumns, setQdColumns] = useState(newcolumns)
const [qdWidth, setQdWidth] = useState()
const getQdViewData = async (id) => {
try {
const res = await httpget2(apiurl.rcgl.jdkh.khrwgl.qdView + `/${id}`)
if (res.code == 200) {
2024-10-15 16:11:21 +08:00
const linshi = handleTableData2(res.data)//将接口里用户的顺序统一
const result = handleTableData(linshi);
2024-09-20 15:02:50 +08:00
const insertCols = [];
result.forEach((item, index, arr) => {
const total = arr?.reduce((total, cur) => total + (cur["assessScore" + index] || 0), 0)
if (item["teamUserName" + index]) {
insertCols.push( {
title: item['teamUserName' + index] + `(${total})`,
key: "assessScore" + index,
dataIndex: "assessScore" + index,
width: 80,
align: "center",
})
}
})
// 综合得分
const zfScore = result?.reduce((total,cur) => total + (cur?.indicatorScore || 0),0 )
insertCols.push({
title: "综合得分" + `(${zfScore})`,
key: "indicatorScore",
dataIndex: "indicatorScore",
width: 100,
align: "center",
render: (v, r) => (
<div style={{display:"flex",columnGap:10,justifyContent:"center"}}>
<span>{record?.scoreWay ==1 ? "取最低": record?.scoreWay ==2 ? "平均" : ''}</span>
<span>{v}</span>
</div>
)
})
columns.splice(3, 1, ...insertCols)
const width = columns?.reduce((total, cur) => total + (cur?.width || 0), 0);
setQdWidth(width)
setQdColumns(columns)
result.forEach(item => {
if (item.rowSpan) delete item.rowSpan;
})
const newData = handleData(result, "name")
setTableData(newData)
}
} catch (error) {
console.log(error);
}
}
// 重置评分
const resetPf = () => {
const newData = [...tableData];
newData.forEach(item => {
item.assessScore = ''
})
setTableData(newData)
tableDataRef.current = newData
}
// 保存评分
const savepf = async () => {
const params = {
taskId: record.id,
score,
ratings: tableData.map(item => ({
indicatorId: item.indicatorId,
standardScore: item.standardScore,
assessScore: item.assessScore,
teamId: Item.id,
isNeedRectify: item.isNeedRectify || 0,
problemDesc: item.problemDesc,
rectifyRequirement: item.rectifyRequirement,
rectifyLastDate: item.rectifyLastDate,
files: item.files,
fileList:undefined,
rectifyStatus:0
}))
}
try {
const res =await httppost2(apiurl.rcgl.jdkh.khrwgl.savePf, params)
if (res.code == 200) {
message.success("保存成功")
refresh()
} else {
message.error("保存失败")
}
} catch (error) {
console.log(error);
}
}
// 确认完成
const confirm = async () => {
const params = {
taskId: record.id,
score,
ratings: tableData.map(item => ({
indicatorId: item.indicatorId,
standardScore: item.standardScore,
assessScore: item.assessScore,
teamId: Item.id,
isNeedRectify: item.isNeedRectify || 0,
problemDesc: item.problemDesc,
rectifyRequirement: item.rectifyRequirement,
rectifyLastDate: item.rectifyLastDate,
files: item.files,
fileList:undefined,
rectifyStatus:0
}))
}
2024-10-16 17:52:43 +08:00
if(tableData.length>0){
let flag = true //fasle有位评分的
params.ratings?.map((item)=>{
if(item.assessScore==null){
flag = false
}
})
if(!flag){
message.error('请输入全部考核评分')
return
}
}
2024-09-20 15:02:50 +08:00
try {
const res = await httppost2(apiurl.rcgl.jdkh.khrwgl.confirmpf, params)
if (res.code == 200) {
message.success("评分完成")
refresh()
onCancel()
}
} catch (error) {
console.log(error);
}
}
// 查看评分详情
const [zgViewOpen, setzgViewOpen] = useState(false)
const zgView = (record) => {
setzgViewOpen(true)
setZgItem(record)
}
const [clickItem, setClickItem] = useState()
// 点击某一行的回调
const handleRowClick = (record) => {
setClickItem(record)
}
const handleRadioChange = (e) => {
2024-09-29 17:42:30 +08:00
if (e.target.value == 1) {
if (tabs == 2) {
getQdViewData(Item?.id)
2024-09-20 15:02:50 +08:00
} else {
2024-09-29 17:42:30 +08:00
getZbTableData(Item?.id,2)
2024-09-20 15:02:50 +08:00
}
2024-09-29 17:42:30 +08:00
} else {
2024-10-21 11:13:02 +08:00
// debugger
const newData = tabs == 2 ? tableData.filter(item => item.standardScore > item.indicatorScore) :
tableData.filter(item => item.standardScore > item.assessScore)
2024-09-29 17:42:30 +08:00
newData.forEach(item => {
if (item.rowSpan) delete item.rowSpan;
})
const res = handleData(newData, "name")
setTableData(res);
}
2024-09-20 15:02:50 +08:00
}
// 整改
const [zgOpen, setZgOpen] = useState(false)
const [form1] = Form.useForm();
const [loading, setLoading] = useState(false)
const [imgloading, setImgLoading] = useState(false)
const [imgfileList, setImgFileList] = useState([]) //上传文件列表
const [zgItem, setZgItem] = useState("")
const zgCallback = (e) => {
setZgOpen(true)
setZgItem(e)
console.log("ee",e);
}
const imgbeforeUpload = (file) => {
const isJpgOrPng =
file.type === 'image/jpeg' ||
file.type === 'image/jpg' ||
file.type === 'image/png';
if (!isJpgOrPng) {
message.error('请上传图片格式的文件!');
}
const isLt2M = file.size / 1024 / 1024 < 5;
if (!isLt2M) {
message.error('图片大小需小于5M!');
}
return isJpgOrPng && isLt2M ? true : Upload.LIST_IGNORE;
};
const imgdeleteFile = (fileId) => {
let filterFile = imgfileList.filter(item => item.response?.data?.fileId !== fileId);
setImgFileList(filterFile)
}
const imgfileChange = (info) => {
console.log("info",info);
if (info.file.status === "done") {
setImgLoading(false);
}
if (info.file.status === "uploading") {
setImgLoading(true);
}
if (info.file.status === "error") {
message.error("文件上传失败")
setImgLoading(false);
}
setImgFileList(info.fileList)
}
// 整改数据
const onfinish = (values) => {
let files = imgfileList.map(item => ({ fileId: item.response?.data?.fileId }))
values.files = files;
values.isNeedRectify = 1;
values.fileList = imgfileList.map(item => item.response.data);
const newData = tableData.map(item => {
if (item.id == zgItem.id) {
return {...item, ...values}
} else {
return item
}
})
setTableData(newData)
setZgOpen(false)
setZgItem("")
form1.resetFields();
}
// 获取指标表格数据
useEffect(() => {
// if (Item.type != "start") {
// if (tabs == 2) {
// getQdViewData(Item?.id)
// } else {
// getZbTableData(Item?.id,2)
// }
// } else {
// getZbTableData(record?.templateId,1)
// }
if (tabs == 2) {
getQdViewData(Item?.id)
} else {
getZbTableData(Item?.id,2)
}
}, [record, Item])
useEffect(() => {
const file = zgItem?.fileList ? zgItem.fileList : zgItem.files
if (file) {
const imgFile = file?.map(o => ({
name: o.fileName,
response: {
data: {
filePath: o.filePath,
fileId:o.fileId
}
},
}))
setImgFileList(imgFile)
} else {
setImgFileList([])
}
form1.setFieldsValue({...zgItem})
}, [zgItem])
return (
<div>
<Radio.Group style={{marginBottom:10}} defaultValue={1} onChange={(e) => handleRadioChange(e)}>
<Radio value={1}>显示全部</Radio>
<Radio value={2}>仅显示扣分项目</Radio>
</Radio.Group>
<Table
components={components}
rowKey="id"
columns={Item?.tabs != 2 ?newcolumns :qdColumns }
dataSource={tableData}
scroll={{x:Item?.tabs != 2 ? 500: qdWidth, y: "calc( 100vh - 400px )"}}
pagination={false}
onRow={(record, rowIndex) => {
return {
onClick: () => handleRowClick(record),
onDoubleClick:(record, rowIndex) => setClickItem()
};
}}
/>
{clickItem ? <div style={{backgroundColor:"#f2f2f2",marginTop:20,padding:10}}>
{clickItem?.indicatorRatings?.map(item => (
<div key={item.id}>
<div>{item?.ratingDesc}</div>
</div>
))}
</div> : null}
{!Item?.view ?
<div className='btns' style={{display:"flex",marginTop:40,justifyContent:"space-between"}}>
<Button type="primary" onClick={resetPf}>重置评分</Button>
<div style={{display:"flex",columnGap:10}}>
<Button type="primary" onClick={onCancel}>取消</Button>
<Button onClick={savepf}>保存</Button>
<Button type="primary" onClick={confirm}>确认完成</Button>
</div>
</div>
:
<div className='btns' style={{display:"flex",marginTop:40,justifyContent:"flex-end"}}>
<Button onClick={onCancel} type='primary'>关闭</Button>
</div>
}
{/* 整改 */}
<Modal
open={zgOpen}
width={800}
footer={null}
onCancel={() => { setZgOpen(false);form1.resetFields(); }}
title="整改详情"
destroyOnClose={true}
>
<Form
form={form1}
{...formItemLayout}
onFinish={onfinish}
// initialValues={zgItem}
>
<Row>
<Col span={24}>
<Form.Item
label="问题描述"
name="problemDesc"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[
{
required: true,
},
]}
>
<Input.TextArea style={{width:'100%',minHeight:'100px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="整改要求"
name="rectifyRequirement"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea style={{width:'100%',minHeight:'100px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="整改期限"
name="rectifyLastDate"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="现场图片"
name="fieldId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Dragger
name='file'
2024-09-30 10:24:35 +08:00
action="/gunshiApp/tsg/assessTeamRating/file/upload/singleSimple"
2024-09-20 15:02:50 +08:00
onChange={imgfileChange}
beforeUpload={imgbeforeUpload}
onDrop={(info) => { console.log(info); }}
fileList={imgfileList}
disabled={imgloading}
>
<p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
<p className="ant-upload-hint">
支持扩展名.jpg .png
</p>
</Dragger>
<Row gutter={[16]}>
{
loading ? <span>文件正在上传中请等待</span> :
imgfileList.length > 0 && imgfileList.map(file => {
return (
<Col span={12}>
<div className={'file-item'} >
<div className='file-description'>
<Image width={60} src={url +file.response?.data?.filePath} alt='' />
<span>{file.name}</span>
</div>
<div
className={'delete-icon'}
onClick={() => imgdeleteFile(file.response?.data?.fileId)}
>
<DeleteOutlined
/>
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
</Form>
</Modal>
{/* 评分详情中整改的详情查看 */}
<Modal
open={zgViewOpen}
width={800}
footer={null}
onCancel={() => { setzgViewOpen(false); ;setZgItem('');}}
title="查看"
destroyOnClose
wrapClassName='zgview-modal'
>
<PfViewModal zgItem={zgItem} record={Item} onCancel={() => {setzgViewOpen(false); ;setZgItem('');}} />
</Modal>
</div>
)
}