瀏覽代碼

Merge branch 'dev' of http://git.ycjcjy.com/jgz/admin into dev

lisenzhou 2 年之前
父節點
當前提交
214e5dfce8

+ 32
- 18
src/components/Wangeditor/index.jsx 查看文件

@@ -5,7 +5,16 @@ import { Editor, Toolbar } from "@wangeditor/editor-for-react";
5 5
 // 工具栏配置参考
6 6
 // https://www.cnblogs.com/-roc/p/16400965.html
7 7
 
8
+const defaultStyle = {
9
+  border: "1px solid #ccc",
10
+  zIndex: 100,
11
+  marginTop: "15px"
12
+}
13
+
8 14
 function MyEditor(props) {
15
+
16
+  const style = React.useMemo(() => ({ ...defaultStyle, ...(props.style || {}) }), [props.style])
17
+
9 18
   const {
10 19
     value = "",
11 20
     onChange = (e) => {
@@ -46,25 +55,30 @@ function MyEditor(props) {
46 55
     console.log(editor.getHtml());
47 56
   }
48 57
 
58
+  const handleChange = (editor) => {
59
+    const raw = editor.getHtml();
60
+    if (raw !== '<p><br></p>') {
61
+      onChange(raw)
62
+    }
63
+  }
64
+
49 65
   return !readonly ? (
50
-    <>
51
-      <div style={{ border: "1px solid #ccc", zIndex: 100, marginTop: "15px" }}>
52
-        <Toolbar
53
-          editor={editor}
54
-          defaultConfig={toolbarConfig}
55
-          mode="default"
56
-          style={{ borderBottom: "1px solid #ccc" }}
57
-        />
58
-        <Editor
59
-          defaultConfig={editorConfig}
60
-          value={html}
61
-          onCreated={setEditor}
62
-          onChange={(editor) => onChange(editor.getHtml())}
63
-          mode="default"
64
-          style={{ height: "500px" }}
65
-        />
66
-      </div>
67
-    </>
66
+    <div className={props.className} style={style}>
67
+      <Toolbar
68
+        editor={editor}
69
+        defaultConfig={toolbarConfig}
70
+        mode="default"
71
+        style={{ borderBottom: "1px solid #ccc" }}
72
+      />
73
+      <Editor
74
+        defaultConfig={editorConfig}
75
+        value={html}
76
+        onCreated={setEditor}
77
+        onChange={handleChange}
78
+        mode="default"
79
+        style={{ height: "500px" }}
80
+      />
81
+    </div>
68 82
   ) : (
69 83
     <div dangerouslySetInnerHTML={{ __html: value }}></div>
70 84
   );

+ 39
- 0
src/pages/dish/edit/Detail.jsx 查看文件

@@ -0,0 +1,39 @@
1
+import React from 'react';
2
+import { Button, Row, Col, Card, Typography, Image } from 'antd';
3
+import { useNavigate, useSearchParams } from 'react-router-dom';
4
+import { getDishById } from '@/services/dish';
5
+
6
+const { Title, Paragraph } = Typography;
7
+
8
+export default (props) => {
9
+  const [searchParams] = useSearchParams();
10
+  const id = searchParams.get('id');
11
+  const [dish, setDish] = React.useState({});
12
+
13
+  const navigate = useNavigate();
14
+
15
+  React.useEffect(() => {
16
+    if (id) {
17
+      getDishById(id).then((res) => {
18
+        setDish(res);
19
+      });
20
+    }
21
+  }, [id]);
22
+
23
+  return (
24
+    <Card title={dish.name} extra={<Button onClick={() => navigate(-1)}>返回</Button>}>
25
+      <Row gutter={24}>
26
+        <Col span={12}>
27
+          <Typography>
28
+            <Paragraph>
29
+              <div dangerouslySetInnerHTML={{ __html: dish.content }}  style={{ fontSize: '16px', lineHeight: '2em' }} />
30
+            </Paragraph>
31
+          </Typography>
32
+        </Col>
33
+        <Col span={12}>
34
+          <Image style={{ minWidth: '240px', maxWidth: '480px' }} src={dish.thumb} />
35
+        </Col>
36
+      </Row>
37
+    </Card>
38
+  )
39
+}

+ 49
- 0
src/pages/dish/edit/Edit.jsx 查看文件

@@ -0,0 +1,49 @@
1
+import { getStoreList, getStoreTypeList } from '@/services/stock';
2
+import { Alert, Row, Col } from 'antd';
3
+import { useEffect, useState, useMemo } from 'react';
4
+import Form from './Form';
5
+
6
+export default (props) => {
7
+  const { dish, onFinish } = props;
8
+
9
+  const [ingredientsList, setIngredientsList] = useState([]);
10
+  const [storeList, setStoreList] = useState([]);
11
+  const [storeTypeList, setStoreTypeList] = useState([]);
12
+  
13
+  const foodDict = useMemo(() => storeList.map(x => ({ label: x.name, value: x.id, })), [storeList]);
14
+  const Nutrition = useMemo(() => {
15
+    if (!ingredientsList.length
16
+      || !storeList.length
17
+      || !storeTypeList.length
18
+      ) return [];
19
+
20
+    return ingredientsList.map(x => storeList.filter(y => y.id === x)[0])
21
+      .map(x => storeTypeList.filter(y => y.id === x.typeId)[0].nutrition)
22
+      .map((it, inx) => (<p key={inx}>{it}</p>));
23
+  }, [ingredientsList, storeList, storeTypeList]);
24
+  
25
+  useEffect(() => {
26
+    getStoreList({ isDish: 1, pageSize: 9999 }).then((res) => {
27
+      setStoreList(res?.records || []);
28
+    });
29
+    getStoreTypeList({ isFood: 1, pageSize: 9999 }).then((res) => {
30
+      setStoreTypeList(res?.records || []);
31
+    });
32
+  }, []);
33
+
34
+  useEffect(() => {
35
+    const { ingredientsIdList } = dish || {};
36
+    setIngredientsList(ingredientsIdList || [])
37
+  }, [dish]);
38
+
39
+  return (
40
+    <Row gutter={48}>
41
+      <Col span={12}>
42
+        <Form dish={dish} onFinish={onFinish} foodDict={foodDict} onIngredientsChange={setIngredientsList} />         
43
+      </Col>
44
+      <Col span={12}>
45
+        <Alert message="营养元素" description={Nutrition} type="info" />
46
+      </Col>
47
+    </Row>
48
+  );
49
+};

+ 88
- 0
src/pages/dish/edit/Form.jsx 查看文件

@@ -0,0 +1,88 @@
1
+import { addDish } from '@/services/dish';
2
+import { ProForm, ProFormSelect, ProFormText, ProFormMoney } from '@ant-design/pro-components';
3
+import { useNavigate, useSearchParams } from 'react-router-dom';
4
+import { Row, Col, Space } from 'antd';
5
+import { useEffect, useRef, useState, useMemo } from 'react';
6
+import UploadFile from '@/components/UploadFile';
7
+import Wangeditor from "@/components/Wangeditor";
8
+import { floatMultiply, floatDivide } from "@/utils/float";
9
+
10
+export default (props) => {
11
+  const [searchParams] = useSearchParams();
12
+  const id = searchParams.get('id');
13
+  const navigate = useNavigate();
14
+
15
+  const formRef = useRef();
16
+
17
+  useEffect(() => {
18
+    if (props.dish) {
19
+      formRef.current.setFieldsValue({ ...props.dish, price: floatDivide(props.dish.price, 100) });
20
+    }
21
+  }, [props.dish]);
22
+
23
+  const onFinish = async (values) => {
24
+    addDish({ ...values, price: floatMultiply(values.price, 100), id }).then((res) => {
25
+      props.onFinish(res);
26
+    });
27
+
28
+    return false;
29
+  };
30
+
31
+  return (
32
+    <ProForm
33
+      formRef={formRef}
34
+      layout={'horizontal'}
35
+      labelCol={{ span: 4 }}
36
+      wrapperCol={{ span: 20 }}
37
+      onFinish={onFinish}
38
+      initialValues={{ type: '1', state: '1' }}
39
+      submitter={{
40
+        searchConfig: {
41
+          resetText: '返回',
42
+        },
43
+        onReset: () => navigate(-1),
44
+        render: (props, doms) => {
45
+          return (
46
+            <Row>
47
+              <Col span={8} offset={8}>
48
+                <Space>{doms}</Space>
49
+              </Col>
50
+            </Row>
51
+          );
52
+        },
53
+      }}
54
+    >
55
+      <ProFormText
56
+        name="name"
57
+        label="名称"
58
+        placeholder="请输入菜肴名称"
59
+        rules={[{ required: true, message: '请输入菜肴名称' }]}
60
+      />
61
+      <ProFormText
62
+        name="unit"
63
+        label="单位"
64
+        placeholder="请输入菜肴单位"
65
+        rules={[{ required: true, message: '请输入菜肴单位' }]}
66
+      />
67
+      <ProFormMoney
68
+        name="price"
69
+        label="价格"
70
+        rules={[{ required: true, message: '请输入菜肴价格' }]}
71
+      />
72
+      <ProFormSelect
73
+        mode="multiple"
74
+        name="ingredientsIdList"
75
+        label="食材"
76
+        placeholder="请选择包含食材"
77
+        options={props.foodDict}
78
+        onChange={props.onIngredientsChange}
79
+      />
80
+      <ProForm.Item name="thumb" label="图片">
81
+        <UploadFile preview={true} />
82
+      </ProForm.Item>
83
+      <ProForm.Item name="content" label="做法">
84
+        <Wangeditor></Wangeditor>
85
+      </ProForm.Item>
86
+    </ProForm>
87
+  );
88
+};

+ 13
- 95
src/pages/dish/edit/index.jsx 查看文件

@@ -1,115 +1,33 @@
1
-import { addDish, getDishById } from '@/services/dish';
2
-import { getStoreList } from '@/services/stock';
3
-import { PageContainer, ProForm, ProFormSelect, ProFormText, ProFormMoney, ProFormDigit } from '@ant-design/pro-components';
1
+import { getDishById } from '@/services/dish';
2
+import { PageContainer } from '@ant-design/pro-components';
4 3
 import { useNavigate, useSearchParams } from 'react-router-dom';
5
-import { Card, Col, message, Row, Space } from 'antd';
6
-import { useEffect, useRef, useState } from 'react';
7
-import { floatMultiply, floatDivide } from "@/utils/float";
4
+import { Alert, Card, Row, Col, message, Space, Button } from 'antd';
5
+import { useEffect, useRef, useState, useMemo } from 'react';
6
+import Edit from './Edit';
8 7
 
9 8
 export default (props) => {
10 9
   const [searchParams] = useSearchParams();
11 10
   const id = searchParams.get('id');
12
-  const [foodDict, setFoodDict] = useState([]);
11
+  const [dish, setDish] = useState();
13 12
   const navigate = useNavigate();
14
-
15
-  const formRef = useRef();
16
-  useEffect(() => {
17
-    getStoreList({ isDish: 1, pageSize: 9999 }).then((res) => {
18
-      setFoodDict(
19
-        res?.records?.map((x) => ({
20
-          label: x.name,
21
-          value: x.id,
22
-        })),
23
-      );
24
-    });
25
-  }, [id]);
26
-
13
+  
27 14
   useEffect(() => {
28 15
     if (id) {
29 16
       getDishById(id).then((res) => {
30
-        formRef.current.setFieldsValue({ ...res, price: floatDivide(res.price, 100) });
17
+        setDish(res);
31 18
       });
32 19
     }
33 20
   }, [id]);
34 21
 
35
-  const onFinish = async (values) => {
36
-    console.log(values, '===');
37
-
38
-    addDish({ ...values, price: floatMultiply(values.price, 100), id }).then((res) => {
39
-      // message.success('添加成功');
40
-      navigate(-1);
41
-    });
42
-
43
-    return false;
22
+  const onFinish = (values) => {
23
+    setDish(values);
24
+    navigate(-1);
44 25
   };
45 26
 
46 27
   return (
47 28
     <PageContainer>
48
-      <Card>
49
-        <ProForm
50
-          formRef={formRef}
51
-          layout={'horizontal'}
52
-          labelCol={{ span: 8 }}
53
-          wrapperCol={{ span: 16 }}
54
-          onFinish={onFinish}
55
-          initialValues={{ type: '1', state: '1' }}
56
-          submitter={{
57
-            searchConfig: {
58
-              resetText: '返回',
59
-            },
60
-            onReset: () => navigate(-1),
61
-            render: (props, doms) => {
62
-              return (
63
-                <Row>
64
-                  <Col span={8} offset={8}>
65
-                    <Space>{doms}</Space>
66
-                  </Col>
67
-                </Row>
68
-              );
69
-            },
70
-          }}
71
-        >
72
-          <ProFormText
73
-            name="name"
74
-            label="菜肴名称"
75
-            placeholder="请输入菜肴名称"
76
-            rules={[{ required: true, message: '请输入菜肴名称' }]}
77
-            width={460}
78
-          />
79
-          <ProFormText
80
-            name="unit"
81
-            label="菜肴单位"
82
-            placeholder="请输入菜肴单位"
83
-            rules={[{ required: true, message: '请输入菜肴单位' }]}
84
-            width={460}
85
-          />
86
-          <ProFormMoney
87
-            name="price"
88
-            label="价格"
89
-            rules={[{ required: true, message: '请输入菜肴价格' }]}
90
-            width={460}
91
-          />
92
-          <ProFormSelect
93
-            mode="multiple"
94
-            name="ingredientsIdList"
95
-            label="包含食材"
96
-            placeholder="请选择包含食材"
97
-            rules={[{ required: true, message: '请选择包含食材' }]}
98
-            width={460}
99
-            options={foodDict}
100
-          />
101
-          <ProFormDigit
102
-            label="元素"
103
-            name="calorie"
104
-            min={0}
105
-            width={460}
106
-            placeholder="卡路里"
107
-            fieldProps={{
108
-              addonAfter: '卡',
109
-              precision: '4'
110
-            }}
111
-          />
112
-        </ProForm>
29
+      <Card style={{ paddingTop: '24px' }}>
30
+        <Edit dish={dish} onFinish={onFinish} />
113 31
       </Card>
114 32
     </PageContainer>
115 33
   );

+ 22
- 0
src/pages/dish/list/components/DishCotent.jsx 查看文件

@@ -0,0 +1,22 @@
1
+import React from 'react';
2
+import { Card } from 'antd';
3
+
4
+const { Meta } = Card;
5
+
6
+export default (props) => {
7
+
8
+  const { dish = {} } = props;
9
+
10
+  const style = {
11
+    height: dish.thumb ? '160px' : '400px',
12
+    overflowY: 'auto',
13
+  }
14
+
15
+  return (
16
+    <Card cover={<img alt='' src={dish.thumb} />} style={{ width: '360px', height: '480px' }}>
17
+      <Meta
18
+        title={dish.name}
19
+        description={<div dangerouslySetInnerHTML={{ __html: dish.content }} style={style} />} />
20
+    </Card>
21
+  )
22
+}

+ 19
- 2
src/pages/dish/list/index.jsx 查看文件

@@ -1,9 +1,10 @@
1 1
 import { getDishList, addDish, updataDish, deleteDish } from '@/services/dish';
2 2
 import { queryTable } from '@/utils/request';
3 3
 import { PageContainer, ProTable } from '@ant-design/pro-components';
4
-import { useNavigate } from 'react-router-dom';
5
-import { Button, message, Popconfirm } from 'antd';
4
+import { useNavigate, Link } from 'react-router-dom';
5
+import { Button, message, Popconfirm, Popover } from 'antd';
6 6
 import { useRef, useState } from 'react';
7
+import DishCotent from './components/DishCotent';
7 8
 
8 9
 const DishList = (props) => {
9 10
   console.log(props, '===');
@@ -34,6 +35,11 @@ const DishList = (props) => {
34 35
     {
35 36
       title: '菜肴名称',
36 37
       dataIndex: 'name',
38
+      render: (t, row) => (
39
+        <Popover placement="right" content={<DishCotent dish={row} />}>
40
+          <Link to={`/stock/dish/detail?id=${row.id}`}>{t}</Link>
41
+        </Popover>
42
+      )
37 43
     },
38 44
 
39 45
     {
@@ -52,6 +58,17 @@ const DishList = (props) => {
52 58
       width: 200,
53 59
       render: (_, record) => [
54 60
 
61
+        <Button
62
+          key={1}
63
+          style={{ padding: 0 }}
64
+          type="link"
65
+          onClick={() => {
66
+            navigate(`/stock/dish/detail?id=${record.id}`);
67
+          }}
68
+        >
69
+          详情
70
+        </Button>,
71
+
55 72
         <Button
56 73
           key={2}
57 74
           style={{ padding: 0 }}

+ 12
- 1
src/pages/evaluate/index.jsx 查看文件

@@ -9,6 +9,7 @@ import { Link, useNavigate } from "react-router-dom";
9 9
 import { Button, message, Popconfirm } from "antd";
10 10
 import moment from "moment";
11 11
 import { useRef, useState } from "react";
12
+import AddeValuate from "./evaluateList/addeValuate";
12 13
 
13 14
 const GuaranteeTaskList = (props) => {
14 15
   const navigate = useNavigate();
@@ -77,6 +78,16 @@ const GuaranteeTaskList = (props) => {
77 78
       valueType: "option",
78 79
       width: 200,
79 80
       render: (_, record) => [
81
+        <Button
82
+          key={1}
83
+          style={{ padding: 0 }}
84
+          type="link"
85
+          onClick={() => {
86
+            navigate(`/task/evaluate/list?id=${record.id}`);
87
+          }}
88
+        >
89
+          评价列表
90
+        </Button>,
80 91
         <Button
81 92
           key={2}
82 93
           style={{ padding: 0 }}
@@ -85,7 +96,7 @@ const GuaranteeTaskList = (props) => {
85 96
             navigate(`/task/evaluate/list?id=${record.id}`);
86 97
           }}
87 98
         >
88
-          评价
99
+          新增评价
89 100
         </Button>,
90 101
       ],
91 102
     },

+ 3
- 3
src/pages/guarantee/list/index.jsx 查看文件

@@ -62,7 +62,7 @@ const GuaranteeList = (props) => {
62 62
           style={{ padding: 0 }}
63 63
           type="link"
64 64
           onClick={() => {
65
-            navigate(`/task/guarantee/edit?id=${record.id}`);
65
+            navigate(`/task/guaranteeUnits/edit?id=${record.id}`);
66 66
           }}
67 67
         >
68 68
           修改
@@ -83,7 +83,7 @@ const GuaranteeList = (props) => {
83 83
          style={{ padding: 0 }}
84 84
          type="link"
85 85
          onClick={() => {
86
-           navigate(`/task/guarantee/personnel/list?id=${record.id}`);
86
+           navigate(`/task/guaranteePerson?id=${record.id}`);
87 87
          }}
88 88
        >
89 89
          人员
@@ -103,7 +103,7 @@ const GuaranteeList = (props) => {
103 103
             key="2"
104 104
             type="primary"
105 105
             onClick={() => {
106
-              navigate("/task/guarantee/edit");
106
+              navigate("/task/guaranteeUnits/edit");
107 107
             }}
108 108
           >
109 109
             新增

+ 2
- 2
src/pages/guarantee/personnel/list/index.jsx 查看文件

@@ -96,7 +96,7 @@ const GuaranteePersonnelList = (props) => {
96 96
           style={{ padding: 0 }}
97 97
           type="link"
98 98
           onClick={() => {
99
-            navigate(`/task/guarantee/personnel/edit?id=${record.id}`);
99
+            navigate(`/task/guaranteePerson/edit?id=${record.id}`);
100 100
           }}
101 101
         >
102 102
           修改
@@ -130,7 +130,7 @@ const GuaranteePersonnelList = (props) => {
130 130
             type="primary"
131 131
             onClick={() => {
132 132
               navigate(
133
-                "/task/guarantee/personnel/edit" + (id ? `?orgId=${id}` : "")
133
+                "/task/guaranteePerson/edit" + (id ? `?orgId=${id}` : "")
134 134
               );
135 135
             }}
136 136
           >

+ 10
- 9
src/pages/guaranteeTask/Edit/DishList.jsx 查看文件

@@ -19,12 +19,12 @@ export default (props) => {
19 19
   const packageRef = useRef();
20 20
   const dishRef = useRef();
21 21
 
22
-  const calorie = useMemo(() => {
23
-    return list.reduce((acc, it) => {
24
-      const dish = dishRef.current.filterItem(it.dishId) || {};
25
-      return acc + dish.calorie || 0;
26
-    }, 0);
27
-  }, [list]);
22
+  // const calorie = useMemo(() => {
23
+  //   return list.reduce((acc, it) => {
24
+  //     const dish = dishRef.current.filterItem(it.dishId) || {};
25
+  //     return acc + dish.calorie || 0;
26
+  //   }, 0);
27
+  // }, [list]);
28 28
 
29 29
   const handlePackageSubmit = ({item, amount}) => {
30 30
     packageRef.current = item;
@@ -35,16 +35,17 @@ export default (props) => {
35 35
       const { records = [] } = res;
36 36
       if (records.length > 0) {
37 37
         for (let it of records) {
38
+          const dishAmount = (it.amount || 1) * amount;
38 39
           const found = list.filter(x => x.dishId === it.id)[0]
39 40
           if (found) {
40
-            found.dishAmount = amount;
41
+            found.dishAmount = dishAmount;
41 42
           } else {
42 43
             list.push({
43 44
               guaranteeId: dataSource.id,
44 45
               dishId: it.id,
45 46
               dishName: it.name,
46 47
               dishUnit: it.unit,
47
-              dishAmount: amount,
48
+              dishAmount: dishAmount,
48 49
             })
49 50
           }
50 51
         }
@@ -144,7 +145,7 @@ export default (props) => {
144 145
       </Col>
145 146
       <Col span={16}>
146 147
         <Card
147
-          title={`已选菜肴 共计${calorie}卡`}
148
+          title="已选菜肴"
148 149
           loading={loading}
149 150
           extra={<Button disabled={!dataSource} type='primary' loading={loading} onClick={onSubmit}>保存</Button>}
150 151
         >

+ 90
- 55
src/pages/package/DishList.jsx 查看文件

@@ -1,15 +1,22 @@
1
-import React, { useEffect, useState, useRef } from 'react';
2
-import { Button, List, Popconfirm, Select } from 'antd';
1
+import React, { useEffect, useState, useRef, forwardRef, useImperativeHandle } from 'react';
2
+import { Button, Modal, List, Popconfirm, Form, Select, InputNumber } from 'antd';
3 3
 import classNames from 'classnames';
4
+import useBool from '@/utils/hooks/useBool';
4 5
 import { getPackageDetailList, addPackageDetail, deletePackageDetail } from '@/services/package';
5 6
 import { getDishList } from '@/services/dish';
6 7
 
7 8
 const { Option } = Select;
9
+const defaultKind = 2;
8 10
 
9
-const Header = props => {
11
+const AddDish = props => {
10 12
   const { onChange } = props;
11 13
   const [data, setData] = useState([]);
12
-  const [value, setValue] = useState();
14
+  const [form] = Form.useForm();
15
+
16
+  const onFinish = (values) => {
17
+    const it = data.filter(x => x.id === values.dishId)[0] || {};
18
+    onChange({...it, ...values });
19
+  };
13 20
 
14 21
   const handleSearch = (newValue) => {
15 22
     if (newValue) {
@@ -21,52 +28,65 @@ const Header = props => {
21 28
     }
22 29
   };
23 30
 
24
-  const handleChange = (newValue) => {
25
-    setValue(newValue);
26
-    if (newValue) {
27
-      onChange(data.filter(x => x.id === newValue)[0]);
28
-    }
29
-  };
30
-
31 31
   const options = data.map(d => <Option key={d.id} value={d.id}>{d.name}</Option>);
32 32
 
33 33
   const initList = () => {
34
-    getDishList({ pageNum: 1, pageSize: 10 }).then(res => {
34
+    getDishList({ pageNum: 1, pageSize: 20 }).then(res => {
35 35
       setData(res.records || []);
36 36
     });
37 37
   }
38 38
 
39 39
   useEffect(() => {
40 40
     initList();
41
+    form.setFieldsValue({ dishKind: 2, amount: 1 });
41 42
   }, [])
42 43
 
43 44
   return (
44
-    <Select
45
-      style={{ width: '100%' }}
46
-      allowClear
47
-      showSearch
48
-      value={value}
49
-      placeholder='请选择菜肴'
50
-      defaultActiveFirstOption={false}
51
-      showArrow={false}
52
-      filterOption={false}
53
-      onSearch={handleSearch}
54
-      onChange={handleChange}
55
-      notFoundContent={null}
56
-      onClear={initList}
57
-    >
58
-      {options}
59
-    </Select>
45
+    <Form form={form} layout="vertical" onFinish={onFinish}>
46
+      <Form.Item name="dishId" label="选择菜肴" rules={[{ required: true, message: '请选择菜肴' }]}>
47
+        <Select
48
+          allowClear
49
+          showSearch
50
+          placeholder='请选择菜肴, 可输入汉字搜索'
51
+          defaultActiveFirstOption={false}
52
+          showArrow={false}
53
+          filterOption={false}
54
+          onSearch={handleSearch}
55
+          // onChange={handleChange}
56
+          notFoundContent={null}
57
+          onClear={initList}
58
+        >
59
+          {options}
60
+        </Select>
61
+      </Form.Item>
62
+      <Form.Item name="dishKind" label="菜肴类型">
63
+        <Select allowClear defaultValue={defaultKind}>
64
+          <Select.Option value={1}>主食</Select.Option>
65
+          <Select.Option value={2}>菜肴</Select.Option>
66
+        </Select>
67
+      </Form.Item>
68
+      <Form.Item name="amount" label="菜肴数量" rules={[{ required: true, message: '请设置数量' }]}>
69
+        <InputNumber style={{ width: '100%' }} min={1} />
70
+      </Form.Item>
71
+      <Form.Item>
72
+        <Button type='primary' htmlType='sumbit'>确定</Button>
73
+      </Form.Item>
74
+    </Form>
60 75
   );
61 76
 }
62 77
 
78
+const kindDict = {
79
+  '1': '主食',
80
+  '2': '菜肴',
81
+}
63 82
 
64
-export default (props) => {
83
+export default forwardRef((props, ref) => {
65 84
   const { current, setCurrent } = props;
66 85
 
67 86
   const packageId = (current || {}).id;
68 87
 
69 88
   const [loading, setLoading] = useState(false);
89
+  const [open, setVisible, hide ] = useBool();
70 90
   const [list, setList] = useState([]);
71 91
   const [detail, setDetail] = useState({});
72 92
   const listRef = useRef();
@@ -74,10 +94,11 @@ export default (props) => {
74 94
 
75 95
   const onAdd = item => {
76 96
     setLoading(true);
77
-    addPackageDetail({ packageId, dishId: item.id }).then(res => {
97
+    addPackageDetail({ ...item, packageId, dishId: item.id }).then(res => {
78 98
       setLoading(false);
79 99
       const newList = listRef.current.concat(res);
80 100
       setList(newList);
101
+      hide();
81 102
     }).catch(() => {
82 103
       setLoading(false);
83 104
     });
@@ -108,30 +129,44 @@ export default (props) => {
108 129
 
109 130
   }, [packageId]);
110 131
 
132
+  useImperativeHandle(ref, () => ({
133
+    new: () => setVisible(),
134
+  }));
135
+
111 136
   return (
112
-    <List
113
-      style={{ minHeight: '300px' }}
114
-      header={<Header onChange={onAdd} />}
115
-      bordered
116
-      loading={loading}
117
-      dataSource={list}
118
-      renderItem={item => (
119
-        <List.Item
120
-          className={classNames({ active: detail.id === item.id })}
121
-          onClick={() => setDetail(item)}
122
-          actions={[
123
-            <Popconfirm
124
-              key="delete"
125
-              title="确认删除?"
126
-              onConfirm={() => onDelete(item)}
127
-              >
128
-              <a href="#">删除</a>
129
-            </Popconfirm>
130
-          ]}
131
-        >
132
-          {item.name}
133
-        </List.Item>
134
-      )}
135
-    />
137
+    <>
138
+      <List
139
+        style={{ minHeight: '300px' }}
140
+        loading={loading}
141
+        dataSource={list}
142
+        renderItem={item => (
143
+          <List.Item
144
+            className={classNames({ active: detail.id === item.id })}
145
+            onClick={() => setDetail(item)}
146
+            actions={[
147
+              <Popconfirm
148
+                key="delete"
149
+                title="确认删除?"
150
+                onConfirm={() => onDelete(item)}
151
+                >
152
+                <a href="#">删除</a>
153
+              </Popconfirm>
154
+            ]}
155
+          >
156
+            {`【${kindDict[`${item.dishKind}`]}】${item.name} x ${item.amount}`}
157
+          </List.Item>
158
+        )}
159
+      />
160
+      <Modal
161
+        title="添加菜肴"
162
+        open={open}
163
+        onCancel={hide}
164
+        maskClosable={false}
165
+        footer={null}
166
+        destroyOnClose
167
+      >
168
+        <AddDish onChange={onAdd} />
169
+      </Modal>
170
+    </>
136 171
   );
137
-}
172
+})

+ 59
- 36
src/pages/package/List.jsx 查看文件

@@ -1,13 +1,17 @@
1
-import React, { useState, useEffect, useRef } from 'react';
2
-import { Row, Col, Button, List, Popconfirm, Input } from 'antd';
1
+import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react';
2
+import { Modal, Button, List, Popconfirm, Input } from 'antd';
3 3
 import classNames from 'classnames';
4
+import BasicForm from './BasicForm';
4 5
 import { getPackageList, deletePackage } from '@/services/package';
6
+import useBool from '@/utils/hooks/useBool';
7
+import { floatDivide } from '@/utils/float';
5 8
 
6
-export default (props) => {
9
+export default forwardRef((props, ref) => {
7 10
   const { current, setCurrent } = props;
8
-  const [loading, setLoading] = useState(false);
9
-  const [hasMore, setHasMore] = useState(true);
10
-  const [filter, setFilter] = useState({ pageNum: 1, pageSize: 10, total: 0 });
11
+  const [loading, startLoading, stopLoading] = useBool();
12
+  const [open, setVisible, hide] = useBool();
13
+  const [hasMore, setHasMore] = useState(false);
14
+  const [filter, setFilter] = useState({ pageNum: 1, pageSize: 20, total: 0 });
11 15
   const [list, setList] = useState([]);
12 16
   const listRef = useRef();
13 17
   listRef.current = list;
@@ -40,10 +44,15 @@ export default (props) => {
40 44
     })
41 45
   }
42 46
 
47
+  const onEdit = (val = {}) => {
48
+    setCurrent(val);
49
+    setVisible();
50
+  }
51
+
43 52
   const onDelete = (item) => {
44
-    setLoading(true);
53
+    startLoading();
45 54
     deletePackage(item.id).then(res => {
46
-      setLoading(false);
55
+      stopLoading();
47 56
 
48 57
       const newList = listRef.current.filter(x => x.id !== item.id);
49 58
       setList(newList);
@@ -51,14 +60,19 @@ export default (props) => {
51 60
         setCurrent(newList[0] || {});
52 61
       }
53 62
     }).catch(() => {
54
-      setLoading(false);
63
+      stopLoading();
55 64
     });
56 65
   };
57 66
 
67
+  const handleForm = (val) => {
68
+    setCurrent(val);
69
+    hide()
70
+  }
71
+
58 72
   useEffect(() => {
59
-    setLoading(true);
73
+    startLoading();
60 74
     getPackageList(filter).then(res => {
61
-      setLoading(false);
75
+      stopLoading();
62 76
 
63 77
       const { records = [], current, total, pages } = res
64 78
 
@@ -71,7 +85,7 @@ export default (props) => {
71 85
 
72 86
       setHasMore(current < pages)
73 87
     }).catch(() => {
74
-      setLoading(false);
88
+      stopLoading();
75 89
     });
76 90
   }, [filter]);
77 91
 
@@ -95,36 +109,45 @@ export default (props) => {
95 109
     setList(newList);
96 110
   }, [current])
97 111
 
112
+  useImperativeHandle(ref, () => ({
113
+    new: () => onEdit(),
114
+  }));
115
+
98 116
   return (
117
+    <>
99 118
     <List
100 119
       style={{ minHeight: '600px' }}
101 120
       bordered
102
-      header={
103
-        <Input.Group compact>
104
-          <Input.Search allowClear placeholder="请输入筛选名称" onSearch={onSearch} style={{ width: 'calc(100% - 60px)' }} />
105
-          <Button type='link' onClick={() => setCurrent({})} >新增</Button>
106
-        </Input.Group>
107
-      }
121
+      header={<Input.Search allowClear placeholder="请输入筛选名称" onSearch={onSearch} />}
108 122
       dataSource={list}
109 123
       loading={loading}
110 124
       loadMore={loadMore}
111
-      renderItem={item => (
112
-        <List.Item
113
-          className={classNames({ active: current.id === item.id })}
114
-          onClick={() => setCurrent(item)}
115
-          actions={[
116
-            <Popconfirm
117
-              key="delete"
118
-              title="确认删除?"
119
-              onConfirm={() => onDelete(item)}
120
-              >
121
-              <a href="#">删除</a>
122
-            </Popconfirm>
123
-          ]}
124
-        >
125
-          {item.name}
126
-        </List.Item>
127
-      )}
125
+      renderItem={item => {
126
+        const price = item.price ? floatDivide(item.price, 100) : 0;
127
+
128
+        return (
129
+          <List.Item
130
+            className={classNames({ active: current.id === item.id })}
131
+            onClick={() => setCurrent(item)}
132
+            actions={[
133
+              <Button key="edit" type='link' onClick={() => onEdit(item)}>编辑</Button>,
134
+              <Popconfirm
135
+                key="delete"
136
+                title="确认删除?"
137
+                onConfirm={() => onDelete(item)}
138
+                >
139
+                <a href="#">删除</a>
140
+              </Popconfirm>
141
+            ]}
142
+          >
143
+            {`${item.name} ¥${price}元`}
144
+          </List.Item>
145
+        )
146
+      }}
128 147
     />
148
+    <Modal open={open} title="套餐维护" footer={null} onCancel={hide} maskClosable={false} >
149
+      <BasicForm current={current} onChange={handleForm}></BasicForm>
150
+    </Modal>
151
+    </>
129 152
   )
130
-}
153
+})

+ 20
- 18
src/pages/package/index.jsx 查看文件

@@ -1,6 +1,6 @@
1
-import React, { useState } from 'react';
1
+import React from 'react';
2 2
 import { PageContainer } from '@ant-design/pro-components';
3
-import { Row, Col, Card } from 'antd';
3
+import { Button, Row, Col, Card } from 'antd';
4 4
 import List from './List';
5 5
 import BasicForm from './BasicForm';
6 6
 import DishList from './DishList';
@@ -8,23 +8,25 @@ import DishList from './DishList';
8 8
 import './style.less';
9 9
 
10 10
 export default (props) => {
11
-  const [current, setCurrent] = useState({});
11
+  const [current, setCurrent] = React.useState({});
12
+  const pkgRef = React.useRef();
13
+  const dishRef = React.useRef();
14
+
15
+  const onAdd = () => pkgRef.current.new();
16
+  const onDishAdd = () => dishRef.current.new();
12 17
 
13 18
   return (
14
-    <PageContainer>
15
-      <Card>
16
-        <Row gutter={100}>
17
-          <Col span={8}>
18
-            <List current={current} setCurrent={setCurrent}/>
19
-          </Col>
20
-          <Col span={8}>
21
-            <BasicForm current={current} onChange={it => setCurrent(it)} />
22
-            <div style={{ marginTop: '24px' }}>
23
-              <DishList current={current} />
24
-            </div>
25
-          </Col>
26
-        </Row>
27
-      </Card>
28
-    </PageContainer>
19
+    <Row gutter={24}>
20
+      <Col span={12}>
21
+        <Card title="套餐列表" extra={<Button type='primary' onClick={onAdd}>新增</Button>}>
22
+          <List ref={pkgRef} current={current} setCurrent={setCurrent}/>
23
+        </Card>
24
+      </Col>
25
+      <Col span={12}>
26
+        <Card title={`${current.name || '套餐'} 明细`} extra={<Button onClick={onDishAdd}>新增</Button>}>
27
+          <DishList current={current} ref={dishRef} />
28
+        </Card>
29
+      </Col>
30
+    </Row>
29 31
   )
30 32
 }

+ 14
- 5
src/pages/stockClassification/edit/index.jsx 查看文件

@@ -1,9 +1,11 @@
1 1
 import { addStoreType, getStoreTypeById, updataStoreType } from '@/services/stock';
2
-import { PageContainer, ProForm, ProFormSelect, ProFormText } from '@ant-design/pro-components';
2
+import { PageContainer, ProForm, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
3 3
 import { useNavigate, useSearchParams } from 'react-router-dom';
4 4
 import { Card, Col, message, Row, Space } from 'antd';
5 5
 import { useEffect, useRef } from 'react';
6 6
 
7
+const width = 540;
8
+
7 9
 export default (props) => {
8 10
   const [searchParams, setSearchParams] = useSearchParams();
9 11
   const id = searchParams.get('id');
@@ -44,7 +46,7 @@ export default (props) => {
44 46
         <ProForm
45 47
           formRef={formRef}
46 48
           layout={'horizontal'}
47
-          labelCol={{ span: 8 }}
49
+          labelCol={{ span: 4 }}
48 50
           wrapperCol={{ span: 16 }}
49 51
           onFinish={onFinish}
50 52
           submitter={{
@@ -67,7 +69,7 @@ export default (props) => {
67 69
             name="name"
68 70
             label="分类名称"
69 71
             placeholder="请输入名称"
70
-            width={460}
72
+            width={width}
71 73
             allowClear={false}
72 74
             rules={[{ required: true, message: '请输入名称' }]}
73 75
           />
@@ -79,7 +81,7 @@ export default (props) => {
79 81
               { label: '否', value: 0 },
80 82
             ]}
81 83
             placeholder="请选择"
82
-            width={460}
84
+            width={width}
83 85
             allowClear={false}
84 86
             rules={[{ required: true, message: '请选择是否食材' }]}
85 87
           />
@@ -91,10 +93,17 @@ export default (props) => {
91 93
               { label: '否', value: 0 },
92 94
             ]}
93 95
             placeholder="请选择"
94
-            width={460}
96
+            width={width}
95 97
             allowClear={false}
96 98
             rules={[{ required: true, message: '请选择是否设备' }]}
97 99
           />
100
+          <ProFormTextArea
101
+            name="nutrition"
102
+            label="营养元素"
103
+            placeholder="请输入名称"
104
+            width={width}
105
+            allowClear={true}
106
+          />
98 107
         </ProForm>
99 108
       </Card>
100 109
     </PageContainer>

+ 27
- 17
src/routes/routes.jsx 查看文件

@@ -24,6 +24,7 @@ import GuaranteePersonnelList from "@/pages/guarantee/personnel/list";
24 24
 import GuaranteePersonnelEdit from "@/pages/guarantee/personnel/edit";
25 25
 import DishList from "@/pages/dish/list";
26 26
 import DishEdit from "@/pages/dish/edit";
27
+import DishDetail from "@/pages/dish/edit/detail";
27 28
 import PackageList from "@/pages/package";
28 29
 import StockList from "@/pages/stock/list";
29 30
 import StockEdit from "@/pages/stock/edit";
@@ -91,14 +92,6 @@ export const authRoutes = [
91 92
         index: true,
92 93
         element: <Navigate to="guaranteeTask" replace />,
93 94
       },
94
-      {
95
-        path: "guaranteeTask",
96
-        element: <GuaranteeTaskList />,
97
-        meta: {
98
-          title: "军供通报",
99
-          permission: 'guaranteeTask',
100
-        },
101
-      },
102 95
       {
103 96
         path: "guaranteeTask/edit",
104 97
         element: <GuaranteeTaskEdit />,
@@ -107,6 +100,14 @@ export const authRoutes = [
107 100
           permission: 'guaranteeTask.edit',
108 101
         },
109 102
       },
103
+      {
104
+        path: "guaranteeTask",
105
+        element: <GuaranteeTaskList />,
106
+        meta: {
107
+          title: "军供通报",
108
+          permission: 'guaranteeTask',
109
+        },
110
+      },
110 111
       {
111 112
         path: "guaranteeTask/print",
112 113
         element: <GuaranteeTaskPrint />,
@@ -136,37 +137,37 @@ export const authRoutes = [
136 137
         },
137 138
       },
138 139
       {
139
-        path: "guarantee/list",
140
+        path: "guaranteeUnits/list",
140 141
         element: <GuaranteeList />,
141 142
         meta: {
142 143
           title: "保障机构",
143
-          // permission: 'guaranteeTask.guarantee',
144
+          permission: 'guaranteeUnits',
144 145
         },
145 146
       },
146 147
       {
147
-        path: "guarantee/edit",
148
+        path: "guaranteeUnits/edit",
148 149
         element: <GuaranteeEdit />,
149 150
         meta: {
150 151
           title: "机构维护",
151 152
           hideInMenu: true,
152
-          // permission: 'guaranteeTask.guarantee',
153
+          permission: 'guaranteeUnits.edit',
153 154
         },
154 155
       },
155 156
       {
156
-        path: "guarantee/personnel/list",
157
+        path: "guaranteePerson",
157 158
         element: <GuaranteePersonnelList />,
158 159
         meta: {
159 160
           title: "机构人员",
160
-          // permission: 'guaranteeTask.guarantee',
161
+          permission: 'guaranteePerson',
161 162
         },
162 163
       },
163 164
       {
164
-        path: "guarantee/personnel/edit",
165
+        path: "guaranteePerson/edit",
165 166
         element: <GuaranteePersonnelEdit />,
166 167
         meta: {
167 168
           title: "机构人员维护",
168 169
           hideInMenu: true,
169
-          // permission: 'guaranteeTask.guarantee',
170
+          permission: 'guaranteePerson.edit',
170 171
         },
171 172
       },
172 173
       {
@@ -174,7 +175,7 @@ export const authRoutes = [
174 175
         element: <Supportability />,
175 176
         meta: {
176 177
           title: "保障能力",
177
-          permission: 'guaranteeTask.evaluate.list',
178
+          permission: 'supportability',
178 179
         },
179 180
       },
180 181
     ],
@@ -208,6 +209,15 @@ export const authRoutes = [
208 209
           permission: 'dish.edit',
209 210
         },
210 211
       },
212
+      {
213
+        path: "dish/detail",
214
+        element: <DishDetail />,
215
+        meta: {
216
+          hideInMenu: true,
217
+          title: "菜肴详情",
218
+          permission: 'dish.detail',
219
+        },
220
+      },
211 221
       {
212 222
         path: "package/list",
213 223
         element: <PackageList />,