Переглянути джерело

Merge branch 'master' of lizhiqi/yongxu-web into master

lizhiqi 2 роки тому
батько
коміт
0e2ba79d22

BIN
public/assets/device.png


BIN
public/assets/user.png


+ 1 - 2
src/app.tsx

@@ -101,7 +101,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
     onPageChange: () => {
       const { location } = history;
       // 如果没有登录,重定向到 login
-      if (!initialState?.currentUser && location.pathname !== loginPath) {
+      if (!initialState?.currentUser?.name && location.pathname !== loginPath) {
         history.push(loginPath);
       }
     },
@@ -112,7 +112,6 @@ export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) =
         const menuData = await queryMenu({ q: 'tree', query_all: 1 });
         const routers: any[] = [];
         permissionsMenu(routers, menuData.data.list);
-
         return loopMenuItem(routers);
       },
     },

+ 1 - 0
src/components/RightContent/AvatarDropdown.tsx

@@ -52,6 +52,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
       const { key } = event;
       if (key === 'logout') {
         setInitialState((s) => ({ ...s, currentUser: undefined }));
+        localStorage.clear();
         loginOut();
         return;
       }

+ 107 - 30
src/pages/RoleManagement/edit.tsx

@@ -1,6 +1,8 @@
-import React from 'react';
-import { Col, Form, Input, message, Modal, Row } from 'antd';
+import React, { useEffect, useState } from 'react';
+import { Col, Form, Input, InputNumber, message, Modal, Row, Table } from 'antd';
+import type { ColumnsType } from 'antd/es/table';
 import { createRole, editRole } from '@/services/role';
+import { queryMenu } from '@/services/menu';
 
 const { TextArea } = Input;
 
@@ -10,6 +12,13 @@ interface editPros {
   params: any;
 }
 
+interface DataType {
+  key: React.Key;
+  name: string;
+  router: string;
+  record_id: string;
+}
+
 /**
  * 角色管理 - 编辑
  * @param props
@@ -17,39 +26,77 @@ interface editPros {
  */
 const Edit: React.FC<editPros> = (props) => {
   const { params, visible, editCallback } = props;
+  const [menuList, setMenuList] = useState([]);
+  const [selectedRowKeys, setSelectedRowKeys] = useState([]);
   const [form] = Form.useForm();
 
+  // 菜单列表数据
+  const getMenuList = () => {
+    const data: any = {
+      q: 'tree',
+      query_all: 1,
+    };
+    queryMenu(data).then((res) => {
+      if (res && res.code === 0) {
+        setMenuList(res.data.list);
+      }
+    });
+  };
+
+  // 初始化
+  useEffect(() => {
+    getMenuList();
+    // 获取被选中菜单的id
+    if (params) {
+      const arr: any = [];
+      params?.menus?.forEach((item: { menu_id: any }) => {
+        arr.push(item.menu_id);
+      });
+      setSelectedRowKeys(arr);
+    }
+  }, []);
+
+  // 提交
   const onOk = () => {
     form.validateFields().then((values) => {
       if (values) {
-        const data = { ...values };
-        if (params) {
-          data.record_id = params.record_id;
-          editRole(data)
-            .then((res) => {
-              if (res && res.code === 0) {
-                message.success('编辑成功');
-                editCallback();
-              } else {
-                message.error('编辑失败');
-              }
-            })
-            .catch((e) => {
-              message.error(e?.message);
-            });
+        if (selectedRowKeys && selectedRowKeys.length) {
+          const data = { ...values };
+          const arr: { menu_id: any }[] = [];
+          selectedRowKeys.forEach((res: any) => {
+            arr.push({ menu_id: res });
+          });
+          data.menus = arr;
+          if (params) {
+            data.record_id = params.record_id;
+            editRole(data)
+              .then((res) => {
+                if (res && res.code === 0) {
+                  message.success('编辑成功');
+                  editCallback();
+                } else {
+                  message.error('编辑失败');
+                }
+              })
+              .catch((e) => {
+                message.error(e?.message);
+              });
+          } else {
+            createRole(data)
+              .then((res) => {
+                if (res && res.code === 0) {
+                  message.success('新增成功');
+                  editCallback();
+                } else {
+                  message.error('新增失败');
+                }
+              })
+              .catch((e) => {
+                message.error(e?.message);
+              });
+          }
         } else {
-          createRole(data)
-            .then((res) => {
-              if (res && res.code === 0) {
-                message.success('新增成功');
-                editCallback();
-              } else {
-                message.error('新增失败');
-              }
-            })
-            .catch((e) => {
-              message.error(e?.message);
-            });
+          message.error('请选择菜单权限');
         }
       }
     });
@@ -60,6 +107,10 @@ const Edit: React.FC<editPros> = (props) => {
     editCallback();
   };
 
+  const handleTableSelectRow = (keys: any) => {
+    setSelectedRowKeys(keys);
+  };
+
   const formItemLayout = {
     labelCol: {
       span: 6,
@@ -73,6 +124,23 @@ const Edit: React.FC<editPros> = (props) => {
     wrapperCol: { span: 21 },
   };
 
+  const columns: ColumnsType<DataType> = [
+    {
+      title: '序号',
+      align: 'center',
+      key: 'index',
+      render: (_: any, row: any, index: number) => index + 1,
+    },
+    {
+      title: '菜单名称',
+      dataIndex: 'name',
+    },
+    {
+      title: '访问路由',
+      dataIndex: 'router',
+    },
+  ];
+
   return (
     <Modal
       title={`${params ? '编辑' : '新增'}`}
@@ -102,7 +170,7 @@ const Edit: React.FC<editPros> = (props) => {
               rules={[{ required: true, message: '请输入排序值' }]}
               initialValue={params?.sequence}
             >
-              <Input placeholder="请输入排序值" />
+              <InputNumber placeholder="请输入排序值" style={{ width: '100%' }} />
             </Form.Item>
           </Col>
           <Col span={24}>
@@ -117,6 +185,15 @@ const Edit: React.FC<editPros> = (props) => {
             </Form.Item>
           </Col>
         </Row>
+        <Table
+          rowSelection={{
+            selectedRowKeys: selectedRowKeys,
+            onChange: handleTableSelectRow,
+          }}
+          columns={columns}
+          rowKey={(record) => record.record_id}
+          dataSource={menuList}
+        />
       </Form>
     </Modal>
   );

+ 4 - 0
src/pages/RoleManagement/index.tsx

@@ -14,6 +14,10 @@ interface DataType {
   record_id: string;
 }
 
+/**
+ * 角色管理
+ * @constructor
+ */
 const RoleManagement: React.FC = () => {
   const [form] = Form.useForm();
   const [loading, setLoading] = useState(false);

+ 31 - 9
src/pages/Welcome.less

@@ -1,13 +1,35 @@
 @import (reference) '~antd/es/style/themes/index';
 
-.welcome {
-  margin: 100px 0;
-  text-align: center;
-  .img_style {
-    width: 500px;
-  }
-  .welcome_text {
-    color: #999;
-    font-size: 16px;
+.statistic {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 15px;
+  .num_style {
+    position: relative;
+    width: 49.5%;
+    height: 128px;
+    padding: 0 30px;
+    background: #fff;
+    .title {
+      margin-top: 30px;
+      font-weight: bold;
+      font-size: 13px;
+    }
+    .num {
+      font-weight: bold;
+      font-size: 35px;
+    }
+    .statistic_icon {
+      position: absolute;
+      top: 0;
+      right: 0;
+    }
   }
 }
+.device_status {
+  margin-bottom: 10px;
+  padding-bottom: 10px;
+  font-weight: bold;
+  font-size: 20px;
+  border-bottom: 1px solid #efefef;
+}

+ 39 - 10
src/pages/Welcome.tsx

@@ -1,25 +1,54 @@
 import { PageContainer } from '@ant-design/pro-components';
 import { Card } from 'antd';
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 import styles from './Welcome.less';
-// import StatisticIndex from '../pages/statistical/index';
+import StatisticIndex from '../pages/statistical/index';
+import { getStatisticData } from '@/services/statistic';
 
 /**
- * 欢迎首页
+ * 首页
  * @constructor
  */
 const Welcome: React.FC = () => {
+  const [data, setData] = useState<any>(null);
+
+  // 获取数据
+  const getData = () => {
+    getStatisticData().then((res) => {
+      if (res?.code === 0) {
+        setData(res.data);
+      }
+    });
+  };
+
+  // 初始化
+  useEffect(() => {
+    getData();
+  }, []);
+
   return (
     <PageContainer>
-      <Card>
-        {/*<StatisticIndex />*/}
-        <div style={{ width: '100%' }} className={styles.welcome}>
-          <img src="/assets/welcome.png" className={styles.img_style} alt="" />
-          <div className={styles.welcome_text} style={{ marginTop: '10px' }}>
-            WELCOME
+      <div className={styles.statistic}>
+        <div className={styles.num_style}>
+          <div className={styles.title}>注册用户</div>
+          <div>
+            <span className={styles.num}>{data?.user_count}</span>
+            <span style={{ fontSize: '12px', marginLeft: '5px' }}>人</span>
           </div>
-          <div className={styles.welcome_text}>欢迎进入永续绿建管理平台</div>
+          <img src="/assets/user.png" alt="用户" className={styles.statistic_icon} />
         </div>
+        <div className={styles.num_style}>
+          <div className={styles.title}>设备数</div>
+          <div>
+            <span className={styles.num}>{data?.device_offline + data?.device_online}</span>
+            <span style={{ fontSize: '12px', marginLeft: '5px' }}>个</span>
+          </div>
+          <img src="/assets/device.png" alt="设备" className={styles.statistic_icon} />
+        </div>
+      </div>
+      <Card>
+        <div className={styles.device_status}>设备状态</div>
+        {data && <StatisticIndex data={data} />}
       </Card>
     </PageContainer>
   );

+ 2 - 2
src/pages/setting/UserManagement/check.tsx

@@ -57,8 +57,8 @@ const Check: React.FC<userCheckPros> = (props) => {
   return (
     <Modal title="查看" open={visible} onOk={onOk} onCancel={onCancel} width={1000}>
       <Descriptions title="用户信息" bordered column={2}>
-        <Descriptions.Item label="用户名">{dataDetail?.user_name}</Descriptions.Item>
-        <Descriptions.Item label="真实姓名">{dataDetail?.real_name}</Descriptions.Item>
+        <Descriptions.Item label="用户名">{dataDetail?.user_name}</Descriptions.Item>
+        {/*<Descriptions.Item label="真实姓名">{dataDetail?.real_name}</Descriptions.Item>*/}
         <Descriptions.Item label="手机号">{dataDetail?.phone}</Descriptions.Item>
         <Descriptions.Item label="状态">
           <span style={{ color: `${{ 1: '#00a650', 2: 'red' }[dataDetail?.status]}` }}>

+ 11 - 11
src/pages/setting/UserManagement/edit.tsx

@@ -158,17 +158,17 @@ const Edit: React.FC<userEditPros> = (props) => {
               <Input type="password" placeholder="请输入密码" />
             </Form.Item>
           </Col>
-          <Col span={12}>
-            <Form.Item
-              {...formItemLayout}
-              name="real_name"
-              label="真实姓名"
-              rules={[{ required: true, message: '请输入真实姓名' }]}
-              initialValue={params?.real_name}
-            >
-              <Input placeholder="请输入真实姓名" />
-            </Form.Item>
-          </Col>
+          {/*<Col span={12}>*/}
+          {/*  <Form.Item*/}
+          {/*    {...formItemLayout}*/}
+          {/*    name="real_name"*/}
+          {/*    label="真实姓名"*/}
+          {/*    rules={[{ required: true, message: '请输入真实姓名' }]}*/}
+          {/*    initialValue={params?.real_name}*/}
+          {/*  >*/}
+          {/*    <Input placeholder="请输入真实姓名" />*/}
+          {/*  </Form.Item>*/}
+          {/*</Col>*/}
           <Col span={12}>
             <Form.Item
               {...formItemLayout}

+ 6 - 6
src/pages/setting/UserManagement/index.tsx

@@ -171,15 +171,15 @@ const UserManagement: React.FC = () => {
       render: (v) => v && <Image width={50} src={v} alt="头像" />,
     },
     {
-      title: '用户名',
+      title: '用户名',
       dataIndex: 'user_name',
       key: 'user_name',
     },
-    {
-      title: '真实姓名',
-      dataIndex: 'real_name',
-      key: 'real_name',
-    },
+    // {
+    //   title: '真实姓名',
+    //   dataIndex: 'real_name',
+    //   key: 'real_name',
+    // },
     {
       title: '手机号',
       dataIndex: 'phone',

+ 26 - 17
src/pages/statistical/index.tsx

@@ -1,28 +1,39 @@
 import * as echarts from 'echarts';
 import React, { useEffect, useRef } from 'react';
 
-const Statistical: React.FC = () => {
-  const chartRef: any = useRef();
+interface editPros {
+  data: any;
+}
 
+const Statistical: React.FC<editPros> = (props) => {
+  const chartRef: any = useRef();
+  const { data } = props;
   const options = {
-    // 标题
     title: {
-      text: '柱状图',
+      left: 'center',
     },
-    // x轴
-    xAxis: {
-      type: 'category',
-      data: ['冬瓜', '茄子', '丝瓜', '玉米', '红薯', '西红柿', '芹菜'],
+    tooltip: {
+      trigger: 'item',
     },
-    // y轴
-    yAxis: {
-      type: 'value',
+    legend: {
+      orient: 'vertical',
+      left: 'left',
     },
     series: [
       {
-        data: [20, 9, 39, 43, 60, 18, 50],
-        type: 'bar', // 柱状图
-        name: '销量',
+        type: 'pie',
+        radius: '50%',
+        data: [
+          { value: data?.device_online, name: '在线' },
+          { value: data?.device_offline, name: '离线' },
+        ],
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)',
+          },
+        },
       },
     ],
   };
@@ -30,10 +41,8 @@ const Statistical: React.FC = () => {
   useEffect(() => {
     // 创建一个echarts实例,返回echarts实例。不能在单个容器中创建多个echarts实例
     const chart = echarts.init(chartRef.current);
-
     // 设置图表实例的配置项和数据
     chart.setOption(options);
-
     // 组件卸载
     return () => {
       chart.dispose();
@@ -42,7 +51,7 @@ const Statistical: React.FC = () => {
 
   return (
     <div>
-      <div style={{ width: '600px', height: '400px' }} ref={chartRef}></div>
+      <div style={{ width: '600px', height: '400px' }} ref={chartRef} />
     </div>
   );
 };

+ 3 - 3
src/pages/user/Login/index.tsx

@@ -113,14 +113,14 @@ const Login: React.FC = () => {
           </div>
           <Form layout="vertical" onFinish={handleSubmit}>
             <FormItem
-              rules={[{ required: true, message: '请输入用户名!' }]}
+              rules={[{ required: true, message: '请输入手机号!' }]}
               className={styles.formItem}
-              name="user_name"
+              name="phone"
             >
               <Input
                 className={styles.formItemInput}
                 size="large"
-                placeholder="请输入用户名"
+                placeholder="请输入手机号"
                 prefix={<UserOutlined />}
                 allowClear
               />

+ 8 - 0
src/services/statistic.ts

@@ -0,0 +1,8 @@
+import { request } from '@@/plugin-request/request';
+
+/**
+ * 首页数据统计
+ */
+export async function getStatisticData() {
+  return request(`/web/v1/statistic/user`);
+}