import { Table, Input, Divider, Tooltip, InputNumber, Select, Grid, } from "antd"; import React, { useState, useMemo, useEffect, useRef } from "react"; import AutoTable from "@/components/Tableform/mtable"; import { Scrollbars } from "react-custom-scrollbars"; import { CloseOutlined } from "@ant-design/icons"; import styles from "./index.less"; let { Option } = Select; const { useBreakpoint } = Grid; function unique(arr, key) { var hash = []; for (var i = 0; i < arr.length; i++) { let hashlist = hash.length > 0 ? hash.map((it) => it[key]) : []; if (arr[i] && hashlist.indexOf(arr[i][key]) == -1) { hash.push(arr[i]); } } return hash; } const usePrevious = (value) => { const ref = useRef(); useEffect(() => { ref.current = value; }); return ref.current; }; export default function CheckTable({ value, onChange, pagination, columns, extraparams, path, editable, rowKey, rowName, tabletype = "checkbox", dataSource, isDisabled, actionRef, }) { let [first, cf] = useState(true), [currentkey, changecur] = useState(), newcolumns = columns, [startData, cfs] = useState([]), [expandedRows, cexpand] = useState([]), [options, setoptions] = useState({}); const preParams = usePrevious(extraparams); const screens = useBreakpoint(); if (editable) { function getval(item, record) { let { dataIndex } = item, //修改字段的key hasval = value && value.length > 0 ? value.filter((it) => it[rowKey] == record[rowKey]) : []; //value中是否存在id为当前的值 if (hasval.length == 0) { //不存在 return record[dataIndex]; } else { //存在 return hasval[0][dataIndex]; } } newcolumns = columns.map((item, i) => { let idlist = value ? value.map((it) => it[rowKey]) : []; //下拉options定义 //编辑逻辑 if (item.selectedRender == "InputNumber") { let render = (_, record) => { if (idlist.indexOf(record[rowKey]) == -1) { return <span>{getval(item, record)}</span>; } else { return ( <InputNumber min={0} value={getval(item, record)} onChange={(val) => { let newvalue = value.map((it) => { if (it[rowKey] == record[rowKey]) { it[item.dataIndex] = val; } return it; }); onChange(newvalue); }} ></InputNumber> ); } }; item.render = render; } else if (item.selectedRender == "Select") { let render = (_, record) => { /** * * renderNull 当前行某一个字段的某种值时,当前单元格渲染为空 * * optionsFields 下拉框的值在当前行数据里面时,optionsFields就是下拉框值在当前行数据中所对应的字段 */ if (item.renderNull && Array.isArray(item.renderNull)) { let klink = {}, names = item.renderNull.map((it) => it.name); names.map((it) => { klink[it] = record[it]; }); let requiredlist = item.renderNull.map((it) => { if (it.equalvalue) { let equalvalue = it.equalvalue && Array.isArray(it.equalvalue) && it.equalvalue.length > 0 ? it.equalvalue.indexOf(klink[it.name]) != -1 : klink[it.name] == it.equalvalue; return equalvalue; } else if (it.unequalvalue) { let unequalvalue = it.unequalvalue && Array.isArray(it.unequalvalue) && it.unequalvalue.length > 0 ? it.unequalvalue.indexOf(klink[it.name]) == -1 : klink[it.name] != it.unequalvalue; return unequalvalue; } else { return true; } }); let rq = requiredlist.some((it) => it == true); if (rq) { return <></>; } } let curselected, alloption; if (item.optionsFields) { alloption = JSON.parse( JSON.stringify(record[item.optionsFields] ?? []) ); } else { if (Array.isArray(item.options)) { } else { curselected = Array.isArray(record[item.dataIndex]) ? record[item.dataIndex] : record[item.dataIndex] ? [record[item.dataIndex]] : []; alloption = unique( [...options[item.key], ...curselected], "value" ); } } let resval = getval(item, record); if (item.mode == "multiple") { return ( <Select disabled={idlist.indexOf(record[rowKey]) == -1} mode={item.mode} value={ resval ? resval.map((it) => (it?.value ? it.value : it)) : [] } onChange={(val) => { let newvalue = value.map((it) => { if (it[rowKey] == record[rowKey]) { it[item.dataIndex] = val; } return it; }); onChange(newvalue); }} > {Array.isArray(item.options) ? item.options.map((it, i) => ( <Option key={i} value={it.value}> {it.label} </Option> )) : alloption.map((it, i) => ( <Option key={i} value={it.value}> {it.label} </Option> ))} </Select> ); } else { return ( <Select disabled={idlist.indexOf(record[rowKey]) == -1} mode={item.mode} value={ resval ? Array.isArray(resval) ? resval.map((it) => (it?.value ? it.value : it))[0] : resval : null } onChange={(val) => { let newvalue = value.map((it) => { if (it[rowKey] == record[rowKey]) { it[item.dataIndex] = val; } return it; }); onChange(newvalue); }} > {Array.isArray(item.options) ? item.options.map((it, i) => ( <Option key={i} value={it.value}> {it.label} </Option> )) : alloption.map((it, i) => ( <Option key={i} value={it.value}> {it.label} </Option> ))} </Select> ); } }; item.render = render; } else if (item.selectedRender == "Input") { let render = (_, record) => { if (idlist.indexOf(record[rowKey]) == -1) { return <span>{getval(item, record)}</span>; } else { return ( <Input value={getval(item, record)} onChange={(e) => { let val = e.target.value; let newvalue = value.map((it) => { if (it[rowKey] == record[rowKey]) { it[item.dataIndex] = val; } return it; }); onChange(newvalue); }} ></Input> ); } }; item.render = render; } return item; }); } function getoptions(extraparams) { columns.map((item) => { if (!Array.isArray(item.options) && item.options) { item .options(item.params ? item.params : { ...extraparams }) .then((res) => { setoptions((options) => { return { ...options, [item.key]: res.data.dataList, }; }); }); } }); } useMemo(() => { if ( !extraparams || JSON.stringify(preParams) == JSON.stringify(extraparams) ) { return; } onChange([]); //传参改变清空数据 getoptions(extraparams); }, [extraparams]); useEffect(() => { if (dataSource && !path) { cfs(value); } }, [dataSource]); return editable ? ( <div style={{ border: "#ddd solid 1px" }} className="fatable"> <AutoTable showQuickJumper="false" rowKey={rowKey} dataSource={!path ? (dataSource ? dataSource : []) : null} withCard={false} columns={newcolumns} pagination={pagination} extraparams={extraparams} getDefaultSelected={(data) => { //查询时的初始化 cfs(data.selectedList); if (data.selectedList && data.selectedList.length > 0 && first) { onChange( data.selectedList.map((it) => { let cir = it; for (let i in it) { if (Array.isArray(it[i])) { let ismu = columns.filter((it) => it.dataIndex == i)[0]; if (ismu && ismu.mode == "multiple") { cir[i] = it[i].map((item) => item?.value ? item?.value : item ); } else { cir[i] = it[i].map((item) => item?.value ? item?.value : item )[0]; } } } return cir; }) ); //设置value cf(false); } }} path={path} rowSelection={{ selectedRowKeys: value ? value.map((it) => it[rowKey]) : [], preserveSelectedRowKeys: true, onChange: (selectedRowKeys, expandedRowes) => { let conval = value && Array.isArray(value) ? value : []; let limits = unique([...conval, ...expandedRowes], rowKey), expander = []; expander = selectedRowKeys.map((it) => { return limits.filter((item) => item[rowKey] == it)[0]; }); expander = expander.map((it) => { let neit = it; Object.keys(options).map((item) => { let vals = neit[item]; if (vals) { if (Array.isArray(vals)) { vals = vals.map((it) => (it?.value ? it.value : it)); } } neit = { ...neit, [item]: vals, }; }); return neit; }); onChange(expander); }, getCheckboxProps: (record) => ({ disabled: isDisabled ? path ? startData?.map((el) => el[rowKey]).indexOf(record[rowKey]) != -1 : value?.map((el) => el[rowKey]).indexOf(record[rowKey]) != -1 : false, }), }} tableRender={(_, dom) => ( <div style={{ display: "flex", width: "100%", overflow: "hidden", }} > <div style={{ flex: 1, }} > {dom} </div> {!isDisabled ? value?.length > 0 && Object.values(screens).filter((it) => it === true).length > 2 && ( <div style={{ width: 120, overflow: "hidden", display: "flex", flexDirection: "column", }} > <div style={{ padding: "14px 6px", display: "flex", justifyContent: "space-between", alignItems: "center", }} > <span style={{ fontSize: 16 }}>选中:</span> <span style={{ fontSize: 16 }}>{value?.length}个</span> </div> <div style={{ flex: 1, paddingBottom: 18 }}> <Scrollbars thumbMinSize={10} autoHide style={{ width: "100%", height: "100%" }} hideTracksWhenNotNeeded={true} > {value.map((it, i) => { return ( <div key={i} className={styles.items} onClick={() => { changecur(it[rowKey]); }} > <Tooltip title={it[rowName] ? it[rowName] : ""}> <i>{it[rowName] ? it[rowName] : ""}</i> </Tooltip> <CloseOutlined onClick={(e) => { e.stopPropagation(); if (it[rowKey] == currentkey) { changecur(null); } let newexpandedRows = value.filter( (its) => its[rowKey] != it[rowKey] ); onChange(newexpandedRows); }} /> </div> ); })} </Scrollbars> </div> </div> ) : value?.length > 0 && Object.values(screens).filter((it) => it === true).length > 2 && value.filter( (item) => startData?.map((el) => el[rowKey])?.indexOf(item[rowKey]) == -1 )?.length > 0 && ( <div style={{ width: 120, overflow: "hidden", display: "flex", flexDirection: "column", }} > <div style={{ padding: "14px 6px", display: "flex", justifyContent: "space-between", alignItems: "center", }} > <span style={{ fontSize: 16 }}>选中:</span> <span style={{ fontSize: 16 }}>{value?.length}个</span> </div> <div style={{ flex: 1, paddingBottom: 18 }}> <Scrollbars thumbMinSize={10} autoHide style={{ width: "100%", height: "100%" }} hideTracksWhenNotNeeded={true} > {value.map((it, i) => { return ( <div key={i} className={styles.items} onClick={() => { changecur(it[rowKey]); }} > <Tooltip title={it[rowName] ? it[rowName] : ""}> <i>{it[rowName] ? it[rowName] : ""}</i> </Tooltip> {startData ?.map((el) => el[rowKey]) ?.indexOf(it[rowKey]) == -1 && ( <CloseOutlined onClick={(e) => { e.stopPropagation(); if (it[rowKey] == currentkey) { changecur(null); } let newexpandedRows = value.filter( (its) => its[rowKey] != it[rowKey] ); onChange(newexpandedRows); }} /> )} </div> ); })} </Scrollbars> </div> </div> )} </div> )} rowClassNameFn={(record, index) => { if (currentkey === record[rowKey]) { return "selectedRow"; } return null; }} actionRef={actionRef ?? null} ></AutoTable> </div> ) : ( <div style={{ border: "#ddd solid 1px" }} className="fatable"> <AutoTable showQuickJumper="false" rowKey={rowKey} columns={columns} dataSource={!path ? (dataSource ? dataSource : []) : null} withCard={false} pagination={pagination} extraparams={extraparams} getDefaultSelected={(data) => { cfs(data.selectedList); if (value && first) { cexpand([...expandedRows, ...value]); cf(false); } }} path={path} rowSelection={ tabletype != "noSelect" ? { selectedRowKeys: value ? value.map((it) => { if (typeof it == "object") { return it[rowKey]; } else { return it; } }) : [], preserveSelectedRowKeys: true, type: tabletype, onChange: (selectedRowKeys, expandedRowes) => { onChange(selectedRowKeys); let limits = unique( [...expandedRows, ...expandedRowes], rowKey ), expander = []; expander = selectedRowKeys.map((it) => { return limits.filter((item) => item[rowKey] == it)[0]; }); cexpand(expander); }, getCheckboxProps: (record) => ({ disabled: isDisabled ? path ? startData ?.map((el) => el[rowKey]) .indexOf(record[rowKey]) != -1 : value ?.map((el) => el[rowKey]) .indexOf(record[rowKey]) != -1 : false, }), } : false } tableRender={(_, dom) => ( <div style={{ display: "flex", width: "100%", overflow: "hidden", }} > <div style={{ flex: 1, }} > {dom} </div> {!isDisabled ? value?.length > 0 && Object.values(screens).filter((it) => it === true).length > 2 && ( <div style={{ width: 120, overflow: "hidden", display: "flex", flexDirection: "column", }} > <div style={{ padding: "14px 6px", display: "flex", justifyContent: "space-between", alignItems: "center", }} > <span style={{ fontSize: 16 }}>选中:</span> <span style={{ fontSize: 16 }}>{value?.length}个</span> </div> <div style={{ flex: 1, paddingBottom: 18 }}> <Scrollbars thumbMinSize={10} autoHide style={{ width: "100%", height: "100%" }} hideTracksWhenNotNeeded={true} > {expandedRows.map((it) => { return ( <div className={styles.items} onClick={() => { changecur(it[rowKey]); }} key={it[rowKey]} > <Tooltip title={it ? it[rowName] : ""}> <i>{it ? it[rowName] : ""}</i> </Tooltip> <CloseOutlined onClick={(e) => { e.stopPropagation(); if (it[rowKey] == currentkey) { changecur(null); } let newvalues = value.filter( (item) => item != it[rowKey] ); onChange(newvalues); let newexpandedRows = expandedRows.filter( (its) => its[rowKey] != it[rowKey] ); cexpand(newexpandedRows); }} /> </div> ); })} </Scrollbars> </div> </div> ) : value?.length > 0 && Object.values(screens).filter((it) => it === true).length > 2 && value.filter( (item) => startData?.map((el) => el[rowKey])?.indexOf(item[rowKey]) == -1 )?.length > 0 && ( <div style={{ width: 120, overflow: "hidden", display: "flex", flexDirection: "column", }} > <div style={{ padding: "14px 6px", display: "flex", justifyContent: "space-between", alignItems: "center", }} > <span style={{ fontSize: 16 }}>选中:</span> <span style={{ fontSize: 16 }}>{value?.length}个</span> </div> <div style={{ flex: 1, paddingBottom: 18 }}> <Scrollbars thumbMinSize={10} autoHide style={{ width: "100%", height: "100%" }} hideTracksWhenNotNeeded={true} > {expandedRows.map((it) => { return ( <div className={styles.items} onClick={() => { changecur(it[rowKey]); }} key={it[rowKey]} > <Tooltip title={it ? it[rowName] : ""}> <i>{it ? it[rowName] : ""}</i> </Tooltip> {startData ?.map((el) => el[rowKey]) ?.indexOf(it[rowKey]) == -1 && ( <CloseOutlined onClick={(e) => { e.stopPropagation(); if (it[rowKey] == currentkey) { changecur(null); } let newvalues = value.filter( (item) => item != it[rowKey] ); onChange(newvalues); let newexpandedRows = expandedRows.filter( (its) => its[rowKey] != it[rowKey] ); cexpand(newexpandedRows); }} /> )} </div> ); })} </Scrollbars> </div> </div> )} </div> )} rowClassNameFn={(record, index) => { if (currentkey === record[rowKey]) { return "selectedRow"; } return null; }} actionRef={actionRef ?? null} ></AutoTable> </div> ); }