//backend const mongoose = require('mongoose') mongoose.set('strictQuery',true) mongoose.connect('mongodb://127.0.0.1:27017/db_zg4yk') conn=mongoose.connection conn.on('open',()=>{<!-- --> console.log('Database connection succeeded') }) conn.on('error',err=>{<!-- --> console.log('Database connection failed') }) module.exports=mongoose //model.js const mongoose = require('./db') const Schema = mongoose.Schema const listScheam=new Schema({<!-- --> name: String, form:Array, browse:Number, sort:Number, isshow: Boolean, date: Date, children: Array, },{<!-- -->versionKey:false}) let listModel = mongoose. model('list', listScheam, 'list') module.exports={<!-- --> listModel, } //router.js var express = require('express'); var router = express. Router(); var jwt = require('jsonwebtoken') var multiparty = require('multiparty') var {<!-- --> listModel} = require('../model/model') router.get('/list', async function(req, res) {<!-- --> let list = await listModel. find() res.send({<!-- --> code:200, data: list, }); }); router. post('/Addchildren', async function(req, res) {<!-- --> let data = req. body console. log(data); let da = await listModel. find({<!-- -->_id:data._id}) da[0].children.push(data.children) await listModel.updateOne({<!-- -->_id:data._id},{<!-- -->children:da[0].children}) res.send({<!-- --> code:200, }); }); router. post('/add', async function(req, res) {<!-- --> let data = req.body await listModel.create({<!-- --> name: data. title, form:data.list, browse:0, sort:255, isshow:true, date:new Date().toISOString(), children:[], }) console. log(data); res.send({<!-- --> code:200, }); }); module.exports = router; //front end //index.js import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import './index.css' import {<!-- -->BrowserRouter as Router} from 'react-router-dom' import {<!-- --> Provider } from 'react-redux' import store from './store/counterSlice' const root = ReactDOM.createRoot(document.getElementById('root')); root. render( <> <Provider store={<!-- -->store}> <Router> <App /> </Router> </Provider> </> ); //index.css *{<!-- --> margin: 0; padding: 0; } html,body,#root{<!-- --> height: 100%; } .list{<!-- --> margin: 10px; padding: 5px; background-color: #fff; } .row1,.row6{<!-- --> display: inline-block; width: 180px; font-size: 18px; font-weight: 500; } .row2,.row3,.row4,.row5{<!-- --> display: inline-block; width: 150px; font-size: 18px; font-weight: 500; } .row7{<!-- --> display: inline-block; width: 200px; font-size: 18px; font-weight: 500; } //router.js import Add from "./components/Add" import Home from "./components/Home" import List from "./components/List" const routes=[ {<!-- --> path:'/', element:<Home></Home>, children:[ {<!-- --> path:'/', element:<List></List> }, {<!-- --> path:'/add', element:<Add></Add> } ] }, ] export default routes //App.js import React from 'react' import {<!-- --> useRoutes } from 'react-router-dom' import routes from './router' export default function App(props) {<!-- --> return ( <div> {<!-- -->useRoutes(routes)} </div> ) } //Parent component Home.js import {<!-- --> FileOutlined, PieChartOutlined, UserOutlined,DesktopOutlined,TeamOutlined } from '@ant-design/icons'; import {<!-- --> Layout, Menu, theme } from 'antd'; import {<!-- --> useState } from 'react'; import {<!-- --> Outlet ,useNavigate} from 'react-router-dom'; import {<!-- --> Input, Button } from 'antd'; export default function Home () {<!-- --> const navigate = useNavigate(); const {<!-- --> Header, Content, Footer, Sider } = Layout; function getItem(label, key, icon, children) {<!-- --> return {<!-- --> key, icon, children, label, }; } const items = [ getItem('Home', '1', <PieChartOutlined onClick={<!-- -->()=>navigate('/')}/>), getItem('Form management', 'sub1', <UserOutlined />, [ getItem('Form List', '3',<UserOutlined onClick={<!-- -->()=>navigate('/')}/>), getItem('Form Add', '4',<UserOutlined onClick={<!-- -->()=>navigate('/add')}/>), ]), ]; const [collapsed, setCollapsed] = useState(false); const {<!-- --> token: {<!-- --> colorBgContainer }, } = theme. useToken(); const {<!-- --> Search } = Input; const onSearch = (value) => console. log(value); return ( <Layout style={<!-- -->{<!-- --> minHeight: '100vh', }} > <Sider collapsible collapsed={<!-- -->collapsed} style={<!-- -->{<!-- -->background: '#fff',}} onCollapse={<!-- - ->(value) => setCollapsed(value)}> <div style={<!-- -->{<!-- --> height: 32, margin: 16, textAlign:'center', }} > Haike form </div> <Menu theme="light" defaultSelectedKeys={<!-- -->['1']} mode="inline" items={<!-- -->items} /> </Sider> <Layout className="site-layout"> <Header style={<!-- -->{<!-- --> padding: 0, background: colorBgContainer, }} /> <Content style={<!-- -->{<!-- --> margin: '0 16px', background:'#f4f9fc', }} > <Outlet></Outlet> </Content> <Footer style={<!-- -->{<!-- --> textAlign: 'center', }} > Ant Design ?2023 Created by Ant UED </Footer> </Layout> </Layout> ); }; //List.js import React from 'react' import {<!-- --> useState,useEffect } from 'react'; import {<!-- --> fetchList,Addchildren } from '../store/counterSlice'; import {<!-- --> useSelector,useDispatch } from 'react-redux' import {<!-- --> useNavigate } from 'react-router-dom' import {<!-- --> Input, Button ,Form} from 'antd'; import {<!-- -->FolderOutlined,ProfileOutlined,AppstoreOutlined} from '@ant-design/icons'; import {<!-- --> Switch ,Drawer} from 'antd'; export default function List() {<!-- --> const navigate = useNavigate() const dispatch = useDispatch(); const state = useSelector(state=>state) console.log(state,'state'); useEffect(() => {<!-- --> dispatch(fetchList()) }, []); const [form] = Form. useForm(); // control style const [style, setstyle] = useState(true) //Switch const onChange = (checked) => {<!-- --> console.log(`switch to ${<!-- -->checked}`); }; //install item let [_id,setId]=useState([]) // control drawer const [open, setOpen] = useState(false) //The component form of the item let [yulan,setYulan] = useState([]) //Click to preview whether to display the form function isShowForm(item){<!-- --> setId(item) setYulan(item. form) setOpen(true) } const onFinish = (values) => {<!-- --> console.log(values,'finish');//{tel:'18932742964,nickname:'giaogiao'} dispatch(Addchildren({<!-- -->_id:_id._id,children:values})) setId([]) setOpen(false) dispatch(fetchList()) }; // search const {<!-- --> Search } = Input; const onSearch = (value) => console. log(value); return ( <div> {<!-- -->/* top search section */} <div style={<!-- -->{<!-- -->height:'90px',padding:'28px 20px'}}> <ProfileOutlined style={<!-- -->{<!-- -->fontSize:'25px'}} onClick={<!-- -->()=>setstyle(true)}/> <AppstoreOutlined style={<!-- -->{<!-- -->fontSize:'25px',marginLeft:'10px'}} onClick={<!-- -->()=>setstyle(false )}/> <Search placeholder="input search text" onSearch={<!-- -->onSearch} style={<!-- -->{<!-- --> width: 200, marginLeft: 10, }} /> <Button type="primary" style={<!-- -->{<!-- -->marginLeft:10,}} onClick={<!-- -->()=>navigate('/add ')}> + New Form</Button> <Button style={<!-- -->{<!-- -->marginLeft:10,}}><FolderOutlined />Create a new directory</Button> </div> {<!-- -->/* table part */} <div style={<!-- -->{<!-- --> padding: 24, minHeight: 360, background: '#fff', }} > <div className="list" style={<!-- -->{<!-- -->margin: '10px',padding: '5px'}}> <span className='row1'>Form Name</span> <span className='row2'>Number of submissions</span> <span className='row3'>Views</span> <span className='row4'>sort</span> <span className='row5'>Whether to display</span> <span className='row6'>Date Added</span> <span className='row7'>Operation</span> </div> {<!-- -->style?( <> {<!-- --> state.list.map(item=>( <div className="list" style={<!-- -->{<!-- -->margin: '10px',padding: '5px'}}> <span className='row1'>{<!-- -->item.name}</span> <span className='row2'>{<!-- -->item.children.length}</span> <span className='row3'>{<!-- -->item.browse}</span> <span className='row4'>{<!-- -->item.sort}</span> <span className='row5'> <Switch defaultChecked={<!-- -->item.isshow} onChange={<!-- -->onChange} /> </span> <span className='row6'> {<!-- -->new Date(item.date).toLocaleString()} </span> <span className='row7'> <span style={<!-- -->{<!-- -->color:'blue'}} >Edit</span> & amp;nbsp; & amp;nbsp; & amp;nbsp; & amp ;nbsp; <span style={<!-- -->{<!-- -->color:'blue'}} >Set</span> & amp;nbsp; & amp;nbsp; & amp;nbsp; & amp ;nbsp; <span style={<!-- -->{<!-- -->color:'blue'}} onClick={<!-- -->()=>{<!-- -->isShowForm (item)}} >Preview</span> <span style={<!-- -->{<!-- -->color:'blue'}} >...</span> </span> </div> )) } </> ):( <div style={<!-- -->{<!-- -->display:'flex',flexWrap:'wrap'}}> {<!-- --> state.list.map(item=>( <div style={<!-- -->{<!-- -->border:'1px solid',margin:'10px',width:'150px',height:'150px',textAlign:'center' }} key={<!-- -->item._id}> <div style={<!-- -->{<!-- -->marginTop:'30px'}}>{<!-- -->item.name}</div> <div style={<!-- -->{<!-- -->marginTop:'30px'}}>{<!-- -->item.children.length} submitted data</div> </div> )) } </div> )} <Drawer title="Submit information" placement="right" onClose={<!-- -->()=>setOpen(false)} open={<!-- -->open}> <Form form={<!-- -->form} name="control-hooks" onFinish={<!-- -->onFinish} style={<!-- -->{<!-- --> maxWidth: 600, }} > {<!-- --> yulan.map((item,index)=>( <Form.Item rules={<!-- -->[{<!-- --> required: item.ischecked, message: 'Please input your username!' }]} label={<!-- -->item.ischecked?<><span style={<!-- -->{<!-- -->color:'red'}}>*</span>{ <!-- -->item.title2}</>:item.title2} name={<!-- -->item.title2} > <Input placeholder={<!-- -->item.tip}/> </Form.Item> )) } <Form.Item> <Button type="primary" htmlType="submit">Submit</Button> </Form.Item> </Form> </Drawer> </div> </div> ) } //Add.js import React, {<!-- --> useEffect, useState } from 'react' import {<!-- --> useNavigate } from 'react-router-dom' import {<!-- --> useDispatch } from 'react-redux'; import {<!-- --> AddList } from '../store/counterSlice'; import {<!-- --> Layout, Space,Button,Input,Switch,Menu,message } from 'antd'; import {<!-- -->PhoneOutlined,FormOutlined,SearchOutlined,LineHeightOutlined} from '@ant-design/icons'; export default function Add() {<!-- --> const {<!-- --> Header, Footer, Sider, Content } = Layout; const navigate = useNavigate() const dispatch = useDispatch(); let [title2,setTitle2]=useState('') //Mobile nickname title let [tip,setTip]=useState('Please enter') //phone nickname input const [list,setList]=useState([]) // put the array of components let [children,setchildren] = useState([]) let [index,setIndex]=useState(0) //component subscript const [rightShow,setRightShow]=useState(false) //Control the display of the right component properties const [checked,setChecked]=useState(false) //control is visible const [formShow,setFormShow]=useState(false) //Control form properties are visible let [title,setTitle]=useState('') //input const {<!-- --> TextArea } = Input; let [value, setValue] = useState(''); //textarea const items=[ {<!-- --> label: 'Component properties', key: 'com', }, {<!-- --> label: 'form attribute', key: 'form', }, ] const [current, setCurrent] = useState('com'); //submit function sub(){<!-- --> if(title==''){<!-- --> message.warning('Please enter the title of the form') }else{<!-- --> list.forEach(item=>{<!-- --> children.push({<!-- --> title2: item.props.children[1].props.children, tip: item.props.children[2].props.value, is checked: checked }) console.log(children,'ischecked'); }) let data={<!-- -->title:title,list:children} dispatch(AddList(data)).then(()=>{<!-- --> navigate('/') }) } } function pre(){<!-- --> console. log(2); } function del(){<!-- --> console. log(3); } function addCom(name){<!-- --> console. log(name); setIndex(list. length) title2=name setTitle2(name) let html= <> <span style={<!-- -->{<!-- -->color:'red',display:'inline-block',width:'10px'}}>{<!-- --> false?'*':''}{<!-- -->false}</span> <span>{<!-- -->title2}</span> <Input style={<!-- -->{<!-- -->marginTop:'10px'}} value={<!-- -->tip} /> </> let newList=[...list,html] setList(newList) } //Click to pass the component to the right function getCom(index,item){<!-- --> setRightShow(true) setIndex(index) console.log(item,'component item'); console.log(index,'index'); setChecked(item. props. children[0]. props. children[1]) setTitle2(item.props.children[1].props.children) setTip(item.props.children[2].props.value) } //Component property modification component function setComState(val,name){<!-- --> //Find the component from the component list and replace the component again let html=list[index] if(name=='title'){<!-- --> setTitle2(val) html=<> <span style={<!-- -->{<!-- -->color:'red',display:'inline-block',width:'10px'}}>{<!-- --> checked?'*':''}</span> <span>{<!-- -->val}</span> <Input style={<!-- -->{<!-- -->marginTop:'10px'}} value={<!-- -->tip} /> </> } if(name=='tip'){<!-- --> setTip(val) html=<> <span style={<!-- -->{<!-- -->color:'red',display:'inline-block',width:'10px'}}>{<!-- --> checked?'*':''}</span> <span>{<!-- -->title2}</span> <Input style={<!-- -->{<!-- -->marginTop:'10px'}} value={<!-- -->val} /> </> } if(name=='checked'){<!-- --> setChecked(val) html=<> <span style={<!-- -->{<!-- -->color:'red',display:'inline-block',width:'10px'}}>{<!-- --> val?'*':''}</span> <span>{<!-- -->title2}</span> <Input style={<!-- -->{<!-- -->marginTop:'10px'}} value={<!-- -->tip} /> </> } list.splice(index,1,html) } const onClick = (e) => {<!-- --> //menu console.log('click', e); setCurrent(e.key); }; return ( <> <div style={<!-- -->{<!-- -->marginTop:'20px'}}> <span style={<!-- -->{<!-- -->marginLeft:'680px',color:'blue'}} onClick={<!-- -->sub}>submit</span > <span style={<!-- -->{<!-- -->marginLeft:'20px',color:'blue'}} onClick={<!-- -->pre}>Preview</span > <span style={<!-- -->{<!-- -->marginLeft:'20px',color:'red'}} onClick={<!-- -->del}>Clear</span > </div> <Space> <Layout> {<!-- -->/* component area */} <Sider width={<!-- -->'300px'} style={<!-- -->{<!-- -->color:'black',background:'#f4f9fc',paddingLeft:' 50px'}}> <div> <div>Special component</div> <Space style={<!-- -->{<!-- -->marginTop:'20px'}} wrap> <Button onClick={<!-- -->()=>addCom('phone number')}><PhoneOutlined />phone number</Button> <Button onClick={<!-- -->()=>addCom('nickname')}><FormOutlined />nickname</Button> </Space> </div> </Sider> {<!-- -->/* form field */} <Sider width={<!-- -->'600px'} style={<!-- -->{<!-- -->color:'black',background:'#f4f9fc',width:' 500px', padding:'10px 30px'}}> <div> form title <Input prefix={<!-- --><SearchOutlined />} style={<!-- -->{<!-- -->marginTop:'10px'}} placeholder="Please enter the title of the form" value={<!-- -->title} onChange={<!-- -->(e)=>setTitle(e.target.value)} /> </div> <div style={<!-- -->{<!-- -->marginTop:'20px',border:'1px solid #d4dbde',background:'#ffffff'}}> <div style={<!-- -->{<!-- -->borderBottom:'1px solid #d4dbde',display:'flex',flexWrap:'wrap'}}> <LineHeightOutlined style={<!-- -->{<!-- -->margin:'5px 10px'}} /> </div> <TextArea style={<!-- -->{<!-- -->border:'none'}} value={<!-- -->value} onChange={<!-- -->(e) => setValue(e.target.value)} placeholder="Please enter the text" autoSize={<!-- -->{<!-- --> minRows: 6, maxRows: 8, }} /> </div> {<!-- -->/* render component */} {<!-- --> list.map((item,index)=>( <div key={<!-- -->index} style={<!-- -->{<!-- -->marginTop:'20px'}} onClick={<!-- -->( )=>getCom(index, item)}> {<!-- -->item} </div> )) } </Sider> <Sider width={<!-- -->'350px'} style={<!-- -->{<!-- -->color:'black',background:'#f4f9fc',width:' 400px'}}> <Menu onClick={<!-- -->onClick} selectedKeys={<!-- -->[current]} mode="horizontal" items={<!-- -->items} /> {<!-- --> rightShow? ( <div> <h3>Title</h3> <Input size="large" onChange={<!-- -->(e)=>setComState(e.target.value,'title')} value={<!-- -->title2} prefix={ <!-- --><SearchOutlined />} /><br/> <h3>Placeholder hint</h3> <Input size="large" onChange={<!-- -->(e)=>setComState(e.target.value,'tip')} value={<!-- -->tip} prefix={ <!-- --><SearchOutlined />} /><br/> <h3>Whether to display</h3> <Switch defaultChecked={<!-- -->checked} onChange={<!-- -->(e)=>setComState(e,'checked')} /> </div> ):<></> } {<!-- --> formShow? ( <div style={<!-- -->{<!-- -->marginLeft:'30px',background:""}}> {<!-- --> list.map((item,index)=>( <div key={<!-- -->index} style={<!-- -->{<!-- -->marginTop:'20px'}}> {<!-- -->item} </div> )) } <Button style={<!-- -->{<!-- -->marginTop:'50px',marginLeft:'150px'}}>Submit</Button><br/> </div> ):<></> } </Sider> </Layout> </Space> </> ) } //store==>Counterslice.js //Single file operation //npm i @reduxjs/[email protected] import {<!-- --> configureStore, createAsyncThunk, createSlice } from '@reduxjs/toolkit'; import axios from 'axios'; // asynchronous request const fetchList = createAsyncThunk('fetchList', async () => {<!-- --> const {<!-- --> data } = await axios.get('http://127.0.0.1:8000/list'); console.log(data,'data'); return data.data; }); const AddList=createAsyncThunk('AddList', async (data)=>{<!-- --> await axios.post('http://127.0.0.1:8000/add',data) return '' }) const Addchildren=createAsyncThunk('Addchildren', async (data)=>{<!-- --> await axios.post('http://127.0.0.1:8000/Addchildren',data) return '' }) const stateSlice = createSlice({<!-- --> name: 'state', initialState: {<!-- --> list:[], num:0 }, reducers: {<!-- --> }, extraReducers(builder) {<!-- --> builder.addCase(fetchList.fulfilled, (state, action)=>{<!-- --> state.list=action.payload }) }, }); const store = configureStore({<!-- --> reducer: stateSlice. reducer, }); // all methods need to be exported // export const { goDetail,del,addform} = stateSlice.actions; export {<!-- --> fetchList,AddList,Addchildren}; export default store;