| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829 |
- import * as React from 'react';
- import AIService from './AIService';
- import Service from './Service';
- import {useNavigate, useLocation} from "react-router";
- import ArrowRightIcon from '@rsuite/icons/ArrowRight';
- import ArrowDownIcon from '@rsuite/icons/ArrowDown';
- import TextField from '@mui/material/TextField';
- import SearchIcon from '@rsuite/icons/Search';
- //registerAllModules();
- import { DataGrid, GridActionsCellItem, zhCN as zh_CN} from '@mui/x-data-grid';
- import Box from '@mui/material/Box';
- import MuiAppBar from '@mui/material/AppBar';
- import { styled, useTheme } from '@mui/material/styles';
- import Toolbar from '@mui/material/Toolbar';
- import Typography from '@mui/material/Typography';
- import CssBaseline from '@mui/material/CssBaseline';
- import AccountCircle from '@mui/icons-material/AccountCircle';
- import Fab from '@mui/material/Fab';
- import Tooltip from '@mui/material/Tooltip';
- import DeleteIcon from '@mui/icons-material/Delete';
- import Button from '@mui/material/Button';
- import Dialog from '@mui/material/Dialog';
- import Drawer from '@mui/material/Drawer';
- import Divider from '@mui/material/Divider';
- import IconButton from '@mui/material/IconButton';
- import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
- import ChevronRightIcon from '@mui/icons-material/ChevronRight';
- import MenuIcon from '@mui/icons-material/Menu';
- import AddIcon from '@mui/icons-material/Add';
- import DialogTitle from '@mui/material/DialogTitle';
- import DialogActions from '@mui/material/DialogActions';
- import CircularProgress from '@mui/material/CircularProgress';
- import Backdrop from '@mui/material/Backdrop';
- import List from '@mui/material/List';
- import ListItem from '@mui/material/ListItem';
- import ListItemButton from '@mui/material/ListItemButton';
- import ListItemIcon from '@mui/material/ListItemIcon';
- import ListItemText from '@mui/material/ListItemText';
- import HomeIcon from '@mui/icons-material/Home';
- import TipsAndUpdatesIcon from '@mui/icons-material/TipsAndUpdates';
- import Stack from '@mui/material/Stack';
- import Title from './Title';
- import {Tree as Tree_2} from 'react-arborist';
- import { CustomProvider } from 'rsuite';
- import './Tree.css';
- import zhCN from 'rsuite/locales/zh_CN';
- import FormControl from '@mui/material/FormControl';
- import InputLabel from '@mui/material/InputLabel';
- import Input from 'rsuite/Input';
- import 'rsuite/Input/styles/index.css';
- import InputGroup from 'rsuite/InputGroup';
- import 'rsuite/InputGroup/styles/index.css';
- import Grid from '@mui/material/Grid';
- import Container from '@mui/material/Container';
- import Paper from '@mui/material/Paper';
- import LinearProgress from '@mui/material/LinearProgress';
- import Chart from './Chart';
- import Chart2 from './Chart2';
- import Chart3 from './Chart3';
- import Select from '@mui/material/Select';
- import MenuItem from '@mui/material/MenuItem';
- export default function AI() {
- const drawerWidth = 240;
- const theme = useTheme();
-
- function RenderDate(props) {
- const { hasFocus, value } = props;
- const buttonElement = React.useRef(null);
- const rippleRef = React.useRef(null);
-
- React.useLayoutEffect(() => {
- if (hasFocus) {
- const input = buttonElement.current.querySelector('input');
- input?.focus();
- } else if (rippleRef.current) {
- // Only available in @mui/material v5.4.1 or later
- rippleRef.current.stop({});
- }
- }, [hasFocus]);
-
- return (
- <strong>
-
- <Button
- ref={buttonElement}
- touchRippleRef={rippleRef}
- variant="contained"
- size="small"
- style={{ marginLeft: 4 }}
-
-
- onClick={(event) => {
- console.log(value);
- event.stopPropagation();
- setSelected();
- handleZujia();
- AIService.qingdan(value).then(x=>{
- setQddetail(x);
- setZjloading(true);
- AIService.zujia(x[0]['清单编码']).then(y=>{
- setZjdetail(y);
- setZjloading(false);
- });
- setTjloading(true);
- AIService.tuijian(x[0]['清单编码']).then(y=>{
- setTjdetail(y);
- setTjloading(false);
- });
- });
-
- }}
- >
- 组价AI
- </Button>
- </strong>
- );
- }
- function RenderDe(props) {
- const { hasFocus, value } = props;
- const buttonElement = React.useRef(null);
- const rippleRef = React.useRef(null);
-
-
-
- return (
-
- <Box>
- {value.split('@').map(x=><Button
- variant="contained"
- size="small"
- style={{ marginLeft: 4 }}
- >{x}</Button>)}
-
- </Box>
-
- );
- }
- function RenderDemc(props) {
- const { hasFocus, value } = props;
- const buttonElement = React.useRef(null);
- const rippleRef = React.useRef(null);
-
-
-
- return (
-
- <Box>
- {value.split('@@').map(x=><Button
- variant="contained"
- size="small"
- style={{ marginLeft: 4, marginTop: 2 }}
- >{x}</Button>)}
-
- </Box>
-
- );
- }
-
-
- const columns = React.useMemo(
- () => [
- { field: '清单编码', headerName: '清单编码', width: 250 },
- { field: '名称', headerName: '名称', width: 400 },
- { field: '数量', headerName: '数量', width: 200 },
- { field: '操作', headerName: '操作', width: 100 , sortable: false, renderCell: RenderDate},
-
-
- ],
-
- );
- const qdcolumns = React.useMemo(
- () => [
- { field: '清单编码', headerName: '清单编码', },
- { field: '项目名称', headerName: '项目名称', },
- { field: '项目特征', headerName: '项目特征', width : 150 },
- { field: '计量单位', headerName: '计量单位', },
- { field: '工程量计算规则', headerName: '工程量计算规则', width: 300 },
- { field: '工作内容', headerName: '工作内容', width: 150 },
-
-
- ],
-
- );
- const zjcolumns = React.useMemo(
- () => [
- { field: '单位', headerName: '单位', },
- { field: '组价定额', headerName: '组价定额', width : 250 , sortable: false, renderCell: RenderDe},
- { field: '定额名称', headerName: '定额名称', width : 250, sortable: false, renderCell: RenderDemc },
- { field: '数量', headerName: '数量', },
- { field: '综合单价', headerName: '综合单价', },
-
-
-
- ],
-
- );
- const tjcolumns = React.useMemo(
- () => [
- { field: '组价定额', headerName: '组价定额', width : 250 , sortable: false, renderCell: RenderDe},
- { field: '定额名称', headerName: '定额名称', width : 350, sortable: false, renderCell: RenderDemc },
- ],
-
- );
- const Style = {
- position: "absolute",
- bottom: 128,
- right: 64,
- };
- const VisuallyHiddenInput = styled('input')({
- display: 'none',
- accept: ".13jz, .13jt, .jszf"
- });
- const itemRef = React.useRef(null);
- const navigate = useNavigate();
- const [detail, setDetail] = React.useState( [
- {label: "", value : 0}
-
-
- ]);
- const [detail2, setDetail2] = React.useState( [
- ["工程类别", "清单数"],
- ["", 0],
-
- ]);
- const [expanded, setExpanded] = React.useState([]);
- const [frequency, setFrequency] = React.useState([]);
- const [qddetail, setQddetail] = React.useState([]);
- const [zjdetail, setZjdetail] = React.useState([]);
- const [tjdetail, setTjdetail] = React.useState([]);
- const [open, setOpen] = React.useState(false);
- const [dopen, setDopen] = React.useState(false);
- const [bopen, setBopen] = React.useState(false);
- const [type, setType] = React.useState();
- const [zjloading, setZjloading] = React.useState(false);
- const [tjloading, setTjloading] = React.useState(false);
- const [cjloading, setCjloading] = React.useState(false);
- const [gploading, setGploading] = React.useState(false);
- const [zhuanye, setZhuanye] = React.useState(10);
- const [tab, setTab] = React.useState(false);
- const [qingdanshu, setQingdanshu] = React.useState([]);
- const [selected, setSelected] = React.useState();
- const [keyword, setKeyword] = React.useState();
- React.useEffect(
- () => {
- AIService.statistics("").then(x=>{
- let t = [];
- for (let i = 1; i < x.length; i++) {
- t.push({label: x[i][0], value: x[i][1]});
- }
- setDetail(t);
- });
- AIService.qingdanshu(10).then(x=>{
- setQingdanshu(x);
- });
- }, []
- );
- const handleRowClick = (params) => {
- //setMessage(`Movie "${params.row.title}" clicked`);
- navigate('/editor/qingdan/'.concat(params.row.id));
- };
- const AppBar = styled(MuiAppBar, {
- shouldForwardProp: (prop) => prop !== 'open',
- })(({ theme }) => ({
- transition: theme.transitions.create(['margin', 'width'], {
- easing: theme.transitions.easing.sharp,
- duration: theme.transitions.duration.leavingScreen,
- }),
- variants: [
- {
- props: ({ open }) => open,
- style: {
- width: `calc(100% - ${drawerWidth}px)`,
- marginLeft: `${drawerWidth}px`,
- transition: theme.transitions.create(['margin', 'width'], {
- easing: theme.transitions.easing.easeOut,
- duration: theme.transitions.duration.enteringScreen,
- }),
- },
- },
- ],
- }));
- const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })(
- ({ theme }) => ({
- flexGrow: 1,
- padding: theme.spacing(3),
- transition: theme.transitions.create('margin', {
- easing: theme.transitions.easing.sharp,
- duration: theme.transitions.duration.leavingScreen,
- }),
- marginLeft: `-${drawerWidth}px`,
- variants: [
- {
- props: ({ open }) => open,
- style: {
- transition: theme.transitions.create('margin', {
- easing: theme.transitions.easing.easeOut,
- duration: theme.transitions.duration.enteringScreen,
- }),
- marginLeft: 0,
- },
- },
- ],
- }),
- );
- const DrawerHeader = styled('div')(({ theme }) => ({
- display: 'flex',
- alignItems: 'center',
- padding: theme.spacing(0, 1),
- // necessary for content to be below app bar
- ...theme.mixins.toolbar,
- justifyContent: 'flex-end',
- }));
- const handleDrawerClose = () => {
- setOpen(false);
- };
- const handleTongji = () => {
- setOpen(false);
- setTab(false);
- };
- const handleZujia = () => {
- setOpen(false);
- setTab(true);
- };
- const handleDrawerOpen = () => {
- setOpen(true);
- };
- const handleClose = () => {
- setDopen(false);
- };
- const handleDelete = () => {
- Service.deleteFiles(itemRef.current).then(x=> {
- Service.generateFiles2().then(x=>{
- setDetail(x.map(y=>{return {'id': y[0], 'ID': y[0], '名称': y[1], '创建时间': y[2], '操作': y[0]};}));
- });
- });
- setDopen(false);
- };
- const onSelect = (selectedKeys) => {
-
- setSelected(selectedKeys['id']);
- setZjloading(true);
- console.log(selectedKeys);
- AIService.qingdan(selectedKeys['title']).then(x=>{
- setQddetail(x);
- AIService.zujia(x[0]['清单编码']).then(y=>{
- setZjdetail(y);
- setZjloading(false);
- });
- setTjloading(true);
- AIService.tuijian(x[0]['清单编码']).then(y=>{
- setTjdetail(y);
- setTjloading(false);
- });
- });
-
-
-
- };
- const onExpand = (expandItemValues, node) => {
- //console.log(expandItemValues);
- //console.log(node);
- setExpanded(expandItemValues);
- };
- const clickLB = (lb) => {
- console.log(lb);
- setType(lb);
- if (lb == null) {
-
- } else if (lb == '建筑与装饰工程') {
- //console.log('建筑与装饰工程');
- setCjloading(true);
- AIService.statistics("建筑与装饰工程").then(x=>{
- let t = [];
- for (let i = 1; i < x.length; i++) {
- t.push({label: x[i][0], value: x[i][1]});
- }
- setDetail2(t);
- setCjloading(false);
-
- });
-
- } else if (lb == '仿古建筑') {
- setCjloading(true);
- AIService.statistics("仿古建筑").then(x=>{
- let t = [];
- for (let i = 1; i < x.length; i++) {
- t.push({label: x[i][0], value: x[i][1]});
- }
- setDetail2(t);
- setCjloading(false);
- });
-
- } else if (lb == '安装工程') {
- setCjloading(true);
- AIService.statistics("安装工程").then(x=>{
- let t = [];
- for (let i = 1; i < x.length; i++) {
- t.push({label: x[i][0], value: x[i][1]});
- }
- setDetail2(t);
- setCjloading(false);
-
- });
-
- } else if (lb == '市政工程') {
- setCjloading(true);
- AIService.statistics("市政工程").then(x=>{
- let t = [];
- for (let i = 1; i < x.length; i++) {
- t.push({label: x[i][0], value: x[i][1]});
- }
- setDetail2(t);
- setCjloading(false);
-
- });
-
- } else if (lb == '园林绿化工程') {
- setCjloading(true);
- AIService.statistics("园林绿化工程").then(x=>{
- let t = [];
- for (let i = 1; i < x.length; i++) {
- t.push({label: x[i][0], value: x[i][1]});
- }
- setDetail2(t);
- setCjloading(false);
-
- });
-
- }
- };
- const clickLB2 = (type, lb) => {
- console.log(type);
- console.log(lb);
- setGploading(true);
- AIService.frequency(type, lb).then(x=>{
- console.log(x);
- setFrequency(x.map(y=>{y['操作'] = y['清单编码'];return y;}));
- setGploading(false);
- });
- };
- const handleChangeZhuanye = (event) => {
- //console.log(event.target.value);
- AIService.qingdanshu(event.target.value).then(x=>{
- setQingdanshu(x);
- });
- setZhuanye(event.target.value);
- };
- const minHeight = 100;
- const maxHeight = 400;
- const CustomInputGroup = ({ placeholder, ...props }) => (
- <InputGroup {...props} style={{"marginTop": 5}}>
- <Input placeholder={placeholder}
- value={keyword}
- onChange={(value)=>{setKeyword(value);}}
- />
- <InputGroup.Addon>
- <SearchIcon />
- </InputGroup.Addon>
- </InputGroup>
- );
- function Node({ node, style }) {
-
- let style_ = {'paddingLeft': style['paddingLeft']};
- style_['fontSize'] = "0.875rem";
- if (node.state.isSelected) {
- style_['backgroundColor'] = "#f2faff";
- style_['color'] = "#1675e0";
- style_['fontWeight'] = "bold";
- console.log(node);
- }
- return (
- <div
-
- style={style_}
-
- onClick={() => {
- if (node.children.length > 0) {node.toggle();}
- else {
- setSelected(node['id']);
- setZjloading(true);
- }
- }
- }
- >
-
- <FolderArrow node={node} />
-
- <span >
- {node.data.name}
- </span>
- </div>
- );
- }
- function FolderArrow({ node }) {
- return (
- <span >
- {node.isInternal ? (
- node.isOpen ? (
- <ArrowDownIcon />
- ) : (
- <ArrowRightIcon />
- )
- ) : null}
- </span>
- );
- }
- return (
- <Box sx={{ display: 'flex' }}>
-
- <CssBaseline />
- <AppBar position="fixed" open={open}>
- <Toolbar>
-
- <IconButton
- color="inherit"
- aria-label="open drawer"
- onClick={handleDrawerOpen}
- edge="start"
- sx={[
- {
- mr: 2,
- },
- open && { display: 'none' },
- ]}
- >
- <MenuIcon />
- </IconButton>
- <Typography variant="h6" noWrap component="div">
- 清单AI
- </Typography>
- <Box sx={{ flexGrow: 1 }} >
- <Stack direction="row" spacing={2} sx={{ml: 4}}>
- <Button
- key={'统计AI'}
- onClick={handleTongji}
- sx={{ my: 2, color: 'white', display: 'block' }}
- >
- 统计AI
- </Button>
- <Button
- key={'组价AI'}
- onClick={handleZujia}
- sx={{ my: 2, color: 'white', display: 'block' }}
- >
- 组价AI
- </Button>
- </Stack>
-
- </Box>
- <Box sx={{ display: { xs: 'none', md: 'flex' } }}>
-
- <IconButton
- size="large"
- edge="end"
- aria-label="account of current user"
-
- aria-haspopup="true"
-
- color="inherit"
- >
- <AccountCircle />
- </IconButton>
- </Box>
- </Toolbar>
- </AppBar>
- <Drawer
- sx={{
- width: drawerWidth,
- flexShrink: 0,
- '& .MuiDrawer-paper': {
- width: drawerWidth,
- boxSizing: 'border-box',
- },
- }}
- variant="persistent"
- anchor="left"
- open={open}
- >
- <DrawerHeader>
- <IconButton onClick={handleDrawerClose}>
- {theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
- </IconButton>
- </DrawerHeader>
- <Divider />
- <List>
- {['工作台', '清单AI'].map((text, index) => (
- <ListItem key={text} disablePadding>
- <ListItemButton onClick={(item)=>{
- if (index == 0) {
- navigate('/editor/index.html');
- }
- }}>
- <ListItemIcon>
- {index % 2 === 0 ? <HomeIcon /> : <TipsAndUpdatesIcon />}
- </ListItemIcon>
- <ListItemText primary={text} />
- </ListItemButton>
- </ListItem>
- ))}
- </List>
- </Drawer>
- <Main open={open}>
- <DrawerHeader />
- <div style={{ width: '100%' }}>
- { !tab && <Container maxWidth="lg" sx={{ mt: 4, mb: 4 }}>
- <Grid container spacing={3}>
- {/* Chart */}
- <Grid item xs={12} md={5} lg={6}>
- <Paper
- sx={{
- p: 2,
- display: 'flex',
- flexDirection: 'column',
- height: 400,
- }}
- >
- <Title>清单分类</Title>
- <Chart data={detail} click={clickLB}></Chart>
- </Paper>
- </Grid>
- {/* Recent Deposits */}
- <Grid item xs={12} md={7} lg={6}>
- <Paper
- sx={{
- p: 2,
- display: 'flex',
- flexDirection: 'column',
- height: 400,
- }}
- >
- <Title>次级清单分类</Title>
- { cjloading && <LinearProgress/>}
- { !cjloading && <Chart2 type={type} click={clickLB2} data={detail2}></Chart2> }
- </Paper>
- </Grid>
- {/* Recent Orders */}
- <Grid item xs={12}>
- <Paper sx={{ p: 2, display: 'flex', flexDirection: 'column' }}>
- <Title>高频清单</Title>
- <DataGrid autoHeight
- rows={frequency} columns={columns}
- disableColumnMenu={true} loading={gploading}
- localeText={zh_CN.components.MuiDataGrid.defaultProps.localeText}
- />
- </Paper>
- </Grid>
- </Grid>
-
- </Container>}
- { tab && <Container maxWidth="xl" sx={{ mt: 4, mb: 4 }}>
- <Grid container spacing={3}>
- {/* Chart */}
- <Grid item xs={12} md={2} lg={3}>
- <Paper
- sx={{
-
- p: 2,
- display: 'flex',
- flexDirection: 'column',
-
- }}
- >
- <Title>清单树</Title>
- <FormControl size="small">
- <InputLabel id="demo-multiple-name-label">专业</InputLabel>
- <Select
- labelId="demo-multiple-name-label"
- id="demo-multiple-name"
- value={zhuanye}
- onChange={handleChangeZhuanye}
- label="专业"
- >
- <MenuItem value={10}>建筑与装饰</MenuItem>
- <MenuItem value={20}>安装</MenuItem>
- <MenuItem value={30}>市政</MenuItem>
- <MenuItem value={40}>园林绿化</MenuItem>
-
- </Select>
- </FormControl>
-
-
- <Chart3 qingdanshu={qingdanshu}
- selected={selected}
- callback={(value)=>{
- onSelect(value);
-
- }}
- ></Chart3>
-
- </Paper>
- </Grid>
- {/* Recent Deposits */}
- <Grid item xs={12} md={10} lg={9}>
- <Paper
- sx={{
- p: 2,
- display: 'flex',
- flexDirection: 'column',
-
- }}
- >
- <DataGrid autoHeight hideFooter={true}
- getRowHeight={() => 'auto'}
- rows={qddetail} columns={qdcolumns}
- disableColumnMenu={true}
- localeText={zh_CN.components.MuiDataGrid.defaultProps.localeText}
- />
- <Title>历史组价</Title>
- <div
- style={{
- minHeight,
- maxHeight,
- "overflowY": "scroll"
- }}
- >
- <DataGrid autoHeight hideFooter={true}
- getRowHeight={() => 'auto'}
- rows={zjdetail} columns={zjcolumns}
- disableColumnMenu={true}
- loading={zjloading}
- localeText={zh_CN.components.MuiDataGrid.defaultProps.localeText}
- />
- </div>
- <Title>AI推荐</Title>
- <div
- style={{
-
- "overflowY": "scroll",
-
- minHeight,
- maxHeight
-
- }}
- >
- <DataGrid autoHeight hideFooter={true}
- getRowHeight={() => 'auto'}
- rows={tjdetail} columns={tjcolumns}
- disableColumnMenu={true}
- loading={tjloading}
- localeText={zh_CN.components.MuiDataGrid.defaultProps.localeText}
- />
- </div>
- </Paper>
- </Grid>
-
-
- </Grid>
- </Container>}
-
- </div>
-
- </Main>
- <Dialog
- open={dopen}
- onClose={handleClose}
- aria-labelledby="alert-dialog-title"
- aria-describedby="alert-dialog-description"
- >
- <DialogTitle id="alert-dialog-title">
- {"删除该项目?"}
- </DialogTitle>
-
- <DialogActions>
- <Button onClick={handleClose}>取消</Button>
- <Button onClick={handleDelete} autoFocus>
- 确定
- </Button>
- </DialogActions>
- </Dialog>
- <Backdrop
- sx={(theme) => ({ color: '#fff', zIndex: theme.zIndex.drawer + 1 })}
- open={bopen}
-
- >
- <CircularProgress color="inherit" />
- </Backdrop>
- </Box>
- );
- }
|