Pārlūkot izejas kodu

edit in djcs, continue to support changguidinge

Xiaopeng Zhang 6 mēneši atpakaļ
vecāks
revīzija
976105ba83
8 mainītis faili ar 744 papildinājumiem un 139 dzēšanām
  1. 8 0
      front/src/App2.js
  2. 209 134
      front/src/Djcs2.js
  3. 4 1
      front/src/Qingdan.js
  4. 444 3
      front/src/Service.js
  5. 34 0
      front/src/editor.js
  6. 26 0
      front/src/utils.js
  7. 8 0
      main.py
  8. 11 1
      subdir/db.py

+ 8 - 0
front/src/App2.js

@@ -306,6 +306,13 @@ const MUI_X_PRODUCTS = [
       });
     };
 
+    const loadingCallback_djcs = () => {
+      setOpen(true); 
+      Service.save_djcs().then(x=>{
+        setOpen(false);
+      });
+    };
+
     const qufeiCallback = (id, data) => {
       setOpen(true); 
       Service.applyFL(id, data).then(x=>{
@@ -984,6 +991,7 @@ const MUI_X_PRODUCTS = [
                          clde={clde}
                          beizhu={beizhu}
                          clickCallback={clickCallback}
+                         loadingCallback={loadingCallback_djcs}
                      />
                    </TabPanel>
                       

+ 209 - 134
front/src/Djcs2.js

@@ -19,8 +19,9 @@ import {TabulatorFull as Tabulator} from "tabulator-tables"; //import Tabulator
 import "tabulator-tables/dist/css/tabulator.min.css"; //import Tabulator stylesheet
 import './Tabulator.css';
 import { DataGrid } from '@mui/x-data-grid';
-import {extractFuzhu} from './utils';
+import {extractFuzhu, match_target} from './utils';
 import Button from '@mui/material/Button';
+import {shanchu_djcs, undo_djcs, redo_djcs, danxiangdinge_djcs, updateDercj_djcs, changguidinge, handleBeizhu, huan, updateShuliang_djcs} from './editor';
 
 import { textRenderer, registerRenderer } from 'handsontable/renderers';
 
@@ -33,97 +34,24 @@ function number_equal(a, b) {
      }
      return false;
 }
-export default function Djcs2({name, bh, rgde, jxde, clde, beizhu, clickCallback}) {
-     
-    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 [detail, setDetail] = React.useState([
-                    
-    ]);
-    const myRef = React.useRef(null);
-    const myTable = React.useRef(null);
-    const [value, setValue] = React.useState("1");
-    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 [rowSelectionModel, setRowSelectionModel] = React.useState({
-     type: 'include',
-     ids: new Set(),
-   });
-    const highlight = React.useRef([]);
-
-    
-    const rgdeRef = React.useRef(null);
-    const jxdeRef = React.useRef(null);
-    const cldeRef = React.useRef(null);
-    const isQdrcj = React.useRef(false);
-    const debmRef = React.useRef(null);
+export default function Djcs2({name, bh, rgde, jxde, clde, beizhu, clickCallback, loadingCallback}) {
 
 
-    React.useEffect(() => {
-     myTable.current = new Tabulator(myRef.current, {
-          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},
-                     {title:"综合单价", field:"综合单价", width:100, headerSort:false},
-                     {title:"合价", field:"合价", width:100, headerSort:false},
-                     {title:"人工费", field:"人工费", width:100, headerSort:false},
-                     {title:"主材费", field:"主材费", width:100, headerSort:false},
-                     {title:"设备费", field:"设备费", width:100, headerSort:false},
-                     {title:"辅材费", field:"辅材费", width:100, headerSort:false},
-                     {title:"材料费", field:"材料费", width:100, headerSort:false},
-                     {title:"机械费", field:"机械费", width:100, headerSort:false},
-                     {title:"管理费", field:"管理费", width:100, headerSort:false},
-                     {title:"利润", field:"利润", width:100, headerSort:false},
-                     {title:"暂估价", field:"暂估价", width:100, headerSort:false},
-                     {title:"综合人工工日", field:"综合人工工日", width:100, headerSort:false},
-             ]
-      }); 
+     var editCheck = function(cell){
+          //cell - the cell component for the editable cell
       
-      myTable.current.on("cellDblClick", function(e, cell){
-          //e - the click event object
-          //cell - cell component
-          console.log(cell);
-      });
+          //get row data
+          //console.log(cell);
+          if(cell._cell.row.data['序号']) return false;
+          return true;
+      }
 
-      myTable.current.on("rowSelected", function(row){
+
+     function handleSelect(row){
           //e - the click event object
           //cell - cell component
-          console.log(row);
+          console.log('rowSelected');
+          selectedRowKeys.current = [row._row['data']['key']];
           let bt = "Djcs" ;
           
           if (row._row.data['序号'] != null && row._row.data['序号'].length >0) {
@@ -208,17 +136,147 @@ export default function Djcs2({name, bh, rgde, jxde, clde, beizhu, clickCallback
                                highlight.current = toHighlight;
                              });
           }
+     }
+     
+    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 [detail, setDetail] = React.useState([
+                    
+    ]);
+    const hotRcjRef = React.useRef(null);
+    const myRef = React.useRef(null);
+    const myTable = React.useRef(null);
+    const [value, setValue] = React.useState("1");
+    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 [rowSelectionModel, setRowSelectionModel] = React.useState({
+     type: 'include',
+     ids: new Set(),
+   });
+    const highlight = React.useRef([]);
+
+    
+    const rgdeRef = React.useRef(null);
+    const jxdeRef = React.useRef(null);
+    const cldeRef = React.useRef(null);
+    const isQdrcj = React.useRef(false);
+    const debmRef = React.useRef(null);
+    const selectedRowKeys = React.useRef([]);
+    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_djcs(selectedRowKeys.current[0], data);
+          myTable.current.updateData(newData).then(function() {
+               let getRow = myTable.current.getSelectedRows(); //get array of currently selected row components.
+               //getRow[0].select();
+               handleSelect(getRow[0]);
+          });
+          
+          
+     }
+   };
+
+    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(cell._cell.row.data);
-          let row = cell._cell.row
-          while(row.modules.dataTree.parent) {
-              row = row.modules.dataTree.parent;
+          //console.log("edited");
+          //console.log();
+          let key = cell._cell.row.data['key'];
+          
+          let [success, data] = updateShuliang_djcs(cell._cell.row.data['数量'], selectedRowKeys.current[0]);
+          if (success) {
+                           myTable.current.updateData(data).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]);
+                           });                            
+                                                       
           }
-          cell._cell.row.component.select();          
-          console.log(row);
       });
 
 
@@ -231,13 +289,7 @@ export default function Djcs2({name, bh, rgde, jxde, clde, beizhu, clickCallback
    }, [bh]);
 
 
-    /*React.useEffect(
-        () => {
-          Service.generateDjcs(name, bh).then(x=>{
-          myTable.current.replaceData(x);
-          });
-        }, [bh]
-      );*/
+ 
     React.useEffect(
         () => {
             console.log(beizhu);
@@ -356,12 +408,17 @@ export default function Djcs2({name, bh, rgde, jxde, clde, beizhu, clickCallback
                <Stack spacing={1}>
                          <Stack direction='row' spacing={2}>
                    <Button variant="outlined" size="small" onClick={() => {
-                      if (selectedRowKeys.length > 0) {
-                         const [success, data] = danxiangdinge(selectedRowKeys[0]);
+                      if (selectedRowKeys.current.length > 0) {
+                         const [success, data] = danxiangdinge_djcs(selectedRowKeys.current[0]);
                          if(success) {
-                            setDetail(data);
-                            detailRef.current = data;
-                            setExpandedRowKeys([...expandedRowKeys, selectedRowKeys[0]]);
+                            myTable.current.updateData(data).then(function(){
+                              selectedRowKeys.current = [];
+                                   setRcjhl([]);
+                                   setFuzhu([]);
+                                   isQdrcj.current = true;
+                                   highlight.current = [];
+                            });
+                            //console.log(data);
                          }
                       }
                  
@@ -369,14 +426,18 @@ export default function Djcs2({name, bh, rgde, jxde, clde, beizhu, clickCallback
                       }}
                    >单项定额</Button>
                       <Button variant="outlined" size="small" onClick={() => {
-                      if (selectedRowKeys.length > 0) {
-                          let newData = shanchu(selectedRowKeys[0]);
-                          setDetail(newData);
-                          detailRef.current = newData;
-                          if (newData.filter(x=>x['key'] == selectedRowKeys[0]).length == 0) {
-                              setSelectedRowKeys([]);
-                              handleSelection([]);
-                          }
+                      if (selectedRowKeys.current.length > 0) {
+                          let newData = shanchu_djcs(selectedRowKeys.current[0]);
+                          myTable.current.updateData(newData).then(function(){
+                              if (newData.filter(x=>x['key'] == selectedRowKeys.current[0]).length == 0) {
+                                   selectedRowKeys.current = [];
+                                   setRcjhl([]);
+                                   setFuzhu([]);
+                                   isQdrcj.current = true;
+                                   highlight.current = [];
+                               }
+                          });
+                          
                           
                           
                       }
@@ -386,30 +447,32 @@ export default function Djcs2({name, bh, rgde, jxde, clde, beizhu, clickCallback
                       }}
                    >删除</Button>
                    <Button variant="outlined" size="small" onClick={() => {
-                      let newData = undo();
-                      setDetail(newData);
-                      detailRef.current = newData;
-                      if (newData.filter(x=>x['key'] == selectedRowKeys[0]).length == 0
-                      && newData.filter(x=>x["children"].filter(y=>y['key']==selectedRowKeys[0]).length > 0).length == 0) {
-                         setSelectedRowKeys([]);
-                         handleSelection([]);
-                     } else {
-                         handleSelection(selectedRowKeys);
-                     }
+                      let newData = undo_djcs();
+                      myTable.current.updateData(newData).then(function(){
+                         
+                            selectedRowKeys.current = [];
+                            setRcjhl([]);
+                            setFuzhu([]);
+                            isQdrcj.current = true;
+                            highlight.current = [];
+                            
+                        
+                      });
+                     
                       
                       }}
                    >撤销</Button>
                    <Button variant="outlined" size="small" onClick={() => {
-                      let newData = redo();
-                      setDetail(newData);
-                      detailRef.current = newData;
-                      if (newData.filter(x=>x['key'] == selectedRowKeys[0]).length == 0
-                      && newData.filter(x=>x["children"].filter(y=>y['key']==selectedRowKeys[0]).length > 0).length == 0) {
-                         setSelectedRowKeys([]);
-                         handleSelection([]);
-                     } else {
-                         handleSelection(selectedRowKeys);
-                     }
+                      let newData = redo_djcs();
+                      myTable.current.updateData(newData).then(function(){
+                         selectedRowKeys.current = [];
+                            setRcjhl([]);
+                            setFuzhu([]);
+                            isQdrcj.current = true;
+                            highlight.current = [];
+                      });
+                      
+                      
                       
                       }}
                    >重做</Button>
@@ -441,9 +504,21 @@ export default function Djcs2({name, bh, rgde, jxde, clde, beizhu, clickCallback
                              data={rcjhl
                              }
                              cells={(row, col) => {
-                              return { readOnly: true, renderer: "customStylesRenderer" };
+                              if (isQdrcj.current) return {readOnly: true, renderer: "customStylesRenderer"};
+                              if (col == 8) {
+                                   return { readOnly: true, renderer: "customStylesRenderer" };
+                              }
+                              if (col <= 1 || col >= 11) {
+                                  return { readOnly: true, renderer: "customStylesRenderer" };
+                              } else if (row == 0){
+                                   return { readOnly: true, renderer: "customStylesRenderer" };
+                              } else {
+                                   return { readOnly: false, renderer: "customStylesRenderer" };
+                              }
                               
                             }}
+                             afterChange={afterChange}
+                             ref = {hotRcjRef}
                              manualColumnResize={true}
                              rowHeaders={true}
                              colHeaders={true}

+ 4 - 1
front/src/Qingdan.js

@@ -343,7 +343,7 @@ export default function Qingdan({name, bh, bt, rgde, jxde, clde, beizhu/*后台
       };
 
       const afterChange = (changes, source) => {
-          if (changes == null) {
+          if (changes == null || changes.every(x=>x[2] == x[3])) {
 
           } else {
                let data =  hotRcjRef.current?.hotInstance?.getData();
@@ -783,6 +783,9 @@ export default function Qingdan({name, bh, bt, rgde, jxde, clde, beizhu/*后台
                              
                               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" };
                                    }

+ 444 - 3
front/src/Service.js

@@ -1,5 +1,5 @@
 import { getTableHeadUtilityClass } from '@mui/material';
-import {copy, danxiangdinge_index, renameDingE, extractFuzhu, match_target} from './utils';
+import {copy, danxiangdinge_index, danxiangdinge_index_djcs, renameDingE, extractFuzhu, match_target} from './utils';
 import { v4 as uuidv4 } from 'uuid';
 class Service{
     
@@ -865,6 +865,28 @@ async generateQingdanTuijian(name, bh, bt, bm) {
         }
     }
 
+    async save_djcs() {
+        const response = await fetch(this.ip().concat( ":8000/savedjcs/"), {
+            method : "POST",
+            headers: {
+                "Content-type": "application/json"
+            },
+            body: JSON.stringify(
+                {
+                    
+                    "name": JSON.stringify(this.cache_djcs)
+                }
+            )
+        });
+        if (!response.ok) {
+            //const error = await response.json();
+            console.error('error');
+        } else {
+            const data = await response.json();
+            return data;
+        }
+    }
+
     async applyFL(id, data) {
         const response = await fetch(this.ip().concat( ":8000/applyFL/"), {
             method : "POST",
@@ -893,6 +915,79 @@ async generateQingdanTuijian(name, bh, bt, bm) {
     ///////////////////////////////////editor//////////////////////////////////
 
 
+    summarize_one_djcs(qd) {///根据定额汇总清单
+        let dict = {};
+        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++) {
+                let hl = copy(dercj[j]);
+                hl[10] = desl * Number(hl[10]);
+                hl[11] = desl * Number(hl[11]);
+                let a = hl[1];//"人材机编码", 
+                let b = a.concat(hl[2]);//"名称", 
+                let c = b.concat(hl[4]);// "单位"
+                if (dict.hasOwnProperty(c)) {
+                    dict[c].push(hl);
+                } else {
+                    dict[c] = [hl];
+                }
+
+            }
+        }
+        let result = [];
+        for(const key in dict) {
+            let list = dict[key];
+            let sum = 0;
+            let danjia = Number(list[0][5]);
+            for (let i =0 ;i < list.length; i++) {
+                sum += Number(list[i][10]);
+            }
+            let entry = [list[0][0], list[0][1], list[0][2], list[0][3], list[0][4], danjia,
+             list[0][6], list[0][7], list[0][8], list[0][9], sum, sum * danjia, list[0][12],
+             list[0][13], list[0][14], list[0][15]
+             ];
+             result.push(entry);
+
+        }
+        let gongri = 0;
+        for(let i = 0; i < result.length; i++) {
+            if (result[i][4] == '工日') {
+                gongri += result[i][10];
+            }
+        }
+        result.sort((a, b) => Number(a[8]) - Number(b[8]));
+        qd['rcj'] = [["ID", "人材机编码", "名称", "规格型号", "单位", "单价", "产地", 
+        "供应厂商", "人材机类别", "甲供标志", "含量", "合价", "暂估价标志", "主要材料标志", "主材标志", "设备标志" ]].concat(result);
+        qd["综合人工工日"] = gongri;
+        qd['综合单价'] = 0;
+        qd['合价'] = 0;
+        qd['人工费'] = 0;
+        qd['主材费'] = 0;
+        qd['设备费'] = 0;
+        qd['辅材费'] = 0;
+        qd['材料费'] = 0;
+        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]['利润']);   
+        }
+
+        return qd;
+    }
+
+
     summarize_one(qd) {///根据定额汇总清单
         let dict = {};
         for(let i = 0; i < qd["children"].length; i++) {
@@ -968,6 +1063,10 @@ async generateQingdanTuijian(name, bh, bt, bm) {
         return data.map(x=>this.summarize_one(x));
     }
 
+    summarize_djcs(data) {
+        return data.map(x=>this.summarize_one_djcs(x));
+    }
+
     push_op(newData) {
         if(this.memory.length == this.mem_pointer + 1) {
             this.memory.push(copy(newData));
@@ -980,6 +1079,18 @@ async generateQingdanTuijian(name, bh, bt, bm) {
        }
     }
 
+    push_op_djcs(newData) {
+        if(this.memory_djcs.length == this.mem_pointer_djcs + 1) {
+            this.memory_djcs.push(copy(newData));
+            this.mem_pointer_djcs = this.mem_pointer_djcs + 1;
+       } else{
+            this.memory_djcs.splice(this.mem_pointer_djcs + 1);
+            this.memory_djcs.push(copy(newData));
+            this.mem_pointer_djcs = this.mem_pointer_djcs + 1; 
+    
+       }
+    }
+
     undo() {
         if (this.mem_pointer > 0) {
             
@@ -992,6 +1103,19 @@ async generateQingdanTuijian(name, bh, bt, bm) {
 
         return copy(this.cache);
     }
+
+    undo_djcs() {
+        if (this.mem_pointer_djcs > 0) {
+            
+            let newData = this.memory_djcs[this.mem_pointer_djcs - 1];
+            this.mem_pointer_djcs = this.mem_pointer_djcs - 1;
+            this.cache_djcs = copy(newData);
+            return copy(newData);
+           
+        }
+
+        return copy(this.cache_djcs);
+    }
     
     redo() {
         if (this.mem_pointer + 1 != this.memory.length) {
@@ -1002,6 +1126,62 @@ async generateQingdanTuijian(name, bh, bt, bm) {
             }
 
         return copy(this.cache);
+    }
+
+    redo_djcs() {
+        if (this.mem_pointer_djcs + 1 != this.memory_djcs.length) {
+            let newData = this.memory_djcs[this.mem_pointer_djcs + 1];
+            this.mem_pointer_djcs = this.mem_pointer_djcs + 1;
+            this.cache_djcs = copy(newData);
+            return copy(newData);
+            }
+
+        return copy(this.cache_djcs);
+    }
+
+    shanchu_djcs(key) {
+        if (this.cache_djcs.filter(x=>x['key'] == key).length > 0) {
+            ///qd
+            let newData = this.cache_djcs.map(x=>{
+                if (x["key"] == key) {
+                    let y = copy(x);
+                    
+                    y["_children"] = [];
+                    return y;
+                } else {
+                    return x;
+                }
+            });
+            let summarized = this.summarize_djcs(newData);
+            this.push_op_djcs(summarized);
+             /////////////////
+            this.cache_djcs = copy(summarized);
+            return copy(this.cache_djcs);
+
+        } else {
+            let qd = this.cache_djcs.filter(x=>x["_children"].filter(y=>y['key'] == key).length > 0)[0];
+            let qdbm = qd['清单编码'];
+            let newData = this.cache_djcs.map(x=>{
+                if (x["清单编码"] == qdbm) {
+                    let y = copy(x);
+                    let origin = y["_children"];
+                    let trans = origin.filter(z=>z["key"]!=key);
+                    y["_children"] = trans;
+                    return y;
+                } else {
+                    return x;
+                }
+            });
+            let summarized = this.summarize_djcs(newData);
+            this.push_op_djcs(summarized);
+            /////////////////
+            this.cache_djcs = copy(summarized);
+            return copy(this.cache_djcs);
+        }
+        
+        
+
+
     }
 
     shanchu(key) {
@@ -1050,6 +1230,141 @@ async generateQingdanTuijian(name, bh, bt, bm) {
     }
 
 
+    updateDercj_djcs_(row, data, xuhao) {///change 一条定额 inplace, 汇总一条定额的rcj, xuhao is for rename
+        console.log("data updated");
+        //处理附注
+        let huan = false;//换
+        let qd = this.cache_djcs.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];//更新单价
+                /****ToDo 更新其他字段 */
+                if (de['rcjdg'][i][2] == data[i][2]) {//更新名称
+                    
+                } else {
+                    huan = true;
+                }
+            }
+
+            if (de['fuzhuEnable'] && de.hasOwnProperty('fuzhu')) {//没强行改过含量
+                
+                for(let j = 1; j < de['rcjdg'].length; j++) {
+                    let origin = Number(de['rcjdg'][j][10]);
+                    for(let i = 0; i < de['fuzhu'].length; i++) {
+                        let selected = de['fuzhu'][i];
+                        let target = selected[0];
+                        
+                        
+                        if (match_target(de['rcjdg'][j][1], target)) {
+                            if (selected[2] == '系数') {
+                                origin = origin * Number(selected[3]);
+
+                            } else if (selected[2] == '含量') {
+                                origin = Number(selected[3]);
+                            } else if (selected[2] == '调整') {
+                                origin = origin + Number(selected[3]);
+                            } else {
+                                throw new Error('无法处理的附注'.concat(selected[2]));
+                            }
+                            
+                        }
+                        
+
+                    }
+                    de['dercj'][j][2] = data[j][2];//名称
+                    de['dercj'][j][1] = data[j][1];//编号
+                    de['dercj'][j][5] = de['rcjdg'][j][5];//单价
+                    de['dercj'][j][10] =  origin;
+                    de['dercj'][j][11] = Number(de['dercj'][j][5]) * origin;
+                }
+
+            } else if (de['fuzhuEnable'] && !de.hasOwnProperty('fuzhu')) {
+                for(let j = 1; j < de['rcjdg'].length; j++) {
+                    let origin = Number(de['rcjdg'][j][10]);
+                    
+                    de['dercj'][j][2] = data[j][2];//名称
+                    de['dercj'][j][1] = data[j][1];//编号
+
+                    de['dercj'][j][5] = de['rcjdg'][j][5];
+                    de['dercj'][j][10] =  origin;
+                    de['dercj'][j][11] = Number(de['dercj'][j][5]) * origin;
+                }
+            }
+
+            else {
+                //强行改含量
+                de['dercj'] = copy(data);
+            }
+        
+
+            
+            data = de['dercj'];
+        } else {////单项定额没有底稿,老数据没底搞,无法判断换部换,暂时统一认为不换
+            //强行改含量
+            de['dercj'] = copy(data);
+            data = de['dercj'];
+        }
+        //模拟formula计算每一行的合价
+        for(let i = 1; i < data.length; i++) {
+            data[i][11] = Number(data[i][10]) * Number(data[i][5]);
+        }
+        let sum = 0;
+        let rgf_sum = 0;
+        let jxf_sum = 0;
+        let clf_sum = 0;
+        for(let i = 1; i < data.length; i++) {
+            sum += Number(data[i][11]);//11-> hejia
+            if (Number(data[i][8]) == 1) {
+                rgf_sum += Number(data[i][11]);
+            }
+            if (Number(data[i][8]) == 2) {
+                clf_sum += Number(data[i][11]);
+            }
+            if (Number(data[i][8]) == 3) {
+                jxf_sum += Number(data[i][11]);
+            }
+        }
+        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]['清单编码'];
+                
+                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;
+                } 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);
+                    } else {
+                        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]["dercj"] = copy(data);
+                qd["_children"][i]['清单编码'] = renameDingE(oldname, xuhao, huan);
+
+            }
+        }
+    }
+
+
     updateDercj_(row, data, xuhao) {///change 一条定额 inplace, 汇总一条定额的rcj, xuhao is for rename
         console.log("data updated");
         //处理附注
@@ -1228,6 +1543,50 @@ async generateQingdanTuijian(name, bh, bt, bm) {
     }
 
 
+    updateDercj_djcs(row, data) {
+        //是否手动设置含量
+        let qd = this.cache_djcs.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'];
+        let change = false;
+        for(let i = 1; i < data.length; i++) {
+            let before = origin[i][10];
+            let after = data[i][10];
+            if (Number(before) - Number(after) < 0.0001 && Number(before) - Number(after) > -0.0001) {
+                //no change
+            } else {
+                change = true;
+                break;
+            }
+        }
+        if (change) {
+            de['fuzhuEnable'] = false;
+        }
+
+
+        
+        this.updateDercj_djcs_(row, data, alreadyFuzhu);
+        //let qd = this.cache.filter(x=>x["children"].filter(y=>y['key']==row).length > 0)[0];
+
+        let newData = this.cache_djcs.map(x=>{
+            if (x['key'] == qd['key']) {
+                return qd;
+            } else {
+                return x;
+            }
+        });
+        let summarized = this.summarize_djcs(newData);
+        this.push_op_djcs(summarized);
+        /////////////////
+        this.cache_djcs = copy(summarized);
+        return copy(this.cache_djcs);
+
+
+    }
+
+
     updateBeizhu(row, selected, xuhao) {//xuhao is for rename
         let qd = this.cache.filter(x=>x["children"].filter(y=>y['key']==row).length > 0)[0];
         if (!qd) return [null, null];
@@ -1301,6 +1660,37 @@ async generateQingdanTuijian(name, bh, bt, bm) {
 
 
 
+    }
+
+
+    updateShuliang_djcs(value, row) {
+        let qd = this.cache_djcs.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];
+        }
+        console.log("shuliang update");
+        de['数量'] = value;
+        de['合价'] = Number(qd['数量']) * Number(de['综合单价']) * Number(de['数量']);
+        let newData = this.cache_djcs.map(x=>{
+            if (x['key'] == qd['key']) {
+                return qd;
+            } else {
+                return x;
+            }
+        });
+        let summarized = this.summarize_djcs(newData);
+        this.push_op_djcs(summarized);
+        /////////////////
+        this.cache_djcs = copy(summarized);
+        return [true, copy(this.cache_djcs)];
+
+
+
+
+
+
     }
 
 
@@ -1379,12 +1769,13 @@ async generateQingdanTuijian(name, bh, bt, bm) {
         if (this.cache.filter(x=>x['key'] == row).length > 0) {
             let selected = this.cache.filter(x=>x['key'] == row)[0];
             let danwei = selected["单位"];
+            let mingcheng = selected['名称'];
             let children = selected["children"];
             children.push({
                 '操作': '',
                 '序号': null,
                 '清单编码': bh,
-                '名称': '',
+                '名称': mingcheng,
                 '项目特征': null,
                 '计算规则': null,
                 '单位': danwei,
@@ -1404,7 +1795,7 @@ async generateQingdanTuijian(name, bh, bt, bm) {
                 '备注': null,
                 "dercj": [["ID", "人材机编码", "名称", "规格型号", "单位", "单价", "产地", 
                 "供应厂商", "人材机类别", "甲供标志", "含量", "合价", "暂估价标志", "主要材料标志", "主材标志", "设备标志" ],
-                   ['', bh, '', '', danwei, '', '', '', '2', '', '1', '', '',  '', '', '' ]
+                   ['', bh, mingcheng, '', danwei, '', '', '', '2', '', '1', '', '',  '', '', '' ]
                       ],
                 'key' :   uuidv4(),
                 "fuzhuEnable": false
@@ -1422,6 +1813,56 @@ async generateQingdanTuijian(name, bh, bt, bm) {
 
     }
 
+    danxiangdinge_djcs(row) {
+        let bh = danxiangdinge_index_djcs(this.cache_djcs);
+        
+        if (this.cache_djcs.filter(x=>x['key'] == row).length > 0) {
+            let selected = this.cache_djcs.filter(x=>x['key'] == row)[0];
+            let danwei = selected["单位"];
+            let mingcheng = selected['名称'];
+            let children = selected["_children"];
+            children.push({
+                
+                '序号': null,
+                '清单编码': bh,
+                '名称': mingcheng,
+                '项目特征': null,
+                '计算规则': null,
+                '单位': danwei,
+                '数量': '1',
+                '综合单价': '',
+                '合价': '',
+                '人工费': '0',
+                '主材费': '0',
+                '设备费': '0',
+                '辅材费': '',
+                '材料费': '',
+                '机械费': '0',
+                '管理费': '0',
+                '利润': '0',
+                '暂估价': null,
+                '综合人工工日': null,
+                '备注': null,
+                "dercj": [["ID", "人材机编码", "名称", "规格型号", "单位", "单价", "产地", 
+                "供应厂商", "人材机类别", "甲供标志", "含量", "合价", "暂估价标志", "主要材料标志", "主材标志", "设备标志" ],
+                   ['', bh, mingcheng, '', danwei, '', '', '', '2', '', '1', '', '',  '', '', '' ]
+                      ],
+                'key' :   uuidv4(),
+                "fuzhuEnable": false
+
+                
+            });
+            let summarized = this.summarize_djcs(this.cache_djcs);
+            this.push_op_djcs(summarized);
+            this.cache_djcs = copy(summarized);
+            
+            return [true, copy(this.cache_djcs)];
+        } else {
+            return [false,null];
+        }
+
+    }
+
     
 }
 

+ 34 - 0
front/src/editor.js

@@ -12,6 +12,11 @@ export const undo = () => {
     return newData;
 };
 
+export const undo_djcs = () => {
+    let newData = Service.undo_djcs();
+    return newData;
+};
+
 
 
 export const redo = () => {
@@ -19,6 +24,11 @@ export const redo = () => {
     return newData;
 };
 
+export const redo_djcs = () => {
+    let newData = Service.redo_djcs();
+    return newData;
+};
+
 export const shanchu = ( selectedRow) => {
    
     
@@ -28,6 +38,15 @@ export const shanchu = ( selectedRow) => {
     return newData;
   };
 
+  export const shanchu_djcs = ( selectedRow) => {
+   
+    
+    
+    let newData = Service.shanchu_djcs(selectedRow);
+    
+    return newData;
+  };
+
 
 
 
@@ -38,11 +57,21 @@ export const danxiangdinge = (selectedRow) => {
     return Service.danxiangdinge(selectedRow);
 };
 
+export const danxiangdinge_djcs = (selectedRow) => {
+    return Service.danxiangdinge_djcs(selectedRow);
+};
+
 export const updateDercj = (row, data) => {
     return Service.updateDercj(row, data);
 
 };
 
+export const updateDercj_djcs = (row, data) => {
+    return Service.updateDercj_djcs(row, data);
+
+};
+
+
 export const huan = (replaceState, row) => {
     return Service.huan(replaceState['old'],replaceState['newBianhao'],replaceState['newName'], replaceState['newJia'], row);
 
@@ -53,6 +82,11 @@ export const updateShuliang = (data, row) => {
 
 };
 
+export const updateShuliang_djcs = (data, row) => {
+    return Service.updateShuliang_djcs(data, row);
+
+};
+
 export const changguidinge = (dingeclick, selectedRow) => {
     return Service.changguidinge(dingeclick, selectedRow);
 

+ 26 - 0
front/src/utils.js

@@ -21,6 +21,32 @@ export const danxiangdinge_index = (data) => {
 
     
   };
+
+  export const danxiangdinge_index_djcs = (data) => {
+    let max = 0;
+    for(let i = 0;  i< data.length; i++) {
+        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")) {
+                    let number = de["清单编码"].substring(1);
+                    let n = Number(number);
+                    if (n > max) {
+                        max = n;
+                    }
+                }
+            }
+        }
+    }
+        let result =  (max + 1).toString();
+        result = result.padStart(5, '0');
+        return "D".concat(result);
+
+    
+  };
+
+
 export const copy = (input) => {
     return JSON.parse(JSON.stringify(input));
 };

+ 8 - 0
main.py

@@ -461,6 +461,14 @@ async def save(r: Info):
     return await db.save(client, data)
 
 
+@app.post("/savedjcs/")
+async def savedjcs(r: Info):
+    data = json.loads(r.name)
+    print(data)
+ 
+    return await db.savedjcs(client, data)
+
+
 @app.post("/applyFL/")
 async def applyFL(r: InfoWithID):
     data = json.loads(r.name)

+ 11 - 1
subdir/db.py

@@ -615,7 +615,7 @@ async def getDjcs(client, objectid, id):
         ##post["ID"] = post["_id"]
         del post["_id"]
         ##print( post["rcj"])
-        del post["DogNum"]
+       ## del post["DogNum"]
         result.append(post)
 
 
@@ -712,6 +712,16 @@ async def save(client, data):
 
     return {"result": "ok"}
 
+async def savedjcs(client, data):
+    db = client["baojia"]
+    collection = db["Djcs"]
+    for entry in data:
+        entry["__children"] = entry["_children"]
+        del entry["_children"]
+        await collection.replace_one({"biao_id": entry["biao_id"], "Dwgcbh": entry["Dwgcbh"],  "清单编码": entry["清单编码"]}, entry)
+
+    return {"result": "ok"}
+
 async def applyFL(client, id, data):
     db = client["baojia"]
     collection = db["qufei"]