fangmingyue 2 年 前
コミット
dda683d6a8

+ 1
- 1
.env.production ファイルの表示

@@ -1 +1 @@
1
-VITE_SERVER_BASE=/api
1
+VITE_SERVER_BASE=http://jgz.njyunzhi.com/api

+ 6
- 14
src/pages/cms/emergencyPlan/detail/index.jsx ファイルの表示

@@ -1,15 +1,9 @@
1
-import { savePosts, getPostsDetail, updatePosts } from "@/services/posts";
2
-import { getStoreList } from "@/services/stock";
3
-import {
4
-  PageContainer,
5
-  ProForm,
6
-  ProFormSelect,
7
-  ProFormText,
8
-} from "@ant-design/pro-components";
1
+import { getPostsDetail } from "@/services/posts";
2
+
9 3
 import { useNavigate, useSearchParams } from "react-router-dom";
10
-import { Card, Typography, message, Row, Button, Space } from "antd";
11
-import { useEffect, useRef, useState } from "react";
12
-import Wangeditor from "@/components/Wangeditor";
4
+import { Card, Typography, Button } from "antd";
5
+import { useEffect, useState } from "react";
6
+
13 7
 const { Title } = Typography;
14 8
 export default (props) => {
15 9
   const [searchParams] = useSearchParams();
@@ -18,8 +12,6 @@ export default (props) => {
18 12
   const [url, setUrl] = useState("");
19 13
   const navigate = useNavigate();
20 14
 
21
-  const formRef = useRef();
22
-
23 15
   useEffect(() => {
24 16
     if (id) {
25 17
       getPostsDetail(id).then((res) => {
@@ -36,7 +28,7 @@ export default (props) => {
36 28
       </Title>
37 29
       <div dangerouslySetInnerHTML={{ __html: data?.detail }}></div>
38 30
       {url && (
39
-        <div style={{marginTop:"2em"}}>
31
+        <div style={{ marginTop: "2em" }}>
40 32
           <a
41 33
             href={`${url}`}
42 34
             download

+ 10
- 1
src/pages/cms/emergencyPlan/list/index.jsx ファイルの表示

@@ -33,6 +33,15 @@ const EmergencyPlanList = (props) => {
33 33
     {
34 34
       title: "内容名称",
35 35
       dataIndex: "title",
36
+      render: (text, record) => (
37
+        <a
38
+          onClick={() => {
39
+            navigate(`/cms/emergency-plan/detail?id=${record.id}`);
40
+          }}
41
+        >
42
+          {text}
43
+        </a>
44
+      ),
36 45
     },
37 46
 
38 47
     {
@@ -41,7 +50,7 @@ const EmergencyPlanList = (props) => {
41 50
       search: false,
42 51
       ellipsis: true,
43 52
       width: "50%",
44
-      renderText: (text) => text.replace(regex, ""),
53
+      renderText: (text) => text?.replace(regex, ""),
45 54
     },
46 55
     {
47 56
       title: "状态",

+ 27
- 16
src/pages/purchase/bill/edit/index.jsx ファイルの表示

@@ -12,11 +12,13 @@ import {
12 12
   ProFormDigit,
13 13
 } from "@ant-design/pro-components";
14 14
 import { useNavigate, useSearchParams } from "react-router-dom";
15
-import { Card, Col, message, Row, Space, Form, Button } from "antd";
15
+import { Card, Col, Modal, Row, Space, Form, Button } from "antd";
16 16
 import { useEffect, useRef, useState } from "react";
17
-import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
17
+import { ExclamationCircleOutlined } from '@ant-design/icons';
18 18
 import { floatMultiply, floatDivide } from "@/utils/float";
19 19
 
20
+const { confirm } = Modal;
21
+
20 22
 export default (props) => {
21 23
   const [searchParams] = useSearchParams();
22 24
   const id = searchParams.get("id");
@@ -53,8 +55,6 @@ export default (props) => {
53 55
   }, [id]);
54 56
 
55 57
   const onFinish = async (values) => {
56
-    console.log(values, "===");
57
-
58 58
     let data = {
59 59
       id: id ? Number(id) : null,
60 60
       ...values,
@@ -74,9 +74,15 @@ export default (props) => {
74 74
   };
75 75
 
76 76
   const onBillFinish = ({ form }) => {
77
-    form.validateFields().then((res) => {
78
-      console.log(res, "===--");
79
-      onFinish({ ...res, isCompleted: true });
77
+    confirm({
78
+      title: '确认采购完成?',
79
+      icon: <ExclamationCircleOutlined />,
80
+      content: '确定之后, 将不能再做修改!',
81
+      onOk: () => {
82
+        form.validateFields().then((res) => {
83
+          onFinish({ ...res, isCompleted: true });
84
+        });
85
+      }
80 86
     });
81 87
   };
82 88
 
@@ -93,6 +99,9 @@ export default (props) => {
93 99
             searchConfig: {
94 100
               resetText: "返回",
95 101
             },
102
+            submitButtonProps: {
103
+              disabled: isCompleted,
104
+            },
96 105
             onReset: () => navigate(-1),
97 106
             render: (props, doms) => {
98 107
               console.log(props, doms, "renderprops");
@@ -100,15 +109,11 @@ export default (props) => {
100 109
                 <Row>
101 110
                   <Col span={8} offset={2}>
102 111
                     <Space>
103
-                      {doms?.map((x, index) => {
104
-                        if (index === 1 && isCompleted) {
105
-                          return null;
106
-                        }
107
-                        return x;
108
-                      })}
109
-                      {id&&!isCompleted && (
112
+                      {doms}
113
+                      {id&& (
110 114
                         <Button
111 115
                           type="primary"
116
+                          disabled={isCompleted}
112 117
                           onClick={() => onBillFinish(props)}
113 118
                         >
114 119
                           采购完成
@@ -184,7 +189,10 @@ export default (props) => {
184 189
                         name={[name, "actAmount"]}
185 190
                         label="采购数量"
186 191
                         placeholder="请输入采购数量"
187
-                        rules={[{ required: true, message: "请输入采购数量" }]}
192
+                        rules={[
193
+                          { required: true, message: "请输入采购数量" },
194
+                          { validator: (_, val) => val > 0 ? Promise.resolve() : Promise.reject(), message: "采购数量必须大于0" },
195
+                        ]}
188 196
                         width={100}
189 197
                         fieldProps={{
190 198
                           precision: 10,
@@ -196,7 +204,10 @@ export default (props) => {
196 204
                         name={[name, "actUnitPrice"]}
197 205
                         label="采购单价"
198 206
                         placeholder="请输入采购单价"
199
-                        rules={[{ required: true, message: "请输入采购单价" }]}
207
+                        rules={[
208
+                          { required: true, message: "请输入采购单价" },
209
+                          { validator: (_, val) => val > 0 ? Promise.resolve() : Promise.reject(), message: "采购单价必须大于0" },
210
+                        ]}
200 211
                         fieldProps={{ precision: 2, prefix: "¥" }}
201 212
                         width={100}
202 213
                       />

+ 61
- 156
src/pages/purchase/inStore/edit/index.jsx ファイルの表示

@@ -1,45 +1,45 @@
1 1
 import {
2
-  savePurchaseInStore,
3 2
   getPurchaseDetail,
3
+  savePurchaseInStore,
4 4
 } from "@/services/purchase";
5 5
 import { getStoreList } from "@/services/stock";
6
-import {
7
-  PageContainer,
8
-  ProForm,
9
-  ProFormSelect,
10
-  ProFormText,
11
-  ProFormDigit,
12
-} from "@ant-design/pro-components";
13 6
 import { useNavigate, useSearchParams } from "react-router-dom";
14
-import { Card, Col, message, Row, Space, Form, Button } from "antd";
15
-import { useEffect, useRef, useState } from "react";
16
-import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
7
+import { Card, Descriptions, Button } from "antd";
8
+import { useEffect, useMemo, useState } from "react";
9
+import moment from "moment";
17 10
 import { floatMultiply, floatDivide } from "@/utils/float";
11
+import useBool from "@/utils/hooks/useBool";
12
+
13
+const Item = Descriptions;
18 14
 
19 15
 export default (props) => {
20 16
   const [searchParams] = useSearchParams();
21 17
   const id = searchParams.get("id");
22 18
   const [storeList, setStoreList] = useState([]);
23
-  const [isInStore, setIsInStore] = useState(false);
19
+  const [detail, setDetail] = useState({});
24 20
   const navigate = useNavigate();
21
+  const [loading, startLoading, cancelLoading] = useBool();
22
+
23
+  const dtStr = useMemo(() => detail.completedDate ? moment(detail.completedDate).format('YYYY-MM-DD'): '', [detail.completedDate]);
24
+
25
+  const onSumbit = () => {
26
+    startLoading()
27
+    savePurchaseInStore(id).then(() => {
28
+      cancelLoading()
29
+      setDetail({ ...detail, isInStore: true })
30
+    }).catch(cancelLoading)
31
+  }
25 32
   
26
-  const formRef = useRef();
27 33
   useEffect(() => {
28 34
     getStoreList({ pageSize: 9999 }).then((res) => {
29
-      setStoreList(
30
-        res?.records?.map((x) => ({
31
-          label: x.name,
32
-          value: x.id,
33
-        }))
34
-      );
35
+      setStoreList(res.records || []);
35 36
     });
36 37
   }, []);
37 38
 
38 39
   useEffect(() => {
39 40
     if (id) {
40 41
       getPurchaseDetail(id).then((res) => {
41
-        setIsInStore(res.isInStore)
42
-        formRef.current.setFieldsValue({
42
+        setDetail({
43 43
           ...res,
44 44
           itemsList: res.itemsList?.map((x) => ({
45 45
             ...x,
@@ -55,143 +55,48 @@ export default (props) => {
55 55
     }
56 56
   }, [id]);
57 57
 
58
-  const onFinish = async (values) => {
59
-    console.log(values, "===");
60
-
61
-
62
-
63
-    savePurchaseInStore(Number(id)).then((res) => {
64
-      // message.success("添加成功");
65
-      navigate(-1);
66
-    });
67
-
68
-    return false;
69
-  };
70
-
71
-
72
-
73 58
   return (
74
-    <PageContainer>
75
-      <Card>
76
-        <ProForm
77
-        
78
-          formRef={formRef}
79
-          layout={"horizontal"}
80
-          labelCol={{ span: 2 }}
81
-          wrapperCol={{ span: 8 }}
82
-          onFinish={onFinish}
83
-          submitter={{
84
-            searchConfig: {
85
-              resetText: "返回",
86
-              submitText:'入库'
87
-            },
88
-            onReset: () => navigate(-1),
89
-            render: (props, doms) => {
90
-              console.log(props, doms, "renderprops");
91
-              return (
92
-                <Row>
93
-                  <Col span={8} offset={2}>
94
-                    <Space>
95
-                      {doms?.map((x, index) => {
96
-                        if (index === 1 && isInStore) {
97
-                          return null;
98
-                        }
99
-                        return x;
100
-                      })}
101
-                    </Space>
102
-                  </Col>
103
-                </Row>
104
-              );
105
-            },
106
-          }}
107
-        >
108
-          <ProFormText
109
-            name="title"
110
-            label="采购计划"
111
-            placeholder="请输入采购计划"
112
-            disabled
113
-            width={480}
114
-          />
115
-          <ProFormText
116
-            name="planDate"
117
-            label="计划时间"
118
-            placeholder="请输入计划时间"
119
-            disabled
120
-            width={480}
121
-          />
122
-          <Form.Item
123
-            label="采购清单"
124
-            labelCol={{ span: 2 }}
125
-            wrapperCol={{ span: 22 }}
59
+    <Card
60
+      title={<div>采购单</div>}
61
+      extra={(
62
+        <>
63
+          <Button
64
+            type="primary"            
65
+            disabled={detail.isInStore || !detail.isCompleted}
66
+            loading={loading}
67
+            onClick={onSumbit}
126 68
           >
127
-            <Form.List name="itemsList">
128
-              {(fields, { add, remove }) => (
129
-                <>
130
-                  {fields.map(({ key, name, ...restField }) => (
131
-                    <Space
132
-                      key={key}
133
-                      style={{ display: "flex" }}
134
-                      align="baseline"
135
-                    >
136
-                      <ProFormSelect
137
-                        {...restField}
138
-                        name={[name, "storeId"]}
139
-                        label="库存名称"
140
-                        placeholder="请选择库存名称"
141
-                        disabled
142
-                        options={storeList}
143
-                      />
69
+            入库
70
+          </Button>
71
+          <Button style={{ marginLeft: '2em' }} onClick={() => navigate(-1)}>返回</Button> 
72
+        </>
73
+      )}
74
+    >
75
+      <Descriptions title="基本信息" bordered>
76
+        <Item label="采购时间">{dtStr}</Item>
77
+        <Item label="计划时间">{detail.planDate}</Item>
78
+      </Descriptions>
79
+      <Descriptions title="明细信息" bordered style={{ marginTop: '24px' }} column={5}>
80
+        {
81
+          (detail.itemsList || []).reduce((acc, it, inx) => {
82
+
83
+            const store = storeList.filter(x => x.id === it.storeId)[0] || {};
84
+            const planUnitPrice = it.planUnitPrice ? `${it.planUnitPrice} 元` : '-';
85
+            const planAmount = it.planAmount ? `${it.planAmount} ${store.unit}` : '-';
86
+            const actUnitPrice = it.actUnitPrice ? `${it.actUnitPrice} 元` : '-';
87
+            const actAmount = it.actAmount ? `${it.actAmount} ${store.unit}` : '-';
144 88
 
145
-                      <ProFormDigit
146
-                        {...restField}
147
-                        name={[name, "planAmount"]}
148
-                        label="计划数量"
149
-                        placeholder="请输入计划数量"
150
-                        disabled
151
-                        width={100}
152
-                        fieldProps={{
153
-                          precision: 10,
154
-                          formatter: (value) => value,
155
-                        }}
156
-                      />
157
-                      <ProFormDigit
158
-                        {...restField}
159
-                        name={[name, "planUnitPrice"]}
160
-                        label="预估单价"
161
-                        placeholder="请输入预估单价"
162
-                        disabled
163
-                        fieldProps={{ precision: 2, prefix: "¥" }}
164
-                        width={100}
165
-                      />
166
-                      <ProFormDigit
167
-                        {...restField}
168
-                        name={[name, "actAmount"]}
169
-                        label="采购数量"
170
-                        placeholder="请输入采购数量"
171
-                        disabled
172
-                        width={100}
173
-                        fieldProps={{
174
-                          precision: 10,
175
-                          formatter: (value) => value,
176
-                        }}
177
-                      />
178
-                      <ProFormDigit
179
-                        {...restField}
180
-                        name={[name, "actUnitPrice"]}
181
-                        label="采购单价"
182
-                        placeholder="请输入采购单价"
183
-                        disabled
184
-                        fieldProps={{ precision: 2, prefix: "¥" }}
185
-                        width={100}
186
-                      />
187
-                    </Space>
188
-                  ))}
189
-                </>
190
-              )}
191
-            </Form.List>
192
-          </Form.Item>
193
-        </ProForm>
194
-      </Card>
195
-    </PageContainer>
89
+            return acc.concat([
90
+                <Item key={`t-${inx}-1`} label="采购物品名称">{store.name}</Item>,
91
+                <Item key={`t-${inx}-2`} label="计划采购单价">{planUnitPrice}</Item>,
92
+                <Item key={`t-${inx}-3`} label="计划采购数量">{planAmount}</Item>,
93
+                <Item key={`t-${inx}-4`} label="实际采购单价">{actUnitPrice}</Item>,
94
+                <Item key={`t-${inx}-5`} label="实际采购数量">{actAmount}</Item>,
95
+              ]
96
+            )
97
+          }, [])
98
+        }
99
+      </Descriptions>
100
+    </Card>
196 101
   );
197 102
 };

+ 12
- 13
src/pages/purchase/plan/edit/index.jsx ファイルの表示

@@ -85,6 +85,10 @@ export default (props) => {
85 85
           submitter={{
86 86
             searchConfig: {
87 87
               resetText: "返回",
88
+              
89
+            },
90
+            submitButtonProps: {
91
+              disabled: isCompleted,
88 92
             },
89 93
             onReset: () => navigate(-1),
90 94
             render: (props, doms) => {
@@ -93,14 +97,7 @@ export default (props) => {
93 97
               return (
94 98
                 <Row>
95 99
                   <Col span={8} offset={2}>
96
-                    <Space>
97
-                      {doms?.map((x, index) => {
98
-                        if (index === 1 && isCompleted) {
99
-                          return null;
100
-                        }
101
-                        return x;
102
-                      })}
103
-                    </Space>
100
+                    <Space>{doms}</Space>
104 101
                   </Col>
105 102
                 </Row>
106 103
               );
@@ -110,12 +107,14 @@ export default (props) => {
110 107
           <ProFormText
111 108
             name="title"
112 109
             label="采购计划"
110
+            allowClear={false}
113 111
             placeholder="请输入采购计划"
114 112
             rules={[{ required: true, message: "请输入采购计划" }]}
115 113
             width={480}
116 114
           />
117 115
           <ProFormText
118 116
             name="planDate"
117
+            allowClear={false}
119 118
             label="计划时间"
120 119
             placeholder="请输入计划时间"
121 120
             rules={[{ required: true, message: "请输入计划时间" }]}
@@ -138,6 +137,7 @@ export default (props) => {
138 137
                       <ProFormSelect
139 138
                         {...restField}
140 139
                         name={[name, "storeId"]}
140
+                        allowClear={false}
141 141
                         label="库存名称"
142 142
                         placeholder="请选择库存名称"
143 143
                         rules={[{ required: true, message: "请输入选择名称" }]}
@@ -146,6 +146,7 @@ export default (props) => {
146 146
 
147 147
                       <ProFormDigit
148 148
                         {...restField}
149
+                        allowClear={false}
149 150
                         name={[name, "planAmount"]}
150 151
                         label="计划数量"
151 152
                         placeholder="请输入计划数量"
@@ -165,20 +166,18 @@ export default (props) => {
165 166
                         fieldProps={{ precision: 2, prefix: "¥" }}
166 167
                         // width={150}
167 168
                       />
168
-                      <MinusCircleOutlined onClick={() => remove(name)} />
169
+                    {  !isCompleted&&<MinusCircleOutlined onClick={() => remove(name)} />}
169 170
                     </Space>
170 171
                   ))}
171
-                  <Form.Item>
172
+                  {!isCompleted&&<Form.Item>
172 173
                     <Button
173 174
                       type="dashed"
174 175
                       onClick={() => add()}
175
-                      // block
176
-                      // style={{width:100}}
177 176
                       icon={<PlusOutlined />}
178 177
                     >
179 178
                       添加
180 179
                     </Button>
181
-                  </Form.Item>
180
+                  </Form.Item>}
182 181
                 </>
183 182
               )}
184 183
             </Form.List>

+ 2
- 2
src/pages/purchase/plan/list/index.jsx ファイルの表示

@@ -91,7 +91,7 @@ const StockList = (props) => {
91 91
             key={4}
92 92
             style={{ padding: 0 }}
93 93
             type="link"
94
-            disabled={record?.isCompleted}
94
+            // disabled={record?.isCompleted}
95 95
             onClick={() => {
96 96
               navigate(`/purchase/bill/edit?id=${record.id}`);
97 97
             }}
@@ -105,7 +105,7 @@ const StockList = (props) => {
105 105
             key={5}
106 106
             style={{ padding: 0 }}
107 107
             type="link"
108
-            disabled={record?.isInStore}
108
+            // disabled={record?.isInStore}
109 109
             onClick={() => {
110 110
               navigate(`/purchase/inStore/edit?id=${record.id}`);
111 111
             }}

+ 1
- 1
src/pages/rotationChart/list/index.jsx ファイルの表示

@@ -143,7 +143,7 @@ const RotationChartList = (props) => {
143 143
             key="2"
144 144
             type="primary"
145 145
             onClick={() => {
146
-              navigate('/cms/rotationChart/edit');
146
+              navigate('/cms/rotationChart/add');
147 147
             }}
148 148
           >
149 149
             新增

+ 59
- 38
src/pages/user/index.jsx ファイルの表示

@@ -1,9 +1,9 @@
1
-import React from 'react';
2
-import { useNavigate } from 'react-router-dom';
3
-import { queryTable } from '@/utils/request';
4
-import { ProTable } from '@ant-design/pro-components';
5
-import { Button, message, Popconfirm } from 'antd';
6
-import { getUserList, updateUserStatus } from '@/services/user';
1
+import React from "react";
2
+import { useNavigate } from "react-router-dom";
3
+import { queryTable } from "@/utils/request";
4
+import { ProTable } from "@ant-design/pro-components";
5
+import { Button, message, Popconfirm } from "antd";
6
+import { getUserList, updateUserStatus,deleteUser } from "@/services/user";
7 7
 
8 8
 const queryUserList = queryTable(getUserList);
9 9
 
@@ -13,56 +13,65 @@ export default (props) => {
13 13
 
14 14
   const updateStatus = (user) => {
15 15
     const status = user.status === 1 ? 0 : 1;
16
-    const hide = message.loading('请稍候...', 0);
17
-    updateUserStatus(user.id, status).then(res => {
18
-      hide();
19
-      actionRef.current.reload();
20
-    }).catch(() => {
21
-      hide();
22
-    })
23
-  }
16
+    const hide = message.loading("请稍候...", 0);
17
+    updateUserStatus(user.id, status)
18
+      .then((res) => {
19
+        hide();
20
+        actionRef.current.reload();
21
+      })
22
+      .catch(() => {
23
+        hide();
24
+      });
25
+  };
26
+  const handleDelete = (id) => {
27
+    if (id) {
28
+      deleteUser(id).then((res) => {
29
+        actionRef.current.reload();
30
+      });
31
+    }
32
+  };
24 33
 
25 34
   const columns = [
26 35
     {
27
-      title: 'id',
28
-      dataIndex: 'id',
36
+      title: "id",
37
+      dataIndex: "id",
29 38
       search: false,
30 39
     },
31 40
     {
32
-      title: '姓名',
33
-      dataIndex: 'name',
41
+      title: "姓名",
42
+      dataIndex: "name",
34 43
     },
35 44
     {
36
-      title: '部门',
37
-      dataIndex: 'dept',
45
+      title: "部门",
46
+      dataIndex: "dept",
38 47
     },
39 48
     {
40
-      title: '手机号',
41
-      dataIndex: 'phone',
49
+      title: "手机号",
50
+      dataIndex: "phone",
42 51
     },
43 52
     {
44
-      title: '账号',
45
-      dataIndex: 'loginName',
53
+      title: "账号",
54
+      dataIndex: "loginName",
46 55
       search: false,
47 56
     },
48 57
     {
49
-      title: '状态',
50
-      dataIndex: 'status',
58
+      title: "状态",
59
+      dataIndex: "status",
51 60
       search: false,
52 61
       valueEnum: {
53 62
         1: {
54
-          text: '正常',
55
-          status: 'Processing',
63
+          text: "正常",
64
+          status: "Processing",
56 65
         },
57 66
         0: {
58
-          text: '禁用',
59
-          status: 'Error',
67
+          text: "禁用",
68
+          status: "Error",
60 69
         },
61 70
       },
62 71
     },
63 72
     {
64
-      title: '操作',
65
-      valueType: 'option',
73
+      title: "操作",
74
+      valueType: "option",
66 75
       width: 200,
67 76
       render: (_, record) => [
68 77
         <Button
@@ -73,22 +82,34 @@ export default (props) => {
73 82
             updateStatus(record);
74 83
           }}
75 84
         >
76
-          {record.status === 1 ? '禁用' : '启用'}
85
+          {record.status === 1 ? "禁用" : "启用"}
77 86
         </Button>,
78 87
         <Button
79 88
           key={2}
80 89
           style={{ padding: 0 }}
81 90
           type="link"
82 91
           onClick={() => {
83
-            console.log(record, ']]');
92
+            console.log(record, "]]");
84 93
             navigate(`/system/user/edit?id=${record.id}`);
85 94
           }}
86 95
         >
87 96
           编辑
88 97
         </Button>,
98
+        <Popconfirm
99
+          key={3}
100
+          title="您是否确认删除 ?"
101
+          onConfirm={() => handleDelete(record.id)}
102
+          okText="确定"
103
+          cancelText="取消"
104
+        >
105
+          {/* manualPush */}
106
+          <Button style={{ padding: 0 }} type="link">
107
+            删除
108
+          </Button>
109
+        </Popconfirm>,
89 110
       ],
90 111
     },
91
-  ]
112
+  ];
92 113
 
93 114
   return (
94 115
     <ProTable
@@ -99,7 +120,7 @@ export default (props) => {
99 120
           key="1"
100 121
           type="primary"
101 122
           onClick={() => {
102
-            navigate('/system/user/edit');
123
+            navigate("/system/user/edit");
103 124
           }}
104 125
         >
105 126
           新增
@@ -108,5 +129,5 @@ export default (props) => {
108 129
       request={queryUserList}
109 130
       columns={columns}
110 131
     />
111
-  )
112
-}
132
+  );
133
+};

+ 44
- 0
src/regulation/detail/index.jsx ファイルの表示

@@ -0,0 +1,44 @@
1
+import { getPostsDetail } from "@/services/posts";
2
+
3
+import { useNavigate, useSearchParams } from "react-router-dom";
4
+import { Card, Typography, Button } from "antd";
5
+import { useEffect, useState } from "react";
6
+
7
+const { Title } = Typography;
8
+export default (props) => {
9
+  const [searchParams] = useSearchParams();
10
+  const id = searchParams.get("id");
11
+  const [data, setData] = useState({});
12
+  const [url, setUrl] = useState("");
13
+  const navigate = useNavigate();
14
+
15
+  useEffect(() => {
16
+    if (id) {
17
+      getPostsDetail(id).then((res) => {
18
+        setData(res);
19
+        setUrl(res.filesList[0]?.fileAddr);
20
+      });
21
+    }
22
+  }, [id]);
23
+
24
+  return (
25
+    <Card title={<Button onClick={() => navigate(-1)}> 返回</Button>}>
26
+      <Title level={2} style={{ marginBottom: "2em" }}>
27
+        {data.title}
28
+      </Title>
29
+      <div dangerouslySetInnerHTML={{ __html: data?.detail }}></div>
30
+      {url && (
31
+        <div style={{ marginTop: "2em" }}>
32
+          <a
33
+            href={`${url}`}
34
+            download
35
+            // rel="noopener noreferrer"
36
+            // key="link"
37
+          >
38
+            {url?.substring(url?.lastIndexOf("/") + 1)}
39
+          </a>
40
+        </div>
41
+      )}
42
+    </Card>
43
+  );
44
+};

+ 81
- 25
src/regulation/edit/index.jsx ファイルの表示

@@ -1,19 +1,29 @@
1
-import { addRegulation, getRegulationById } from '@/services/regulation';
2
-import { queryDict } from '@/utils/request';
3
-import { PageContainer, ProForm, ProFormSelect, ProFormText } from '@ant-design/pro-components';
4
-import { Card, Col, message, Row, Space } from 'antd';
5
-import { useNavigate, useSearchParams } from 'react-router-dom';
6
-import { useEffect, useRef, useState } from 'react';
1
+import { savePosts, getPostsDetail } from "@/services/posts";
2
+import {
3
+  PageContainer,
4
+  ProForm,
5
+  ProFormSelect,
6
+  ProFormText,
7
+} from "@ant-design/pro-components";
8
+import { useNavigate, useSearchParams } from "react-router-dom";
9
+import { Card, Col, Row, Space } from "antd";
10
+import { useEffect, useRef } from "react";
11
+import UploadFile from "@/components/UploadFile";
12
+import Wangeditor from "@/components/Wangeditor";
7 13
 
8 14
 export default (props) => {
9
-  const [searchParams, setSearchParams] = useSearchParams();
10
-  const id = searchParams.get('id');
11
-  const formRef = useRef();
15
+  const [searchParams] = useSearchParams();
16
+  const id = searchParams.get("id");
12 17
   const navigate = useNavigate();
18
+
19
+  const formRef = useRef();
13 20
   useEffect(() => {
14 21
     if (id) {
15
-      getRegulationById(id).then((res) => {
16
-        formRef.current.setFieldsValue(res);
22
+      getPostsDetail(id).then((res) => {
23
+        formRef.current.setFieldsValue({
24
+          ...res,
25
+          filesList: res.filesList?.map((x) => x.fileAddr)[0] || null,
26
+        });
17 27
       });
18 28
     }
19 29
   }, [id]);
@@ -22,9 +32,27 @@ export default (props) => {
22 32
     console.log(values);
23 33
 
24 34
     //添加,修改
25
-    addRegulation({ ...values, id }).then((res) => {
35
+    // addRegulation({ ...values, id }).then((res) => {
36
+    savePosts({
37
+      ...values,
38
+      type: 'regulation',
39
+      filesList: values.filesList
40
+        ? [
41
+          {
42
+            fileAddr: values.filesList,
43
+            fileName: values.filesList?.substring(
44
+              values.filesList?.lastIndexOf("/") + 1
45
+            ),
46
+          },
47
+        ]
48
+        : null,
49
+      status: Number(values.status),
50
+      ...(id ? { id } : {}),
51
+    }).then((res) => {
26 52
       navigate(-1);
27 53
     });
54
+    // }
55
+
28 56
     return false;
29 57
   };
30 58
 
@@ -33,13 +61,14 @@ export default (props) => {
33 61
       <Card>
34 62
         <ProForm
35 63
           formRef={formRef}
36
-          layout={'horizontal'}
64
+          layout={"horizontal"}
37 65
           labelCol={{ span: 8 }}
38
-          wrapperCol={{ span: 16 }}
66
+          wrapperCol={{ span: 12 }}
39 67
           onFinish={onFinish}
68
+          initialValues={{ status: 0 }}
40 69
           submitter={{
41 70
             searchConfig: {
42
-              resetText: '返回',
71
+              resetText: "返回",
43 72
             },
44 73
             onReset: () => navigate(-1),
45 74
             render: (props, doms) => {
@@ -54,23 +83,50 @@ export default (props) => {
54 83
           }}
55 84
         >
56 85
           <ProFormText
86
+            name="title"
87
+            label="内容名称"
88
+            placeholder="请输入内容名称"
89
+            rules={[{ required: true, message: "请输入内容名称" }]}
90
+            width={460}
91
+          />
92
+
93
+          <ProForm.Item
57 94
             name="detail"
58
-            label="发布内容"
59
-            placeholder="请输入发布内容"
60
-            rules={[{ required: true, message: '请输入发布内容' }]}
61
-            allowClear={false}
95
+            label="发布详情"
96
+            placeholder="请输入发布详情"
97
+            rules={[{ required: true, message: "请输入发布详情" }]}
98
+          >
99
+            <Wangeditor></Wangeditor>
100
+          </ProForm.Item>
101
+          <ProForm.Item name="filesList" label="文件">
102
+            <UploadFile preview={true}></UploadFile>
103
+          </ProForm.Item>
104
+
105
+          <ProFormSelect
106
+            name="status"
107
+            label="状态"
108
+            placeholder="请选择"
109
+            rules={[{ required: true, message: "请选择状态" }]}
62 110
             width={460}
111
+            options={[
112
+              {
113
+                value: 0,
114
+                label: "未发布",
115
+              },
116
+              {
117
+                value: 1,
118
+                label: "已发布",
119
+              },
120
+            ]}
63 121
           />
64 122
           <ProFormText
65
-            name="title"
66
-            label="内容名称"
67
-            placeholder="请输入内容名称"
68
-            rules={[{ required: true, message: '请输入内容名称' }]}
69
-            allowClear={false}
123
+            name="createPerson"
124
+            label="发布人"
125
+            placeholder="请输入发布人"
70 126
             width={460}
71 127
           />
72 128
         </ProForm>
73 129
       </Card>
74 130
     </PageContainer>
75 131
   );
76
-}
132
+};

+ 73
- 41
src/regulation/index.jsx ファイルの表示

@@ -1,19 +1,28 @@
1
-import { getRegulationList, deleteRegulation } from '@/services/regulation';
2
-import { PageContainer, ProTable } from '@ant-design/pro-components';
3
-import { useRef, useState, useEffect } from 'react';
4
-import { useNavigate } from 'react-router-dom';
5
-import { queryTable } from '@/utils/request';
6
-import { Button, message, Popconfirm } from 'antd';
1
+import { getPostsList, deletePosts, updatePosts } from "@/services/posts";
2
+import { queryTable } from "@/utils/request";
3
+import { PageContainer, ProTable } from "@ant-design/pro-components";
4
+import { useNavigate } from "react-router-dom";
5
+import { Button, Popconfirm } from "antd";
6
+import { useRef } from "react";
7
+
8
+const regex = /(<([^>]+)>)/gi;
7 9
 
8 10
 const RegulationList = (props) => {
11
+
9 12
   const actionRef = useRef();
10 13
   const navigate = useNavigate();
11
-  // const turn = replace(/<[^]+>/g, '');
14
+
15
+  const updata = (row) => {
16
+    if (row.id) {
17
+      updatePosts(row.id, { status: row.status === 1 ? 0 : 1 }).then((res) => {
18
+        actionRef.current.reload();
19
+      });
20
+    }
21
+  };
12 22
 
13 23
   const handleDelete = (id) => {
14 24
     if (id) {
15
-      deleteRegulation(id).then((res) => {
16
-        // message.success('删除成功');
25
+      deletePosts(id).then((res) => {
17 26
         actionRef.current.reload();
18 27
       });
19 28
     }
@@ -21,54 +30,76 @@ const RegulationList = (props) => {
21 30
 
22 31
   const columns = [
23 32
     {
24
-      title: 'id',
25
-      dataIndex: 'id',
26
-      width: 200,
27
-      search: false,
28
-    },
29
-    {
30
-      title: '标题',
31
-      dataIndex: 'title',
32
-      width: 200,
33
-      search: true,
33
+      title: "内容名称",
34
+      dataIndex: "title",
35
+      render: (text, record) => (
36
+        <a
37
+          onClick={() => {
38
+            navigate(`/cms/regulation/detail?id=${record.id}`);
39
+          }}
40
+        >
41
+          {text}
42
+        </a>
43
+      ),
34 44
     },
35 45
 
36 46
     {
37
-      title: '内容',
38
-      dataIndex: 'detail',
39
-      width: 200,
47
+      title: "发布内容",
48
+      dataIndex: "detail",
40 49
       search: false,
50
+      ellipsis: true,
51
+      width: "50%",
52
+      renderText: (text) => text?.replace(regex, ""),
41 53
     },
42
-
43 54
     {
44
-      title: '发布人',
45
-      dataIndex: 'create_person',
46
-      width: 200,
47
-      search: false,
55
+      title: "状态",
56
+      dataIndex: "status",
57
+      valueType: "select",
58
+      valueEnum: {
59
+        0: { text: "未发布", status: "Error" },
60
+        1: { text: "已发布", status: "Processing" },
61
+      },
48 62
     },
49 63
     {
50
-      title: '发布时间',
51
-      dataIndex: 'create_date',
52
-      width: 200,
64
+      title: "发布人",
65
+      dataIndex: "createPerson",
53 66
       search: false,
54 67
     },
55 68
     {
56
-      title: '操作',
57
-      valueType: 'option',
69
+      title: "操作",
70
+      valueType: "option",
58 71
       width: 200,
59 72
       render: (_, record) => [
73
+        <Button
74
+          key={4}
75
+          style={{ padding: 0 }}
76
+          type="link"
77
+          onClick={() => {
78
+            updata(record);
79
+          }}
80
+        >
81
+          {record.status === 1 ? "下架" : "发布"}
82
+        </Button>,
83
+        <Button
84
+          key={1}
85
+          style={{ padding: 0 }}
86
+          type="link"
87
+          onClick={() => {
88
+            navigate(`/cms/regulation/detail?id=${record.id}`);
89
+          }}
90
+        >
91
+          详情
92
+        </Button>,
60 93
         <Button
61 94
           key={2}
62 95
           style={{ padding: 0 }}
63 96
           type="link"
64 97
           onClick={() => {
65
-            console.log(record, ']]');
66
-            navigate(`/cms/regulation/add?id=${record.id}`);
98
+            navigate(`/cms/regulation/edit?id=${record.id}`);
67 99
           }}
68 100
         >
69
-          编辑
101
+          修改
70 102
         </Button>,
71
-
72 103
         <Popconfirm
73 104
           key={3}
74 105
           title="您是否确认删除 ?"
@@ -88,7 +119,6 @@ const RegulationList = (props) => {
88 119
   return (
89 120
     <PageContainer>
90 121
       <ProTable
91
-        search={true}
92 122
         actionRef={actionRef}
93 123
         rowKey="id"
94 124
         toolBarRender={() => [
@@ -96,17 +126,19 @@ const RegulationList = (props) => {
96 126
             key="2"
97 127
             type="primary"
98 128
             onClick={() => {
99
-              navigate('/cms/regulation/add');
129
+              navigate("/cms/regulation/edit");
100 130
             }}
101 131
           >
102 132
             新增
103 133
           </Button>,
104 134
         ]}
105
-        request={queryTable(getRegulationList)}
135
+        // search={false}
136
+        params={{ type: 'regulation' }}
137
+        request={queryTable(getPostsList)}
106 138
         columns={columns}
107 139
       />
108 140
     </PageContainer>
109 141
   );
110
-}
142
+};
111 143
 
112
-export default RegulationList;
144
+export default RegulationList;

+ 11
- 1
src/routes/routes.jsx ファイルの表示

@@ -35,6 +35,7 @@ import RotationChartDetail from "@/pages/rotationChart/detail";
35 35
 import Roles from "@/pages/roles/index";
36 36
 import RegulationList from "@/regulation";
37 37
 import RegulationEdit from "@/regulation/edit";
38
+import RegulationDetail from "@/regulation/detail";
38 39
 import UserList from "@/pages/user";
39 40
 import UserEdit from "@/pages/user/Edit";
40 41
 import PurchasePlanList from "@/pages/purchase/plan/list";
@@ -306,7 +307,7 @@ export const authRoutes = [
306 307
         },
307 308
       },
308 309
       {
309
-        path: "regulation/add",
310
+        path: "regulation/edit",
310 311
         element: <RegulationEdit />,
311 312
         meta: {
312 313
           hideInMenu: true,
@@ -314,6 +315,15 @@ export const authRoutes = [
314 315
           permission: 'regulation.edit',
315 316
         },
316 317
       },
318
+      {
319
+        path: "regulation/detail",
320
+        element: <RegulationDetail />,
321
+        meta: {
322
+          hideInMenu: true,
323
+          title: "规章制度详情",
324
+          permission: 'regulation.detail',
325
+        },
326
+      },
317 327
       {
318 328
         path: "emergency-plan",
319 329
         element: <EmergencyPlanList />,

+ 2
- 2
src/services/regulation.js ファイルの表示

@@ -5,7 +5,7 @@ import request from '@/utils/request';
5 5
  * @param {*} params
6 6
  * @returns
7 7
  */
8
-export const getRegulationList = (params) => request('/posts', { params });
8
+export const getRegulationList = (params) => request('/posts', { params,successTip:false });
9 9
 
10 10
 /**
11 11
 * 新增,更新
@@ -20,7 +20,7 @@ export const addRegulation = (data) => request(`/posts`, { method: 'post', data
20 20
 * @param {*} id
21 21
 * @returns
22 22
 */
23
-export const getRegulationById = (id) => request(`/posts/${id}`);
23
+export const getRegulationById = (id) => request(`/posts/${id}` ,{successTip:false});
24 24
 
25 25
 /**
26 26
  * 删除

+ 1
- 1
src/services/stock.js ファイルの表示

@@ -89,7 +89,7 @@ export const deleteStoreType = (id) => request(`/storeType/${id}`, { method: 'de
89 89
  * @param {*} params
90 90
  * @returns
91 91
  */
92
-export const getStoreLogList = (params) => request('/storeLog', { params });
92
+export const getStoreLogList = (params) => request('/storeLog', { params, successTip: false });
93 93
 
94 94
 /**
95 95
  * 新增

+ 8
- 7
src/utils/request.js ファイルの表示

@@ -18,9 +18,9 @@ instance.interceptors.request.use(function (config) {
18 18
     successTip,
19 19
     headers: {
20 20
       ...headers,
21
-      responseType: download ? 'blob' : responseType,
22 21
       Authorization: token,
23
-    }
22
+    },    
23
+    responseType: download ? 'blob' : responseType,
24 24
   };
25 25
 }, function (error) {
26 26
   // 对请求错误做些什么
@@ -33,8 +33,8 @@ instance.interceptors.response.use(function (response) {
33 33
   // 对响应数据做点什么
34 34
 
35 35
   const { data, config } = response;
36
-  if (config.download) {
37
-    return downloadBlob(response.data, '下载文件');
36
+  if (config.download && !data.code) {
37
+    return downloadBlob(response, '下载文件');
38 38
   }
39 39
   
40 40
   if (data.code === 1000) {
@@ -128,15 +128,16 @@ export function restful(url) {
128 128
 
129 129
 function downloadBlob(response) {
130 130
   let fileName = '未知文件';
131
+  const contentType = response.headers['content-type'];
131 132
   const contentDisposition = response.headers['content-disposition'];
132 133
   if (contentDisposition) {
133 134
     const parts = contentDisposition.split(';filename=');
134 135
     if (parts[1]) {
135
-      fileName = parts[1];
136
+      fileName = decodeURIComponent(parts[1]);
136 137
     }
137 138
   }
138
-
139
-  const url = window.URL.createObjectURL(response.data);
139
+console.log(response);
140
+  const url = window.URL.createObjectURL(new Blob([response.data], { type: contentType }));
140 141
   const link = document.createElement('a');
141 142
   link.href = url;
142 143
   link.setAttribute('download', fileName);

+ 1
- 0
vite.config.js ファイルの表示

@@ -5,6 +5,7 @@ import vitePluginImp from 'vite-plugin-imp'
5 5
 
6 6
 // https://vitejs.dev/config/
7 7
 export default defineConfig({
8
+  base: '/jgz/',
8 9
   server: {
9 10
     host: '0.0.0.0',
10 11
     proxy: {