Pārlūkot izejas kodu

replace qingdan with tabulator

Xiaopeng Zhang 6 mēneši atpakaļ
vecāks
revīzija
be22f9c9fb
6 mainītis faili ar 912 papildinājumiem un 62 dzēšanām
  1. 2 2
      front/src/App2.js
  2. 17 3
      front/src/Djcs2.js
  3. 836 0
      front/src/Qingdan2.js
  4. 54 54
      front/src/Service.js
  5. 1 1
      front/src/editor.js
  6. 2 2
      front/src/utils.js

+ 2 - 2
front/src/App2.js

@@ -19,7 +19,7 @@ import TabList from "@mui/lab/TabList";
 import TabPanel from "@mui/lab/TabPanel";
 //import { registerPlugin, NestedRows } from 'handsontable/plugins';
 //registerPlugin(NestedRows);
-import Qingdan from './Qingdan';
+import Qingdan2 from './Qingdan2';
 import Zjcs from './Zjcs';
 import Djcs2 from './Djcs2';
 import Service from './Service';
@@ -951,7 +951,7 @@ const MUI_X_PRODUCTS = [
                       </TabList>
                    </Box>
                    {qdbt.map((x, index)=><TabPanel sx={{p: 1}} value={(index+1).toString()}>
-                             <Qingdan
+                             <Qingdan2
                                 name={location["id"]}
                                 bh={qdbh}
                                 bt={x}

+ 17 - 3
front/src/Djcs2.js

@@ -232,9 +232,23 @@ export default function Djcs2({name, bh, rgde, jxde, clde, beizhu, beizhuFK, cli
      
           let newData = updateDercj_djcs(selectedRowKeysTable.current[0], data);
           myTable.current.updateData(newData.filter(x=>x['key'] == selectedRowKeysTableParent.current)).then(function() {
-               let getRow = myTable.current.getSelectedRows(); //get array of currently selected row components.
-               //getRow[0].select();
-               handleSelect(getRow[0]);
+               let getRow = myTable.current.getRows(); //get array of currently selected row components.
+               let component = null;
+               for(let i = 0; i < getRow.length; i++) {
+                    let entry = getRow[i]._row.modules.dataTree.children;
+                    for(let j = 0; j < entry.length; j++) {
+                         let child = entry[j];
+                         if(child.data['key'] == selectedRowKeysTable.current[0]) {
+                              //console.log(child);
+                              component = child.component;
+                              break;
+                         }
+                         
+                    }
+
+               }
+               
+               handleSelect(component);
           });
           
           

+ 836 - 0
front/src/Qingdan2.js

@@ -0,0 +1,836 @@
+import * as React from 'react';
+import Box from "@mui/material/Box";
+import 'handsontable/dist/handsontable.full.min.css';
+//import 'handsontable/styles/ht-theme-main.min.css';
+import { HandsonTable } from 'handsontable/base';
+import { Table, ConfigProvider, Button as AButton } from "antd";
+import {HotTable} from "@handsontable/react-wrapper";
+import { registerAllModules } from 'handsontable/registry';
+import {RichTreeView } from "@mui/x-tree-view/RichTreeView";
+import { Grid } from '@mui/material';
+import Tab from "@mui/material/Tab";
+import TabContext from "@mui/lab/TabContext";
+import TabList from "@mui/lab/TabList";
+import TabPanel from "@mui/lab/TabPanel";
+import Stack from "@mui/material/Stack";
+//import { registerPlugin, NestedRows } from 'handsontable/plugins';
+//registerPlugin(NestedRows);
+import Service from './Service';
+import { textRenderer, registerRenderer } from 'handsontable/renderers';
+import Button from '@mui/material/Button';
+import ButtonGroup from '@mui/material/ButtonGroup';
+import {extractFuzhu} from './utils';
+import {shanchu, undo, redo, danxiangdinge, updateDercj, changguidinge, handleBeizhu, huan, updateShuliang} from './editor';
+import { ConfigValueTooSmallError, HyperFormula } from 'hyperformula';
+import Backdrop from '@mui/material/Backdrop';
+import CircularProgress from '@mui/material/CircularProgress';
+import { DataGrid } from '@mui/x-data-grid';
+import { useHotEditor } from "@handsontable/react-wrapper";
+import Dialog from '@mui/material/Dialog';
+import DialogTitle from '@mui/material/DialogTitle';
+import DialogContent from '@mui/material/DialogContent';
+import IconButton from '@mui/material/IconButton';
+import Typography from '@mui/material/Typography';
+import Editable from './Editable';
+import {
+
+     SettingFilled,
+
+   } from '@ant-design/icons';
+
+import zhCN from 'antd/locale/zh_CN';
+
+import {TabulatorFull as Tabulator} from "tabulator-tables"; //import Tabulator library
+import "tabulator-tables/dist/css/tabulator.min.css"; //import Tabulator stylesheet
+import './Tabulator.css';
+registerAllModules();
+
+
+/**
+ * 
+本条规定了工程量清单编码的表示方式:十二位阿拉伯数字及其设置规定。
+各位数字的含义是:一、二位为专业工程代码(01—房屋建筑与装饰工程;02—仿古建筑工程;
+03—通用安装工程;04—市政工程;05—园林绿化工程;06—矿山工程;07—构筑物工程;08—城市
+轨道交通工程;09—爆破工程。以后进入国标的专业工程代码以此类推);三、四位为附录分类顺序码;
+五、六位为分部工程顺序码;七、八、九位为分项工程项目名称顺序码;十至十二位为清单项目名称
+顺序码。
+ */
+
+
+
+
+
+
+
+
+export default function Qingdan2({name, bh, bt, rgde, jxde, clde, beizhu/*后台传回来的附注信息,要整理后才能成为展示用的行*/ , beizhuFK, clickCallback, loadingCallback, dingeclick, tihuanCallback, tihuanClick}) {
+     registerRenderer('customStylesRenderer', (hotInstance, TD, row, column, prop, value, ...rest) => {
+          let newValue = value; 
+          if ((column == 10 || column == 11 || column == 5) && row > 0) {
+            newValue = Number(value).toFixed(2).toString();
+         }
+          textRenderer(hotInstance, TD, row, column, prop, newValue, ...rest);
+         for (let i = 0; i < highlight.current.length; i++) {
+          let entry = highlight.current[i];
+          if (entry.row == row && entry.col == column) {
+               TD.style.fontWeight = 'bold';
+               TD.style.color = 'green';
+               TD.style.background = '#d7f1e1';
+          }
+         }
+         
+       });
+     const myTable = React.useRef(null);
+     const myRef = React.useRef(null);
+     const [valueTab, setValueTab] = React.useState("1");
+     const handleChange = (event, newValue) => {
+          setValueTab(newValue);
+        };
+     const [rcjhl, setRcjhl] = React.useState([]);
+     const [rcjhl2, setRcjhl2] = React.useState([]);
+     const [fuzhu, setFuzhu] = React.useState([]);//展示用的附注行
+     const [tuijian, setTuijian] = React.useState([]);
+     const [fuzhuEnable, setFuzhuEnable] = React.useState(false);
+     const hotRcjRef = React.useRef(null);
+     const hotTuijianRef = React.useRef(null);
+     const highlight = React.useRef([]);
+     const debmRef = React.useRef(null);
+     const lastClickRef = React.useRef(null);
+
+     const [detail, setDetail] = React.useState([
+                    
+     ]);
+
+     const selectedRowKeysTable = React.useRef([]);
+     const selectedRowKeysTableParent = React.useRef(null);
+     const beizhuFKRef = React.useRef(null);
+
+
+     const rgdeRef = React.useRef(null);
+     const jxdeRef = React.useRef(null);
+     const cldeRef = React.useRef(null);
+     const isQdrcj = React.useRef(false);
+     const [selectedRowKeys, setSelectedRowKeys] = React.useState([]);
+     const onSelectChange = (newSelectedRowKeys) => {
+          console.log('selectedRowKeys changed: ', newSelectedRowKeys);
+          setSelectedRowKeys(newSelectedRowKeys);
+          const [newData, newHl] = handleBeizhu(beizhuFKRef.current, selectedRowKeysTable.current[0], newSelectedRowKeys, fuzhu);
+                                       if (newData) {
+                                          myTable.current.updateData(newData.filter(x=>x['key'] == selectedRowKeysTableParent.current));
+                                          setRcjhl(newHl);
+     
+                                       }
+        };
+
+
+     /**fuzhu select */
+     const rowSelection = {
+          selectedRowKeys,
+          onChange: onSelectChange,
+          getCheckboxProps: (record) => {
+               return {
+                    disabled: !fuzhuEnable
+               };
+          }
+     };
+
+
+     var editCheck = function(cell){
+          //cell - the cell component for the editable cell
+      
+          //get row data
+          //console.log(cell);
+          if(cell._cell.row.data['序号']) return false;
+          return true;
+      }
+
+      function handleSelect(row){
+          selectedRowKeysTable.current = [row._row['data']['key']];
+          if (row._row.data['序号'] != null && row._row.data['序号'].length >0) {
+               selectedRowKeysTableParent.current = row._row['data']['key'];
+
+               setFuzhu([]);
+               Service.generateQingdanrcj(name, bh,bt,row._row.data['清单编码']).then(x=>{
+                
+                setRcjhl(x);
+                //hotRcjRef.current?.hotInstance?.loadData(x);
+                
+                  isQdrcj.current = true;
+                  highlight.current = [];
+               });
+               Service.generateQingdanTuijian(name, bh,bt,row._row.data['清单编码']).then(x=>{
+                setTuijian(x);
+                
+             });
+          }else{
+               setTuijian([]);
+
+              let row_parent = row._row;
+              while(row_parent.modules.dataTree.parent) {
+                   row_parent = row_parent.modules.dataTree.parent;
+              }
+              
+
+               //console.log(name, bh,bt,qdbm, selected[1]);
+               debmRef.current = row._row['data']['清单编码'];
+               selectedRowKeysTableParent.current = row_parent['data']['key'];
+               let qdbm = row_parent['data']['清单编码'];
+               let debm = row._row['data']['清单编码'];
+               console.log('debm=');
+               console.log(debm);
+               let danwei = row._row['data']['单位'];
+
+               clickCallback(qdbm, debm);
+               Service.generateDingercj(name, bh,bt,qdbm, debm, danwei).then(x=>{
+                 console.log(x);
+                 setRcjhl(x[0]);
+                 setFuzhuEnable(x[1]);
+                 //hotRcjRef.current?.hotInstance?.loadData(x);
+                 isQdrcj.current = false;
+                 let toHighlight = [];
+                 for(let i = 1; i < x[0].length; i++) {
+                     let entry = x[0][i];
+                     let bianhao = entry[1];
+                     let rcjlb = entry[8];
+                     let hit = false;
+                     if (Number(rcjlb) == 1 &&  rgdeRef.current  ) {
+                        for (let j = 0;j < rgdeRef.current.length; j++) {
+                           if (rgdeRef.current[j]["CLBH"] == bianhao) {
+                               if(rgdeRef.current[j]["CLMC"] == entry[2])hit = true;
+                                let danjia = Number(entry[5]);
+                                if (danjia != rgdeRef.current[j]["YSJG"]) {
+                                     //console.log(`[${i},5]danjia bu yizhi`);
+                                     toHighlight.push({row: i, col: 5, renderer: "customStylesRenderer"});
+                                }
+                                let hanliang = Number(entry[10]);
+                                if (hanliang != rgdeRef.current[j]["gr"]) {
+                                     //console.log(`[${i}, 10]hanliang bu yizhi`);
+                                     toHighlight.push({row: i, col: 10, renderer: "customStylesRenderer"});
+                                }
+                           }
+                        }
+
+                     }   
+                     if (Number(rcjlb) == 3 && jxdeRef.current  ) {
+                        for (let j = 0; j < jxdeRef.current.length; j++) {
+                           if (jxdeRef.current[j]["jxbh"] == bianhao) {
+                               if(jxdeRef.current[j]["jxmc"] == entry[2])hit = true;
+                                 let danjia = Number(entry[5]);
+                                 if (danjia != jxdeRef.current[j]["tbdj"]) {
+                                      //console.log(`[${i},5]danjia bu yizhi`);
+                                      toHighlight.push({row: i, col: 5, renderer: "customStylesRenderer"});
+                                 }
+                                 let hanliang = Number(entry[10]);
+                                 if (hanliang != jxdeRef.current[j]["sl"]) {
+                                      //console.log(`[${i}, 10]hanliang bu yizhi`);
+                                      toHighlight.push({row: i, col: 10, renderer: "customStylesRenderer"});
+                                 }
+                           }
+                        }
+
+                     }   
+                     if (Number(rcjlb) == 2 && cldeRef.current  ) {
+                        for (let j = 0; j < cldeRef.current.length; j++) {
+                           if (cldeRef.current[j]["CLBH"] == bianhao) {
+                               if(cldeRef.current[j]["CLMC"] == entry[2])hit = true;
+                                 let danjia = Number(entry[5]);
+                                 if (danjia != cldeRef.current[j]["YSJG"]) {
+                                      //console.log(`[${i},5]danjia bu yizhi`);
+                                      toHighlight.push({row: i, col: 5, renderer: "customStylesRenderer"});
+                                 }
+                                 let hanliang = Number(entry[10]);
+                                 if (hanliang != cldeRef.current[j]["SL"]) {
+                                      //console.log(`[${i}, 10]hanliang bu yizhi`);
+                                      toHighlight.push({row: i, col: 10, renderer: "customStylesRenderer"});
+                                 }
+                           }
+                        }
+
+                     }
+                     if (!hit) {
+                          toHighlight.push({row: i, col: 1, renderer: "customStylesRenderer"});
+                     }   
+                 }
+                 highlight.current = toHighlight;
+               });
+
+          }
+
+      }
+
+
+     const afterChange = (changes, source) => {
+          if (changes == null || changes.every(x=>x[2] == x[3])) {
+
+          } else {
+               let data =  hotRcjRef.current?.hotInstance?.getData();
+               for(let i = 1; i < data.length; i++) {
+                    data[i][11] = Number(data[i][10]) * Number(data[i][5]);
+                }
+                setRcjhl(data);
+          
+          let newData = updateDercj(selectedRowKeysTable.current[0], data);
+          myTable.current.updateData(newData.filter(x=>x['key'] == selectedRowKeysTableParent.current)).then(function() {
+               let getRow = myTable.current.getRows(); //get array of currently selected row components.
+                                   let component = null;
+                                   for(let i = 0; i < getRow.length; i++) {
+                                        let entry = getRow[i]._row.modules.dataTree.children;
+                                        for(let j = 0; j < entry.length; j++) {
+                                             let child = entry[j];
+                                             if(child.data['key'] == selectedRowKeysTable.current[0]) {
+                                                  //console.log(child);
+                                                  component = child.component;
+                                                  break;
+                                             }
+                                             
+                                        }
+     
+                                   }
+                                   
+                                   handleSelect(component);
+                                   //handleSelect(getRow[0]);
+          });
+          }
+        };
+     
+     const afterOnCellMouseDown = (event, coord, TD) => {
+          
+          if (lastClickRef.current == null) {
+               lastClickRef.current = Date.now();
+          } else {
+               let origin = lastClickRef.current;
+               lastClickRef.current = Date.now();
+               let delta = lastClickRef.current - origin;
+               if (delta < 300 && coord.col == 1 && coord.row > 0 && !isQdrcj.current){//300 ms -> 换
+                   tihuanCallback(coord.row, coord.col);
+               }
+          }
+        };
+
+
+
+     React.useEffect(() => {
+          myTable.current = new Tabulator(myRef.current, {
+               index: "key",
+               height: 380,
+             data: detail, //link data to table
+             reactiveData: false, //enable data reactivity
+             dataTreeStartExpanded:true,
+             dataTree: true,
+             selectableRows:1, //make rows selectable
+             editTriggerEvent:"dblclick", //trigger edit on double click
+             dataTreeStartExpanded:function(row, level){
+                 //console.log(row);
+                 //console.log(level);
+                 return true; //expand rows where the "driver" data field is true;
+             },
+             columns: [ //Define Table Columns
+                          {title:"序号", field:"序号", width:80, headerSort:false, frozen: true}, //never hide this column
+                          {title:"清单编码", field:"清单编码", width:120,headerSort:false, frozen: true },
+                          {title:"名称", field:"名称", width:150, headerSort:false, formatter:"textarea"}, //hide this column first
+                          {title:"项目特征", field:"项目特征", width:150 , headerSort:false, formatter:"textarea"},
+                          {title:"计算规则", field:"计算规则", width:150, headerSort:false, formatter:"textarea"},
+                          {title:"单位", field:"单位", width:100, headerSort:false},
+                          {title:"数量", field:"数量", width:100, headerSort:false, editor: "input", editable: editCheck },
+                          {title:"综合单价", field:"综合单价", width:100, headerSort:false, formatter:"money"},
+                          {title:"合价", field:"合价", width:100, headerSort:false, formatter:"money"},
+                          {title:"人工费", field:"人工费", width:100, headerSort:false, formatter:"money"},
+                          {title:"主材费", field:"主材费", width:100, headerSort:false, formatter:"money"},
+                          {title:"设备费", field:"设备费", width:100, headerSort:false, formatter:"money"},
+                          {title:"辅材费", field:"辅材费", width:100, headerSort:false, formatter:"money"},
+                          {title:"材料费", field:"材料费", width:100, headerSort:false, formatter:"money"},
+                          {title:"机械费", field:"机械费", width:100, headerSort:false, formatter:"money"},
+                          {title:"管理费", field:"管理费", width:100, headerSort:false, formatter:"money"},
+                          {title:"利润", field:"利润", width:100, headerSort:false, formatter:"money"},
+                          {title:"暂估价", field:"暂估价", width:100, headerSort:false, formatter:"money"},
+                          {title:"综合人工工日", field:"综合人工工日", width:100, headerSort:false},
+                  ]
+           }); 
+           
+           myTable.current.on("cellDblClick", function(e, cell){
+               //e - the click event object
+               //cell - cell component
+               console.log(cell);
+           });
+     
+           myTable.current.on("rowSelected", handleSelect);
+           
+     
+           myTable.current.on("cellEdited", function(cell){
+               //console.log("edited");
+               //console.log();
+               let key = cell._cell.row.data['key'];
+               myTable.current.deselectRow();
+               let [success, data] = updateShuliang(cell._cell.row.data['数量'], selectedRowKeysTable.current[0]);
+               if (success) {
+                                myTable.current.updateData(data.filter(x=>x['key'] == selectedRowKeysTableParent.current)).then(function() {
+                                   let getRow = myTable.current.getRows(); //get array of currently selected row components.
+                                   let component = null;
+                                   for(let i = 0; i < getRow.length; i++) {
+                                        let entry = getRow[i]._row.modules.dataTree.children;
+                                        for(let j = 0; j < entry.length; j++) {
+                                             let child = entry[j];
+                                             if(child.data['key'] == key) {
+                                                  //console.log(child);
+                                                  component = child.component;
+                                                  break;
+                                             }
+                                             
+                                        }
+     
+                                   }
+                                   component.select();
+                                   handleSelect(component);
+                                   //handleSelect(getRow[0]);
+                                });                            
+                                                            
+               }
+           });
+     
+     
+           myTable.current.on("tableBuilt", () => {
+               Service.generateQingdanmingxi(name, bh, bt).then(x=>{
+                    myTable.current.replaceData(x);
+                    });
+             });
+         
+        }, [bh, bt]);
+
+
+
+        React.useEffect(
+          () => {
+            //console.log("rgde changed");
+            //console.log(rgde);
+            rgdeRef.current = rgde;
+            jxdeRef.current = jxde;
+            cldeRef.current = clde;
+            if (isQdrcj.current) {
+               highlight.current = [];
+            } else {
+            let toHighlight = [];
+            for(let i = 1; i < rcjhl.length; i++) {
+                let entry = rcjhl[i];
+                let bianhao = entry[1];
+                let rcjlb = entry[8];
+                let hit = false;
+                if (Number(rcjlb) == Number(1) && rgde) {
+                    for (let j = 0; j < rgde.length; j++) {
+                        if (rgde[j]["CLBH"] == bianhao) {
+                            if(rgde[j]["CLMC"] == entry[2])hit = true;
+                            let danjia = Number(entry[5]);
+                            if (danjia != rgde[j]["YSJG"]) {
+                                 //console.log(`[${i},5]danjia bu yizhi`);
+                                 toHighlight.push({row: i, col: 5, renderer: "customStylesRenderer"});
+                            }
+                            let hanliang = Number(entry[10]);
+                            if (hanliang != rgde[j]["gr"]) {
+                                 //console.log(`[${i}, 10]hanliang bu yizhi`);
+                                 toHighlight.push({row: i, col: 10, renderer: "customStylesRenderer"});
+                            }
+  
+                        }              
+                    }
+  
+                }   
+                if (Number(rcjlb) == Number(3) && jxde ) {
+                     for (let j = 0; j < jxde.length; j++) {
+                        if (jxde[j]["jxbh"] == bianhao) {
+                           if(jxde[j]["jxmc"] == entry[2])hit = true;
+                           let danjia = Number(entry[5]);
+                           if (danjia != jxde[j]["tbdj"]) {
+                                //console.log(`[${i},5]danjia bu yizhi`);
+                                toHighlight.push({row: i, col: 5, renderer: "customStylesRenderer"});
+                           }
+                           let hanliang = Number(entry[10]);
+                           if (hanliang != jxde[j]["sl"]) {
+                                //console.log(`[${i}, 10]hanliang bu yizhi`);
+                                toHighlight.push({row: i, col: 10, renderer: "customStylesRenderer"});
+                           }
+                        }
+                     }
+  
+                }   
+                if (Number(rcjlb) == Number(2) && clde ) {
+                     for (let j = 0; j < clde.length; j++) {
+                        if (clde[j]["CLBH"] == bianhao) {
+                           if(clde[j]["CLMC"] == entry[2])hit = true;
+                           let danjia = Number(entry[5]);
+                           if (danjia != clde[j]["YSJG"]) {
+                                //console.log(`[${i},5]danjia bu yizhi`);
+                                toHighlight.push({row: i, col: 5, renderer: "customStylesRenderer"});
+                           }
+                           let hanliang = Number(entry[10]);
+                           if (hanliang != clde[j]["SL"]) {
+                                //console.log(`[${i}, 10]hanliang bu yizhi`);
+                                toHighlight.push({row: i, col: 10, renderer: "customStylesRenderer"});
+                           }
+                        }
+                     }
+  
+                }
+                if (!hit) {
+                   toHighlight.push({row: i, col: 1, renderer: "customStylesRenderer"});
+                }   
+            }
+            //console.log(toHighlight);
+            highlight.current = toHighlight;
+            }
+            let bzrcjhl = [["人材机编码", "名称", "单位", "单价", "合价", "含量"]] 
+            if (rgde)
+            for (let i = 0; i  < rgde.length; i++) {
+                 bzrcjhl.push([rgde[i]["CLBH"], rgde[i]["CLMC"], rgde[i]["JLDW"], rgde[i]["YSJG"], rgde[i]["gf"], rgde[i]["gr"]]);
+            }
+            
+            if (clde)
+            for (let i = 0; i  < clde.length; i++) {
+                 bzrcjhl.push([clde[i]["CLBH"], clde[i]["CLMC"], clde[i]["JLDW"], clde[i]["YSJG"], clde[i]["HJ"], clde[i]["SL"]]);
+            }
+            if (jxde)
+            for (let i = 0; i  < jxde.length; i++) {
+                 bzrcjhl.push([jxde[i]["jxbh"], jxde[i]["jxmc"], jxde[i]["DW"], jxde[i]["tbdj"], jxde[i]["hj"], jxde[i]["sl"]]);
+            }
+            setRcjhl2(bzrcjhl);
+          }, [rgde, jxde, clde]
+        );
+
+
+
+        React.useEffect(
+          () => {
+              console.log(beizhu);
+              let result = [];
+              if (beizhu != null) { 
+                  let keys = Object.keys(beizhu["BZBH"]);
+                  for(let i = 0; i < keys.length; i++) {
+                      let key = keys[i];
+                      result.push({'key': i+1, '序号': i+1, '编号': beizhu["BZBH"][key], '说明': beizhu["SM"][key]});//序号很重要
+                  }
+                  setFuzhu(result);
+                  let newSelect = extractFuzhu(debmRef.current);
+                  setSelectedRowKeys(newSelect);
+                  //setSelectedRowKeys([1]);
+                  
+              }
+          }, [beizhu]
+        );
+
+        React.useEffect(
+          () => {
+               beizhuFKRef.current = beizhuFK;
+          }, [beizhuFK]
+      );
+
+
+      React.useEffect(
+          () => {
+               myTable.current.deselectRow();
+               //console.log(dingeclick);
+               if (selectedRowKeysTable.current.length > 0 ) {
+                    const [success, data, key] = changguidinge(JSON.parse(dingeclick), selectedRowKeysTable.current[0]);
+                    if (success) {
+                         myTable.current.updateData(data.filter(x=>x['key'] == selectedRowKeysTableParent.current)).then(function(){
+                              let getRow = myTable.current.getRows(); //get array of currently selected row components.
+                              let component = null;
+                              for(let i = 0; i < getRow.length; i++) {
+                                   let entry = getRow[i]._row.modules.dataTree.children;
+                                   for(let j = 0; j < entry.length; j++) {
+                                        let child = entry[j];
+                                        if(child.data['key'] == key) {
+                                             //console.log(child);
+                                             component = child.component;
+                                             break;
+                                        }
+                                        
+                                   }
+
+                              }
+                              
+                              component.select();
+                              handleSelect(component);
+
+                                   
+                               
+                          });
+                    }
+               }
+               
+          }, [dingeclick]//常规添加定额
+      );
+
+
+      React.useEffect(
+          () => {
+               //console.log(dingeclick);
+               if (selectedRowKeysTable.current.length > 0 ) {
+                    const data = huan(JSON.parse(tihuanClick), selectedRowKeysTable.current[0]);
+                    
+                    myTable.current.updateData(data.filter(x=>x['key'] == selectedRowKeysTableParent.current)).then(function(){
+                         let getRow = myTable.current.getRows(); //get array of currently selected row components.
+                         let component = null;
+                         for(let i = 0; i < getRow.length; i++) {
+                              let entry = getRow[i]._row.modules.dataTree.children;
+                              for(let j = 0; j < entry.length; j++) {
+                                   let child = entry[j];
+                                   if(child.data['key'] == selectedRowKeysTable.current[0]) {
+                                        //console.log(child);
+                                        component = child.component;
+                                        break;
+                                   }
+                                   
+                              }
+
+                         }
+                         
+                         
+                         handleSelect(component);
+
+                              
+                          
+                     });
+                         
+
+                        
+                    
+               }
+               
+          }, [tihuanClick]//替换定额人材机
+      );
+
+
+
+
+    return (
+        <Stack spacing={2}>
+
+                   <Box>
+                   <Stack direction='row' spacing={2}>
+                   <Button variant="outlined" size="small" onClick={() => {
+                      if (selectedRowKeysTable.current.length > 0) {
+                         const [success, data] = danxiangdinge(selectedRowKeysTable.current[0]);
+                         if(success) {
+                              myTable.current.updateData(data.filter(x=>x['key'] == selectedRowKeysTableParent.current)).then(function(){
+                                   selectedRowKeysTable.current = [];
+                                   selectedRowKeysTableParent.current = null;
+                                        setRcjhl([]);
+                                        setFuzhu([]);
+                                        isQdrcj.current = true;
+                                        highlight.current = [];
+                                 });
+                         }
+                      }
+                 
+                      
+                      }}
+                   >单项定额</Button>
+                      <Button variant="outlined" size="small" onClick={() => {
+                      if (selectedRowKeysTable.current.length > 0) {
+                         let newData = shanchu(selectedRowKeysTable.current[0]);
+                         myTable.current.updateData(newData.filter(x=>x['key'] == selectedRowKeysTableParent.current)).then(function(){
+                             if (newData.filter(x=>x['key'] == selectedRowKeysTable.current[0]).length == 0) {
+                                  selectedRowKeysTable.current = [];
+                                  selectedRowKeysTableParent.current = [];
+                                  setRcjhl([]);
+                                  setFuzhu([]);
+                                  isQdrcj.current = true;
+                                  highlight.current = [];
+                              }
+                         });
+                         
+                         
+                         
+                     }
+                      
+                 
+                      
+                      }}
+                   >删除</Button>
+                   <Button variant="outlined" size="small" onClick={() => {
+                   let newData = undo();
+                   myTable.current.updateData(newData).then(function(){
+                      
+                         selectedRowKeysTable.current = [];
+                         selectedRowKeysTableParent.current = null;
+                         setRcjhl([]);
+                         setFuzhu([]);
+                         isQdrcj.current = true;
+                         highlight.current = [];
+                         
+                     
+                   });
+                      
+                      }}
+                   >撤销</Button>
+                   <Button variant="outlined" size="small" onClick={() => {
+                   let newData = redo();
+                   myTable.current.updateData(newData).then(function(){
+                      selectedRowKeysTable.current = [];
+                      selectedRowKeysTableParent.current = null;
+
+                         setRcjhl([]);
+                         setFuzhu([]);
+                         isQdrcj.current = true;
+                         highlight.current = [];
+                   });
+                   
+                      
+                      }}
+                   >重做</Button>
+                   <Button variant="outlined" size="small" onClick={() => {
+                            console.log("save to cloud");
+                            loadingCallback();
+                      
+                      }}
+                   >保存</Button>
+
+                  
+                   </Stack>
+                   <div ref={myRef}> 
+                  </div>
+                  </Box>
+
+
+
+                   <Box >
+                   
+                   <TabContext value={valueTab}>
+                       <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
+                         <TabList sx={{minHeight: '24px'}} onChange={handleChange} aria-label="lab API tabs example">
+                           <Tab sx={{p: 0, minHeight: '24px'}} label="人材机含量" value="1" />
+                           <Tab sx={{p: 0, minHeight: '24px'}} label="标准定额人材机含量" value="2" />
+                           <Tab sx={{p: 0, minHeight: '24px'}} label="定额附注" value="3" />
+                           <Tab sx={{p: 0, minHeight: '24px'}} label="组价推荐" value="4" />
+                         </TabList>
+                       </Box>
+                       
+                       <TabPanel sx={{p: 1}} value="1">
+                          <HotTable 
+                          nestedRows={false}
+                             data={rcjhl
+                             }
+                             //cell={highlight}
+                             manualColumnResize={true}
+                             rowHeaders={true}
+                             colHeaders={true}
+                             height="190"
+                             
+                             
+                              cells={(row, col) => {
+                                   if (isQdrcj.current) return {readOnly: true, renderer: "customStylesRenderer"};
+                                   if (col == 8) {
+                                        return { readOnly: true, renderer: "customStylesRenderer" };
+                                   }
+                                   if (row === 0) {
+                                     return { readOnly: true, renderer: "customStylesRenderer" };
+                                   }
+                                   if (col <= 1 || col === 11) {
+                                        return { readOnly: true, renderer: "customStylesRenderer" };
+                                   }
+                           
+                                   return {renderer: "customStylesRenderer" };
+                                 }}
+                             fixedRowsTop={1}
+                             selectionMode="single"
+                             autoWrapRow={false}
+                             autoWrapCol={false}
+                             ref = {hotRcjRef}
+                             afterChange={afterChange}
+                             afterOnCellMouseDown={afterOnCellMouseDown}
+                             licenseKey="non-commercial-and-evaluation" // for non-commercial use only
+                           >
+                              
+                         </HotTable>
+
+                       </TabPanel>
+                       <TabPanel sx={{p: 1}} value="2">
+                          <HotTable 
+                          nestedRows={false}
+                             data={rcjhl2
+                             }
+                             manualColumnResize={true}
+                             rowHeaders={true}
+                             colHeaders={true}
+                             height="190"
+                             readOnly={true}
+                             fixedRowsTop={1}
+                             selectionMode="single"
+                             autoWrapRow={false}
+                             autoWrapCol={false}
+                             licenseKey="non-commercial-and-evaluation" // for non-commercial use only
+                           />
+
+                           
+
+                       </TabPanel>
+                       <TabPanel sx={{p: 1}} value="3">
+                       <Box sx={{maxHeight: `190px`}}>
+                       <ConfigProvider
+                          locale={zhCN}
+                          theme={{
+                            components: {
+                              Table: {
+                                 /* here is your component tokens */
+                                 cellPaddingBlock : 8
+                              },
+                            },
+                          }}
+                        >
+
+                          <Table 
+                             scroll={{ x: 'max-content' , y : 190}}
+                             pagination={false}
+                             rowSelection={rowSelection}
+                             columns={
+                              [
+                                   { title: '序号', dataIndex: '序号', width : 80},
+                                   {
+                                        title: '编号',
+                                        dataIndex: '编号',
+                                     
+                                   },
+                                   {
+                                        title: '说明',
+                                        dataIndex: '说明',
+                                     width: 550
+                                    
+                                   },
+                                  
+                                 ]
+                             }
+                           dataSource={fuzhu} />
+
+                        </ConfigProvider>
+                       </Box>
+                          
+
+                       </TabPanel>
+                       <TabPanel sx={{p: 1}} value="4">
+                          <HotTable 
+                          nestedRows={false}
+                             data={tuijian
+                             }
+                             ref = {hotTuijianRef}
+                             manualColumnResize={true}
+                             rowHeaders={true}
+                             colHeaders={true}
+                             height="190"
+                             readOnly={true}
+                             fixedRowsTop={1}
+                             selectionMode="single"
+                             autoWrapRow={false}
+                             autoWrapCol={false}
+                             licenseKey="non-commercial-and-evaluation" // for non-commercial use only
+                           />
+
+                       </TabPanel>
+                     </TabContext>
+                  </Box>
+                  </Stack>
+                  
+
+
+
+
+
+    );
+}

+ 54 - 54
front/src/Service.js

@@ -113,10 +113,10 @@ class Service{
             }
         }
         this.cache = this.cache.map(x=>{
-            x["children"] = x["__children"];
+            x["_children"] = x["__children"];
 
             x["key"] = x["序号"];
-            x["children"] = x["children"].map(y=>{
+            x["_children"] = x["_children"].map(y=>{
                 if (!y.hasOwnProperty('key')) {
                     y['key'] = uuidv4();
                 }
@@ -625,7 +625,7 @@ class Service{
         
         }
         let qd = this.cache.filter(x=>x["清单编码"] == qdbm)[0];
-        let de = qd["children"].filter(x=>x["清单编码"]==debm)[0];
+        let de = qd["_children"].filter(x=>x["清单编码"]==debm)[0];
         return [copy(de["dercj"]), de["fuzhuEnable"]];
         
         
@@ -990,8 +990,8 @@ async generateQingdanTuijian(name, bh, bt, bm) {
 
     summarize_one(qd) {///根据定额汇总清单
         let dict = {};
-        for(let i = 0; i < qd["children"].length; i++) {
-            let de = qd["children"][i];
+        for(let i = 0; i < qd["_children"].length; i++) {
+            let de = qd["_children"][i];
             let desl = Number(de['数量']);
             let dercj = de['dercj'];
             for (let j = 1; j < dercj.length; j++) {
@@ -1044,17 +1044,17 @@ async generateQingdanTuijian(name, bh, bt, bm) {
         qd['机械费'] = 0;
         qd['管理费'] = 0;
         qd['利润'] = 0;
-        for(let i = 0; i < qd["children"].length; i++) {
-            qd['综合单价'] += Number(qd['children'][i]['数量']) * Number(qd['children'][i]['综合单价']);
-            qd['合价'] += Number(qd['children'][i]['合价']);
-            qd['人工费'] += Number(qd['children'][i]['数量']) * Number(qd['children'][i]['人工费']);
-            qd['主材费'] += Number(qd['children'][i]['数量']) * Number(qd['children'][i]['主材费']);
-            qd['设备费'] += Number(qd['children'][i]['数量']) * Number(qd['children'][i]['设备费']);
-            qd['辅材费'] += Number(qd['children'][i]['数量']) * Number(qd['children'][i]['辅材费']);
-            qd['材料费'] += Number(qd['children'][i]['数量']) * Number(qd['children'][i]['材料费']);
-            qd['机械费'] += Number(qd['children'][i]['数量']) * Number(qd['children'][i]['机械费']);
-            qd['管理费'] += Number(qd['children'][i]['数量']) * Number(qd['children'][i]['管理费']);
-            qd['利润'] += Number(qd['children'][i]['数量']) * Number(qd['children'][i]['利润']);   
+        for(let i = 0; i < qd["_children"].length; i++) {
+            qd['综合单价'] += Number(qd['_children'][i]['数量']) * Number(qd['_children'][i]['综合单价']);
+            qd['合价'] += Number(qd['_children'][i]['合价']);
+            qd['人工费'] += Number(qd['_children'][i]['数量']) * Number(qd['_children'][i]['人工费']);
+            qd['主材费'] += Number(qd['_children'][i]['数量']) * Number(qd['_children'][i]['主材费']);
+            qd['设备费'] += Number(qd['_children'][i]['数量']) * Number(qd['_children'][i]['设备费']);
+            qd['辅材费'] += Number(qd['_children'][i]['数量']) * Number(qd['_children'][i]['辅材费']);
+            qd['材料费'] += Number(qd['_children'][i]['数量']) * Number(qd['_children'][i]['材料费']);
+            qd['机械费'] += Number(qd['_children'][i]['数量']) * Number(qd['_children'][i]['机械费']);
+            qd['管理费'] += Number(qd['_children'][i]['数量']) * Number(qd['_children'][i]['管理费']);
+            qd['利润'] += Number(qd['_children'][i]['数量']) * Number(qd['_children'][i]['利润']);   
         }
 
         return qd;
@@ -1191,7 +1191,7 @@ async generateQingdanTuijian(name, bh, bt, bm) {
                 if (x["key"] == key) {
                     let y = copy(x);
                     
-                    y["children"] = [];
+                    y["_children"] = [];
                     return y;
                 } else {
                     return x;
@@ -1204,14 +1204,14 @@ async generateQingdanTuijian(name, bh, bt, bm) {
             return copy(this.cache);
 
         } else {
-            let qd = this.cache.filter(x=>x["children"].filter(y=>y['key'] == key).length > 0)[0];
+            let qd = this.cache.filter(x=>x["_children"].filter(y=>y['key'] == key).length > 0)[0];
             let qdbm = qd['清单编码'];
             let newData = this.cache.map(x=>{
                 if (x["清单编码"] == qdbm) {
                     let y = copy(x);
-                    let origin = y["children"];
+                    let origin = y["_children"];
                     let trans = origin.filter(z=>z["key"]!=key);
-                    y["children"] = trans;
+                    y["_children"] = trans;
                     return y;
                 } else {
                     return x;
@@ -1369,8 +1369,8 @@ async generateQingdanTuijian(name, bh, bt, bm) {
         console.log("data updated");
         //处理附注
         let huan = false;//换
-        let qd = this.cache.filter(x=>x["children"].filter(y=>y['key']==row).length > 0)[0];
-        let de = qd["children"].filter(x=>x['key'] == row)[0];
+        let qd = this.cache.filter(x=>x["_children"].filter(y=>y['key']==row).length > 0)[0];
+        let de = qd["_children"].filter(x=>x['key'] == row)[0];
         if (de.hasOwnProperty("rcjdg")) {//新数据
             for (let i = 1; i < de['rcjdg'].length; i++) {
                 de['rcjdg'][i][5] = data[i][5];//更新单价
@@ -1463,37 +1463,37 @@ async generateQingdanTuijian(name, bh, bt, bm) {
         console.log("sum=".concat(sum));
         
         let shuliang = Number(qd['数量']);
-        for(let i = 0; i< qd["children"].length; i++) {
-            if(qd["children"][i]['key'] == row) {
-                let desl = Number(qd["children"][i]['数量']);
-                let oldname = qd["children"][i]['清单编码'];
+        for(let i = 0; i< qd["_children"].length; i++) {
+            if(qd["_children"][i]['key'] == row) {
+                let desl = Number(qd["_children"][i]['数量']);
+                let oldname = qd["_children"][i]['清单编码'];
                 
-                qd["children"][i]['辅材费'] = clf_sum;
-                qd["children"][i]['材料费'] = clf_sum;
-                qd["children"][i]['人工费'] = rgf_sum;
-                qd["children"][i]['主材费'] = 0;
-                qd["children"][i]['设备费'] = 0;
-                qd["children"][i]['机械费'] = jxf_sum;
+                qd["_children"][i]['辅材费'] = clf_sum;
+                qd["_children"][i]['材料费'] = clf_sum;
+                qd["_children"][i]['人工费'] = rgf_sum;
+                qd["_children"][i]['主材费'] = 0;
+                qd["_children"][i]['设备费'] = 0;
+                qd["_children"][i]['机械费'] = jxf_sum;
                 if (oldname.startsWith("D")) {//单项清单
-                    qd["children"][i]['管理费'] = 0;
-                    qd["children"][i]['利润'] = 0;
+                    qd["_children"][i]['管理费'] = 0;
+                    qd["_children"][i]['利润'] = 0;
                 } else {
                     if (this.qufeiEntry['备注'].length == 0) {
                         //changuiqufei
-                        qd["children"][i]['管理费'] = (rgf_sum + jxf_sum) * Number(this.qufeiEntry['管理费(%)']) / Number(100);
-                        qd["children"][i]['利润'] = (rgf_sum + jxf_sum) * Number(this.qufeiEntry['利润(%)']) / Number(100);
+                        qd["_children"][i]['管理费'] = (rgf_sum + jxf_sum) * Number(this.qufeiEntry['管理费(%)']) / Number(100);
+                        qd["_children"][i]['利润'] = (rgf_sum + jxf_sum) * Number(this.qufeiEntry['利润(%)']) / Number(100);
                     } else {
-                        qd["children"][i]['管理费'] = (rgf_sum) * Number(this.qufeiEntry['管理费(%)']) / Number(100);
-                        qd["children"][i]['利润'] = (rgf_sum) * Number(this.qufeiEntry['利润(%)']) / Number(100);
+                        qd["_children"][i]['管理费'] = (rgf_sum) * Number(this.qufeiEntry['管理费(%)']) / Number(100);
+                        qd["_children"][i]['利润'] = (rgf_sum) * Number(this.qufeiEntry['利润(%)']) / Number(100);
                     }
                 }
-                qd["children"][i]['综合单价'] = sum + qd["children"][i]['管理费'] + qd["children"][i]['利润'];
-                qd["children"][i]['合价'] = (qd["children"][i]['综合单价'] * shuliang * desl);
+                qd["_children"][i]['综合单价'] = sum + qd["_children"][i]['管理费'] + qd["_children"][i]['利润'];
+                qd["_children"][i]['合价'] = (qd["_children"][i]['综合单价'] * shuliang * desl);
                 
                 
                 
-                qd["children"][i]["dercj"] = copy(data);
-                qd["children"][i]['清单编码'] = renameDingE(oldname, xuhao, huan);
+                qd["_children"][i]["dercj"] = copy(data);
+                qd["_children"][i]['清单编码'] = renameDingE(oldname, xuhao, huan);
 
             }
         }
@@ -1501,8 +1501,8 @@ async generateQingdanTuijian(name, bh, bt, bm) {
 
     updateDercj(row, data) {
         //是否手动设置含量
-        let qd = this.cache.filter(x=>x["children"].filter(y=>y['key']==row).length > 0)[0];
-        let de = qd["children"].filter(x=>x['key'] == row)[0];
+        let qd = this.cache.filter(x=>x["_children"].filter(y=>y['key']==row).length > 0)[0];
+        let de = qd["_children"].filter(x=>x['key'] == row)[0];
         let bm = de['清单编码'];
         let alreadyFuzhu = extractFuzhu(bm);//[xuhao]
         let origin = de['dercj'];
@@ -1588,9 +1588,9 @@ async generateQingdanTuijian(name, bh, bt, bm) {
 
 
     updateBeizhu(row, selected, xuhao) {//xuhao is for rename
-        let qd = this.cache.filter(x=>x["children"].filter(y=>y['key']==row).length > 0)[0];
+        let qd = this.cache.filter(x=>x["_children"].filter(y=>y['key']==row).length > 0)[0];
         if (!qd) return [null, null];
-        let de = qd["children"].filter(x=>x['key'] == row)[0];
+        let de = qd["_children"].filter(x=>x['key'] == row)[0];
         if (de.hasOwnProperty("rcjdg")) {//底稿
 
         } else {///老数据不能有底稿,附注功能也不使能
@@ -1645,8 +1645,8 @@ async generateQingdanTuijian(name, bh, bt, bm) {
     }
 
     huan(old_index, new_bianhao, new_name, new_jia, row) {
-        let qd = this.cache.filter(x=>x["children"].filter(y=>y['key']==row).length > 0)[0];
-        let de = qd["children"].filter(x=>x['key'] == row)[0];
+        let qd = this.cache.filter(x=>x["_children"].filter(y=>y['key']==row).length > 0)[0];
+        let de = qd["_children"].filter(x=>x['key'] == row)[0];
         let rcj = copy(de['dercj']);
         rcj[old_index][1] = new_bianhao;
         rcj[old_index][2] = new_name;
@@ -1662,8 +1662,8 @@ async generateQingdanTuijian(name, bh, bt, bm) {
     }
 
     updateShuliang(value, row) {
-        let qd = this.cache.filter(x=>x["children"].filter(y=>y['key']==row).length > 0)[0];
-        let de = qd["children"].filter(x=>x['key'] == row)[0];
+        let qd = this.cache.filter(x=>x["_children"].filter(y=>y['key']==row).length > 0)[0];
+        let de = qd["_children"].filter(x=>x['key'] == row)[0];
         let origin = de['数量']
         if (Number(origin) - Number(value) < 0.0001 && Number(origin) - Number(value) > -0.0001) {
             return [false, null];
@@ -1820,7 +1820,7 @@ async generateQingdanTuijian(name, bh, bt, bm) {
                     '', '', '', '' ]);
                 }
                 let newKey = uuidv4();
-                qd["children"].push({
+                qd["_children"].push({
                     '操作': '',
                     '序号': null,
                     '清单编码': res['DEBH'][key],
@@ -1857,9 +1857,9 @@ async generateQingdanTuijian(name, bh, bt, bm) {
                 //return copy(this.cache);
             
 
-            return [true, copy(this.cache)];
+            return [true, copy(this.cache), newKey];
         } else {
-            return [false, null];
+            return [false, null, null];
         }
     }
 
@@ -1870,7 +1870,7 @@ async generateQingdanTuijian(name, bh, bt, bm) {
             let selected = this.cache.filter(x=>x['key'] == row)[0];
             let danwei = selected["单位"];
             let mingcheng = selected['名称'];
-            let children = selected["children"];
+            let children = selected["_children"];
             children.push({
                 '操作': '',
                 '序号': null,

+ 1 - 1
front/src/editor.js

@@ -108,7 +108,7 @@ export const handleBeizhu = (beizhuFK, derow, fuzhuSelect, fuzhu ) => {
     for(let j = 0; j < fuzhuSelect_.length; j++) {
         let entry = fuzhuSelect_[j];
         for(let i = 0; i < fuzhu.length; i++) {
-            if (fuzhu[i]['id'] == entry) {
+            if (fuzhu[i]['key'] == entry) {
                 bianma.push(fuzhu[i]['编号']);
                 xuhao.push(fuzhu[i]['序号']);
             }

+ 2 - 2
front/src/utils.js

@@ -1,8 +1,8 @@
 export const danxiangdinge_index = (data) => {
     let max = 0;
     for(let i = 0;  i< data.length; i++) {
-        if (data[i].hasOwnProperty("children")) {
-            let child = data[i]["children"];
+        if (data[i].hasOwnProperty("_children")) {
+            let child = data[i]["_children"];
             for (let j = 0; j < child.length; j++) {
                 let de = child[j];
                 if (de["清单编码"].startsWith("D")) {