瀏覽代碼

support 费率

Xiaopeng Zhang 6 月之前
父節點
當前提交
2c7d08722c
共有 9 個文件被更改,包括 1023 次插入7 次删除
  1. 27 4
      front/src/App2.js
  2. 89 0
      front/src/EditableSelect.js
  3. 106 0
      front/src/EditableSelectGC.js
  4. 660 0
      front/src/Qufei.js
  5. 41 0
      front/src/Service.js
  6. 12 0
      main.py
  7. 40 0
      qufei.py
  8. 31 3
      subdir/db.py
  9. 17 0
      subdir/service.py

+ 27 - 4
front/src/App2.js

@@ -23,6 +23,7 @@ import Qingdan from './Qingdan';
 import Zjcs from './Zjcs';
 import Djcs from './Djcs';
 import Service from './Service';
+import Qufei from './Qufei';
 import {useLocation, useParams} from "react-router";
 import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
 import Typography from '@mui/material/Typography';
@@ -46,6 +47,7 @@ import DialogActions from '@mui/material/DialogActions';
 import IconButton from '@mui/material/IconButton';
 import CloseIcon from '@mui/icons-material/Close';
 import SearchIcon from '@mui/icons-material/Search';
+import Button from '@mui/material/Button';
 
 import {
   Toolbar,
@@ -215,6 +217,7 @@ const MUI_X_PRODUCTS = [
     const [nest, setNest] = React.useState(false);
     const [qingdan, setQingdan] = React.useState(false);
     const [cuoshi, setCuoshi] = React.useState(false);
+    const [qufei, setQufei] = React.useState(false);
     const [qdbt, setQdbt] = React.useState([]);
     const [qdbh, setQdbh] = React.useState(null);
     const [value, setValue] = React.useState('1');
@@ -627,6 +630,7 @@ const MUI_X_PRODUCTS = [
                   setNest(true);
                   setQingdan(false);
                   setCuoshi(false);
+                  setQufei(false);
                   setColumnHeaders(["序号", "名称", "金额", "暂估价", "类别"]);
                 });
         }
@@ -638,6 +642,7 @@ const MUI_X_PRODUCTS = [
                   setNest(true);
                   setQingdan(false);
                   setCuoshi(false);
+                  setQufei(false);
                   setColumnHeaders(["序号", "名称", "取费基数", "计算基础", "金额", "类别"]);
                 });
 
@@ -652,6 +657,7 @@ const MUI_X_PRODUCTS = [
                   setCuoshi(false);
                   setQdbt(x);
                   setQdbh(id);
+                  setQufei(false);
                   //setColumnHeaders(["序号", "名称", "取费基数", "计算基础", "金额", "类别"]);
                 });
 
@@ -664,6 +670,7 @@ const MUI_X_PRODUCTS = [
           setQingdan(false);
           setCuoshi(true);
           setDwgc(id);
+          setQufei(false);
           //setColumnHeaders(["序号", "名称", "取费基数", "计算基础", "金额", "类别"]);
 
         }
@@ -677,6 +684,7 @@ const MUI_X_PRODUCTS = [
                   setNest(true);
                   setQingdan(false);
                   setCuoshi(false);
+                  setQufei(false);
                   setColumnHeaders(["序号", "名称", "金额", "项目类别", "备注"]);
                 });
 
@@ -691,6 +699,7 @@ const MUI_X_PRODUCTS = [
                   setNest(false);
                   setQingdan(false);
                   setCuoshi(false);
+                  setQufei(false);
                 });
 
         }
@@ -704,6 +713,7 @@ const MUI_X_PRODUCTS = [
                   setNest(false);
                   setQingdan(false);
                   setCuoshi(false);
+                  setQufei(false);
                 });
 
         }
@@ -717,6 +727,7 @@ const MUI_X_PRODUCTS = [
                   setNest(false);
                   setQingdan(false);
                   setCuoshi(false);
+                  setQufei(false);
                 });
 
         }
@@ -730,6 +741,7 @@ const MUI_X_PRODUCTS = [
                   setNest(false);
                   setQingdan(false);
                   setCuoshi(false);
+                  setQufei(false);
                 });
 
         }
@@ -743,6 +755,7 @@ const MUI_X_PRODUCTS = [
                   setNest(false);
                   setQingdan(false);
                   setCuoshi(false);
+                  setQufei(false);
                 });
 
         }
@@ -752,6 +765,7 @@ const MUI_X_PRODUCTS = [
             setCuoshi(false);
             setDetail(x);
             setNest(false);
+            setQufei(false);
         });
 
         }
@@ -862,6 +876,13 @@ const MUI_X_PRODUCTS = [
                    </Stack>
                    </AccordionDetails>
                  </Accordion>
+
+                 <Button variant="outlined" fullWidth onClick={()=> {
+                  setQufei(true);
+                  setQingdan(false);
+                  setCuoshi(false);
+                 }}>费率</Button>
+
             
 
 
@@ -869,7 +890,7 @@ const MUI_X_PRODUCTS = [
             </Grid>
             <Grid size={9}>
              
-            {!nest && !qingdan && !cuoshi && <HotTable nestedRows={false}
+            {!nest && !qingdan && !cuoshi && !qufei && <HotTable nestedRows={false}
                     data={detail
                     }
                     rowHeaders={true}
@@ -882,7 +903,7 @@ const MUI_X_PRODUCTS = [
                     autoWrapCol={false}
                     licenseKey="non-commercial-and-evaluation" // for non-commercial use only
                   />}
-            {nest && !qingdan && !cuoshi && <HotTable nestedRows={true}
+            {nest && !qingdan && !cuoshi && !qufei && <HotTable nestedRows={true}
                     data={nestDetail
                     }
                     readOnly={true}
@@ -897,8 +918,10 @@ const MUI_X_PRODUCTS = [
                     autoWrapCol={false}
                     licenseKey="non-commercial-and-evaluation" // for non-commercial use only
                   />}
+            {!qingdan && !cuoshi && qufei && <Qufei id={location['id']}
+                  />}
 
-            {!nest && qingdan && !cuoshi && <TabContext value={value}>
+            {!nest && qingdan && !cuoshi && !qufei &&  <TabContext value={value}>
                    <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
                       <TabList scrollButtons='auto' 
                               variant="scrollable"
@@ -926,7 +949,7 @@ const MUI_X_PRODUCTS = [
                      </TabPanel>
                       )}
                 </TabContext>}
-            {!nest && !qingdan && cuoshi && <TabContext value={value}>
+            {!nest && !qingdan && cuoshi && !qufei &&  <TabContext value={value}>
                    <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
                       <TabList scrollButtons='auto' 
                               variant="scrollable"

+ 89 - 0
front/src/EditableSelect.js

@@ -0,0 +1,89 @@
+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 {HotTable} from "@handsontable/react";
+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 { registerPlugin, NestedRows } from 'handsontable/plugins';
+//registerPlugin(NestedRows);
+import Qingdan from './Qingdan';
+import Zjcs from './Zjcs';
+import Djcs from './Djcs';
+import Service from './Service';
+import {useLocation} from "react-router";
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+import Typography from '@mui/material/Typography';
+import InputLabel from '@mui/material/InputLabel';
+import MenuItem from '@mui/material/MenuItem';
+import FormControl from '@mui/material/FormControl';
+import Select from '@mui/material/Select';
+import Accordion from '@mui/material/Accordion';
+import AccordionActions from '@mui/material/AccordionActions';
+import AccordionSummary from '@mui/material/AccordionSummary';
+import AccordionDetails from '@mui/material/AccordionDetails';
+import Stack from '@mui/material/Stack';
+import { DataGrid } from '@mui/x-data-grid';
+
+import Button from '@mui/material/Button';
+import TextField from '@mui/material/TextField';
+
+
+
+
+  export default function EditableSelect({ initialText,  onChange }) {
+    const [isEditing, setIsEditing] = React.useState(false);
+    const [textValue, setTextValue] = React.useState(initialText);
+    const handleChange = (event) => {
+      setTextValue(event.target.value);
+      setIsEditing(false);
+      onChange(event.target.value);
+    };
+    React.useEffect(
+      () => {
+        setTextValue(initialText);
+        setIsEditing(false);
+        
+      }, [initialText]
+    );
+    return (
+
+        <Box>
+        {isEditing ? (
+            <FormControl sx={{ m: 1, minWidth: 100 }} size="small">
+            <InputLabel id="demo-select-small-label">工程类别</InputLabel>
+            <Select
+              labelId="demo-select-small-label"
+              id="demo-select-small"
+              value={textValue}
+              label="工程类别"
+              onChange={handleChange}
+              onBlur={()=>{
+                setIsEditing(false);
+              }}
+            >
+              <MenuItem value="">
+                <em></em>
+              </MenuItem>
+              <MenuItem value={"一类工程"}>一类工程</MenuItem>
+              <MenuItem value={"二类工程"}>二类工程</MenuItem>
+              <MenuItem value={"三类工程"}>三类工程</MenuItem>
+            </Select>
+          </FormControl>
+          ) : (
+            <Button disableRipple variant="text" color="#000000"
+               onDoubleClick={()=>{
+                setIsEditing(true);
+               }}
+            >{textValue}</Button>
+          )}
+        </Box>
+    
+    );
+  }

+ 106 - 0
front/src/EditableSelectGC.js

@@ -0,0 +1,106 @@
+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 {HotTable} from "@handsontable/react";
+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 { registerPlugin, NestedRows } from 'handsontable/plugins';
+//registerPlugin(NestedRows);
+import Qingdan from './Qingdan';
+import Zjcs from './Zjcs';
+import Djcs from './Djcs';
+import Service from './Service';
+import {useLocation} from "react-router";
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
+import Typography from '@mui/material/Typography';
+import InputLabel from '@mui/material/InputLabel';
+import MenuItem from '@mui/material/MenuItem';
+import FormControl from '@mui/material/FormControl';
+import Select from '@mui/material/Select';
+import Accordion from '@mui/material/Accordion';
+import AccordionActions from '@mui/material/AccordionActions';
+import AccordionSummary from '@mui/material/AccordionSummary';
+import AccordionDetails from '@mui/material/AccordionDetails';
+import Stack from '@mui/material/Stack';
+import { DataGrid } from '@mui/x-data-grid';
+
+import Button from '@mui/material/Button';
+import TextField from '@mui/material/TextField';
+
+import ListSubheader from '@mui/material/ListSubheader';
+
+
+
+  export default function EditableSelectGC({ initialText,  onChange }) {
+    const [isEditing, setIsEditing] = React.useState(false);
+    const [textValue, setTextValue] = React.useState(initialText);
+    const handleChange = (event) => {
+      setTextValue(event.target.value);
+      setIsEditing(false);
+      onChange(event.target.value);
+    };
+    React.useEffect(
+      () => {
+        setTextValue(initialText);
+        setIsEditing(false);
+        
+      }, [initialText]
+    );
+    return (
+
+        <Box>
+        {isEditing ? (
+            <FormControl sx={{ m: 1, minWidth: 100 }} size="small">
+            <InputLabel id="demo-select-small-label">工程类型</InputLabel>
+            <Select
+              labelId="demo-select-small-label"
+              id="demo-select-small"
+              value={textValue}
+              label="工程类型"
+              onChange={handleChange}
+              onBlur={()=>{
+                setIsEditing(false);
+              }}
+            >
+              <MenuItem value="">
+                <em></em>
+              </MenuItem>
+              <ListSubheader>建筑工程</ListSubheader>
+              <MenuItem value={"建筑工程"}>建筑工程</MenuItem>
+              <MenuItem value={"单独预制构件制作"}>单独预制构件制作</MenuItem>
+              <MenuItem value={"打预制桩、单独构件吊装"}>打预制桩、单独构件吊装</MenuItem>
+              <MenuItem value={"单独预制构件制作"}>单独预制构件制作</MenuItem>
+              <MenuItem value={"制作兼打桩"}>制作兼打桩</MenuItem>
+              <MenuItem value={"大型土石方工程"}>大型土石方工程</MenuItem>
+              <ListSubheader>单独装饰工程</ListSubheader>
+              <MenuItem value={"单独装饰工程"}>单独装饰工程</MenuItem>
+              <ListSubheader>安装工程</ListSubheader>
+              <MenuItem value={"安装工程"}>安装工程</MenuItem>
+              <ListSubheader>市政工程</ListSubheader>
+              <MenuItem value={"通用项目、道路、排水工程"}>通用项目、道路、排水工程</MenuItem>
+              <MenuItem value={"桥梁、水工构筑物"}>桥梁、水工构筑物</MenuItem>
+              <MenuItem value={"给水、燃气与集中供热"}>给水、燃气与集中供热</MenuItem>
+              <MenuItem value={"路灯及交通设施工程"}>路灯及交通设施工程</MenuItem>
+              <MenuItem value={"(市)大型土石方工程"}>(市)大型土石方工程</MenuItem>
+              
+
+            </Select>
+          </FormControl>
+          ) : (
+            <Button disableRipple variant="text" color="#000000"
+               onDoubleClick={()=>{
+                setIsEditing(true);
+               }}
+            >{textValue}</Button>
+          )}
+        </Box>
+    
+    );
+  }

+ 660 - 0
front/src/Qufei.js

@@ -0,0 +1,660 @@
+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 {HotTable} from "@handsontable/react";
+//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 { Table, ConfigProvider, Button as AButton } from "antd";
+import EditableSelect from './EditableSelect';
+import EditableSelectGC from './EditableSelectGC';
+import Editable from './Editable';
+import Button from '@mui/material/Button';
+
+import {copy} from './utils';
+
+export default function Qufei({id}) {
+    
+  const [detail, setDetail] = React.useState([
+    {"序号": null, "清单编码" : null, "名称" : null,"项目特征" : null,
+    "计算规则" : null,
+    "单位" : null,
+    "数量": null,
+    "综合单价" : null,
+    "合价" : null,
+    "人工费": null,
+    "主材费" : null,
+    "设备费": null,
+    "辅材费": null,
+    "材料费" : null,
+    "机械费" : null,
+    "管理费": null,
+    "利润": null,
+    "暂估价" : null,
+    "综合人工工日" : null,
+    "备注" : null}]
+);
+
+const hotRef = React.useRef(null);
+const [expandedRowKeys, setExpandedRowKeys] = React.useState([]);
+const [selectedRowKeys, setSelectedRowKeys] = React.useState([]);
+
+
+
+const apply = () => {
+  let checked = check(detail);
+  if (checked) {
+    Service.applyFL(id, detail).then(x=>{
+
+    });
+  }
+};
+
+const check = (data) => {
+  for(let i = 0; i < data.length; i++) {
+    if (data[i]['管理费(%)'].length == 0) {
+      return false;
+    }
+    if (data[i]['利润(%)'].length == 0) {
+      return false;
+    }
+    if (data[i].hasOwnProperty('children')) {
+       let checked = check(data[i]['children']);
+       if (!checked) {
+          return false;
+       }
+       return true;
+    }
+    else {
+      return true;
+    }
+    
+
+  }
+};
+
+
+const rowSelection = {
+  selectedRowKeys,
+  onChange: (selectedRowKeys) => {
+       //console.log(selectedRowKeys);
+       if (selectedRowKeys.length > 0) {
+            setExpandedRowKeys([selectedRowKeys.at(-1)]);
+       } else {
+       setSelectedRowKeys(selectedRowKeys);
+       //handleSelection(selectedRowKeys);
+       }
+  }
+};
+
+const traverse = (data) => {
+  for(let i = 0; i < data.length; i++) {
+    if (data[i]['工程类型'].length > 0 && data[i]['工程类别'].length > 0) {
+        if (data[i]['工程类型'] == '建筑工程') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '32';
+            data[i]['利润(%)'] = '12';
+            data[i]['备注'] = '';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '29';
+            data[i]['利润(%)'] = '12';
+            data[i]['备注'] = '';
+          } else {
+            data[i]['管理费(%)'] = '26';
+            data[i]['利润(%)'] = '12';
+            data[i]['备注'] = '';
+          }
+        }
+        if (data[i]['工程类型'] == '单独预制构件制作') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '15';
+            data[i]['利润(%)'] = '6';
+            data[i]['备注'] = '';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '13';
+            data[i]['利润(%)'] = '6';
+            data[i]['备注'] = '';
+          } else {
+            data[i]['管理费(%)'] = '11';
+            data[i]['利润(%)'] = '6';
+            data[i]['备注'] = '';
+          }
+        }
+        if (data[i]['工程类型'] == '打预制桩、单独构件吊装') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '11';
+            data[i]['利润(%)'] = '5';
+            data[i]['备注'] = '';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '9';
+            data[i]['利润(%)'] = '5';
+            data[i]['备注'] = '';
+          } else {
+            data[i]['管理费(%)'] = '7';
+            data[i]['利润(%)'] = '5';
+            data[i]['备注'] = '';
+          }
+        }
+        if (data[i]['工程类型'] == '制作兼打桩') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '17';
+            data[i]['利润(%)'] = '7';
+            data[i]['备注'] = '';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '15';
+            data[i]['利润(%)'] = '7';
+            data[i]['备注'] = '';
+          } else {
+            data[i]['管理费(%)'] = '12';
+            data[i]['利润(%)'] = '7';
+            data[i]['备注'] = '';
+          }
+        }
+        if (data[i]['工程类型'] == '大型土石方工程') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '7';
+            data[i]['利润(%)'] = '4';
+            data[i]['备注'] = '';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '7';
+            data[i]['利润(%)'] = '4';
+            data[i]['备注'] = '';
+          } else {
+            data[i]['管理费(%)'] = '7';
+            data[i]['利润(%)'] = '4';
+            data[i]['备注'] = '';
+          }
+        }
+        if (data[i]['工程类型'] == '单独装饰工程') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '43';
+            data[i]['利润(%)'] = '15';
+            data[i]['备注'] = '';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '43';
+            data[i]['利润(%)'] = '15';
+            data[i]['备注'] = '';
+          } else {
+            data[i]['管理费(%)'] = '43';
+            data[i]['利润(%)'] = '15';
+            data[i]['备注'] = '';
+          }
+        }
+        if (data[i]['工程类型'] == '安装工程') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '48';
+            data[i]['利润(%)'] = '14';
+            data[i]['备注'] = '计算基础:人工费';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '44';
+            data[i]['利润(%)'] = '14';
+            data[i]['备注'] = '计算基础:人工费';
+          } else {
+            data[i]['管理费(%)'] = '40';
+            data[i]['利润(%)'] = '14';
+            data[i]['备注'] = '计算基础:人工费';
+          }
+        }
+        if (data[i]['工程类型'] == '通用项目、道路、排水工程') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '26';
+            data[i]['利润(%)'] = '10';
+            data[i]['备注'] = '';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '23';
+            data[i]['利润(%)'] = '10';
+            data[i]['备注'] = '';
+          } else {
+            data[i]['管理费(%)'] = '20';
+            data[i]['利润(%)'] = '10';
+            data[i]['备注'] = '';
+          }
+        }
+        if (data[i]['工程类型'] == '桥梁、水工构筑物') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '35';
+            data[i]['利润(%)'] = '10';
+            data[i]['备注'] = '';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '32';
+            data[i]['利润(%)'] = '10';
+            data[i]['备注'] = '';
+          } else {
+            data[i]['管理费(%)'] = '29';
+            data[i]['利润(%)'] = '10';
+            data[i]['备注'] = '';
+          }
+        }
+        if (data[i]['工程类型'] == '给水、燃气与集中供热') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '45';
+            data[i]['利润(%)'] = '13';
+            data[i]['备注'] = '计算基础:人工费';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '41';
+            data[i]['利润(%)'] = '13';
+            data[i]['备注'] = '计算基础:人工费';
+          } else {
+            data[i]['管理费(%)'] = '37';
+            data[i]['利润(%)'] = '13';
+            data[i]['备注'] = '计算基础:人工费';
+          }
+        }
+        if (data[i]['工程类型'] == '路灯及交通设施工程') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '43';
+            data[i]['利润(%)'] = '13';
+            data[i]['备注'] = '计算基础:人工费';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '43';
+            data[i]['利润(%)'] = '13';
+            data[i]['备注'] = '计算基础:人工费';
+          } else {
+            data[i]['管理费(%)'] = '43';
+            data[i]['利润(%)'] = '13';
+            data[i]['备注'] = '计算基础:人工费';
+          }
+        }
+        if (data[i]['工程类型'] == '(市)大型土石方工程') {
+          if (data[i]['工程类别'] == '一类工程') {
+            data[i]['管理费(%)'] = '7';
+            data[i]['利润(%)'] = '4';
+            data[i]['备注'] = '';
+          } else if (data[i]['工程类别'] == '二类工程') {
+            data[i]['管理费(%)'] = '7';
+            data[i]['利润(%)'] = '4';
+            data[i]['备注'] = '';
+          } else {
+            data[i]['管理费(%)'] = '7';
+            data[i]['利润(%)'] = '4';
+            data[i]['备注'] = '';
+          }
+        }
+
+    }
+    if (data[i].hasOwnProperty("children")) {
+      traverse(data[i]['children']);
+    }
+  }
+  return data;
+};
+
+
+
+const handleChangeLR = (value) => {
+  if (selectedRowKeys.length > 0 && detail.length > 0) {
+    let selected = selectedRowKeys[0];
+    if (detail[0]['key'] == selected) {
+      //总选择
+      let newData = copy(detail);
+      newData[0]['利润(%)'] = value;
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        child['利润(%)'] = value;
+        for(let j = 0; j < child['children'].length; j++) {
+          child['children'][j]['利润(%)'] = value;
+        }
+      }
+      setDetail(newData);
+
+    }
+    else if (detail[0]["children"].filter(x=>x['key'] == selected).length > 0) {
+      //某个单项工程
+      let newData = copy(detail);
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        if (child['key'] == selected) {
+          child['利润(%)'] = value;
+          for(let j = 0; j < child['children'].length; j++) {
+            child['children'][j]['利润(%)'] = value;
+          }
+        }
+        
+      } 
+      setDetail(newData);
+    } else {
+      //具体一行
+      let newData = copy(detail);
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        
+        for(let j = 0; j < child['children'].length; j++) {
+          if (child['children'][j]['key'] == selected) {  
+              child['children'][j]['利润(%)'] = value;
+          }
+        }
+        
+        
+      } 
+      setDetail(newData);
+    }
+
+
+  }
+};
+
+
+const handleChangeGLF = (value) => {
+  if (selectedRowKeys.length > 0 && detail.length > 0) {
+    let selected = selectedRowKeys[0];
+    if (detail[0]['key'] == selected) {
+      //总选择
+      let newData = copy(detail);
+      newData[0]['管理费(%)'] = value;
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        child['管理费(%)'] = value;
+        for(let j = 0; j < child['children'].length; j++) {
+          child['children'][j]['管理费(%)'] = value;
+        }
+      }
+      setDetail(newData);
+
+    }
+    else if (detail[0]["children"].filter(x=>x['key'] == selected).length > 0) {
+      //某个单项工程
+      let newData = copy(detail);
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        if (child['key'] == selected) {
+          child['管理费(%)'] = value;
+          for(let j = 0; j < child['children'].length; j++) {
+            child['children'][j]['管理费(%)'] = value;
+          }
+        }
+        
+      } 
+      setDetail(newData);
+    } else {
+      //具体一行
+      let newData = copy(detail);
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        
+        for(let j = 0; j < child['children'].length; j++) {
+          if (child['children'][j]['key'] == selected) {  
+              child['children'][j]['管理费(%)'] = value;
+          }
+        }
+        
+        
+      } 
+      setDetail(newData);
+    }
+
+
+  }
+};
+
+
+const handleChange = (value) => {
+  if (selectedRowKeys.length > 0 && detail.length > 0) {
+    let selected = selectedRowKeys[0];
+    if (detail[0]['key'] == selected) {
+      //总选择
+      let newData = copy(detail);
+      newData[0]['工程类别'] = value;
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        child['工程类别'] = value;
+        for(let j = 0; j < child['children'].length; j++) {
+          child['children'][j]['工程类别'] = value;
+        }
+      }
+      setDetail(traverse(newData));
+
+    }
+    else if (detail[0]["children"].filter(x=>x['key'] == selected).length > 0) {
+      //某个单项工程
+      let newData = copy(detail);
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        if (child['key'] == selected) {
+          child['工程类别'] = value;
+          for(let j = 0; j < child['children'].length; j++) {
+            child['children'][j]['工程类别'] = value;
+          }
+        }
+        
+      } 
+      setDetail(traverse(newData));
+    } else {
+      //具体一行
+      let newData = copy(detail);
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        
+        for(let j = 0; j < child['children'].length; j++) {
+          if (child['children'][j]['key'] == selected) {  
+              child['children'][j]['工程类别'] = value;
+          }
+        }
+        
+        
+      } 
+      setDetail(traverse(newData));
+    }
+
+
+  }
+};
+
+const handleChangeGC = (value) => {
+  if (selectedRowKeys.length > 0 && detail.length > 0) {
+    let selected = selectedRowKeys[0];
+    if (detail[0]['key'] == selected) {
+      //总选择
+      let newData = copy(detail);
+      newData[0]['工程类型'] = value;
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        child['工程类型'] = value;
+        for(let j = 0; j < child['children'].length; j++) {
+          child['children'][j]['工程类型'] = value;
+        }
+      }
+      setDetail(traverse(newData));
+
+    }
+    else if (detail[0]["children"].filter(x=>x['key'] == selected).length > 0) {
+      //某个单项工程
+      let newData = copy(detail);
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        if (child['key'] == selected) {
+          child['工程类型'] = value;
+          for(let j = 0; j < child['children'].length; j++) {
+            child['children'][j]['工程类型'] = value;
+          }
+        }
+        
+      } 
+      setDetail(traverse(newData));
+    } else {
+      //具体一行
+      let newData = copy(detail);
+      for(let i = 0; i < newData[0]["children"].length; i++) {
+        let child = newData[0]['children'][i];
+        
+        for(let j = 0; j < child['children'].length; j++) {
+          if (child['children'][j]['key'] == selected) {  
+              child['children'][j]['工程类型'] = value;
+          }
+        }
+        
+        
+      } 
+      setDetail(traverse(newData));
+    }
+
+
+  }
+};
+
+function selectRow(record) {
+  /*
+  const selectedRowKeys_ = [...selectedRowKeys];
+  if (selectedRowKeys_.indexOf(record.key) >= 0) {
+       selectedRowKeys_.splice(selectedRowKeys_.indexOf(record.key), 1);
+  } else {
+       selectedRowKeys_.push(record.key);
+  }*/
+   setSelectedRowKeys([record.key]);
+}
+React.useEffect(
+  () => {
+    
+    Service.generateQufei(id).then(x=>{
+
+    setDetail(x);
+    });
+  
+     
+  }, [id]
+);
+
+
+    return (
+                 <Box>
+                <Button variant="outlined" onClick={apply}>应用</Button>
+                <ConfigProvider
+                   theme={{
+                    components: {
+                      Table: {
+                        /* here is your component tokens */
+                        cellPaddingBlock : 8
+                      },
+                    },
+                  }}
+                   >
+                 <Table 
+                    dataSource={detail}
+                    
+                    
+                    //afterSelection={handleSelection}
+                    //afterSelection={handleSelection}
+                    ref = {hotRef}
+                    expandable = {
+                         {
+                              expandedRowKeys,
+                              onExpand: (expandable, record) => {
+                                   if (expandable) {
+                                     setExpandedRowKeys([...expandedRowKeys, record.key]);
+                                   } else {
+                                     setExpandedRowKeys(expandedRowKeys.filter((id) => record.key !== id));
+                                   }
+                                 },
+                              expandRowByClick: true
+                         }
+                    }
+
+                    rowSelection= {rowSelection}
+                    onRow={(record)=>({
+                         onClick: () => {
+                              selectRow(record);
+                            }
+                    })}
+                    scroll={{ x: 'max-content' , y : 'calc(100vh - 200px)'}}
+                    //pagination={{ position: ['none', 'none'] }}
+                    pagination={false}
+                    columns = {[
+                         
+                         { dataIndex: '操作',        title : '操作',        key : '操作'          , width : 30 , fixed: 'left'   },
+                         { dataIndex: '名称'   ,      title : '名称'  ,       key : '名称'        , width : 250         },
+                         { dataIndex: '工程类型' ,    title : '工程类型' ,  
+                           key : '工程类型'    , width : 150  ,
+                           render: (text, record) => {
+                            //console.log("column render");
+                            //console.log("text".concat(text));
+                            //console.log(record);
+                                   
+                                      return ( 
+                                           <EditableSelectGC initialText={text}  onChange={handleChangeGC}
+                                           >
+                                          </EditableSelectGC>
+                                       );
+                                    
+                                    //console.log(text);
+                                    
+                            }
+                             },
+                         { dataIndex: '工程类别' ,    title : '工程类别' ,  
+                           key : '工程类别'    , width : 100  ,
+                           render: (text, record) => {
+                            //console.log("column render");
+                            //console.log("text".concat(text));
+                            //console.log(record);
+                                   
+                                      return ( 
+                                           <EditableSelect initialText={text}  onChange={handleChange}
+                                           >
+                                          </EditableSelect>
+                                       );
+                                    
+                                    //console.log(text);
+                                    
+                            }
+                             },
+                         { dataIndex: '管理费(%)' ,    title : '管理费(%)' ,    key : '管理费(%)'    , width : 50   ,
+                         render: (text, record) => {
+                          //console.log("column render");
+                          //console.log("text".concat(text));
+                          //console.log(record);
+                                 
+                                    return ( 
+                                         <Editable initialText={text}  onChange={handleChangeGLF}
+                                         >
+                                        </Editable>
+                                     );
+                                  
+                                  //console.log(text);
+                                  
+                          }      },
+                         { dataIndex: '利润(%)'    ,     title : '利润(%)'  ,       key : '利润(%)'        , width : 50  ,
+                         render: (text, record) => {
+                          //console.log("column render");
+                          //console.log("text".concat(text));
+                          //console.log(record);
+                                 
+                                    return ( 
+                                         <Editable initialText={text}  onChange={handleChangeLR}
+                                         >
+                                        </Editable>
+                                     );
+                                  
+                                  //console.log(text);
+                                  
+                          }
+                        },
+                        { dataIndex: '备注',        title : '备注',        key : '备注'          , width : 100   },
+
+                       
+                        
+
+                         
+                             
+                            
+                       ]}
+                   
+                  />
+                  </ConfigProvider>
+
+
+                 </Box>
+
+                  
+
+
+
+    );
+}

+ 41 - 0
front/src/Service.js

@@ -71,6 +71,25 @@ class Service{
             return data;
         }
     }
+
+    async generateQufei(name) {
+        const response = await fetch(this.ip().concat( ":8000/qufei"), {
+            method : "POST",
+            headers: {
+                "Content-type": "application/json"
+            },
+            body : JSON.stringify({
+                "name": name
+            })
+        });
+        if (!response.ok) {
+            //const error = await response.json();
+            console.error('error');
+        } else {
+            const data = await response.json();
+            return data;
+        }
+    }
     async generateOutline2(name) {
         const response = await fetch(this.ip().concat( ":8000/outline2"), {
             method : "POST",
@@ -800,6 +819,28 @@ async generateQingdanTuijian(name, bh, bt, bm) {
         }
     }
 
+    async applyFL(id, data) {
+        const response = await fetch(this.ip().concat( ":8000/applyFL/"), {
+            method : "POST",
+            headers: {
+                "Content-type": "application/json"
+            },
+            body: JSON.stringify(
+                {
+                    "id": id,
+                    "name": JSON.stringify(data)
+                }
+            )
+        });
+        if (!response.ok) {
+            //const error = await response.json();
+            console.error('error');
+        } else {
+            const data = await response.json();
+            return data;
+        }
+    }
+
 
 
 

+ 12 - 0
main.py

@@ -400,6 +400,10 @@ async def read_pbxl(r: Info):
     #print(result)
     return result
 
+@app.post("/qufei/")
+async def read_qufei(r: Info):
+    return await db.getQufei(client, r.name)
+
 @app.post("/dexilie/")
 async def read_dexilie(r: DingeXilieRequest):
     result = service.getDeXilie(r.value, r.id)
@@ -450,6 +454,14 @@ async def save(r: Info):
     return await db.save(client, data)
 
 
+@app.post("/applyFL/")
+async def applyFL(r: InfoWithID):
+    data = json.loads(r.name)
+    print(data)
+ 
+    return await db.applyFL(client, r.id, data)
+
+
 
 
 async def resolve(websocket, data):

+ 40 - 0
qufei.py

@@ -0,0 +1,40 @@
+import xml.etree.ElementTree as ET
+from subdir import service
+from bson.objectid import ObjectId
+from pymongo import AsyncMongoClient
+import asyncio
+
+import uuid
+
+
+
+
+client = AsyncMongoClient()
+async def resolve(data):
+    db = client["baojia"]
+    collection = db["jingjibiao"]
+    document = await collection.find_one({'_id': ObjectId(data)})
+    dxgc = document['Dxgcxx']
+    result = []
+    for entry in dxgc:
+        newone = {"名称" : entry['Dxgcmc'], "工程类型":"", "工程类别": "", "管理费(%)": "", "利润(%)": "", "备注":"", "key" : str(uuid.uuid4()) }
+        children = []
+        for dwgc in entry['Dwgc']:
+            children.append({"名称" : dwgc['Dwgcmc'],"工程类型":"", "工程类别": "", "管理费(%)": "", "利润(%)": "","备注":"", "key" : dwgc['Dwgcbh']})
+        newone["children"] = children
+        result.append(newone)
+    collection = db["qufei"]
+    await collection.insert_one({"biao_id": data, "qufei": [{
+        "名称" : document['Xmmc'], "工程类型":"", "工程类别": "", "管理费(%)": "", "利润(%)": "", "备注":"", "key" : str(uuid.uuid4()), "children" : result
+    }]})
+
+
+
+import os
+ttt = ['685be235156b8e6675e2b39f', '685be248ba168dc7c2b52b96', '685be25244c5be685dd5c7c8']
+
+asyncio.run(resolve(ttt[2]))
+
+
+
+

+ 31 - 3
subdir/db.py

@@ -1,7 +1,7 @@
 import xml.etree.ElementTree as ET
 from subdir import service
 from bson.objectid import ObjectId
-
+import uuid
 def getDingercj_(root, bh, bt, qdbm, debm):
     result = [["ID", "人材机编码", "名称", "规格型号", "单位", "单价", "产地", 
     "供应厂商", "人材机类别", "甲供标志", "含量", "合价", "暂估价标志", "主要材料标志", "主材标志", "设备标志" ]]
@@ -401,8 +401,20 @@ async def resolve(manager, websocket, data, client):
                 await collection.insert_one(qd)
             
 
-    
-
+    collection = db["qufei"]
+    document = jingjibiao
+    dxgc = document['Dxgcxx']
+    result = []
+    for entry in dxgc:
+        newone = {"名称" : entry['Dxgcmc'],  "工程类型":"", "工程类别": "", "管理费(%)": "", "利润(%)": "","备注":"", "key" : str(uuid.uuid4()) }
+        children = []
+        for dwgc in entry['Dwgc']:
+            children.append({"名称" : dwgc['Dwgcmc'], "工程类型":"",  "工程类别": "", "管理费(%)": "", "利润(%)": "","备注":"", "key" : dwgc['Dwgcbh']})
+        newone["children"] = children
+        result.append(newone)
+    await collection.insert_one({"biao_id": biao_id, "qufei": [{
+        "名称" : document['Xmmc'], "工程类型":"", "工程类别": "", "管理费(%)": "", "利润(%)": "","备注":"", "key" : str(uuid.uuid4()), "children" : result
+    }]})
 
 
 
@@ -681,6 +693,14 @@ async def getDingercj(client, name, bh, bt, qdbm, debm):
     return result
 
 
+
+async def getQufei(client, id):
+    db = client["baojia"]
+    collection = db["qufei"]
+    document = await collection.find_one({'biao_id': id})
+    return document['qufei']
+
+
 async def save(client, data):
     db = client["baojia"]
     collection = db["qdxm"]
@@ -690,3 +710,11 @@ async def save(client, data):
         await collection.replace_one({"biao_id": entry["biao_id"], "Dwgcbh": entry["Dwgcbh"], "bt": entry["bt"], "清单编码": entry["清单编码"]}, entry)
 
     return {"result": "ok"}
+
+async def applyFL(client, id, data):
+    db = client["baojia"]
+    collection = db["qufei"]
+    
+    await collection.replace_one({"biao_id": id}, {"biao_id": id, "qufei": data})
+
+    return {"result": "ok"}

+ 17 - 0
subdir/service.py

@@ -919,6 +919,23 @@ def getDeXilie(value, id):
         filtered = gj[gj["YSDELBH"]==int(index)]
     return filtered.to_json(force_ascii=False)
 
+
+def getQufei(name):
+    if name == "0":
+        gj = pd.read_csv("de/tj/JD_PeiBi.csv")
+        return gj.to_json(force_ascii=False)
+    shu = pd.read_csv("de/tj/JD_PeiBiFLB.csv")
+    hit = shu[shu["ID"]==int(name)]
+    print(hit)
+    if len(hit) == 0:
+        return []
+    hit0 = hit.iloc[0]
+    index = str(hit0['pblbh'])
+    index_list = index.split(";")
+    gj = pd.read_csv("de/tj/JD_PeiBi.csv")
+    filtered = gj[gj["PBBH"].str.startswith(tuple(index_list))]
+    return filtered.to_json(force_ascii=False)
+
 def getPbxl(name):
     if name == "0":
         gj = pd.read_csv("de/tj/JD_PeiBi.csv")