fangmingyue пре 2 година
родитељ
комит
e4881a2fb1
45 измењених фајлова са 1416 додато и 408 уклоњено
  1. BIN
      src/assets/images/statistic/人员统计.png
  2. BIN
      src/assets/images/statistic/任务统计.png
  3. BIN
      src/assets/images/statistic/保障机构数.png
  4. BIN
      src/assets/images/statistic/军供保障能力.png
  5. BIN
      src/assets/images/statistic/接待军人总数.png
  6. BIN
      src/assets/images/statistic/数字统计.png
  7. BIN
      src/assets/images/statistic/社会保障机构分类统计.png
  8. BIN
      src/assets/images/statistic/设备分类统计.png
  9. BIN
      src/assets/images/statistic/设备数量.png
  10. 61
    40
      src/components/UploadFile/index.jsx
  11. 10
    6
      src/components/Wangeditor/index.jsx
  12. 11
    3
      src/components/chart/index.jsx
  13. 2
    2
      src/layouts/AuthLayout/components/Container.jsx
  14. 5
    4
      src/layouts/AuthLayout/index.jsx
  15. 15
    1
      src/pages/cms/emergencyPlan/detail/index.jsx
  16. 31
    44
      src/pages/cms/emergencyPlan/edit/index.jsx
  17. 1
    1
      src/pages/cms/emergencyPlan/list/index.jsx
  18. 35
    34
      src/pages/cms/files/list/addFiles.jsx
  19. 26
    115
      src/pages/cms/files/list/index.jsx
  20. 35
    32
      src/pages/guaranteeTask/index.jsx
  21. 40
    0
      src/pages/message/detail.jsx
  22. 36
    21
      src/pages/message/index.jsx
  23. 43
    0
      src/pages/statis/charts.jsx
  24. 100
    0
      src/pages/statis/components/Age.jsx
  25. 84
    0
      src/pages/statis/components/DeviceType.jsx
  26. 132
    0
      src/pages/statis/components/Edu.jsx
  27. 88
    0
      src/pages/statis/components/Filter.jsx
  28. 26
    0
      src/pages/statis/components/StatisCard.jsx
  29. 84
    0
      src/pages/statis/components/StoreCost.jsx
  30. 41
    0
      src/pages/statis/components/Sumary.jsx
  31. 81
    0
      src/pages/statis/components/Task.jsx
  32. 25
    0
      src/pages/statis/components/User.jsx
  33. 101
    0
      src/pages/statis/components/style.global.less
  34. 75
    0
      src/pages/statis/components/style.module.less
  35. 74
    0
      src/pages/statis/style.module.less
  36. 8
    19
      src/pages/stock/list/index.jsx
  37. 4
    0
      src/pages/stock/list/style.less
  38. 14
    2
      src/pages/stockClassification/edit/index.jsx
  39. 98
    78
      src/routes/routes.jsx
  40. 1
    1
      src/services/dish.js
  41. 1
    1
      src/services/guaranteeTask.js
  42. 5
    1
      src/services/message.js
  43. 1
    1
      src/services/package.js
  44. 21
    1
      src/services/posts.js
  45. 1
    1
      vite.config.js

BIN
src/assets/images/statistic/人员统计.png Прегледај датотеку


BIN
src/assets/images/statistic/任务统计.png Прегледај датотеку


BIN
src/assets/images/statistic/保障机构数.png Прегледај датотеку


BIN
src/assets/images/statistic/军供保障能力.png Прегледај датотеку


BIN
src/assets/images/statistic/接待军人总数.png Прегледај датотеку


BIN
src/assets/images/statistic/数字统计.png Прегледај датотеку


BIN
src/assets/images/statistic/社会保障机构分类统计.png Прегледај датотеку


BIN
src/assets/images/statistic/设备分类统计.png Прегледај датотеку


BIN
src/assets/images/statistic/设备数量.png Прегледај датотеку


+ 61
- 40
src/components/UploadFile/index.jsx Прегледај датотеку

@@ -1,64 +1,85 @@
1
-import React, { useCallback, useState } from 'react'
2
-import { UploadOutlined } from '@ant-design/icons';
3
-import { Upload, Button } from 'antd';
4
-import { uploadFile } from '@/services/rotationChart';
1
+import React, { useCallback, useState } from "react";
2
+import { UploadOutlined } from "@ant-design/icons";
3
+import { Upload, Button } from "antd";
4
+import { uploadFile } from "@/services/rotationChart";
5 5
 
6 6
 const customRequest = ({ file, onError, onSuccess }) => {
7 7
   const data = new FormData();
8
-  data.append('file', file);
8
+  data.append("file", file);
9 9
 
10
-  uploadFile(data).then((res) => {
11
-    onSuccess(res.url)
12
-  }).catch((err) => {
13
-    onError(err);
14
-  })
10
+  uploadFile(data)
11
+    .then((res) => {
12
+      onSuccess(res.url);
13
+    })
14
+    .catch((err) => {
15
+      onError(err);
16
+    });
15 17
 
16 18
   return {
17 19
     abort() {
18
-      console.log('upload progress is aborted.');
20
+      console.log("upload progress is aborted.");
19 21
     },
20 22
   };
21
-}
23
+};
22 24
 
23 25
 export default (props) => {
24 26
   const { value, onChange, preview, ...inputProps } = props;
25 27
   const [loading, setLoading] = useState(false);
26 28
 
27
-  const onUpload = useCallback((e) => {
28
-    const { files } = e.target;
29
-    if (!files || files.length < 1) return;
30
-
31
-    setLoading(true);
32
-    const data = new FormData();
33
-    data.append('file', files[0]);
29
+  const onUpload = useCallback(
30
+    (e) => {
31
+      const { files } = e.target;
32
+      if (!files || files.length < 1) return;
34 33
 
35
-    uploadFile(data).then((res) => {
36
-      setLoading(false);
37
-      if (typeof onChange === 'function') {
38
-        onChange(res.url)
39
-      }
40
-    }).catch((err) => {
41
-      setLoading(false);
42
-      // onError(err);
43
-    })
34
+      setLoading(true);
35
+      const data = new FormData();
36
+      data.append("file", files[0]);
44 37
 
45
-  }, [onChange])
38
+      uploadFile(data)
39
+        .then((res) => {
40
+          setLoading(false);
41
+          if (typeof onChange === "function") {
42
+            onChange(res.url);
43
+          }
44
+        })
45
+        .catch((err) => {
46
+          setLoading(false);
47
+          // onError(err);
48
+        });
49
+    },
50
+    [onChange]
51
+  );
46 52
 
47 53
   const onClick = () => {
48
-    const input = document.createElement('input');
49
-    input.type = 'file';
50
-    Object.assign(input, inputProps);    
51
-    input.addEventListener('change', onUpload);
54
+    const input = document.createElement("input");
55
+    input.type = "file";
56
+    Object.assign(input, inputProps);
57
+    input.addEventListener("change", onUpload);
52 58
     // input.removeEventListener('change', onUpload);
53 59
     input.click();
54
-  }
60
+  };
55 61
 
56 62
   return (
57 63
     <div>
58
-      <Button icon={<UploadOutlined />} onClick={onClick}>上传文件</Button>
59
-      {
60
-        value && typeof preview === 'function' && preview(value)
61
-      }
64
+      <Button icon={<UploadOutlined />} onClick={onClick}>
65
+        上传文件
66
+      </Button>
67
+      {value &&
68
+        preview &&
69
+        (typeof preview === "function" ? (
70
+          preview(value)
71
+        ) : (
72
+          <div style={{ marginTop: "1em" }}>
73
+            <a
74
+              href={`${value}`}
75
+              download
76
+              // rel="noopener noreferrer"
77
+              // key="link"
78
+            >
79
+              {value?.substring(value?.lastIndexOf("/") + 1)}
80
+            </a>
81
+          </div>
82
+        ))}
62 83
     </div>
63
-  )
64
-}
84
+  );
85
+};

+ 10
- 6
src/components/Wangeditor/index.jsx Прегледај датотеку

@@ -2,6 +2,9 @@ import React, { useState, useEffect } from "react";
2 2
 import "@wangeditor/editor/dist/css/style.css";
3 3
 import { Editor, Toolbar } from "@wangeditor/editor-for-react";
4 4
 
5
+// 工具栏配置参考
6
+// https://www.cnblogs.com/-roc/p/16400965.html
7
+
5 8
 function MyEditor(props) {
6 9
   const {
7 10
     value,
@@ -10,11 +13,9 @@ function MyEditor(props) {
10 13
     },
11 14
     toolbarConfig = {
12 15
       excludeKeys: [
13
-        "insertImage",
14
-        "viewImageLink",
15
-        "editImage",
16
-        "uploadImage",
17
-        "uploadVideo",
16
+
17
+        "group-image",
18
+        "group-video",
18 19
       ],
19 20
     },
20 21
     editorConfig = {
@@ -27,7 +28,10 @@ function MyEditor(props) {
27 28
   console.log(props, "MyEditor");
28 29
   // 模拟 ajax 请求,异步设置 html
29 30
   useEffect(() => {
30
-    console.log(editor     );
31
+    if(editor){
32
+      console.log(editor,editor.getConfig(),editor.getAllMenuKeys(),editor.getMenuConfig('image')) ;
33
+    }
34
+   
31 35
 
32 36
     setHtml(value);
33 37
   }, [value]);

+ 11
- 3
src/components/chart/index.jsx Прегледај датотеку

@@ -1,4 +1,4 @@
1
-import React, { useRef, useEffect } from 'react';
1
+import React, { useRef, useEffect, } from 'react';
2 2
 
3 3
 // 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
4 4
 import * as echarts from 'echarts/core';
@@ -51,7 +51,7 @@ echarts.use([
51 51
 ]);
52 52
 
53 53
 export default (props) => {
54
-  const { className, style, option } = props;
54
+  const { className, style, option, onInited, onRendered } = props;
55 55
 
56 56
   const domRef = useRef();
57 57
   const chartRef = useRef();
@@ -59,6 +59,10 @@ export default (props) => {
59 59
   useEffect(() => {
60 60
     if (!chartRef.current) {
61 61
       chartRef.current = echarts.init(domRef.current);
62
+
63
+      if (typeof onInited === 'function') {
64
+        onInited(chartRef.current);
65
+      }
62 66
     }
63 67
 
64 68
     const resize = () => {
@@ -71,6 +75,10 @@ export default (props) => {
71 75
     chartRef.current.setOption(option);
72 76
     resize();
73 77
 
78
+    if (typeof onRendered === 'function') {
79
+      onRendered(chartRef.current);
80
+    }
81
+
74 82
     window.addEventListener('resize', resize);    
75 83
     return () => window.removeEventListener('resize', resize);
76 84
   }, [option]);
@@ -78,4 +86,4 @@ export default (props) => {
78 86
   return (
79 87
     <div className={className} style={style} ref={domRef}></div>
80 88
   )
81
-}
89
+};

+ 2
- 2
src/layouts/AuthLayout/components/Container.jsx Прегледај датотеку

@@ -13,7 +13,7 @@ export default (props) => {
13 13
   
14 14
   useEffect(() => {
15 15
     const containerHeight = containerRef.current.offsetHeight;
16
-    const footerHeight = document.querySelector('.ant-layout-footer').offsetHeight;
16
+    const footerHeight = (document.querySelector('.ant-layout-footer') || {}).offsetHeight || 0;
17 17
     setMinHeight(containerHeight - footerHeight);
18 18
   }, []);
19 19
 
@@ -24,7 +24,7 @@ export default (props) => {
24 24
           <Outlet />
25 25
         {/* </PageTransition> */}
26 26
       </Content>
27
-      <Footer />
27
+      {!props.noFooter && <Footer />}      
28 28
     </div>
29 29
   )
30 30
 }

+ 5
- 4
src/layouts/AuthLayout/index.jsx Прегледај датотеку

@@ -16,7 +16,8 @@ export default (props) => {
16 16
   const { theme } = useModel('system');
17 17
   const { user, menus } = useModel('user');
18 18
   const location = useLocation();
19
-  const currentRoute = useRoute();
19
+  const { meta } = useRoute() || {};
20
+  const { noLayout = false, noSiderBar = false, noFooter = false } = meta || {};
20 21
 
21 22
   const splitMenus = useMemo(() => menus.map(x => ({ ...x, children: undefined })), [menus]);
22 23
   const siderMenus = useMemo(() => {
@@ -29,14 +30,14 @@ export default (props) => {
29 30
       <HtmlTitle />
30 31
       <RequireLogin>
31 32
         {
32
-          currentRoute && currentRoute.meta && currentRoute.meta.noLayout
33
+          noLayout
33 34
             ? <Outlet />
34 35
             : (
35 36
               <Layout style={{ minHeight: '100vh' }}>
36 37
                 <Header theme={theme} menus={splitMenus} location={location} />
37 38
                 <Layout>
38
-                  <SiderBar theme={theme} menus={siderMenus} location={location} />
39
-                  <Container location={location} />
39
+                  { !noSiderBar && <SiderBar theme={theme} menus={siderMenus} location={location} /> }
40
+                  <Container location={location} noFooter={noFooter} />
40 41
                 </Layout>
41 42
               </Layout>
42 43
             )

+ 15
- 1
src/pages/cms/emergencyPlan/detail/index.jsx Прегледај датотеку

@@ -15,6 +15,7 @@ export default (props) => {
15 15
   const [searchParams] = useSearchParams();
16 16
   const id = searchParams.get("id");
17 17
   const [data, setData] = useState({});
18
+  const [url, setUrl] = useState("");
18 19
   const navigate = useNavigate();
19 20
 
20 21
   const formRef = useRef();
@@ -23,16 +24,29 @@ export default (props) => {
23 24
     if (id) {
24 25
       getPostsDetail(id).then((res) => {
25 26
         setData(res);
27
+        setUrl(res.filesList[0]?.fileAddr);
26 28
       });
27 29
     }
28 30
   }, [id]);
29 31
 
30 32
   return (
31
-    <Card extra={<Button onClick={()=>navigate(-1)}> 返回</Button>}>
33
+    <Card extra={<Button onClick={() => navigate(-1)}> 返回</Button>}>
32 34
       <Title level={2} style={{ marginBottom: "2em" }}>
33 35
         {data.title}
34 36
       </Title>
35 37
       <div dangerouslySetInnerHTML={{ __html: data?.detail }}></div>
38
+      {url && (
39
+        <div style={{marginTop:"2em"}}>
40
+          <a
41
+            href={`${url}`}
42
+            download
43
+            // rel="noopener noreferrer"
44
+            // key="link"
45
+          >
46
+            {url?.substring(url?.lastIndexOf("/") + 1)}
47
+          </a>
48
+        </div>
49
+      )}
36 50
     </Card>
37 51
   );
38 52
 };

+ 31
- 44
src/pages/cms/emergencyPlan/edit/index.jsx Прегледај датотеку

@@ -19,21 +19,14 @@ export default (props) => {
19 19
   const navigate = useNavigate();
20 20
 
21 21
   const formRef = useRef();
22
-  // useEffect(() => {
23
-  //   getStoreList({ isDish: 1, pageSize: 9999 }).then((res) => {
24
-  //     setFoodDict(
25
-  //       res?.records?.map((x) => ({
26
-  //         label: x.name,
27
-  //         value: x.id,
28
-  //       }))
29
-  //     );
30
-  //   });
31
-  // }, [id]);
32 22
 
33 23
   useEffect(() => {
34 24
     if (id) {
35 25
       getPostsDetail(id).then((res) => {
36
-        formRef.current.setFieldsValue(res);
26
+        formRef.current.setFieldsValue({
27
+          ...res,
28
+          filesList: res.filesList?.map((x) => x.fileAddr)[0]||null,
29
+        });
37 30
       });
38 31
     }
39 32
   }, [id]);
@@ -41,17 +34,31 @@ export default (props) => {
41 34
   const onFinish = async (values) => {
42 35
     console.log(values, "===");
43 36
 
44
-    if (id) {
45
-      updatePosts(id, { ...values, status: Number(values.status) }).then(
46
-        (res) => {
47
-          navigate(-1);
48
-        }
49
-      );
50
-    } else {
51
-      savePosts({ ...values, status: Number(values.status) }).then((res) => {
52
-        navigate(-1);
53
-      });
54
-    }
37
+    // if (id) {
38
+    //   updatePosts(id, { ...values, status: Number(values.status) }).then(
39
+    //     (res) => {
40
+    //       navigate(-1);
41
+    //     }
42
+    //   );
43
+    // } else {
44
+    savePosts({
45
+      ...values,
46
+      filesList: values.filesList
47
+        ? [
48
+            {
49
+              fileAddr: values.filesList,
50
+              fileName: values.filesList?.substring(
51
+                values.filesList?.lastIndexOf("/") + 1
52
+              ),
53
+            },
54
+          ]
55
+        : null,
56
+      status: Number(values.status),
57
+      ...(id?{id}:{}),
58
+    }).then((res) => {
59
+      navigate(-1);
60
+    });
61
+    // }
55 62
 
56 63
     return false;
57 64
   };
@@ -98,28 +105,8 @@ export default (props) => {
98 105
           >
99 106
             <Wangeditor></Wangeditor>
100 107
           </ProForm.Item>
101
-          <ProForm.Item
102
-            name="file"
103
-            label="文件"
104
-   
105
-           
106
-          >
107
-            <UploadFile
108
-              preview={(value) => {
109
-                return (
110
-                  <div style={{ marginTop: "2em" }}>
111
-                    <a
112
-                      href={value}
113
-                      target="_blank"
114
-                      rel="noopener noreferrer"
115
-                      key="link"
116
-                    >
117
-                      {value}
118
-                    </a>
119
-                  </div>
120
-                );
121
-              }}
122
-            ></UploadFile>
108
+          <ProForm.Item name="filesList" label="文件">
109
+            <UploadFile preview={true}></UploadFile>
123 110
           </ProForm.Item>
124 111
 
125 112
           <ProFormSelect

+ 1
- 1
src/pages/cms/emergencyPlan/list/index.jsx Прегледај датотеку

@@ -64,7 +64,7 @@ const EmergencyPlanList = (props) => {
64 64
       width: 200,
65 65
       render: (_, record) => [
66 66
         <Button
67
-          key={3}
67
+          key={4}
68 68
           style={{ padding: 0 }}
69 69
           type="link"
70 70
           onClick={() => {

+ 35
- 34
src/pages/cms/files/list/addFiles.jsx Прегледај датотеку

@@ -1,55 +1,56 @@
1
-import { PlusOutlined } from '@ant-design/icons';
1
+import { PlusOutlined } from "@ant-design/icons";
2 2
 import {
3 3
   ModalForm,
4 4
   ProForm,
5 5
   ProFormDateRangePicker,
6 6
   ProFormSelect,
7 7
   ProFormText,
8
-} from '@ant-design/pro-components';
9
-import { Button, Form, message } from 'antd';
8
+} from "@ant-design/pro-components";
9
+import { Button, Form, message } from "antd";
10
+import { getPostsFilesList, savePostsFiles } from "@/services/posts";
11
+import UploadFile from "@/components/UploadFile";
10 12
 
11
-
12
-
13
-export default () => {
13
+export default ({onsuccess=()=>{}}) => {
14 14
   const [form] = Form.useForm();
15 15
 
16
+  const onFinish = async (values) => {
17
+    console.log(values);
18
+    // await waitTime(2000);
16 19
 
17
-  const onFinish = ()=>{
18
-
19
-  }
20
+    await savePostsFiles(values);
21
+    onsuccess()
22
+    return true;
23
+  };
20 24
 
21 25
   return (
22 26
     <ModalForm
23
-      title="新建表单"
24
-      trigger={
25
-        <Button type="primary">
26
-          <PlusOutlined />
27
-          新建表单
28
-        </Button>
29
-      }
27
+      title="新增文件"
28
+      trigger={<Button type="primary">新增</Button>}
30 29
       form={form}
31
-      autoFocusFirstInput
30
+      layout={"horizontal"}
31
+      labelCol={{ span: 8 }}
32
+      wrapperCol={{ span: 12 }}
32 33
       modalProps={{
33 34
         destroyOnClose: true,
34
-        onCancel: () => console.log('run'),
35
+        onCancel: () => console.log("run"),
35 36
       }}
36 37
       submitTimeout={2000}
37
-      onFinish={async (values) => {
38
-        await waitTime(2000);
39
-        console.log(values.name);
40
-        message.success('提交成功');
41
-        return true;
42
-      }}
38
+      onFinish={onFinish}
43 39
     >
44
-    
45
-        <ProFormText
46
-          width="md"
47
-          name="name"
48
-          label="文件名称"
49
-
50
-          placeholder="请输入名称"
51
-        />
52
-
40
+      <ProFormText
41
+        width="md"
42
+        name="fileName"
43
+        label="文件名称"
44
+        rules={[{ required: true, message: "请输入文件名称" }]}
45
+        placeholder="请输入名称"
46
+      />
47
+      <ProForm.Item
48
+        name="fileAddr"
49
+        label="文件"
50
+        rules={[{ required: true, message: "请上传文件" }]}
51
+      >
52
+        <UploadFile preview={true}></UploadFile>
53
+      </ProForm.Item>
53 54
     </ModalForm>
54 55
   );
55
-};
56
+};

+ 26
- 115
src/pages/cms/files/list/index.jsx Прегледај датотеку

@@ -1,157 +1,68 @@
1
-import { getPostsList, deletePosts, updatePosts } from "@/services/posts";
1
+import { getPostsFilesList, deletePostsFiles } from "@/services/posts";
2 2
 import { queryTable } from "@/utils/request";
3 3
 import { PageContainer, ProTable, ProList } from "@ant-design/pro-components";
4 4
 import { useNavigate } from "react-router-dom";
5 5
 import { Button, message, Popconfirm } from "antd";
6 6
 import { useRef, useState, useEffect } from "react";
7 7
 import { floatMultiply, floatDivide } from "@/utils";
8
-import AddFiles from './addFiles'
8
+import AddFiles from "./addFiles";
9 9
 
10 10
 const FilesList = (props) => {
11
-
12 11
   const [showDetail, setShowDetail] = useState(false);
13 12
   const [activeKey, setActiveKey] = useState("");
14 13
   const actionRef = useRef();
15 14
   const navigate = useNavigate();
16 15
 
17
-
18
-  const updata = (row) => {
19
-    if (row.id) {
20
-      updatePosts(row.id, { status: row.status === 1 ? 0 : 1 }).then((res) => {
21
-        actionRef.current.reload();
22
-      });
23
-    }
24
-  };
25
-
26 16
   const handleDelete = (id) => {
27 17
     if (id) {
28
-      deletePosts(id).then((res) => {
18
+      deletePostsFiles(id).then((res) => {
29 19
         actionRef.current.reload();
30 20
       });
31 21
     }
32 22
   };
33 23
 
34
-  const columns = [
35
-    {
36
-      title: "内容名称",
37
-      dataIndex: "title",
38
-    },
39
-
40
-    {
41
-      title: "状态",
42
-      dataIndex: "status",
43
-      valueType: "select",
44
-      valueEnum: {
45
-        0: { text: "未发布", status: "Error" },
46
-        1: { text: "已发布", status: "Processing" },
47
-      },
48
-    },
49
-    {
50
-      title: "发布人",
51
-      dataIndex: "createPerson",
52
-      search: false,
53
-    },
54
-    {
55
-      title: "操作",
56
-      valueType: "option",
57
-      width: 200,
58
-      render: (_, record) => [
59
-        <Button
60
-          key={3}
61
-          style={{ padding: 0 }}
62
-          type="link"
63
-          onClick={() => {
64
-            updata(record);
65
-          }}
66
-        >
67
-          {record.status === 1 ? "下架" : "发布"}
68
-        </Button>,
69
-        <Button
70
-          key={1}
71
-          style={{ padding: 0 }}
72
-          type="link"
73
-          onClick={() => {
74
-            navigate(`/cms/emergency-plan/detail?id=${record.id}`);
75
-          }}
76
-        >
77
-          详情
78
-        </Button>,
79
-        <Button
80
-          key={2}
81
-          style={{ padding: 0 }}
82
-          type="link"
83
-          onClick={() => {
84
-            navigate(`/cms/emergency-plan/edit?id=${record.id}`);
85
-          }}
86
-        >
87
-          修改
88
-        </Button>,
89
-        <Popconfirm
90
-          key={3}
91
-          title="您是否确认删除 ?"
92
-          onConfirm={() => handleDelete(record.id)}
93
-          okText="确定"
94
-          cancelText="取消"
95
-        >
96
-          {/* manualPush */}
97
-          <Button style={{ padding: 0 }} type="link">
98
-            删除
99
-          </Button>
100
-        </Popconfirm>,
101
-      ],
102
-    },
103
-  ];
104
-
105 24
   return (
106 25
     <PageContainer>
107 26
       <ProList
108 27
         toolBarRender={() => {
109 28
           return [
110
-           <AddFiles />,
29
+            <AddFiles
30
+              onsuccess={() => {
31
+                actionRef.current.reload();
32
+              }}
33
+            />,
111 34
           ];
112 35
         }}
36
+        actionRef={actionRef}
37
+        request={queryTable(getPostsFilesList)}
113 38
         search={{}}
114 39
         rowKey="id"
115 40
         // headerTitle="基础列表"
116
-        pagination={{
117
-          pageSize: 5,
118
-        }}
119
-        showActions="hover"
41
+        pagination={true}
42
+        // showActions="hover"
120 43
         metas={{
121 44
           title: {
122 45
             dataIndex: "fileName",
123 46
             title: "文件名称",
124 47
           },
125
-          description: {
126
-            dataIndex: "title",
127
-            search: false,
128
-          },
48
+
129 49
           actions: {
130 50
             render: (text, row) => [
131
-              <a
132
-                href={row.url}
133
-                target="_blank"
134
-                rel="noopener noreferrer"
135
-                key="link"
136
-              >
137
-                链路
138
-              </a>,
139
-              <a
140
-                href={row.url}
141
-                target="_blank"
142
-                rel="noopener noreferrer"
143
-                key="warning"
144
-              >
145
-                报警
51
+              <a href={row.fileAddr} download>
52
+                下载
146 53
               </a>,
147
-              <a
148
-                href={row.url}
149
-                target="_blank"
150
-                rel="noopener noreferrer"
151
-                key="view"
54
+              <Popconfirm
55
+                key={3}
56
+                title="您是否确认删除 ?"
57
+                onConfirm={() => handleDelete(row.id)}
58
+                okText="确定"
59
+                cancelText="取消"
152 60
               >
153
-                查看
154
-              </a>,
61
+                {/* manualPush */}
62
+                <Button style={{ padding: 0 }} type="link">
63
+                  删除
64
+                </Button>
65
+              </Popconfirm>,
155 66
             ],
156 67
             search: false,
157 68
           },

+ 35
- 32
src/pages/guaranteeTask/index.jsx Прегледај датотеку

@@ -1,11 +1,14 @@
1
-import { deleteGuaranteeTask, getGuaranteeTaskList } from '@/services/guaranteeTask';
2
-import { queryTable } from '@/utils/request';
3
-import { PageContainer, ProTable } from '@ant-design/pro-components';
4
-import { Link, useNavigate } from 'react-router-dom';
1
+import {
2
+  deleteGuaranteeTask,
3
+  getGuaranteeTaskList,
4
+} from "@/services/guaranteeTask";
5
+import { queryTable } from "@/utils/request";
6
+import { PageContainer, ProTable } from "@ant-design/pro-components";
7
+import { Link, useNavigate } from "react-router-dom";
5 8
 
6
-import { Button, message, Popconfirm } from 'antd';
7
-import moment from 'moment';
8
-import { useRef, useState } from 'react';
9
+import { Button, message, Popconfirm } from "antd";
10
+import moment from "moment";
11
+import { useRef, useState } from "react";
9 12
 
10 13
 const GuaranteeTaskList = (props) => {
11 14
   const navigate = useNavigate();
@@ -18,7 +21,7 @@ const GuaranteeTaskList = (props) => {
18 21
   const handleDelete = (id) => {
19 22
     if (id) {
20 23
       deleteGuaranteeTask(id).then((res) => {
21
-        message.success('删除成功');
24
+        message.success("删除成功");
22 25
         actionRef.current.reload();
23 26
       });
24 27
     }
@@ -31,47 +34,47 @@ const GuaranteeTaskList = (props) => {
31 34
 
32 35
   const columns = [
33 36
     {
34
-      title: '保障序号',
35
-      dataIndex: 'guaranteeNo',
37
+      title: "保障序号",
38
+      dataIndex: "guaranteeNo",
36 39
     },
37 40
     {
38
-      title: '受领人',
39
-      dataIndex: 'receiver',
41
+      title: "受领人",
42
+      dataIndex: "receiver",
40 43
     },
41 44
     {
42
-      title: '时间区间',
43
-      dataIndex: 'dateRange',
44
-      valueType: 'dateRange',
45
+      title: "时间区间",
46
+      dataIndex: "dateRange",
47
+      valueType: "dateRange",
45 48
       search: {
46 49
         transform: (value) => {
47
-          console.log(value, value[0].valueOf(), 'valuevalue');
50
+          console.log(value, value[0].valueOf(), "valuevalue");
48 51
 
49 52
           return {
50
-            startDate: moment(value[0]).format('yyyy-MM-DD'),
51
-            endDate: moment(value[1]).format('yyyy-MM-DD'),
53
+            startDate: moment(value[0]).format("yyyy-MM-DD"),
54
+            endDate: moment(value[1]).format("yyyy-MM-DD"),
52 55
           };
53 56
         },
54 57
       },
55 58
     },
56 59
     {
57
-      title: '保障地点',
58
-      dataIndex: 'address',
60
+      title: "保障地点",
61
+      dataIndex: "address",
59 62
       search: false,
60 63
     },
61 64
     {
62
-      title: '保障人数',
63
-      dataIndex: 'totalPersonNum',
65
+      title: "保障人数",
66
+      dataIndex: "totalPersonNum",
64 67
       search: false,
65 68
     },
66 69
     {
67
-      title: '伙食标准',
68
-      dataIndex: 'standard',
70
+      title: "伙食标准",
71
+      dataIndex: "standard",
69 72
       search: false,
70 73
     },
71 74
 
72 75
     {
73
-      title: '操作',
74
-      valueType: 'option',
76
+      title: "操作",
77
+      valueType: "option",
75 78
       width: 200,
76 79
       render: (_, record) => [
77 80
         <Button
@@ -97,13 +100,13 @@ const GuaranteeTaskList = (props) => {
97 100
             删除
98 101
           </Button>
99 102
         </Popconfirm>,
100
-        <Button
103
+        <a
101 104
           key={4}
102
-          style={{ padding: 0 }}
103
-          type="link"
105
+          href={`${window.location.pathname}#/task/guaranteeTask/print?id=${record.id}`}
106
+          target="_blank"
104 107
         >
105
-          <Link target="_blank" to={`/task/guaranteeTask/print?id=${record.id}`}>打印</Link>
106
-        </Button>,
108
+          执行
109
+        </a>,
107 110
       ],
108 111
     },
109 112
   ];
@@ -125,7 +128,7 @@ const GuaranteeTaskList = (props) => {
125 128
             key="2"
126 129
             type="primary"
127 130
             onClick={() => {
128
-              history.push('/guaranteeTask/edit');
131
+              navigate(`/task/guaranteeTask/edit`);
129 132
             }}
130 133
           >
131 134
             新增

+ 40
- 0
src/pages/message/detail.jsx Прегледај датотеку

@@ -0,0 +1,40 @@
1
+import React from 'react';
2
+import { Button, Card, Typography } from 'antd';
3
+import { useSearchParams, Link } from 'react-router-dom';
4
+import { getMessage } from '@/services/message';
5
+import useBool from '@/utils/hooks/useBool';
6
+
7
+export default (props) => {
8
+  const [searchParams] = useSearchParams();
9
+  const [loading, startLoading, cancelLoading] = useBool(false);
10
+
11
+  const [detail, setDetail] = React.useState({});
12
+  const id = searchParams.get('id');
13
+
14
+  React.useEffect(() => {
15
+    if (id) {
16
+      startLoading()
17
+      getMessage(id).then((res) => {
18
+        setDetail(res);
19
+        cancelLoading();
20
+      }).catch(() => {
21
+        cancelLoading();
22
+      });
23
+    }
24
+  }, [id]);
25
+
26
+  return (
27
+    <Card
28
+      loading={loading}
29
+      title={detail.createDate}
30
+      actions={[
31
+        <Button key={1} type="link" disabled={detail.isReaded}>设为已读</Button>,
32
+        <Link>去处理</Link>
33
+      ]}
34
+    >
35
+      <Typography.Paragraph>
36
+        {detail.message}
37
+      </Typography.Paragraph>
38
+    </Card>
39
+  )
40
+}

+ 36
- 21
src/pages/message/index.jsx Прегледај датотеку

@@ -1,24 +1,28 @@
1 1
 import React from 'react';
2
-import { useNavigate } from 'react-router-dom';
2
+import { useNavigate, Link } from 'react-router-dom';
3 3
 import { queryTable } from '@/utils/request';
4 4
 import { ProTable } from '@ant-design/pro-components';
5 5
 import { Button, message, Popconfirm } from 'antd';
6
-import { getMessageList } from '@/services/message';
6
+import { getMessageList, setMessageReaded } from '@/services/message';
7 7
 
8 8
 const queryMessage = queryTable(getMessageList);
9 9
 
10 10
 export default (props) => {
11
+  const actionRef = React.useRef();
12
+
13
+  const setReaded = (id) => {
14
+    setMessageReaded(id).then(() => {
15
+      actionRef.current.reset();
16
+    })
17
+  }
18
+
11 19
   const columns = [
12
-    {
13
-      title: 'id',
14
-      dataIndex: 'id',
15
-      search: false,
16
-    },
17 20
     {
18 21
       title: '时间',
19 22
       dataIndex: 'createDate',
20 23
       valueType: 'date',
21 24
       search: false,
25
+      width: 160,
22 26
     },
23 27
     {
24 28
       title: '时间',
@@ -42,12 +46,13 @@ export default (props) => {
42 46
       title: '状态',
43 47
       dataIndex: 'isReaded',
44 48
       search: false,
49
+      width: 120,
45 50
       valueEnum: {
46
-        1: {
51
+        true: {
47 52
           text: '已读',
48 53
           status: 'Processing',
49 54
         },
50
-        0: {
55
+        false: {
51 56
           text: '未读',
52 57
           status: 'Error',
53 58
         },
@@ -57,24 +62,34 @@ export default (props) => {
57 62
       title: '操作',
58 63
       valueType: 'option',
59 64
       width: 200,
60
-      render: (_, record) => [
61
-        <Button
62
-          key={2}
63
-          style={{ padding: 0 }}
64
-          type="link"
65
-          onClick={() => {
66
-            navigate(`/system/message/detail?id=${record.id}`);
67
-          }}
68
-        >
69
-          详情
70
-        </Button>,
71
-      ],
65
+      render: (_, record) => {
66
+        const doUrl = record.targetType === 'store' ?
67
+        `/stock/list?id=${record.targetId}` : undefined;
68
+
69
+        return [
70
+          <Button
71
+            key={1}
72
+            type="link"
73
+            disabled={record.isReaded}
74
+            onClick={() => setReaded(record.id)}
75
+          >
76
+            设为已读
77
+          </Button>,
78
+          <Link
79
+            key={2}
80
+            to={doUrl}
81
+          >
82
+            去处理
83
+          </Link>,
84
+        ]
85
+      },
72 86
     },
73 87
   ]
74 88
 
75 89
   return (
76 90
     <ProTable
77 91
       rowKey="id"
92
+      actionRef={actionRef}
78 93
       request={queryMessage}
79 94
       columns={columns}
80 95
     />

+ 43
- 0
src/pages/statis/charts.jsx Прегледај датотеку

@@ -0,0 +1,43 @@
1
+import React from 'react';
2
+import { Row, Col } from 'antd';
3
+import Sumary from './components/Sumary';
4
+import Task from './components/Task';
5
+import DeviceType from './components/DeviceType';
6
+import StoreCost from './components/StoreCost';
7
+import User from './components/User';
8
+import Styles from './style.module.less';
9
+
10
+const mtp = {
11
+  marginTop: '24px',
12
+}
13
+
14
+export default (props) => {
15
+  const gutter = 24;
16
+
17
+  return (
18
+    <div className={Styles['chart-page']}>
19
+      <Sumary gutter={gutter} />
20
+      <Row gutter={gutter} style={mtp}>
21
+        <Col span={18}>
22
+          <Task />
23
+        </Col>
24
+        <Col span={6}>
25
+          <DeviceType />
26
+        </Col>
27
+      </Row>
28
+      <Row gutter={gutter} style={mtp}>
29
+        <Col span={12}>
30
+          <StoreCost />
31
+        </Col>
32
+        <Col span={12}>
33
+          <User />
34
+        </Col>
35
+      </Row>
36
+      <Row gutter={gutter} style={mtp}>
37
+        <Col span={24}>
38
+          <Task />
39
+        </Col>
40
+      </Row>
41
+    </div>
42
+  )
43
+}

+ 100
- 0
src/pages/statis/components/Age.jsx Прегледај датотеку

@@ -0,0 +1,100 @@
1
+import React from 'react';
2
+import * as echarts from 'echarts/core';
3
+import Chart from '@/components/chart';
4
+
5
+let dataIndex = 0;
6
+export default (props) => {
7
+
8
+  const chartRef = React.useRef();
9
+  const option = getOption({"20(含)至29岁": 10, "20(含)至39岁": 20, "40(含)至49岁": 30, "50(含)岁以上": 40});
10
+
11
+  React.useEffect(() => {
12
+    const t = setTimeout(() => {
13
+      const chart = chartRef.current;
14
+      chart.on('mousemove', function(e) {
15
+        chart.dispatchAction({ type: 'downplay', dataIndex });
16
+        chart.dispatchAction({ type: 'highlight', dataIndex: e.dataIndex });
17
+        dataIndex = e.dataIndex
18
+      });
19
+      chart.dispatchAction({ type: 'highlight', dataIndex });
20
+      clearTimeout(t);
21
+    }, 300);
22
+  }, []);
23
+
24
+  const onInited = (chart) => chartRef.current = chart;
25
+
26
+  return (
27
+    <Chart option={option} style={{ height: '270px' }} onInited={onInited} />
28
+  )
29
+}
30
+
31
+function getOption(seriesData) {
32
+  const data = Object.keys(seriesData).map(function(key) {
33
+    return {
34
+      value: seriesData[key],
35
+      name: key
36
+    }
37
+  });
38
+
39
+  return {
40
+    title: {
41
+      show: true,
42
+      top: '6%',
43
+      left: 'center',
44
+      text: '人员年龄统计',
45
+      textStyle: {
46
+        color: '#fff',
47
+        fontSize: 18,
48
+        fontWeight: 'normal'
49
+      }
50
+    },
51
+    color: ['#3DE0A4', '#FF8940', '#3FC9F4', '#CB55E9'],
52
+    series: [
53
+      {
54
+        type: 'pie',
55
+        top: '10%',
56
+        radius: ['60%', '70%'],
57
+        label: {
58
+          show: false,
59
+          position: 'center',
60
+          lineHeight: 28,
61
+          borderRadius: [100, 100, 100, 100],
62
+          borderColor: '#FD8F00',
63
+          borderWidth: 2,
64
+          padding: 16,
65
+          width: 100,
66
+          height: 100,
67
+          formatter: [
68
+            '{s1|{d}%}',
69
+            '{s2|{b}}',
70
+            '{s3|{c}}',
71
+          ].join('\n'),
72
+          rich: {
73
+            s1: {
74
+              color: '#FD8F00',
75
+              fontSize: 24,
76
+            },
77
+            s2: {
78
+              color: 'rgba(255, 255, 255, .7)',
79
+              fontSize: 16,
80
+            },
81
+            s3: {
82
+              color: '#fff',
83
+              fontSize: 18,
84
+            },
85
+          }
86
+        },
87
+        emphasis: {
88
+          scaleSize: 10,
89
+          label: {
90
+            show: true,
91
+          }
92
+        },
93
+        labelLine: {
94
+          show: false
95
+        },
96
+        data: data,
97
+      },
98
+    ]
99
+  };
100
+}

+ 84
- 0
src/pages/statis/components/DeviceType.jsx Прегледај датотеку

@@ -0,0 +1,84 @@
1
+import React from 'react';
2
+import * as echarts from 'echarts/core';
3
+import icon from '@/assets/images/statistic/设备分类统计.png';
4
+import Chart from '@/components/chart';
5
+import StatisCard from './StatisCard';
6
+
7
+let dataIndex = 0;
8
+
9
+export default (props) => {
10
+
11
+  const chartRef = React.useRef();
12
+  const option = getOption({ "制餐设备": 20, "运输设备": 33, "野外保障设备": 10 });
13
+
14
+  React.useEffect(() => {
15
+    const t = setTimeout(() => {
16
+      const chart = chartRef.current;
17
+      chart.on('mousemove', function(e) {
18
+        chart.dispatchAction({ type: 'downplay', dataIndex });
19
+        chart.dispatchAction({ type: 'highlight', dataIndex: e.dataIndex });
20
+        dataIndex = e.dataIndex
21
+      });
22
+      chart.dispatchAction({ type: 'highlight', dataIndex });
23
+      clearTimeout(t);
24
+    }, 300);
25
+  }, []);
26
+
27
+  const onInited = (chart) => chartRef.current = chart;
28
+
29
+  return (
30
+    <StatisCard
31
+      title="设备分类统计"
32
+      icon={icon}
33
+    >
34
+      <Chart option={option} style={{ height: '300px' }} onInited={onInited} />
35
+    </StatisCard>
36
+  )
37
+}
38
+
39
+function getOption(seriesData) {
40
+  const data = Object.keys(seriesData).map(function(key) {
41
+    return {
42
+      value: seriesData[key],
43
+      name: key
44
+    }
45
+  });
46
+
47
+  return {
48
+    color: ['#3DE0A4', '#FF8940', '#3FC9F4', '#CB55E9'],
49
+    series: [
50
+      {
51
+        name: '设备分类统计',
52
+        type: 'pie',
53
+        radius: ['40%', '70%'],
54
+        avoidLabelOverlap: false,
55
+        itemStyle: {
56
+          borderRadius: 10,
57
+          borderColor: '#071C51',
58
+          borderWidth: 4
59
+        },
60
+        label: {
61
+          show: false,
62
+          position: 'center',
63
+        },
64
+        emphasis: {
65
+          scaleSize: 16,
66
+          label: {
67
+            show: true,
68
+            color: '#ffffff',
69
+            fontSize: 16,
70
+            fontWeight: 'bold',
71
+            lineHeight: 24,
72
+            formatter: function (params) {
73
+              return params.name + '\n' + params.value
74
+            },
75
+          }
76
+        },
77
+        labelLine: {
78
+          show: false
79
+        },
80
+        data: data,
81
+      }
82
+    ]
83
+  };
84
+}

+ 132
- 0
src/pages/statis/components/Edu.jsx Прегледај датотеку

@@ -0,0 +1,132 @@
1
+import React from 'react';
2
+import * as echarts from 'echarts/core';
3
+import Chart from '@/components/chart';
4
+
5
+export default (props) => {
6
+
7
+  const option = getOption(["本科以上", "本科及大专", "大专以下"], [10, 20, 30]);
8
+
9
+  return (
10
+    <Chart option={option} style={{ height: '300px' }} />
11
+  )
12
+}
13
+
14
+function getOption(yAxisData, seriesData) {
15
+  var maxValue = seriesData.slice().sort().reverse()[0] - 0 + 10
16
+
17
+  var title = {
18
+    show: true,
19
+    top: '6%',
20
+    left: 'center',
21
+    text: '人员学历统计',
22
+    textStyle: {
23
+      color: '#fff',
24
+      fontSize: 18,
25
+      fontWeight: 'normal'
26
+    }
27
+  }
28
+
29
+  // 实际上是绘制了 seriesData.length 个的柱图
30
+  var percent = 100 / seriesData.length
31
+  var grid = seriesData.map(function (_, index) {
32
+    return {
33
+      top: (20 + index * 20 ) + '%',
34
+      height: percent + '%',
35
+    }
36
+  })
37
+
38
+  var xAxis = seriesData.map(function (_, index) {
39
+    return { type: 'value', show: false, gridIndex: index }
40
+  })
41
+
42
+  var yAxis = yAxisData.map(function(_, index) {
43
+    return {
44
+      type: 'category',
45
+      position: 'right',
46
+      gridIndex: index,
47
+      axisLine: { show: false },
48
+      axisTick: { show: false },
49
+      axisLabel: {
50
+        color: '#fff',
51
+        fontSize: 16,
52
+        formatter: function () {
53
+          return seriesData[index];
54
+        }
55
+      }
56
+    }
57
+  })
58
+
59
+  var colors = [
60
+    new echarts.graphic.LinearGradient(0, 0, 1, 0, [
61
+      { offset: 0, color: '#87E8C5' },
62
+      { offset: 1, color: '#15E096' }
63
+    ]),
64
+    new echarts.graphic.LinearGradient(0, 0, 1, 0, [
65
+      { offset: 0, color: '#00BFFA' },
66
+      { offset: 1, color: '#0160EB' }
67
+    ]),
68
+    new echarts.graphic.LinearGradient(0, 0, 1, 0, [
69
+      { offset: 0, color: '#FFBE4E' },
70
+      { offset: 1, color: '#F77C30' }
71
+    ]),
72
+  ]
73
+
74
+  var barGaps = []; // 用来做背景
75
+  var pictorialBar = []; // 尾部的圆
76
+  var series = seriesData.map(function(dt, index) {
77
+    barGaps.push({
78
+      type: 'bar',
79
+      silent: true,
80
+      name: yAxisData[index],
81
+      xAxisIndex: index,
82
+      yAxisIndex: index,
83
+      barWidth: 16,
84
+      barGap: '-180%',
85
+      data: [maxValue],
86
+      label: {
87
+        show: true,
88
+        position: [0, '-160%'],
89
+        formatter: '{a}',
90
+        color: '#fff',
91
+        fontSize: 16,
92
+      },
93
+      itemStyle: {
94
+        color: 'rgba(255, 255, 255, 0.05)',
95
+        borderColor: 'rgba(255, 255, 255, 0.2)',
96
+        borderWidth: 1
97
+      }
98
+    })
99
+
100
+    pictorialBar.push({
101
+      silent: true,
102
+      type: 'pictorialBar',
103
+      xAxisIndex: index,
104
+      yAxisIndex: index,
105
+      data: [dt],
106
+      symbol: 'circle',
107
+      symbolSize: [10, 10],
108
+      symbolPosition: 'end',
109
+      symbolOffset: ['50%', '-25%'],
110
+    })
111
+
112
+    return {
113
+      data: [dt],
114
+      type: 'bar',
115
+      barWidth: 6,
116
+      xAxisIndex: index,
117
+      yAxisIndex: index,
118
+    }
119
+  })
120
+
121
+  var option = {
122
+    title: title,
123
+    xAxis: xAxis,
124
+    yAxis: yAxis,
125
+    grid: grid,
126
+    color: colors,
127
+    series: series.concat(barGaps).concat(pictorialBar)
128
+  }
129
+
130
+  // console.log(option)
131
+  return option
132
+}

+ 88
- 0
src/pages/statis/components/Filter.jsx Прегледај датотеку

@@ -0,0 +1,88 @@
1
+import React from 'react';
2
+import { Row, Col, Radio, DatePicker } from 'antd';
3
+import moment from 'moment';
4
+import 'moment/locale/zh-cn';
5
+import locale from 'antd/es/locale/zh_CN';
6
+
7
+const { RangePicker } = DatePicker;
8
+const radioOptions = [
9
+  { label: '本月', value: '1' },
10
+  // { label: '本季', value: '2' },
11
+  { label: '本年', value: '3' },
12
+];
13
+
14
+export const yearRange = [
15
+  moment().startOf('year'),
16
+  moment(),
17
+]
18
+export const quarterRange = [
19
+  moment().startOf('quarter'),
20
+  moment(),
21
+]
22
+export const monthRange = [
23
+  moment().startOf('quarter'),
24
+  moment(),
25
+]
26
+
27
+export default (props) => {
28
+  const [dateRange, setDateRange] = React.useState([]);
29
+  const [radioValue, setRadioValue] = React.useState();
30
+
31
+  const onChange = (val) => {
32
+    if (typeof props.onChange === 'function') {
33
+      props.onChange(getStrValue(val));
34
+    }
35
+  }
36
+
37
+  const onPickerChange = val => {
38
+    setDateRange(val);
39
+    setRadioValue();
40
+    onChange(getStrValue(val));
41
+  }
42
+
43
+  const onRadioChange = e => {
44
+    const val = e.target.value;
45
+    setRadioValue(val);
46
+    let dateRange = [];
47
+    switch (val) {
48
+      case '1':
49
+        dateRange = monthRange;
50
+        break;
51
+      case '2':
52
+        dateRange = quarterRange;
53
+        break;
54
+      case '3':
55
+        dateRange = yearRange;
56
+        break;
57
+      default:
58
+        break;
59
+    }
60
+    
61
+    setDateRange(dateRange);
62
+    onChange(getStrValue(dateRange));
63
+  }
64
+
65
+  return (
66
+    <Row style={{ width: '460px' }} gutter={8}>
67
+      <Col span={14}>
68
+        <RangePicker locale={locale} value={dateRange} onChange={onPickerChange} />
69
+      </Col>
70
+      <Col span={10}>
71
+        <Radio.Group
72
+          options={radioOptions}
73
+          value={radioValue}
74
+          onChange={onRadioChange}
75
+          optionType="button"
76
+          buttonStyle="solid"
77
+        />
78
+      </Col>
79
+    </Row>
80
+  )
81
+}
82
+
83
+export function getStrValue(range) {
84
+  return [
85
+    range[0].format('YYYY-MM-DD'),
86
+    range[1].format('YYYY-MM-DD'),
87
+  ];
88
+}

+ 26
- 0
src/pages/statis/components/StatisCard.jsx Прегледај датотеку

@@ -0,0 +1,26 @@
1
+import React from 'react';
2
+import { Card } from 'antd';
3
+import './style.global.less';
4
+
5
+const Header = props => {
6
+  return (
7
+    <div className="statis-card-header">
8
+      <img src={props.icon} />
9
+      <span>{props.children}</span>
10
+    </div>
11
+  )
12
+}
13
+
14
+export default (props) => {
15
+  const { icon, title, extra } = props;
16
+
17
+  return (
18
+    <Card
19
+      className="statis-card"
20
+      title={<Header icon={icon}>{title}</Header>}
21
+      extra={extra}
22
+    >
23
+      {props.children}
24
+    </Card>
25
+  )
26
+}

+ 84
- 0
src/pages/statis/components/StoreCost.jsx Прегледај датотеку

@@ -0,0 +1,84 @@
1
+import React from 'react';
2
+import icon from '@/assets/images/statistic/社会保障机构分类统计.png';
3
+import Chart from '@/components/chart';
4
+import StatisCard from './StatisCard';
5
+import Filter from './Filter';
6
+
7
+export default (props) => {
8
+
9
+  const [year, setYear] = React.useState();
10
+  const option = getOption(["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], [0, 0, 0, 0, 0, 0, 8, 9, 10, 1, 1, 6])
11
+
12
+  return (
13
+    <StatisCard
14
+      title="成本分析"
15
+      icon={icon}
16
+      extra={<Filter />}
17
+    >
18
+      <Chart option={option} style={{ height: '300px' }} />
19
+    </StatisCard>
20
+  )
21
+}
22
+
23
+function getOption(xAxisData, seriesData) {
24
+  var axisLabel = {
25
+    fontSize: 14,
26
+    color: 'rgba(255,255,255, .6)'
27
+  };
28
+  var lineStyle = {
29
+    color: 'rgba(255,255,255, .16)',
30
+    type: 'dashed'
31
+  };
32
+
33
+  return {
34
+    xAxis: {
35
+      type: 'category',
36
+      axisLabel: Object.assign({
37
+        rotate: 45
38
+      }, axisLabel),
39
+      axisLine: {
40
+        show: true,
41
+        lineStyle: lineStyle
42
+      },
43
+      data: xAxisData
44
+    },
45
+    yAxis: {
46
+      axisLabel: axisLabel,
47
+      axisLine: {
48
+        show: true,
49
+        lineStyle: lineStyle
50
+      },
51
+      splitLine: {
52
+        lineStyle: lineStyle
53
+      },
54
+      type: 'value'
55
+    },
56
+    tooltip : {
57
+      trigger: 'axis',
58
+      axisPointer : {
59
+        type : 'shadow'
60
+      }
61
+    },
62
+    grid: {
63
+      top: 20,
64
+      left: 50,
65
+      right: 20,
66
+      bottom: 70,
67
+    },
68
+    color: ['#9242D1'],
69
+    animationEasing: 'elasticOut',
70
+    series: [
71
+      {
72
+        data: seriesData,
73
+        type: 'pictorialBar',
74
+        barWidth: 16,
75
+        symbol: 'rect',
76
+        symbolRepeat: true,
77
+        animationDuration: 6000,
78
+        animationDelay: function (dataIndex, params) {
79
+          return params.index * 30;
80
+        }
81
+      }
82
+    ]
83
+  }
84
+}

+ 41
- 0
src/pages/statis/components/Sumary.jsx Прегледај датотеку

@@ -0,0 +1,41 @@
1
+import React from 'react';
2
+import { Row, Col } from 'antd';
3
+import classNames from 'classnames';
4
+import icon1 from '@/assets/images/statistic/数字统计.png';
5
+import icon2 from '@/assets/images/statistic/接待军人总数.png';
6
+import icon3 from '@/assets/images/statistic/保障机构数.png';
7
+import icon4 from '@/assets/images/statistic/设备数量.png';
8
+import Styles from './style.module.less';
9
+
10
+const DataCard = (props) => {
11
+  const { className, icon } = props;
12
+
13
+  const cls = classNames(Styles['data-card'], className);
14
+
15
+  return (
16
+    <dl className={cls}>
17
+      <dt>0</dt>
18
+      <dd>任务总数</dd>
19
+      <img src={icon} alt="" />
20
+    </dl>
21
+  )
22
+}
23
+
24
+export default (props) => {
25
+  return (
26
+    <Row gutter={props.gutter} justify="space-between">
27
+      <Col span={6}>
28
+        <DataCard icon={icon1} className={Styles['bk1']} />
29
+      </Col>
30
+      <Col span={6}>
31
+        <DataCard icon={icon2} className={Styles['bk2']} />
32
+      </Col>
33
+      <Col span={6}>
34
+        <DataCard icon={icon3} className={Styles['bk3']} />
35
+      </Col>
36
+      <Col span={6}>
37
+        <DataCard icon={icon4} className={Styles['bk4']} />
38
+      </Col>
39
+    </Row>
40
+  )
41
+}

+ 81
- 0
src/pages/statis/components/Task.jsx Прегледај датотеку

@@ -0,0 +1,81 @@
1
+import React from 'react';
2
+import * as echarts from 'echarts/core';
3
+import icon from '@/assets/images/statistic/任务统计.png';
4
+import Chart from '@/components/chart';
5
+import StatisCard from './StatisCard';
6
+import Filter from './Filter';
7
+
8
+export default (props) => {
9
+
10
+  const option = getOption(["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], [0, 0, 0, 0, 0, 0, 8, 9, 10, 1, 1, 6])
11
+
12
+  return (
13
+    <StatisCard
14
+      title="任务统计"
15
+      icon={icon}
16
+      extra={<Filter />}
17
+    >
18
+      <Chart option={option} style={{ height: '300px' }} />
19
+    </StatisCard>
20
+  )
21
+}
22
+
23
+function getOption(xAxisData, seriesData) {
24
+  var axisLabel = {
25
+    fontSize: 14,
26
+    color: 'rgba(255,255,255, .6)',
27
+  };
28
+  var lineStyle = {
29
+    color: 'rgba(255,255,255, .16)',
30
+    type: 'dashed'
31
+  };
32
+
33
+  return {
34
+    tooltip : {
35
+      trigger: 'axis',
36
+      axisPointer : {
37
+        type : 'shadow'
38
+      }
39
+    },
40
+    xAxis: {
41
+      type: 'category',
42
+      axisLabel: axisLabel,
43
+      axisLine: {
44
+        show: true,
45
+        lineStyle: lineStyle
46
+      },
47
+      data: xAxisData
48
+    },
49
+    yAxis: {
50
+      axisLabel: axisLabel,
51
+      axisLine: {
52
+        show: true,
53
+        lineStyle: lineStyle
54
+      },
55
+      splitLine: {
56
+        lineStyle: lineStyle
57
+      },
58
+      type: 'value'
59
+    },
60
+    grid: {
61
+      top: 20,
62
+      left: 50,
63
+      right: 20,
64
+      bottom: 50,
65
+    },
66
+    series: [
67
+      {
68
+        data: seriesData,
69
+        type: 'bar',
70
+        barWidth: 16,
71
+        itemStyle: {
72
+          borderRadius: [16, 16, 0, 0],
73
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
74
+            { offset: 0, color: '#1EAED1' },
75
+            { offset: 1, color: '#6F39B9' }
76
+          ])
77
+        }
78
+      }
79
+    ]
80
+  }
81
+}

+ 25
- 0
src/pages/statis/components/User.jsx Прегледај датотеку

@@ -0,0 +1,25 @@
1
+import React from 'react';
2
+import { Row, Col } from 'antd';
3
+import icon from '@/assets/images/statistic/人员统计.png';
4
+import StatisCard from './StatisCard';
5
+import Edu from './Edu';
6
+import Age from './Age';
7
+
8
+
9
+export default (props) => {
10
+  return (
11
+    <StatisCard
12
+      title="人员统计"
13
+      icon={icon}
14
+    >
15
+      <Row>
16
+        <Col span={12}>
17
+          <Edu />
18
+        </Col>
19
+        <Col span={12}>
20
+          <Age />
21
+        </Col>
22
+      </Row>
23
+    </StatisCard>
24
+  )
25
+}

+ 101
- 0
src/pages/statis/components/style.global.less Прегледај датотеку

@@ -0,0 +1,101 @@
1
+@chart-card-bg: #071C51;
2
+@chart-card-radius: 20px;
3
+
4
+.statis-card {
5
+	position: relative;
6
+	border-radius: @chart-card-radius;
7
+  background: transparent;
8
+  box-shadow: none;
9
+  border-color: transparent;
10
+  z-index: 0;
11
+
12
+  .ant-card-head {
13
+    border-bottom: none;
14
+  }
15
+
16
+  .ant-picker, .ant-radio-button-wrapper, .ant-picker-separator {
17
+    background: transparent !important;
18
+    color: #bbb !important;
19
+  }
20
+
21
+  .ant-radio-button-wrapper-checked {
22
+    background: #1890ff !important;
23
+    color: #fff !important;
24
+  }
25
+
26
+  .ant-picker-input {
27
+    & > input {
28
+      color: #bbb !important;
29
+    }
30
+  }
31
+
32
+  .ant-select-selector {
33
+    background: transparent !important;
34
+    border: none !important;
35
+    color: #bbb;
36
+    font-size: 1.4em;
37
+  }
38
+
39
+  .ant-select-arrow {
40
+    color: #bbb;
41
+  }
42
+  
43
+  &, &::before, &::after {
44
+    overflow: hidden;
45
+    box-sizing: border-box;
46
+  }
47
+
48
+  @keyframes chart-card-rotate {
49
+    100% {
50
+      transform: rotate(1turn);
51
+    }
52
+  }
53
+
54
+  &::before {
55
+    content: '';
56
+    position: absolute;
57
+    z-index: -2;
58
+    left: -450%;
59
+    top: -450%;
60
+    width: 1000%;
61
+    height: 1000%;
62
+    background-color: #1E5983;
63
+    background-repeat: no-repeat;
64
+    background-position: 0 0, 100% 100%;
65
+    background-image: conic-gradient(from 0, transparent, rgba(168, 239, 255, 1), transparent 20%),
66
+    conic-gradient(from 180deg,transparent, rgba(168, 239, 255, 1), transparent 20%);
67
+    animation: chart-card-rotate 10s linear infinite;
68
+  }
69
+
70
+  &::after {
71
+    content: '';
72
+    position: absolute;
73
+    z-index: -1;
74
+    left: 2px;
75
+    top: 2px;
76
+    width: calc(100% - 4px);
77
+    height: calc(100% - 4px);
78
+    background: @chart-card-bg;
79
+    border-radius: @chart-card-radius - 2px;
80
+    box-shadow: 2px 2px 10px rgba(255,255,255, .2) inset, -2px -2px 10px rgba(255,255,255, .2) inset;
81
+  }
82
+
83
+  .statis-card-header {
84
+    img {
85
+      width: 28px;
86
+      height: 28px;
87
+      vertical-align: middle;
88
+      display: inline-block;
89
+      margin-right: .5em;
90
+    }
91
+    span {
92
+      font-size: 22px;
93
+      font-weight: 500;
94
+      color: transparent;
95
+      background-image: linear-gradient(0deg, #6F39B9 0%, #1EAED1 100%);
96
+      vertical-align: middle;
97
+      background-clip: text;
98
+      -webkit-background-clip: text;
99
+    }
100
+  }
101
+}

+ 75
- 0
src/pages/statis/components/style.module.less Прегледај датотеку

@@ -0,0 +1,75 @@
1
+@chart-card-bg: #071C51;
2
+@chart-card-radius: 20px;
3
+
4
+.data-card {
5
+  overflow: hidden;
6
+  position: relative;
7
+  border-radius: 8px;
8
+  box-shadow: rgba(0, 0, 0, 0.3) 0px 2px 3px;
9
+  box-sizing: border-box;
10
+  padding: 24px 0px 36px;
11
+  padding-left: 150px;
12
+  // box-sizing: border-box;
13
+  // padding-left: 150px;
14
+
15
+  dt {
16
+    font-size: 36px;
17
+  }
18
+
19
+  dd {
20
+    font-size: 16px;
21
+  }
22
+
23
+  dt, dd {
24
+    padding: 0;
25
+    font-weight: 400;
26
+    color: rgb(255, 255, 255);
27
+    line-height: 1.53846;
28
+  }
29
+
30
+  img {
31
+    position: absolute;
32
+    display: block;
33
+    top: 24px;
34
+    left: 30px;
35
+    width: 88px;
36
+    height: 88px;
37
+  }
38
+
39
+  &::before,&::after {
40
+    content: "";
41
+    position: absolute;
42
+    background: #FFFFFF;
43
+    opacity: 0.1;
44
+    border-radius: 50%;
45
+    font-size: 0;
46
+  }
47
+
48
+  &::before {
49
+    width: 166px;
50
+    height: 140px;
51
+    left: calc(100% - 88px);
52
+    top: -40px;
53
+  }
54
+  
55
+  &::after {
56
+    width: 281px;
57
+    height: 177px;
58
+    border-radius: 50%;
59
+    left: calc(100% - 160px);
60
+    top: 81px;
61
+  }
62
+
63
+  &.bk1 {
64
+    background: linear-gradient(90deg, #3886D6, #003789);
65
+  }
66
+  &.bk2 {
67
+    background: linear-gradient(90deg, #29A0B1, #3C1A63);
68
+  }
69
+  &.bk3 {
70
+    background: linear-gradient(90deg, #1570AB, #343894);
71
+  }
72
+  &.bk4 {
73
+    background: linear-gradient(90deg, #2788B6, #083A8C);
74
+  }
75
+}

+ 74
- 0
src/pages/statis/style.module.less Прегледај датотеку

@@ -0,0 +1,74 @@
1
+
2
+@chart-card-bg: #071C51;
3
+@chart-card-radius: 20px;
4
+
5
+
6
+.chart-page {
7
+  width: 100%;
8
+  height: calc(100vh - var(--header-height));
9
+  overflow-y: auto;
10
+  background: @chart-card-bg;
11
+  box-sizing: border-box;
12
+  padding: 24px;
13
+
14
+  .count {
15
+    border-radius: 20px;
16
+    
17
+    dl {
18
+      overflow: hidden;
19
+      position: relative;
20
+      box-sizing: border-box;
21
+      padding-left: 150px;
22
+
23
+      dt, dd {
24
+        padding: 0;
25
+      }
26
+
27
+      img {
28
+        position: absolute;
29
+        display: block;
30
+        top: 24px;
31
+        left: 30px;
32
+        width: 88px;
33
+        height: 88px;
34
+      }
35
+
36
+      &::before,&::after {
37
+        content: "";
38
+        position: absolute;
39
+        background: #FFFFFF;
40
+        opacity: 0.1;
41
+        border-radius: 50%;
42
+        font-size: 0;
43
+      }
44
+
45
+      &::before {
46
+        width: 166px;
47
+        height: 140px;
48
+        left: calc(100% - 88px);
49
+        top: -40px;
50
+      }
51
+      
52
+      &::after {
53
+        width: 281px;
54
+        height: 177px;
55
+        border-radius: 50%;
56
+        left: calc(100% - 160px);
57
+        top: 81px;
58
+      }
59
+
60
+      &:nth-child(1) {
61
+        background: linear-gradient(90deg, #3886D6, #003789);
62
+      }
63
+      &:nth-child(2) {
64
+        background: linear-gradient(90deg, #29A0B1, #3C1A63);
65
+      }
66
+      &:nth-child(3) {
67
+        background: linear-gradient(90deg, #1570AB, #343894);
68
+      }
69
+      &:nth-child(4) {
70
+        background: linear-gradient(90deg, #2788B6, #083A8C);
71
+      }
72
+    }
73
+  }
74
+}

+ 8
- 19
src/pages/stock/list/index.jsx Прегледај датотеку

@@ -1,29 +1,21 @@
1 1
 import { deleteStore, getStoreList, getStoreTypeList, storeExport } from '@/services/stock';
2 2
 import { queryDict, queryTable } from '@/utils/request';
3 3
 import { PageContainer, ProTable } from '@ant-design/pro-components';
4
-import { useNavigate } from 'react-router-dom';
4
+import { useNavigate, useSearchParams } from 'react-router-dom';
5 5
 import { Button, message, Modal, Popconfirm } from 'antd';
6 6
 import { useRef, useState } from 'react';
7 7
 import OutAndIn from '../outAndIn';
8
+import './style.less';
8 9
 
9 10
 const StockList = (props) => {
10 11
   const [isOpen, setIsOpen] = useState(false);
11 12
   const [modalData, setModalData] = useState({});
12
-  // const [storeTypeDict, setStoreTypeDict] = useState([]);
13 13
   const actionRef = useRef();
14 14
   const formRef = useRef();
15 15
   const navigate = useNavigate();
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
-  // }, []);
16
+  const [searchParams] = useSearchParams();
17
+
18
+  const id = searchParams.get('id');
27 19
 
28 20
   const handleDelete = (id) => {
29 21
     if (id) {
@@ -44,14 +36,10 @@ const StockList = (props) => {
44 36
   };
45 37
 
46 38
   const columns = [
47
-    // {
48
-    //   title: 'id',
49
-    //   dataIndex: 'id',
50
-    //   search: false,
51
-    // },
52 39
     {
53 40
       title: '名称',
54 41
       dataIndex: 'name',
42
+      render: (t, row) => row.warnAmount >= row.amount ? `${t} (库存不足)` : t
55 43
     },
56 44
     {
57 45
       title: '单位',
@@ -70,7 +58,6 @@ const StockList = (props) => {
70 58
       dataIndex: 'amount',
71 59
       search: false,
72 60
     },
73
-
74 61
     {
75 62
       title: '操作',
76 63
       valueType: 'option',
@@ -120,7 +107,9 @@ const StockList = (props) => {
120 107
       <ProTable
121 108
         actionRef={actionRef}
122 109
         formRef={formRef}
110
+        params={{ id }}
123 111
         rowKey="id"
112
+        rowClassName={(row) => row.warnAmount >= row.amount ? 'store-danger' : ''}
124 113
         toolBarRender={() => [
125 114
           <Button
126 115
             key="2"

+ 4
- 0
src/pages/stock/list/style.less Прегледај датотеку

@@ -0,0 +1,4 @@
1
+
2
+.store-danger {
3
+  color: #ff4d4f;
4
+}

+ 14
- 2
src/pages/stockClassification/edit/index.jsx Прегледај датотеку

@@ -65,7 +65,7 @@ export default (props) => {
65 65
         >
66 66
           <ProFormText
67 67
             name="name"
68
-            label="名称"
68
+            label="分类名称"
69 69
             placeholder="请输入名称"
70 70
             width={460}
71 71
             allowClear={false}
@@ -73,7 +73,7 @@ export default (props) => {
73 73
           />
74 74
           <ProFormSelect
75 75
             name="isFood"
76
-            label="食材"
76
+            label="是否食材"
77 77
             options={[
78 78
               { label: '是', value: 1 },
79 79
               { label: '否', value: 0 },
@@ -83,6 +83,18 @@ export default (props) => {
83 83
             allowClear={false}
84 84
             rules={[{ required: true, message: '请选择是否食材' }]}
85 85
           />
86
+          <ProFormSelect
87
+            name="isDevice"
88
+            label="是否设备"
89
+            options={[
90
+              { label: '是', value: 1 },
91
+              { label: '否', value: 0 },
92
+            ]}
93
+            placeholder="请选择"
94
+            width={460}
95
+            allowClear={false}
96
+            rules={[{ required: true, message: '请选择是否设备' }]}
97
+          />
86 98
         </ProForm>
87 99
       </Card>
88 100
     </PageContainer>

+ 98
- 78
src/routes/routes.jsx Прегледај датотеку

@@ -44,6 +44,8 @@ import EmergencyPlanEdit from "@/pages/cms/emergencyPlan/edit";
44 44
 import EmergencyPlanDetail from "@/pages/cms/emergencyPlan/detail";
45 45
 import FilesList from "@/pages/cms/files/list";
46 46
 import MessageList from '@/pages/message';
47
+import MessageDetail from '@/pages/message/detail';
48
+import StatisCharts from '@/pages/statis/charts';
47 49
 
48 50
 /**
49 51
  * meta 用来扩展自定义数据数据
@@ -51,157 +53,166 @@ import MessageList from '@/pages/message';
51 53
  *    title: 用于页面或者菜单的标题, 没有此字段, 菜单不会显示
52 54
  *    hideInMenu: 布尔值, 如果为 false, 菜单不会显示
53 55
  *    noLayout: 布尔值, 如果为 true, 将不会使用默认布局
56
+ *    noSiderBar: 布尔值, 如果为 true, 将没有左侧菜单栏
57
+ *    noFooter: 布尔值, 如果为 true, 将没有底部 footer 
54 58
  *    target: 字符串, 如果为 _blank, 将在新窗口打开
55 59
  * }
56 60
  */
57 61
 
58 62
 export const authRoutes = [
59 63
   {
60
-    path: 'task',
64
+    path: "task",
61 65
     element: <Container />,
62 66
     meta: {
63
-      title: '军供任务',
67
+      title: "军供任务",
64 68
       icon: <AppstoreOutlined />,
65 69
     },
66 70
     children: [
67 71
       {
68 72
         index: true,
69
-        element: <Navigate to='guaranteeTask' replace />,
73
+        element: <Navigate to="guaranteeTask" replace />,
70 74
       },
71 75
       {
72
-        path: 'guaranteeTask',
76
+        path: "guaranteeTask",
73 77
         element: <GuaranteeTaskList />,
74 78
         meta: {
75
-          title: '军供通报',
79
+          title: "军供通报",
76 80
         },
77 81
       },
78 82
       {
79
-        path: 'guaranteeTask/edit',
83
+        path: "guaranteeTask/edit",
80 84
         element: <GuaranteeTaskEdit />,
81 85
         meta: {
82
-          title: '任务配置',
86
+          title: "任务配置",
83 87
         },
84 88
       },
85 89
       {
86
-        path: 'guaranteeTask/print',
90
+        path: "guaranteeTask/print",
87 91
         element: <GuaranteeTaskPrint />,
88 92
         meta: {
89 93
           hideInMenu: true,
90 94
           noLayout: true,
91
-          target: '_blank',
92
-          title: '任务执行',
95
+          target: "_blank",
96
+          title: "任务执行",
93 97
         },
94
-      }
95
-    ]
98
+      },
99
+      {
100
+        path: "guaranteeTask/print",
101
+        element: <GuaranteeTaskPrint />,
102
+        meta: {
103
+          title: "任务评价",
104
+        },
105
+      },
106
+    ],
96 107
   },
97 108
   {
98
-    path: 'material',
109
+    path: "material",
99 110
     element: <Container />,
100 111
     meta: {
101
-      title: '物资管理',
112
+      title: "物资管理",
102 113
       icon: <AppstoreOutlined />,
103 114
     },
104 115
     children: [
105 116
       {
106 117
         index: true,
107
-        element: <Navigate to='dish/list' replace />,
118
+        element: <Navigate to="dish/list" replace />,
108 119
       },
109 120
       {
110
-        path: 'dish/list',
121
+        path: "dish/list",
111 122
         element: <DishList />,
112 123
         meta: {
113
-          title: '菜肴管理',
124
+          title: "菜肴管理",
114 125
         },
115 126
       },
116 127
       {
117
-        path: 'dish/edit',
128
+        path: "dish/edit",
118 129
         element: <DishEdit />,
119 130
         meta: {
120 131
           hideInMenu: true,
121
-          title: '菜肴维护',
132
+          title: "菜肴维护",
122 133
         },
123 134
       },
124 135
       {
125
-        path: 'package/list',
136
+        path: "package/list",
126 137
         element: <PackageList />,
127 138
         meta: {
128
-          title: '套餐管理',
139
+          title: "套餐管理",
129 140
         },
130 141
       },
131
-    ]
142
+    ],
132 143
   },
133 144
   {
134
-    path: 'stock',
145
+    path: "stock",
135 146
     element: <Container />,
136 147
     meta: {
137
-      title: '库存管理',
148
+      title: "库存管理",
138 149
       icon: <AppstoreOutlined />,
139 150
     },
140 151
     children: [
141 152
       {
142 153
         index: true,
143
-        element: <Navigate to='list' replace />,
154
+        element: <Navigate to="list" replace />,
144 155
       },
145 156
       {
146
-        path: 'list',
157
+        path: "list",
147 158
         element: <StockList />,
148 159
         meta: {
149
-          title: '库存列表',
160
+          title: "库存列表",
150 161
         },
151 162
       },
152 163
       {
153
-        path: 'add',
164
+        path: "add",
154 165
         element: <StockEdit />,
155 166
         meta: {
156
-          title: '库存维护',
167
+          title: "库存维护",
157 168
         },
158 169
       },
159 170
     ],
160 171
   },
161 172
   {
162
-    path: 'cms',
173
+    path: "cms",
163 174
     element: <Container />,
164 175
     meta: {
165
-      title: '公告文件',
176
+      title: "公告文件",
166 177
     },
167 178
     children: [
168 179
       {
169 180
         index: true,
170
-        element: <Navigate to='rotationChart/list' replace />,
181
+        element: <Navigate to="rotationChart/list" replace />,
171 182
       },
172 183
       {
173
-        path: 'station',
184
+        path: "station",
174 185
         element: null,
175 186
         meta: {
176
-          title: '本站信息',
187
+          title: "本站信息",
177 188
         },
178 189
       },
179 190
       {
180
-        path: 'rotationChart/list',
191
+        path: "rotationChart/list",
181 192
         element: <RotationChartList />,
182 193
         meta: {
183
-          title: '公告内容',
194
+          title: "公告内容",
184 195
         },
185 196
       },
186 197
       {
187
-        path: 'rotationChart/add',
198
+        path: "rotationChart/add",
188 199
         element: <RotationChartEdit />,
189 200
         meta: {
190
-          title: '公告维护',
201
+          title: "公告维护",
191 202
         },
192 203
       },
193 204
       {
194
-        path: 'rotationChart/introduction',
205
+        path: "rotationChart/introduction",
195 206
         element: <RotationChartIntroduction />,
196 207
         meta: {
197
-          title: '本站信息简介',
208
+          title: "本站信息简介",
198 209
         },
199 210
       },
200 211
       {
201 212
         path: 'regulation',
202 213
         element: <RegulationList />,
203 214
         meta: {
204
-          title: '规章制度',
215
+          title: "规章制度",
205 216
         },
206 217
       },
207 218
       {
@@ -243,78 +254,87 @@ export const authRoutes = [
243 254
           title: "文件管理",
244 255
         },
245 256
       },
246
-
247 257
     ],
248 258
   },
249 259
   {
250 260
     path: 'static',
251
-    element: <Container />,
261
+    element: <StatisCharts />,
252 262
     meta: {
253 263
       title: '数据分析',
264
+      noSiderBar: true,
265
+      noFooter: true,
254 266
     },
255 267
   },
256 268
   {
257
-    path: 'system',
269
+    path: "system",
258 270
     element: <Container />,
259 271
     meta: {
260
-      title: '系统管理',
272
+      title: "系统管理",
261 273
     },
262 274
     children: [
263 275
       {
264 276
         index: true,
265
-        element: <Navigate to='stockClassification/list' replace />,
277
+        element: <Navigate to="stockClassification/list" replace />,
266 278
       },
267 279
       {
268
-        path: 'stockClassification/list',
280
+        path: "stockClassification/list",
269 281
         element: <StockClassificationList />,
270 282
         meta: {
271
-          title: '库存分类管理',
283
+          title: "库存分类",
272 284
         },
273 285
       },
274 286
       {
275
-        path: 'stockClassification/edit',
287
+        path: "stockClassification/edit",
276 288
         element: <StockClassificationEdit />,
277 289
         meta: {
278
-          title: '库存分类维护',
290
+          title: "库存分类维护",
279 291
           hideInMenu: true,
280 292
         },
281 293
       },
282 294
       {
283
-        path: 'log',
295
+        path: "log",
284 296
         element: <StockLog />,
285 297
         meta: {
286
-          title: '库存操作日志',
298
+          title: "操作日志",
287 299
         },
288 300
       },
289 301
       {
290
-        path: 'roles',
302
+        path: "roles",
291 303
         element: <Roles />,
292 304
         meta: {
293
-          title: '系统角色管理',
305
+          title: "角色管理",
294 306
         },
295 307
       },
296 308
       {
297
-        path: 'user',
309
+        path: "user",
298 310
         element: <UserList />,
299 311
         meta: {
300
-          title: '系统用户管理',
312
+          title: "用户管理",
301 313
         },
302 314
       },
303 315
       {
304
-        path: 'user/edit',
316
+        path: "user/edit",
305 317
         element: <UserEdit />,
306 318
         meta: {
307 319
           hideInMenu: true,
308
-          title: '系统用户编辑',
320
+          title: "系统用户编辑",
309 321
         },
310 322
       },
311 323
       {
312
-        path: 'message',
324
+        path: "message",
313 325
         element: <MessageList />,
314 326
         meta: {
315
-          title: '消息列表',
327
+          title: "消息列表",
316 328
         },
317
-      }
329
+      },
330
+      {
331
+        path: "message/detail",
332
+        element: <MessageDetail />,
333
+        meta: {
334
+          title: "消息详情",
335
+          hideInMenu: true,
336
+        },
337
+      },
318 338
     ],
319 339
   },
320 340
   {
@@ -375,11 +395,11 @@ export const authRoutes = [
375 395
       },
376 396
     ],
377 397
   },
378
-]
398
+];
379 399
 
380 400
 export const defaultRoutes = [
381 401
   {
382
-    path: '/',
402
+    path: "/",
383 403
     element: <AuthLayout />,
384 404
     children: [
385 405
       {
@@ -387,27 +407,27 @@ export const defaultRoutes = [
387 407
         element: <Home />,
388 408
       },
389 409
       {
390
-        path: 'home',
410
+        path: "home",
391 411
         element: <Home />,
392 412
         meta: {
393
-          title: '首页',
413
+          title: "首页",
394 414
           icon: <DesktopOutlined />,
395 415
         },
396 416
       },
397 417
       {
398
-        path: '*',
399
-        element: <Page404 />
400
-      }
418
+        path: "*",
419
+        element: <Page404 />,
420
+      },
401 421
     ],
402 422
   },
403 423
   {
404
-    path: '/login',
424
+    path: "/login",
405 425
     element: <Login />,
406 426
   },
407 427
   {
408
-    path: '*',
409
-    element: <Page404 />
410
-  }
428
+    path: "*",
429
+    element: <Page404 />,
430
+  },
411 431
 ];
412 432
 
413 433
 export function mergeAuthRoutes (r1, r2) {
@@ -419,22 +439,22 @@ export function mergeAuthRoutes (r1, r2) {
419 439
 
420 440
 // 全部路由
421 441
 export const routes = mergeAuthRoutes(defaultRoutes, authRoutes);
422
-
423
-function getPath (parent = '/', current = '') {
424
-  if (current.indexOf('/') === 0 || current.indexOf('http') === 0) return current;
425
-  return `${parent}/${current}`.replace(/\/\//g, '/');
442
+function getPath (parent = "/", current = "") {
443
+  if (current.indexOf("/") === 0 || current.indexOf("http") === 0)
444
+    return current;
445
+  return `${parent}/${current}`.replace(/\/\//g, "/");
426 446
 }
427 447
 
428 448
 // 路由数组, 一维数组
429 449
 export const routeArr = (() => {
430
-  const flatten = (routes, parentPath = '/') => {
450
+  const flatten = (routes, parentPath = "/") => {
431 451
     return routes.reduce((acc, route) => {
432 452
       const path = getPath(parentPath, route.path);
433 453
       const children = route.children ? flatten(route.children, path) : [];
434 454
 
435 455
       return acc.concat([{ ...route, path }].concat(children));
436 456
     }, []);
437
-  }
457
+  };
438 458
 
439 459
   return flatten(routes);
440 460
 })();

+ 1
- 1
src/services/dish.js Прегледај датотеку

@@ -5,7 +5,7 @@ import request from '@/utils/request';
5 5
  * @param {*} params
6 6
  * @returns
7 7
  */
8
-export const getDishList = (params) => request('/dishes', { params });
8
+export const getDishList = (params) => request('/dishes', { params,successTip:false });
9 9
 
10 10
 /**
11 11
  * 查询食材列表

+ 1
- 1
src/services/guaranteeTask.js Прегледај датотеку

@@ -50,7 +50,7 @@ import request from '@/utils/request';
50 50
  * @param {*} params
51 51
  * @returns
52 52
  */
53
-export const getGuaranteeTaskList = (params) => request('/guaranteeTask', { params });
53
+export const getGuaranteeTaskList = (params) => request('/guaranteeTask', { params,successTip:false });
54 54
 
55 55
 /**
56 56
  * 删除

+ 5
- 1
src/services/message.js Прегледај датотеку

@@ -1,9 +1,13 @@
1
-import { restful } from '@/utils/request';
1
+import request, { restful } from '@/utils/request';
2 2
 
3 3
 const [
4 4
   getMessageList,
5
+  getMessage,
5 6
 ] = restful("/noticeMessage");
6 7
 
7 8
 export {
8 9
   getMessageList,
10
+  getMessage,
9 11
 }
12
+
13
+export const setMessageReaded = id => request.put(`/noticeMessage/${id}/readed`)

+ 1
- 1
src/services/package.js Прегледај датотеку

@@ -5,7 +5,7 @@ import request from '@/utils/request';
5 5
  * @param {*} params
6 6
  * @returns
7 7
  */
8
-export const getPackageList = (params) => request('/package', { params });
8
+export const getPackageList = (params) => request('/package', { params,successTip:false });
9 9
 
10 10
 
11 11
 /**

+ 21
- 1
src/services/posts.js Прегледај датотеку

@@ -7,4 +7,24 @@ import { restful } from "@/utils/request";
7 7
 const [getPostsList, getPostsDetail, savePosts, updatePosts, deletePosts] =
8 8
   restful("/posts");
9 9
 
10
-export { getPostsList, getPostsDetail, savePosts, updatePosts, deletePosts };
10
+const [
11
+  getPostsFilesList,
12
+  getPostsFilesDetail,
13
+  savePostsFiles,
14
+  updatePostsFiles,
15
+  deletePostsFiles,
16
+] = restful("/postsFiles");
17
+
18
+export {
19
+  getPostsList,
20
+  getPostsDetail,
21
+  savePosts,
22
+  updatePosts,
23
+  deletePosts,
24
+  
25
+  getPostsFilesList,
26
+  getPostsFilesDetail,
27
+  savePostsFiles,
28
+  updatePostsFiles,
29
+  deletePostsFiles,
30
+};

+ 1
- 1
vite.config.js Прегледај датотеку

@@ -9,7 +9,7 @@ export default defineConfig({
9 9
     proxy: {
10 10
       '/api/': {
11 11
         // 要代理的地址
12
-        target: 'http://192.168.89.147:8087',
12
+        target: 'http://jgz.njyunzhi.com',
13 13
         // 配置了这个可以从 http 代理到 https
14 14
         // 依赖 origin 的功能可能需要这个,比如 cookie
15 15
         changeOrigin: true,