瀏覽代碼

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

fangmingyue 2 年之前
父節點
當前提交
6e24d4f09d

+ 1
- 1
config/proxy.js 查看文件

@@ -12,7 +12,7 @@ export default {
12 12
     '/api/': {
13 13
       // 要代理的地址
14 14
       //http://192.168.89.147:8087
15
-      target: 'http://localhost:8087',
15
+      target: 'http://192.168.89.147:8087',
16 16
       // 配置了这个可以从 http 代理到 https
17 17
       // 依赖 origin 的功能可能需要这个,比如 cookie
18 18
       changeOrigin: true,

+ 51
- 0
config/routes.js 查看文件

@@ -88,6 +88,57 @@
88 88
     // hideInMenu: true,
89 89
     component: './guaranteeTask/Edit/index',
90 90
   },
91
+  {
92
+    path: '/stock/list',
93
+    name: '库存管理',
94
+    icon: 'smile',
95
+    component: './stock/list',
96
+  },
97
+  {
98
+    path: '/stock/add',
99
+    name: '库存新增',
100
+    hideInMenu: true,
101
+    component: './stock/edit',
102
+  },
103
+
104
+  {
105
+    path: '/stock/edit',
106
+    name: '库存详细',
107
+    hideInMenu: true,
108
+    component: './stock/edit',
109
+  },
110
+  {
111
+    path: '/stock/outAndIn',
112
+    name: '出入库管理',
113
+    hideInMenu: true,
114
+    component: './stock/outAndIn',
115
+  },
116
+  {
117
+    path: '/stockLog/list',
118
+    name: '库存日志',
119
+    icon: 'VideoCameraOutlined',
120
+    component: './stock/stockLog',
121
+  },
122
+  {
123
+    path: '/stockClassification/list',
124
+    name: '分类管理',
125
+    icon: 'smile',
126
+    component: './stockClassification/list',
127
+  },
128
+  {
129
+    path: '/stockClassification/edit',
130
+    name: '分类管理',
131
+    icon: 'smile',
132
+    hideInMenu: true,
133
+    component: './stockClassification/edit',
134
+  },
135
+  {
136
+    path: '/guaranteeTask/print',
137
+    name: '保障单',
138
+    hideInMenu: true,
139
+    layout: false,
140
+    component: './guaranteeTask/print/index',
141
+  },
91 142
   {
92 143
     component: './404',
93 144
   },

+ 15
- 0
src/components/EditableTag/Tag.jsx 查看文件

@@ -0,0 +1,15 @@
1
+import React from 'react';
2
+import { Button } from 'antd';
3
+import { CloseOutlined } from '@ant-design/icons';
4
+import './style.less'
5
+
6
+export default (props) => {
7
+  const { size, type, onDelete, children } = props;
8
+
9
+  return (
10
+    <div className='tag-btn-group'>
11
+      <Button size={size} type={type}>{children}</Button>
12
+      <Button size={size} type="primary" icon={<CloseOutlined />} onClick={onDelete} />
13
+    </div>
14
+  )
15
+}

+ 21
- 0
src/components/EditableTag/index.jsx 查看文件

@@ -0,0 +1,21 @@
1
+import React from 'react';
2
+import { Button } from 'antd';
3
+import Tag from './Tag';
4
+import './style.less'
5
+
6
+export default (props) => {
7
+  const { size, type, list = [], onDelete, keyFuc, labelFunc } = props;
8
+
9
+  return (
10
+    <div className='editable-tag-box'>
11
+      {
12
+        list.map((item, index) => {
13
+          const key = keyFuc(item, index);
14
+          const label = labelFunc(item, index);
15
+
16
+          return <Tag key={key} size={size} type={type} onDelete={() => onDelete(item)}>{label}</Tag>
17
+        })
18
+      }
19
+    </div>
20
+  )
21
+}

+ 27
- 0
src/components/EditableTag/style.less 查看文件

@@ -0,0 +1,27 @@
1
+.tag-btn-group {
2
+  .ant-btn {
3
+    vertical-align: middle;
4
+  }
5
+
6
+  .ant-btn:first-child {
7
+    border-right: none;
8
+  }
9
+
10
+  .ant-btn:last-child {
11
+    // border-left: none;
12
+    border-top-left-radius: 0;
13
+    border-bottom-left-radius: 0;
14
+    margin-left: -1px;
15
+  }
16
+}
17
+
18
+.editable-tag-box {
19
+  display: flex;
20
+  flex-wrap: wrap;
21
+
22
+  .tag-btn-group {
23
+    flex: none;
24
+    box-sizing: border-box;
25
+    padding: 1em;
26
+  }
27
+}

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

@@ -7,7 +7,7 @@ import { values } from 'lodash';
7 7
 import { useEffect, useRef, useState } from 'react';
8 8
 
9 9
 export default (props) => {
10
-  const [searchParams, setSearchParams] = useSearchParams();
10
+  const [searchParams] = useSearchParams();
11 11
   const id = searchParams.get('id');
12 12
   const [datas, setDatas] = useState([]);
13 13
   const [data, setData] = useState({});

+ 63
- 20
src/pages/guaranteeTask/Edit/BasicForm.jsx 查看文件

@@ -1,12 +1,19 @@
1
-import React, { useState } from 'react';
1
+import React, { useState, useEffect } from 'react';
2
+import moment from 'moment';
3
+import { Link } from 'umi';
2 4
 import { Button, Row, Col, Form, Input, InputNumber, DatePicker, notification } from 'antd';
5
+import { addGuaranteeTask, updateGuaranteeTask } from '@/services/api/guaranteeTask';
3 6
 
4 7
 const { TextArea } = Input;
5 8
 const { RangePicker } = DatePicker;
6 9
 
7 10
 export default (props) => {
11
+  const { dataSource, setDataSource } = props;
12
+  const id = dataSource ? dataSource.id : undefined;
13
+
8 14
   const [form] = Form.useForm()
9 15
   const [rangeDate, setRangeDate] = useState([]);
16
+  const [loading, setLoading] = useState(false);
10 17
 
11 18
   const onChange = (dts) => {
12 19
     const [start, end] = dts;
@@ -22,10 +29,43 @@ export default (props) => {
22 29
       notification.warn({ message: '未检索到填写内容' });
23 30
       return ;
24 31
     }
32
+
33
+    const [start, end] = rangeDate;
34
+    const startDate = start ? start.format('YYYY-MM-DD') : undefined;
35
+    const endDate = end ? end.format('YYYY-MM-DD') : undefined;
36
+
37
+    const func = id ? updateGuaranteeTask : addGuaranteeTask;
38
+
39
+    setLoading(true);
40
+    func({ ...values, startDate, endDate }, id).then(res => {
41
+      setLoading(false);
42
+      setDataSource(res);
43
+      notification.success({ message: '操作成功' })
44
+    }).catch(() => {
45
+      setLoading(false);
46
+    });
25 47
   }
26 48
 
49
+  useEffect(() => {
50
+    if (dataSource) {
51
+      form.setFieldsValue(dataSource);
52
+
53
+      let rangeDt = [];
54
+
55
+      if (dataSource.startDate) {
56
+        rangeDt[0] = moment(dataSource.startDate);
57
+      }
58
+
59
+      if (dataSource.endDate) {
60
+        rangeDt[1] = moment(dataSource.endDate);
61
+      }
62
+
63
+      setRangeDate(rangeDt);
64
+    }
65
+  }, [dataSource, form]);
66
+
27 67
   return (
28
-    <Form layout="vertical" onFinish={onFinish}>
68
+    <Form layout="vertical" form={form} onFinish={onFinish}>
29 69
       <h3 style={{ marginBottom: '1.5em', fontWeight: 700 }}>人员安排</h3>
30 70
       <Row gutter={48}>
31 71
         <Col span={6}>
@@ -39,12 +79,12 @@ export default (props) => {
39 79
           </Form.Item>
40 80
         </Col>
41 81
         <Col span={6}>
42
-          <Form.Item label="部队联系人" name="concat_person">
82
+          <Form.Item label="部队联系人" name="concatPerson">
43 83
             <Input allowClear />
44 84
           </Form.Item>
45 85
         </Col>
46 86
         <Col span={6}>
47
-          <Form.Item label="部队联系人电话" name="concat_phone">
87
+          <Form.Item label="部队联系人电话" name="concatPhone">
48 88
             <Input allowClear />
49 89
           </Form.Item>
50 90
         </Col>
@@ -56,17 +96,17 @@ export default (props) => {
56 96
           </Form.Item>
57 97
         </Col>
58 98
         <Col span={6}>
59
-          <Form.Item label="制餐人电话" name="chef_phone">
99
+          <Form.Item label="制餐人电话" name="chefPhone">
60 100
             <Input allowClear />
61 101
           </Form.Item>
62 102
         </Col>
63 103
         <Col span={6}>
64
-          <Form.Item label="送餐人" name="delivery_man">
104
+          <Form.Item label="送餐人" name="deliveryMan">
65 105
             <Input allowClear />
66 106
           </Form.Item>
67 107
         </Col>
68 108
         <Col span={6}>
69
-          <Form.Item label="送餐人电话" name="delivery_phone">
109
+          <Form.Item label="送餐人电话" name="deliveryPhone">
70 110
             <Input allowClear />
71 111
           </Form.Item>
72 112
         </Col>
@@ -75,34 +115,34 @@ export default (props) => {
75 115
       <h3 style={{ margin: '1.5em 0', fontWeight: 700 }}>基本情况</h3>
76 116
       <Row gutter={48}>
77 117
         <Col span={6}>
78
-          <Form.Item label="军代表" name="deputy_man">
118
+          <Form.Item label="军代表" name="deputyMan">
79 119
             <Input allowClear />
80 120
           </Form.Item>
81 121
         </Col>
82 122
         <Col span={6}>
83
-          <Form.Item label="电话" name="deputy_phone">
123
+          <Form.Item label="电话" name="deputyPhone">
84 124
             <Input allowClear />
85 125
           </Form.Item>
86 126
         </Col>
87 127
         <Col span={6}>
88
-          <Form.Item label="通报时间" name="got_date">
128
+          <Form.Item label="通报时间" name="gotDate">
89 129
             <Input allowClear />
90 130
           </Form.Item>
91 131
         </Col>
92 132
       </Row>
93 133
       <Row gutter={48}>
94 134
         <Col span={6}>
95
-          <Form.Item label="保障序号" name="guarantee_no">
135
+          <Form.Item label="保障序号" name="guaranteeNo">
96 136
             <Input allowClear />
97 137
           </Form.Item>
98 138
         </Col>
99 139
         <Col span={6}>
100
-          <Form.Item label="军运号" name="transport_no">
140
+          <Form.Item label="军运号" name="transportNo">
101 141
             <Input allowClear />
102 142
           </Form.Item>
103 143
         </Col>
104 144
         <Col span={6}>
105
-          <Form.Item label="车次" name="trips_no">
145
+          <Form.Item label="车次" name="tripsNo">
106 146
             <Input allowClear />
107 147
           </Form.Item>
108 148
         </Col>
@@ -114,24 +154,24 @@ export default (props) => {
114 154
           </Form.Item>
115 155
         </Col>
116 156
         <Col span={6}>
117
-          <Form.Item label="保障时间" name="time_range">
157
+          <Form.Item label="保障时间" name="timeRange">
118 158
             <Input allowClear />
119 159
           </Form.Item>
120 160
         </Col>
121 161
       </Row>
122 162
       <Row gutter={48}>
123 163
         <Col span={6}>
124
-          <Form.Item label="保障人数" name="total_person_num">
164
+          <Form.Item label="保障人数" name="totalPersonNum">
125 165
             <InputNumber min={1} style={{ width: '100%' }}/>
126 166
           </Form.Item>
127 167
         </Col>
128 168
         <Col span={6}>
129
-          <Form.Item label="其中回民" name="hui_person_num">
169
+          <Form.Item label="其中回民" name="huiPersonNum">
130 170
             <InputNumber min={0} style={{ width: '100%' }}/>
131 171
           </Form.Item>
132 172
         </Col>
133 173
         <Col span={6}>
134
-          <Form.Item label="其中病号" name="patient_num">
174
+          <Form.Item label="其中病号" name="patientNum">
135 175
             <InputNumber min={0} style={{ width: '100%' }}/>
136 176
           </Form.Item>
137 177
         </Col>
@@ -157,9 +197,12 @@ export default (props) => {
157 197
       </Row>
158 198
 
159 199
       <Row gutter={48}>
160
-        <Col offset={6} span={6}>
161
-          <Button type="primary" htmlType="submit">提交</Button>
162
-          <Button style={{ marginLeft: '100px' }}>返回</Button>
200
+        <Col offset={6} span={12}>
201
+          <Button type="primary" htmlType="submit" loading={loading}>提交</Button>
202
+          <Button style={{ marginLeft: '48px' }}>返回</Button>
203
+          <Button style={{ marginLeft: '48px' }}>
204
+            <Link target="_blank" to={`/guaranteeTask/print?id=${id}`}>打印预览</Link>
205
+          </Button>
163 206
         </Col>
164 207
       </Row>
165 208
 

+ 144
- 2
src/pages/guaranteeTask/Edit/DishList.jsx 查看文件

@@ -1,7 +1,149 @@
1
-import React from 'react'
1
+import React, { useState, useEffect, useRef } from 'react';
2
+import { Row, Col, Card, Button, notification } from 'antd';
3
+import EditableTag from '@/components/EditableTag';
4
+import { getDishList } from '@/services/api/dish';
5
+import { getPackageList, getPackageDetailList } from '@/services/api/package';
6
+import {
7
+  updateGuaranteeTask,
8
+  getGuaranteeDetailList,
9
+  addGuaranteeDetailBatch,
10
+  deleteGuaranteeDetail
11
+} from '@/services/api/guaranteeTask';
12
+import Selector from './components/Selector';
2 13
 
3 14
 export default (props) => {
15
+  const { dataSource, setDataSource } = props;
16
+
17
+  const [list, setList] = useState([]);
18
+  const [loading, setLoading] = useState(false);
19
+  const packageRef = useRef();
20
+
21
+  const handlePackageSubmit = ({item, amount}) => {
22
+    packageRef.current = item;
23
+
24
+    // 获取套餐下所有的菜肴
25
+    // 然后把菜肴放入到列表
26
+    getPackageDetailList({ pageNum: 1, pageSize: 500, packageId: item.id }).then(res => {
27
+      const { records = [] } = res;
28
+      if (records.length > 0) {
29
+        for (let it of records) {
30
+          const found = list.filter(x => x.dishId === it.id)[0]
31
+          if (found) {
32
+            found.dishAmount = amount;
33
+          } else {
34
+            list.push({
35
+              guaranteeId: dataSource.id,
36
+              dishId: it.id,
37
+              dishName: it.name,
38
+              dishUnit: it.unit,
39
+              dishAmount: amount,
40
+            })
41
+          }
42
+        }
43
+
44
+        setList(list.slice());
45
+      }
46
+    })
47
+  };
48
+
49
+  const handleDishSubmit = ({item, amount}) => {
50
+    const found = list.filter(x => x.dishId === item.id)[0]
51
+    if (found) {
52
+      found.dishAmount = amount;
53
+    } else {
54
+      list.push({
55
+        guaranteeId: dataSource.id,
56
+        dishId: item.id,
57
+        dishName: item.name,
58
+        dishUnit: item.unit,
59
+        dishAmount: amount,
60
+      })
61
+    }
62
+
63
+    setList(list.slice());
64
+  };
65
+
66
+  const onDelete = (item) => {
67
+    if (item.id) {
68
+      setLoading(true);
69
+      deleteGuaranteeDetail(item.id).then(res => {
70
+        setLoading(false);
71
+
72
+        const nwList = list.filter(x => x.dishId !== item.dishId);
73
+        setList(nwList);
74
+      }).catch(() => {
75
+        setLoading(false);
76
+      })
77
+    } else {
78
+      const nwList = list.filter(x => x.dishId !== item.dishId);
79
+      setList(nwList);
80
+    }
81
+  }
82
+
83
+  const onSubmit = () => {
84
+    setLoading(true);
85
+    addGuaranteeDetailBatch(list, dataSource.id).then(res => {
86
+      setLoading(false);
87
+      setList(res);
88
+      notification.success({ message: '操作成功' });
89
+    }).catch(() => {
90
+      setLoading(false);
91
+    });
92
+
93
+    if (packageRef.current) {
94
+      dataSource.packageName = packageRef.current.name;
95
+      updateGuaranteeTask(dataSource, dataSource.id).then(res => {
96
+        setDataSource(res);
97
+      });
98
+    }
99
+  }
100
+
101
+  useEffect(() => {
102
+    if (dataSource.id) {
103
+      setLoading(true);
104
+      getGuaranteeDetailList({ pageNum: 1, pageSize: 500, guaranteeId: dataSource.id }).then(res => {
105
+        setLoading(false);
106
+        setList(res.records || []);
107
+      }).catch(() => {
108
+        setLoading(false);
109
+      })
110
+    }
111
+  }, [dataSource.id])
112
+
4 113
   return (
5
-    <div></div>
114
+    <Row gutter={48}>
115
+      <Col span={8}>
116
+        <div>
117
+          <h3>选择套餐</h3>
118
+          <Selector
119
+            placeholder="请选择套餐"
120
+            fetch={getPackageList}
121
+            onSubmit={handlePackageSubmit}
122
+          />
123
+        </div>
124
+        <div style={{ marginTop: '48px' }}>
125
+          <h3>选择菜肴</h3>
126
+          <Selector
127
+            placeholder="请选择菜肴"
128
+            fetch={getDishList}
129
+            onSubmit={handleDishSubmit}
130
+          />
131
+        </div>
132
+      </Col>
133
+      <Col span={16}>
134
+        <Card
135
+          title="已选菜肴"
136
+          loading={loading}
137
+          extra={<Button type='primary' loading={loading} onClick={onSubmit}>保存</Button>}
138
+        >
139
+          <EditableTag
140
+            list={list}
141
+            keyFuc={x => x.dishId}
142
+            labelFunc={x => `${x.dishName} × ${x.dishAmount}`}
143
+            onDelete={onDelete}
144
+          />
145
+        </Card>
146
+      </Col>
147
+    </Row>
6 148
   )
7 149
 }

+ 70
- 0
src/pages/guaranteeTask/Edit/components/Selector.jsx 查看文件

@@ -0,0 +1,70 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Button, Input, InputNumber, Select, notification } from 'antd';
3
+
4
+const { Group } = Input;
5
+const { Option } = Select;
6
+
7
+export default (props) => {
8
+  const { fetch, placeholder, onSubmit } = props;
9
+
10
+  const [data, setData] = useState([]);
11
+  const [value, setValue] = useState();
12
+  const [amount, setAmount] = useState();
13
+
14
+  const options = data.map(d => <Option key={d.id}>{d.name}</Option>);
15
+
16
+  const handleSearch = (name) => {
17
+    fetch({ pageNum: 1, pageSize: 20, name }).then(res => {
18
+      setData(res.records || []);
19
+    })
20
+  };
21
+
22
+  const handleChange = (val) => {
23
+    setValue(val);
24
+  }
25
+
26
+  const handleSubmit = () => {
27
+    if (!amount || amount <= 0) {
28
+      notification.warn({ message: '请输入正确的数量' });
29
+      return;
30
+    }
31
+
32
+    if (!value) {
33
+      notification.warn({ message: placeholder });
34
+      return;
35
+    }
36
+
37
+    const item = data.filter(x => `${x.id}` === `${value}`)[0];
38
+    if (item) {
39
+      onSubmit({ item, amount });
40
+    }
41
+  }
42
+
43
+  useEffect(() => {
44
+    fetch({ pageNum: 1, pageSize: 20 }).then(res => {
45
+      setData(res.records || []);
46
+    })
47
+  }, []);
48
+
49
+  return (
50
+    <Group compact>
51
+      <Select
52
+        allowClear
53
+        showSearch
54
+        value={value}
55
+        style={{ width: '50%' }}
56
+        placeholder={placeholder}
57
+        defaultActiveFirstOption={false}
58
+        showArrow={false}
59
+        filterOption={false}
60
+        onSearch={handleSearch}
61
+        onChange={handleChange}
62
+        notFoundContent={null}
63
+      >
64
+        {options}
65
+      </Select>
66
+      <InputNumber style={{ width: '30%' }} placeholder="请输入数量" value={amount} onChange={setAmount} />
67
+      <Button type="primary" onClick={handleSubmit}>确定</Button>
68
+    </Group>
69
+  )
70
+}

+ 23
- 5
src/pages/guaranteeTask/Edit/index.jsx 查看文件

@@ -1,33 +1,51 @@
1
-import React, { useState } from 'react';
1
+import React, { useState, useEffect } from 'react';
2
+import { useSearchParams } from '@umijs/max';
2 3
 import { Tabs, Card } from 'antd';
3 4
 import { PageContainer } from '@ant-design/pro-components';
5
+import { getGuaranteeTask } from '@/services/api/guaranteeTask';
4 6
 import BasicForm from './BasicForm';
5 7
 import DishList from './DishList';
6 8
 
7 9
 export default (props) => {
8 10
   const [activeTabKey, setActiveTabKey] = useState('item-1');
11
+  const [loading, setLoading] = useState(false);
12
+  const [dataSource, setDataSource] = useState();
13
+  const [searchParams] = useSearchParams();
14
+  const id = searchParams.get('id');
9 15
 
10 16
   const tabList = [
11 17
     { tab: '基本情况', key: 'item-1', }, // 务必填写 key
12
-    { tab: '菜单详情', key: 'item-2', },
18
+    { tab: '军供菜单', key: 'item-2', },
13 19
   ];
14 20
 
21
+  useEffect(() => {
22
+    if (id) {
23
+      setLoading(true);
24
+      getGuaranteeTask(id).then(res => {
25
+        setLoading(false);
26
+        setDataSource(res);
27
+      }).catch(() => {
28
+        setLoading(false);
29
+      });
30
+    }
31
+  }, [id]);
32
+
15 33
   return (
16 34
     <PageContainer>
17 35
       <Card
18 36
         style={{ width: '100%' }}
37
+        loading={loading}
19 38
         tabList={tabList}
20 39
         activeTabKey={activeTabKey}
21 40
         onTabChange={setActiveTabKey}>
22 41
 
23 42
         {
24
-          activeTabKey === 'item-1' && <BasicForm />
43
+          activeTabKey === 'item-1' && <BasicForm dataSource={dataSource} setDataSource={setDataSource} />
25 44
         }
26 45
 
27 46
         {
28
-          activeTabKey === 'item-2' && <DishList />
47
+          activeTabKey === 'item-2' && <DishList dataSource={dataSource} setDataSource={setDataSource} />
29 48
         }
30
-
31 49
       </Card>
32 50
     </PageContainer>
33 51
   )

+ 132
- 0
src/pages/guaranteeTask/print/index.jsx 查看文件

@@ -0,0 +1,132 @@
1
+import React, { useRef, useState, useEffect } from 'react';
2
+import moment from 'moment';
3
+import { Button } from 'antd';
4
+import { useSearchParams } from '@umijs/max';
5
+import { getGuaranteeTask } from '@/services/api/guaranteeTask';
6
+import { getGuaranteeDetailList } from '@/services/api/guaranteeTask';
7
+import Styles from './style.less';
8
+
9
+export default (props) => {
10
+  const [dataSource, setDataSource] = useState({});
11
+  const [list, setList] = useState([]);
12
+  const [searchParams] = useSearchParams();
13
+  const id = searchParams.get('id');
14
+
15
+  const onPrint = () => {
16
+    window.print();
17
+  }
18
+  
19
+  useEffect(() => {
20
+    if (id) {
21
+      // setLoading(true);
22
+      getGuaranteeTask(id).then(res => {
23
+        // setLoading(false);
24
+        setDataSource(res);
25
+      }).catch(() => {
26
+        // setLoading(false);
27
+      });
28
+      
29
+      // setLoading(true);
30
+      getGuaranteeDetailList({ pageNum: 1, pageSize: 500, guaranteeId: id }).then(res => {
31
+        // setLoading(false);
32
+        setList(res.records || []);
33
+      }).catch(() => {
34
+        // setLoading(false);
35
+      })
36
+    }
37
+  }, [id]);
38
+
39
+  const details = list.map(x => `${x.dishName} × ${x.dishAmount}`).join(',');
40
+  const startDate = dataSource.startDate ? moment(dataSource.startDate).format('YYYY-MM-DD') : '';
41
+  const endDate = dataSource.endDate ? moment(dataSource.endDate).format('YYYY-MM-DD') : '';
42
+  const dateStr = `${startDate} ~ ${endDate}`;
43
+
44
+  return (
45
+    <div className={Styles['print-page']}>
46
+      <table className={Styles['print-table']}>
47
+        {/* col 用于固定宽度 */}
48
+        <col />
49
+        <col />
50
+        <col />
51
+        <col />
52
+        <col />
53
+        <col />
54
+        <col />
55
+        <col />
56
+        <thead>
57
+          <tr>
58
+            <th className={Styles['title']} colSpan={8}>江苏省海安军供站军供保障受领单</th>
59
+          </tr>
60
+          <tr className={Styles['sub-title']}>
61
+            <th colSpan={2}><div>军代表:{dataSource.deputyMan || ' '}</div></th>
62
+            <th colSpan={2}><div>电话:{dataSource.deputyPhone || ' '}</div></th>
63
+            <th colSpan={2}><div>通报时间:{dataSource.gotDate || ' '}</div></th>
64
+            <th colSpan={2}><div>受领人:{dataSource.receiver || ' '}</div></th>
65
+          </tr>
66
+        </thead>
67
+        <tbody>
68
+          <tr>
69
+            <td><div>保障序号</div></td>
70
+            <td colSpan={2}><div>{dataSource.guaranteeNo || ' '}</div></td>
71
+            <td><div>军运号</div></td>
72
+            <td colSpan={2}><div>{dataSource.transportNo || ' '}</div></td>
73
+            <td><div>车次</div></td>
74
+            <td><div>{dataSource.tripsNo || ' '}</div></td>
75
+          </tr>
76
+          <tr>
77
+            <td><div>保障日期</div></td>
78
+            <td colSpan={3}>{dateStr}</td>
79
+            <td><div>保障时间</div></td>
80
+            <td colSpan={3}>{dataSource.timeRange || ' '}</td>
81
+          </tr>
82
+          <tr>
83
+            <td rowSpan={2}><div>保障人数</div></td>
84
+            <td rowSpan={2}>{dataSource.totalPersonNum || ' '}</td>
85
+            <td><div>其中回民</div></td>
86
+            <td>{dataSource.huiPersonNum || ' '}</td>
87
+            <td rowSpan={2}><div>伙食标准</div></td>
88
+            <td>{dataSource.standard || ' '}</td>
89
+          </tr>
90
+          <tr>
91
+            <td className={Styles['bd-left']}><div>其中病号</div></td>
92
+            <td>{dataSource.patientNum || ' '}</td>
93
+            <td>套餐: {dataSource.packageName || ' '}</td>
94
+          </tr>
95
+          <tr>
96
+            <td><div>保障地点</div></td>
97
+            <td colSpan={7}>{dataSource.address || ' '}</td>
98
+          </tr>
99
+          <tr>
100
+            <td><div>部队联系人</div></td>
101
+            <td colSpan={3}>{dataSource.concatPerson || ' '}</td>
102
+            <td><div>联系电话</div></td>
103
+            <td colSpan={3}>{dataSource.concatPhone || ' '}</td>
104
+          </tr>
105
+          <tr>
106
+            <td><div>制餐人</div></td>
107
+            <td colSpan={3}>{dataSource.chef || ' '}</td>
108
+            <td><div>联系电话</div></td>
109
+            <td colSpan={3}>{dataSource.chefPhone || ' '}</td>
110
+          </tr>
111
+          <tr>
112
+            <td><div>配送人</div></td>
113
+            <td colSpan={3}>{dataSource.deliveryMan || ' '}</td>
114
+            <td><div>联系电话</div></td>
115
+            <td colSpan={3}>{dataSource.deliveryPhone || ' '}</td>
116
+          </tr>
117
+          <tr className={Styles['cell-lg']}>
118
+            <td>配餐明细</td>
119
+            <td colSpan={7}><div>{details}</div></td>
120
+          </tr>
121
+          <tr className={Styles['cell-lg']}>
122
+            <td>备注</td>
123
+            <td colSpan={7}><div>{dataSource.remark || ' '}</div></td>
124
+          </tr>
125
+        </tbody>
126
+      </table>
127
+      <div className={Styles['print-btn']}>
128
+        <Button type="primary" onClick={onPrint}>打印</Button>
129
+      </div>
130
+    </div>
131
+  )
132
+}

+ 109
- 0
src/pages/guaranteeTask/print/style.less 查看文件

@@ -0,0 +1,109 @@
1
+.print-page {
2
+  width: 100%;
3
+  height: 100%;
4
+  position: relative;
5
+  box-sizing: border-box;
6
+  padding: 1cm;
7
+}
8
+
9
+// A4 大小 210 * 279
10
+@width: 190mm; // 210 - 20
11
+@height: 277mm;  // 279 - 20
12
+
13
+@minWidth: calc(@width / 8);
14
+
15
+.print-table {
16
+  table-layout: fixed;
17
+  width: @width;
18
+  height: @height;
19
+  margin: auto;
20
+  font-size: 16px;
21
+  overflow-x: hidden;
22
+
23
+  col {
24
+    width: @minWidth;
25
+  }
26
+
27
+  th {
28
+    font-weight: 400;
29
+  }
30
+
31
+  thead {
32
+    tr {
33
+      border: none !important;
34
+    }
35
+  }
36
+
37
+  @border: 1.5px solid #333;
38
+
39
+  tbody {
40
+    border: @border;
41
+  }
42
+  
43
+  tr {
44
+    & + tr {
45
+      border-top: @border;
46
+    }
47
+  }
48
+
49
+  td {
50
+    padding: 0 .5em;
51
+    overflow: hidden;
52
+    text-overflow: ellipsis;
53
+    div {
54
+      min-width: @minWidth;
55
+      min-height: 10mm;
56
+      line-height: 10mm;
57
+    }
58
+
59
+    & + td {
60
+      border-left: @border;
61
+    }
62
+  }
63
+
64
+  .cell-lg {
65
+    div {
66
+      width: auto;
67
+      min-height: 70mm;
68
+      line-height: 1.6em;
69
+    }
70
+  }
71
+
72
+  .title {
73
+    font-size: 2em;
74
+  }
75
+
76
+  .sub-title {
77
+    // font-size: 12px;
78
+  }
79
+
80
+  .bd-left {
81
+    border-left: @border;
82
+  }
83
+}
84
+
85
+@media screen {
86
+  .print-btn {
87
+    text-align: center;
88
+    margin: 64px auto;
89
+  }
90
+
91
+  .print-table {
92
+    padding: 5mm 5mm 5mm 10mm;
93
+  }
94
+}
95
+
96
+@media print {
97
+  .print-table {
98
+    padding: 0;
99
+  }
100
+
101
+  .print-btn {
102
+    display: none;
103
+  }
104
+}
105
+
106
+@page {
107
+  size: A4;
108
+  margin: 0;
109
+}

+ 30
- 27
src/pages/package/BasicForm.jsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import React, { useState, useEffect } from 'react';
2
-import { Button, Checkbox, Form, Input } from 'antd';
2
+import { Button, Checkbox, Card, Form, Input, notification } from 'antd';
3 3
 import { addPackage, updataPackage } from '@/services/api/package';
4 4
 
5 5
 export default (props) => {
@@ -17,6 +17,7 @@ export default (props) => {
17 17
     func(data, current.id).then(res => {
18 18
       setLoading(false);
19 19
       onChange(res);
20
+      notification.success({ message: '操作成功' })
20 21
     }).catch(() => {
21 22
       setLoading(false);
22 23
     });
@@ -30,33 +31,35 @@ export default (props) => {
30 31
   }, [form, current])
31 32
 
32 33
   return (
33
-    <Form
34
-      form={form}
35
-      labelCol={{ span: 6 }}
36
-      wrapperCol={{ span: 16 }}
37
-      onFinish={onFinish}
38
-      autoComplete="off"
39
-    >
40
-      <Form.Item
41
-        label="套餐名称"
42
-        name="name"
43
-        rules={[{ required: true, message: '请输入套餐名称' }]}
34
+    <Card>
35
+      <Form
36
+        form={form}
37
+        labelCol={{ span: 6 }}
38
+        wrapperCol={{ span: 16 }}
39
+        onFinish={onFinish}
40
+        autoComplete="off"
44 41
       >
45
-        <Input placeholder='请输入套餐名称' />
46
-      </Form.Item>
42
+        <Form.Item
43
+          label="套餐名称"
44
+          name="name"
45
+          rules={[{ required: true, message: '请输入套餐名称' }]}
46
+        >
47
+          <Input placeholder='请输入套餐名称' />
48
+        </Form.Item>
47 49
 
48
-      <Form.Item
49
-        label="套餐单位"
50
-        name="unit"
51
-      >
52
-        <Input placeholder='请输入套餐单位' />
53
-      </Form.Item>
54
-
55
-      <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
56
-        <Button type="primary" htmlType="submit" loading={loading}>
57
-          提交
58
-        </Button>
59
-      </Form.Item>
60
-    </Form>
50
+        <Form.Item
51
+          label="套餐单位"
52
+          name="unit"
53
+        >
54
+          <Input placeholder='请输入套餐单位' />
55
+        </Form.Item>
56
+
57
+        <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
58
+          <Button type="primary" htmlType="submit" loading={loading}>
59
+            保存
60
+          </Button>
61
+        </Form.Item>
62
+      </Form>
63
+    </Card>
61 64
   )
62 65
 }

+ 1
- 0
src/pages/package/DishList.jsx 查看文件

@@ -118,6 +118,7 @@ export default (props) => {
118 118
       renderItem={item => (
119 119
         <List.Item
120 120
           className={classNames({ active: detail.id === item.id })}
121
+          onClick={() => setDetail(item)}
121 122
           actions={[
122 123
             <Popconfirm
123 124
               key="delete"

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

@@ -19,7 +19,7 @@ export default (props) => {
19 19
           </Col>
20 20
           <Col span={8}>
21 21
             <BasicForm current={current} onChange={it => setCurrent(it)} />
22
-            <div style={{ marginTop: '100px' }}>
22
+            <div style={{ marginTop: '24px' }}>
23 23
               <DishList current={current} />
24 24
             </div>
25 25
           </Col>

+ 104
- 0
src/pages/stock/edit/index.jsx 查看文件

@@ -0,0 +1,104 @@
1
+import { updataDish } from '@/services/api/dish';
2
+import { addStore, getStoreTypeList,getStoreById,updataStore } from '@/services/api/stock';
3
+import { queryDict } from '@/utils/request';
4
+import { PageContainer, ProForm, ProFormSelect, ProFormText } from '@ant-design/pro-components';
5
+import { history, useSearchParams } from '@umijs/max';
6
+import { Card, Col, message, Row, Space } from 'antd';
7
+import { useEffect, useRef } from 'react';
8
+
9
+export default (props) => {
10
+  const [searchParams, setSearchParams] = useSearchParams();
11
+  const id = searchParams.get('id');
12
+  const formRef = useRef();
13
+  useEffect(() => {
14
+    if (id) {
15
+      getStoreById(id).then((res) => {
16
+        formRef.current.setFieldsValue(res);
17
+      });
18
+    }
19
+  }, [id]);
20
+
21
+  const onFinish = async (values) => {
22
+    console.log(values);
23
+
24
+    if (id) {
25
+      // 修改
26
+      updataStore(id, { ...values }).then((res) => {
27
+        message.success('修改成功');
28
+        history.back();
29
+      });
30
+    } else {
31
+      // 新增
32
+      addStore({ ...values }).then((res) => {
33
+        message.success('添加成功');
34
+        history.back();
35
+      });
36
+    }
37
+
38
+    return false;
39
+  };
40
+
41
+  return (
42
+    <PageContainer>
43
+      <Card>
44
+        <ProForm
45
+          formRef={formRef}
46
+          layout={'horizontal'}
47
+          labelCol={{ span: 8 }}
48
+          wrapperCol={{ span: 16 }}
49
+          onFinish={onFinish}
50
+          // initialValues={{ type: '1', state: '1' }}
51
+          submitter={{
52
+            searchConfig: {
53
+              resetText: '返回',
54
+            },
55
+            onReset: () => history.back(),
56
+            render: (props, doms) => {
57
+              return (
58
+                <Row>
59
+                  <Col span={8} offset={8}>
60
+                    <Space>{doms}</Space>
61
+                  </Col>
62
+                </Row>
63
+              );
64
+            },
65
+          }}
66
+        >
67
+          <ProFormSelect
68
+            name="typeId"
69
+            label="分类"
70
+            placeholder="请选择分类"
71
+            request={() => queryDict(getStoreTypeList)()}
72
+            rules={[{ required: true, message: '请选择分类' }]}
73
+            allowClear={false}
74
+            width={460}
75
+          />
76
+          <ProFormText
77
+            name="name"
78
+            label="名称"
79
+            placeholder="请输入名称"
80
+            rules={[{ required: true, message: '请输入名称' }]}
81
+            allowClear={false}
82
+            width={460}
83
+          />
84
+          <ProFormText
85
+            name="unit"
86
+            label="单位"
87
+            placeholder="请输入单位"
88
+            rules={[{ required: true, message: '请输入单位' }]}
89
+            allowClear={false}
90
+            width={460}
91
+          />
92
+          <ProFormText
93
+            name="amount"
94
+            label="库存"
95
+            disabled={true}
96
+            placeholder="请输入库存"
97
+            allowClear={false}
98
+            width={460}
99
+          />
100
+        </ProForm>
101
+      </Card>
102
+    </PageContainer>
103
+  );
104
+};

+ 165
- 0
src/pages/stock/list/index.jsx 查看文件

@@ -0,0 +1,165 @@
1
+import { deleteStore, getStoreList, getStoreTypeList, storeExport } from '@/services/api/stock';
2
+import { downloadBlob } from '@/utils/download';
3
+import { queryDict, queryTable } from '@/utils/request';
4
+import { PageContainer, ProTable } from '@ant-design/pro-components';
5
+import { history } from '@umijs/max';
6
+import { Button, message, Modal, Popconfirm } from 'antd';
7
+import { useRef, useState } from 'react';
8
+import OutAndIn from '../outAndIn';
9
+
10
+const StockList = (props) => {
11
+  const [isOpen, setIsOpen] = useState(false);
12
+  const [modalData, setModalData] = useState({});
13
+  // const [storeTypeDict, setStoreTypeDict] = useState([]);
14
+  const actionRef = useRef();
15
+  const formRef = useRef();
16
+  
17
+  // useEffect(() => {
18
+  //   getStoreTypeList({ pageSize: 9999, pageNum: 1 }).then((res) => {
19
+  //     setStoreTypeDict(
20
+  //       res?.records?.map((x) => ({
21
+  //         label: x.name,
22
+  //         value: x.id,
23
+  //       })) || [],
24
+  //     );
25
+  //   });
26
+  // }, []);
27
+
28
+  const handleDelete = (id) => {
29
+    if (id) {
30
+      deleteStore(id).then((res) => {
31
+        message.success('删除成功');
32
+        actionRef.current.reload();
33
+      });
34
+    }
35
+  };
36
+
37
+  const onCancel = () => {
38
+    setIsOpen(false);
39
+    setModalData({});
40
+  };
41
+
42
+  const onExport = () => {
43
+    storeExport(formRef.current.getFieldsValue()).then((res) => {
44
+      downloadBlob(res, '库存列表.xlsx');
45
+    });
46
+  };
47
+
48
+  const columns = [
49
+    // {
50
+    //   title: 'id',
51
+    //   dataIndex: 'id',
52
+    //   search: false,
53
+    // },
54
+    {
55
+      title: '名称',
56
+      dataIndex: 'name',
57
+    },
58
+    {
59
+      title: '单位',
60
+      dataIndex: 'unit',
61
+      search: false,
62
+    },
63
+    {
64
+      title: '分类',
65
+      dataIndex: 'typeId',
66
+      valueType: 'select',
67
+      // option: storeTypeDict,
68
+      request: () => queryDict(getStoreTypeList)(),
69
+    },
70
+    {
71
+      title: '库存',
72
+      dataIndex: 'amount',
73
+      search: false,
74
+    },
75
+
76
+    {
77
+      title: '操作',
78
+      valueType: 'option',
79
+      width: 200,
80
+      render: (_, record) => [
81
+        <Button
82
+          key={1}
83
+          style={{ padding: 0 }}
84
+          type="link"
85
+          onClick={() => {
86
+            console.log(record, 'record');
87
+            setModalData(record);
88
+            setIsOpen(true);
89
+            // history.push(`/stock/outAndIn?id=${record.id}`);
90
+          }}
91
+        >
92
+          出入库
93
+        </Button>,
94
+        <Button
95
+          key={2}
96
+          style={{ padding: 0 }}
97
+          type="link"
98
+          onClick={() => {
99
+            history.push(`/stock/edit?id=${record.id}`);
100
+          }}
101
+        >
102
+          修改
103
+        </Button>,
104
+
105
+        <Popconfirm
106
+          key={3}
107
+          title="您是否确认删除 ?"
108
+          onConfirm={() => handleDelete(record.id)}
109
+          okText="确定"
110
+          cancelText="取消"
111
+        >
112
+          {/* manualPush */}
113
+          <Button style={{ padding: 0 }} type="link">
114
+            删除
115
+          </Button>
116
+        </Popconfirm>,
117
+      ],
118
+    },
119
+  ];
120
+
121
+  return (
122
+    <PageContainer>
123
+      <ProTable
124
+        actionRef={actionRef}
125
+        formRef={formRef}
126
+        rowKey="id"
127
+        toolBarRender={() => [
128
+          <Button
129
+            key="2"
130
+            type="primary"
131
+            onClick={() => {
132
+              history.push('/stock/add');
133
+            }}
134
+          >
135
+            新增
136
+          </Button>,
137
+          <Button
138
+            key="2"
139
+            type="primary"
140
+            onClick={() => {
141
+              onExport();
142
+              // history.push('/stock/add');
143
+            }}
144
+          >
145
+            导出
146
+          </Button>,
147
+        ]}
148
+        request={queryTable(getStoreList)}
149
+        columns={columns}
150
+      />
151
+      <Modal open={isOpen} footer={null} onCancel={onCancel}>
152
+        <OutAndIn
153
+          data={modalData}
154
+          onCancel={onCancel}
155
+          onSuccess={() => {
156
+            actionRef.current.reload();
157
+            onCancel();
158
+          }}
159
+        />
160
+      </Modal>
161
+    </PageContainer>
162
+  );
163
+};
164
+
165
+export default StockList;

+ 73
- 0
src/pages/stock/outAndIn/components/outAndInForm.jsx 查看文件

@@ -0,0 +1,73 @@
1
+import { ProForm, ProFormDigit, ProFormText } from '@ant-design/pro-components';
2
+import { Col, Row, Space } from 'antd';
3
+import { useEffect, useRef } from 'react';
4
+
5
+export default (props) => {
6
+  const { data, type, onFinish, storeTypeDict = [], onCancel } = props;
7
+  const formRef = useRef();
8
+  useEffect(() => {
9
+    // formRef.current.resetFields();
10
+    formRef.current.setFieldsValue({
11
+      typeId: data.typeName,
12
+      name: data.name,
13
+      unit: data.unit,
14
+      amount: null,
15
+    });
16
+  }, [data]);
17
+
18
+  return (
19
+    <ProForm
20
+      formRef={formRef}
21
+      layout={'horizontal'}
22
+      labelCol={{ span: 4 }}
23
+      wrapperCol={{ span: 18 }}
24
+      onFinish={onFinish}
25
+      // initialValues={{ type: '1', state: '1' }}
26
+      submitter={{
27
+        searchConfig: {
28
+          resetText: '返回',
29
+        },
30
+        onReset: () => onCancel(),
31
+        render: (props, doms) => {
32
+          return (
33
+            <Row>
34
+              <Col span={8} offset={8}>
35
+                <Space>{doms}</Space>
36
+              </Col>
37
+            </Row>
38
+          );
39
+        },
40
+      }}
41
+    >
42
+      <ProFormText
43
+        name="typeId"
44
+        label="分类"
45
+        disabled={true}
46
+        placeholder="请选择分类"
47
+        allowClear={false}
48
+      />
49
+      <ProFormText
50
+        name="name"
51
+        label="名称"
52
+        placeholder="请输入名称"
53
+        disabled={true}
54
+        allowClear={false}
55
+      />
56
+      <ProFormText
57
+        name="unit"
58
+        label="单位"
59
+        placeholder="请输入单位"
60
+        disabled={true}
61
+        allowClear={false}
62
+      />
63
+      <ProFormDigit
64
+        name="amount"
65
+        label="库存"
66
+        addonBefore={type === 'out' ? '-' : '+'}
67
+        placeholder="请输入库存"
68
+        fieldProps={{ precision: 0 }}
69
+        rules={[{ required: true, message: '请输入库存' }]}
70
+      />
71
+    </ProForm>
72
+  );
73
+};

+ 51
- 0
src/pages/stock/outAndIn/components/outAndInList.jsx 查看文件

@@ -0,0 +1,51 @@
1
+import { ProTable } from '@ant-design/pro-components';
2
+import {getStoreLogList} from '@/services/api/stock'
3
+import { queryTable,queryDict } from '@/utils/request';
4
+import { useRef, useState } from 'react';
5
+
6
+const OutAndInList = (props) => {
7
+  const { id } = props;
8
+
9
+  const [showDetail, setShowDetail] = useState(false);
10
+  const [activeKey, setActiveKey] = useState('');
11
+  const actionRef = useRef();
12
+
13
+  const columns = [
14
+    {
15
+      title: '名称',
16
+      dataIndex: 'name',
17
+    },
18
+    {
19
+      title: '分类',
20
+      dataIndex: 'type',
21
+    },
22
+    {
23
+      title: '操作',
24
+      dataIndex: 'optType',
25
+      search: false,
26
+    },
27
+    {
28
+      title: '操作量',
29
+      dataIndex: 'amount',
30
+      search: false,
31
+    },
32
+    {
33
+      title: '操作后库存',
34
+      dataIndex: 'pre_amount',
35
+      search: false,
36
+    },
37
+  ];
38
+
39
+  return (
40
+    <ProTable
41
+      actionRef={actionRef}
42
+      params={{storeId:id}}
43
+      rowKey="id"
44
+      // search={false}
45
+      request={queryTable(getStoreLogList)}
46
+      columns={columns}
47
+    />
48
+  );
49
+};
50
+
51
+export default OutAndInList;

+ 67
- 0
src/pages/stock/outAndIn/index.jsx 查看文件

@@ -0,0 +1,67 @@
1
+import { addStoreLog } from '@/services/api/stock';
2
+import { ProCard } from '@ant-design/pro-components';
3
+// import { history, useSearchParams } from '@umijs/max';
4
+import { message } from 'antd';
5
+import { useState } from 'react';
6
+import OutAndInForm from './components/outAndInForm';
7
+
8
+const OutAndIn = (props) => {
9
+  const { data, onCancel, onSuccess } = props;
10
+
11
+  const [tabKey, setTabKey] = useState('in');
12
+
13
+  const onFinish = async (values) => {
14
+    console.log(data, values);
15
+
16
+    if (data.id) {
17
+      addStoreLog({
18
+        storeId: Number(data.id),
19
+        amount: tabKey === 'out' ? -values.amount : values.amount,
20
+        optType: tabKey,
21
+      }).then((res) => {
22
+        message.success('操作成功');
23
+
24
+        onSuccess();
25
+      });
26
+    }
27
+  };
28
+
29
+  return (
30
+    <ProCard
31
+      tabs={{
32
+        // tabPosition,
33
+        centered: true,
34
+        activeKey: tabKey,
35
+        destroyInactiveTabPane: false,
36
+        items: [
37
+          {
38
+            label: `入库`,
39
+            key: 'in',
40
+            children: (
41
+              <OutAndInForm data={data} type={tabKey} onFinish={onFinish} onCancel={onCancel} />
42
+            ),
43
+          },
44
+          {
45
+            label: `出库`,
46
+            key: 'out',
47
+            children: (
48
+              <OutAndInForm data={data} type={tabKey} onFinish={onFinish} onCancel={onCancel} />
49
+            ),
50
+          },
51
+          {
52
+            label: `盘点`,
53
+            key: 'fix',
54
+            children: (
55
+              <OutAndInForm data={data} type={tabKey} onFinish={onFinish} onCancel={onCancel} />
56
+            ),
57
+          },
58
+        ],
59
+        onChange: (key) => {
60
+          setTabKey(key);
61
+        },
62
+      }}
63
+    />
64
+  );
65
+};
66
+
67
+export default OutAndIn;

+ 81
- 0
src/pages/stock/stockLog/index.jsx 查看文件

@@ -0,0 +1,81 @@
1
+import { getStoreLogList, getStoreTypeList,storeLogExport } from '@/services/api/stock';
2
+import { queryDict, queryTable } from '@/utils/request';
3
+import { downloadBlob } from '@/utils/download';
4
+import { PageContainer, ProTable } from '@ant-design/pro-components';
5
+import { Button } from 'antd';
6
+import { useRef } from 'react';
7
+
8
+const StockLog = (props) => {
9
+  const actionRef = useRef();
10
+  const formRef = useRef()
11
+  const onExport = () => {
12
+    storeLogExport(formRef.current.getFieldsValue()).then((res) => {
13
+      downloadBlob(res, '库存日志.xlsx');
14
+    });
15
+  };
16
+  const columns = [
17
+    {
18
+      title: '名称',
19
+      dataIndex: 'storeName',
20
+    },
21
+    {
22
+      title: '分类',
23
+      dataIndex: 'typeId',
24
+      valueType: 'select',
25
+      request: () => queryDict(getStoreTypeList)(),
26
+    },
27
+    {
28
+      title: '操作',
29
+      dataIndex: 'optType',
30
+      valueEnum: {
31
+        in: '入库',
32
+        out: '出库',
33
+        fix: '盘点',
34
+      },
35
+      search: false,
36
+    },
37
+    {
38
+      title: '操作量',
39
+      dataIndex: 'amount',
40
+      search: false,
41
+    },
42
+    {
43
+      title: '操作后库存',
44
+      dataIndex: 'aftAmount',
45
+      search: false,
46
+    },
47
+    {
48
+      title: '操作时间',
49
+      dataIndex: 'createDate',
50
+      valueType: 'dateTime',
51
+      search: false,
52
+    },
53
+  ];
54
+
55
+  return (
56
+    <PageContainer>
57
+      <ProTable
58
+        actionRef={actionRef}
59
+        formRef={formRef}
60
+        rowKey="id"
61
+        toolBarRender={() => [
62
+          <Button
63
+            key="2"
64
+            type="primary"
65
+            onClick={() => {
66
+              onExport();
67
+              // history.push('/stock/add');
68
+            }}
69
+          >
70
+            导出
71
+          </Button>,
72
+        ]}
73
+        // search={false}
74
+        request={queryTable(getStoreLogList)}
75
+        columns={columns}
76
+      />
77
+    </PageContainer>
78
+  );
79
+};
80
+
81
+export default StockLog;

+ 89
- 0
src/pages/stockClassification/edit/index.jsx 查看文件

@@ -0,0 +1,89 @@
1
+import { addStoreType, getStoreTypeById, updataStoreType } from '@/services/api/stock';
2
+import { PageContainer, ProForm, ProFormSelect, ProFormText } from '@ant-design/pro-components';
3
+import { history, useSearchParams } from '@umijs/max';
4
+import { Card, Col, message, Row, Space } from 'antd';
5
+import { useEffect, useRef } from 'react';
6
+
7
+export default (props) => {
8
+  const [searchParams, setSearchParams] = useSearchParams();
9
+  const id = searchParams.get('id');
10
+
11
+  const formRef = useRef();
12
+  useEffect(() => {
13
+    if (id) {
14
+      getStoreTypeById(id).then((res) => {
15
+        formRef.current.setFieldsValue(res);
16
+      });
17
+    }
18
+  }, [id]);
19
+
20
+  const onFinish = async (values) => {
21
+    console.log(values);
22
+
23
+    if (id) {
24
+      // 修改
25
+      updataStoreType(id, { ...values }).then((res) => {
26
+        message.success('修改成功');
27
+        history.back();
28
+      });
29
+    } else {
30
+      // 新增;
31
+      addStoreType({ ...values }).then((res) => {
32
+        message.success('添加成功');
33
+        history.back();
34
+      });
35
+    }
36
+
37
+    return false;
38
+  };
39
+
40
+  return (
41
+    <PageContainer>
42
+      <Card>
43
+        <ProForm
44
+          formRef={formRef}
45
+          layout={'horizontal'}
46
+          labelCol={{ span: 8 }}
47
+          wrapperCol={{ span: 16 }}
48
+          onFinish={onFinish}
49
+          submitter={{
50
+            searchConfig: {
51
+              resetText: '返回',
52
+            },
53
+            onReset: () => history.back(),
54
+            render: (props, doms) => {
55
+              return (
56
+                <Row>
57
+                  <Col span={8} offset={8}>
58
+                    <Space>{doms}</Space>
59
+                  </Col>
60
+                </Row>
61
+              );
62
+            },
63
+          }}
64
+        >
65
+          <ProFormText
66
+            name="name"
67
+            label="名称"
68
+            placeholder="请输入名称"
69
+            width={460}
70
+            allowClear={false}
71
+            rules={[{ required: true, message: '请输入名称' }]}
72
+          />
73
+          <ProFormSelect
74
+            name="isFood"
75
+            label="食材"
76
+            options={[
77
+              { label: '是', value: 1 },
78
+              { label: '否', value: 0 },
79
+            ]}
80
+            placeholder="请选择"
81
+            width={460}
82
+            allowClear={false}
83
+            rules={[{ required: true, message: '请选择是否食材' }]}
84
+          />
85
+        </ProForm>
86
+      </Card>
87
+    </PageContainer>
88
+  );
89
+};

+ 97
- 0
src/pages/stockClassification/list/index.jsx 查看文件

@@ -0,0 +1,97 @@
1
+
2
+import { getStoreTypeList,deleteStoreType } from '@/services/api/stock';
3
+import { queryTable } from '@/utils/request';
4
+import { PageContainer, ProTable } from '@ant-design/pro-components';
5
+import { history } from '@umijs/max';
6
+import { Button, message, Popconfirm } from 'antd';
7
+import { useRef, useState } from 'react';
8
+
9
+const StockList = (props) => {
10
+  const [showDetail, setShowDetail] = useState(false);
11
+  const [activeKey, setActiveKey] = useState('');
12
+  const actionRef = useRef();
13
+
14
+
15
+
16
+  const handleDelete = (id) => {
17
+    if (id) {
18
+      deleteStoreType(id).then((res) => {
19
+        message.success('删除成功');
20
+        actionRef.current.reload();
21
+      });
22
+    }
23
+  };
24
+
25
+  const columns = [
26
+    {
27
+      title: '分类名称',
28
+      dataIndex: 'name',
29
+    },
30
+
31
+    {
32
+      title: '排序',
33
+      dataIndex: 'isFood',
34
+      search: false,
35
+      valueEnum: {
36
+        1: '是',
37
+        0: '否',
38
+      },
39
+    },
40
+
41
+    {
42
+      title: '操作',
43
+      valueType: 'option',
44
+      width: 200,
45
+      render: (_, record) => [
46
+        <Button
47
+          key={2}
48
+          style={{ padding: 0 }}
49
+          type="link"
50
+          onClick={() => {
51
+            history.push(`/stockClassification/edit?id=${record.id}`);
52
+          }}
53
+        >
54
+          修改
55
+        </Button>,
56
+
57
+        <Popconfirm
58
+          key={3}
59
+          title="您是否确认删除 ?"
60
+          onConfirm={() => handleDelete(record.id)}
61
+          okText="确定"
62
+          cancelText="取消"
63
+        >
64
+          {/* manualPush */}
65
+          <Button style={{ padding: 0 }} type="link">
66
+            删除
67
+          </Button>
68
+        </Popconfirm>,
69
+      ],
70
+    },
71
+  ];
72
+
73
+  return (
74
+    <PageContainer>
75
+      <ProTable
76
+        actionRef={actionRef}
77
+        rowKey="id"
78
+        toolBarRender={() => [
79
+          <Button
80
+            key="2"
81
+            type="primary"
82
+            onClick={() => {
83
+              history.push('/stockClassification/edit');
84
+            }}
85
+          >
86
+            新增
87
+          </Button>,
88
+        ]}
89
+        // search={false}
90
+        request={queryTable(getStoreTypeList)}
91
+        columns={columns}
92
+      />
93
+    </PageContainer>
94
+  );
95
+};
96
+
97
+export default StockList;

+ 44
- 0
src/services/api/guaranteeTask.js 查看文件

@@ -0,0 +1,44 @@
1
+import { request } from '@umijs/max';
2
+
3
+/**
4
+ * 详情
5
+ * @param {*} data
6
+ * @returns
7
+ */
8
+ export const getGuaranteeTask = (id) => request(`/guaranteeTask/${id}`);
9
+
10
+/**
11
+ * 新增
12
+ * @param {*} data
13
+ * @returns
14
+ */
15
+ export const addGuaranteeTask = (data) => request('/guaranteeTask', { method: 'post', data });
16
+
17
+ 
18
+/**
19
+ * 更新
20
+ * @param {*} data
21
+ * @returns
22
+ */
23
+ export const updateGuaranteeTask = (data, id) => request(`/guaranteeTask/${id}`, { method: 'put', data });
24
+
25
+ /**
26
+  * 查询明细
27
+  * @param {*} data
28
+  * @returns
29
+  */
30
+  export const getGuaranteeDetailList = (params) => request('/guaranteeDetail', { params });
31
+
32
+/**
33
+ * 批量新增明细
34
+ * @param {*} data
35
+ * @returns
36
+ */
37
+ export const addGuaranteeDetailBatch = (data, guaranteeId) => request('/guaranteeDetail/batch', { method: 'post', data, params: { guaranteeId } });
38
+ 
39
+/**
40
+ * 删除明细
41
+ * @param {*} data
42
+ * @returns
43
+ */
44
+ export const deleteGuaranteeDetail = id => request(`/guaranteeDetail/${id}`, { method: 'delete' });

+ 107
- 0
src/services/api/stock.js 查看文件

@@ -0,0 +1,107 @@
1
+import { request } from '@umijs/max';
2
+
3
+// 库存
4
+/**
5
+ * 查询列表
6
+ * @param {*} params
7
+ * @returns
8
+ */
9
+export const getStoreList = (params) => request('/store', { params });
10
+
11
+/**
12
+ * 新增
13
+ * @param {*} data
14
+ * @returns
15
+ */
16
+export const addStore = (data) => request('/store', { method: 'post', data });
17
+
18
+/**
19
+ * 详情
20
+ * @param {*} id
21
+ * @returns
22
+ */
23
+export const getStoreById = (id) => request(`/store/${id}`);
24
+
25
+/**
26
+ * 编辑
27
+ *  @param {*} id
28
+ * @param {*} data
29
+ * @returns
30
+ */
31
+export const updataStore = (id, data) => request(`/store/${id}`, { method: 'put', data });
32
+
33
+/**
34
+ * 删除
35
+ * @param {*} id
36
+ * @returns
37
+ */
38
+export const deleteStore = (id) => request(`/store/${id}`, { method: 'delete' });
39
+
40
+/**
41
+ * 导出
42
+ * @param {*} params
43
+ * @returns
44
+ */
45
+export const storeExport = (params) => request('/store/export',  { responseType: 'arraybuffer', params });
46
+
47
+
48
+// 库存分类
49
+/**
50
+ * 查询列表
51
+ * @param {*} params
52
+ * @returns
53
+ */
54
+export const getStoreTypeList = (params) => request('/storeType', { params });
55
+
56
+/**
57
+ * 新增
58
+ * @param {*} data
59
+ * @returns
60
+ */
61
+export const addStoreType = (data) => request('/storeType', { method: 'post', data });
62
+
63
+/**
64
+ * 详情
65
+ * @param {*} id
66
+ * @returns
67
+ */
68
+export const getStoreTypeById = (id) => request(`/storeType/${id}`);
69
+
70
+/**
71
+ * 编辑
72
+ *  @param {*} id
73
+ * @param {*} data
74
+ * @returns
75
+ */
76
+export const updataStoreType = (id, data) => request(`/storeType/${id}`, { method: 'put', data });
77
+
78
+/**
79
+ * 删除
80
+ * @param {*} id
81
+ * @returns
82
+ */
83
+export const deleteStoreType = (id) => request(`/storeType/${id}`, { method: 'delete' });
84
+
85
+// 库存日志
86
+
87
+/**
88
+ * 查询列表
89
+ * @param {*} params
90
+ * @returns
91
+ */
92
+export const getStoreLogList = (params) => request('/storeLog', { params });
93
+
94
+/**
95
+ * 新增
96
+ * @param {*} data
97
+ * @returns
98
+ */
99
+export const addStoreLog = (data) => request('/storeLog', { method: 'post', data });
100
+
101
+
102
+/**
103
+ * 导出
104
+ * @param {*} params
105
+ * @returns
106
+ */
107
+ export const storeLogExport = (params) => request('/storeLog/export',  { responseType: 'arraybuffer', params });

+ 1
- 1
src/utils/download.js 查看文件

@@ -3,7 +3,7 @@ export function fetchBlob(url) {
3 3
 }
4 4
 
5 5
 export function downloadBlob(blob, fileName) {
6
-  const url = window.URL.createObjectURL(blob);
6
+  const url = window.URL.createObjectURL(new Blob([blob]));
7 7
   const link = document.createElement('a');
8 8
   link.href = url;
9 9
   link.setAttribute('download', fileName);

+ 34
- 11
src/utils/request.js 查看文件

@@ -19,7 +19,14 @@ function requestInterceptor(url, options) {
19 19
   };
20 20
 }
21 21
 
22
-function responseInterceptor(response) {
22
+async function responseInterceptor(response) {
23
+  console.log(response, 'responseresponse');
24
+
25
+  if (response.headers['content-type'] === 'application/vnd.ms-excel;charset=utf-8') {
26
+    console.log(response.data, 'data');
27
+    return response;
28
+  }
29
+
23 30
   const { data } = response;
24 31
   if (data.code === 1000) {
25 32
     return data;
@@ -36,12 +43,13 @@ export const requestConfig = {
36 43
 
37 44
 export function queryTable(apiRequest) {
38 45
   return function (params) {
46
+    const { current, pageSize, ...leftParams } = params;
39 47
     return apiRequest({
40
-      ...params,
48
+      pageSize,
41 49
       pageNum: params.current,
50
+      ...(leftParams || {}),
42 51
     })
43 52
       .then((res) => {
44
-        console.log(res, '--000');
45 53
         return {
46 54
           data: res.records,
47 55
           success: true,
@@ -55,11 +63,26 @@ export function queryTable(apiRequest) {
55 63
       });
56 64
   };
57 65
 }
58
-// return {
59
-//   data: msg.result,
60
-//   // success 请返回 true,
61
-//   // 不然 table 会停止解析数据,即使有数据
62
-//   success: boolean,
63
-//   // 不传会使用 data 的长度,如果是分页一定要传
64
-//   total: number,
65
-// };
66
+
67
+export function queryDict(apiRequest) {
68
+  return function (params, labelKey = 'name', valueKey = 'id') {
69
+    const { current, pageSize, ...leftParams } = params || {};
70
+    return apiRequest({
71
+      pageSize: 9999,
72
+      pageNum: 1,
73
+      ...(leftParams || {}),
74
+    })
75
+      .then((res) => {
76
+        return res?.records?.map((x) => ({
77
+          label: x[labelKey],
78
+          value: x[valueKey],
79
+          ...x,
80
+        }));
81
+      })
82
+      .catch((err) => {
83
+        return {
84
+          success: false,
85
+        };
86
+      });
87
+  };
88
+}