Your Name преди 2 години
родител
ревизия
bda3aebaad

+ 2
- 1
.eslintrc Целия файл

3
   "rules": {
3
   "rules": {
4
     "react/jsx-uses-react": "off",
4
     "react/jsx-uses-react": "off",
5
     "react/react-in-jsx-scope": "off",
5
     "react/react-in-jsx-scope": "off",
6
-    "no-unused-vars": "warn"
6
+    "no-unused-vars": "warn",
7
+    "jsx-quotes": ["warn", "prefer-double"]
7
   }
8
   }
8
 }
9
 }

+ 1
- 1
babel.config.js Целия файл

13
       {
13
       {
14
         libraryName: "@antmjs/vantui",
14
         libraryName: "@antmjs/vantui",
15
         libraryDirectory: "es",
15
         libraryDirectory: "es",
16
-        style: true
16
+        style: (name) => `${name}/style/less`,
17
       },
17
       },
18
       "@antmjs/vantui"
18
       "@antmjs/vantui"
19
     ]
19
     ]

+ 2
- 1
config/dev.js Целия файл

3
     NODE_ENV: '"development"'
3
     NODE_ENV: '"development"'
4
   },
4
   },
5
   defineConstants: {
5
   defineConstants: {
6
-    HOST: '"http://192.168.89.147:9087"'
6
+    // HOST: '"http://127.0.0.1:9087"'
7
+    HOST: '"http://192.168.1.2:9087"'
7
   },
8
   },
8
   mini: {},
9
   mini: {},
9
   h5: {}
10
   h5: {}

+ 1
- 0
package.json Целия файл

48
     "@tarojs/taro": "3.5.7",
48
     "@tarojs/taro": "3.5.7",
49
     "@tarojs/taro-h5": "3.5.7",
49
     "@tarojs/taro-h5": "3.5.7",
50
     "@zjxpcyc/react-tiny-store": "^2.0.1",
50
     "@zjxpcyc/react-tiny-store": "^2.0.1",
51
+    "md5": "^2.3.0",
51
     "react": "^18.0.0",
52
     "react": "^18.0.0",
52
     "react-dom": "^18.0.0"
53
     "react-dom": "^18.0.0"
53
   },
54
   },

+ 3
- 3
src/app.config.js Целия файл

1
 export default defineAppConfig({
1
 export default defineAppConfig({
2
   pages: [
2
   pages: [
3
-    'pages/login/index',
4
     'pages/home/index',
3
     'pages/home/index',
4
+    'pages/login/index',
5
     'pages/index3/index',
5
     'pages/index3/index',
6
     'pages/index4/index',
6
     'pages/index4/index',
7
     'pages/index5/index',
7
     'pages/index5/index',
11
   tabBar: {
11
   tabBar: {
12
     list: [
12
     list: [
13
       {
13
       {
14
-        "pagePath": "pages/login/index",
14
+        "pagePath": "pages/home/index",
15
         "text": "首页"
15
         "text": "首页"
16
       },
16
       },
17
       {
17
       {
18
-        "pagePath": "pages/home/index",
18
+        "pagePath": "pages/reporting/index",
19
         "text": "公告"
19
         "text": "公告"
20
       },
20
       },
21
       {
21
       {

+ 3
- 1
src/app.js Целия файл

10
       success: (res) => {
10
       success: (res) => {
11
         store.getState('user').login(res.code);
11
         store.getState('user').login(res.code);
12
       }
12
       }
13
-    })
13
+    });
14
+
15
+    store.getState('user').current();
14
   });
16
   });
15
 
17
 
16
   return (
18
   return (

+ 4
- 3
src/app.less Целия файл

7
   --main-space: 4vw;
7
   --main-space: 4vw;
8
 
8
 
9
   // antm-js 样式修改
9
   // antm-js 样式修改
10
-  // 按钮主色
11
-  --buttonPrimaryBackgroundColor: #1A7565;
10
+  // 按钮
11
+  --button-primary-color: #FFFFFF;
12
+  --button-primary-background-color: var(--main-bg-color);
12
   // 菊花转主色
13
   // 菊花转主色
13
-  --loading-spinner-color: #1A7565;
14
+  --loading-spinner-color: var(--main-bg-color);
14
 }
15
 }
15
 
16
 
16
 view {
17
 view {

+ 1
- 1
src/components/Auth.jsx Целия файл

20
     }
20
     }
21
   }
21
   }
22
 
22
 
23
-  return hasRights ? props.children : (
23
+  return !roles.length || hasRights ? props.children : (
24
     <View style={{width: '100%', height: '100%', display: 'grid', placeItems: 'center'}}>
24
     <View style={{width: '100%', height: '100%', display: 'grid', placeItems: 'center'}}>
25
       <View>暂无权限</View>
25
       <View>暂无权限</View>
26
     </View>
26
     </View>

+ 23
- 2
src/layouts/index.jsx Целия файл

1
 import React from 'react';
1
 import React from 'react';
2
+import Taro from '@tarojs/taro';
2
 import { View } from '@tarojs/components';
3
 import { View } from '@tarojs/components';
3
 import { useModel } from '@/store';
4
 import { useModel } from '@/store';
4
 import { Loading } from '@antmjs/vantui';
5
 import { Loading } from '@antmjs/vantui';
6
 import laySty from './layout.module.less';
7
 import laySty from './layout.module.less';
7
 
8
 
8
 export default (props) => {
9
 export default (props) => {
9
-  const { className, style, roles } = props;
10
+  const { className, style, roles, showTabBar } = props;
10
 
11
 
11
-  const { person } = useModel('user');
12
+  const { person, user } = useModel('user');
12
 
13
 
13
   const classNames = `${laySty['page-wrapper']} ${className}`;
14
   const classNames = `${laySty['page-wrapper']} ${className}`;
14
 
15
 
16
+  React.useMemo(() => {
17
+    if (showTabBar) {
18
+      Taro.showTabBar();
19
+    } else {
20
+      Taro.hideTabBar();
21
+    }
22
+  }, [showTabBar]);
23
+
24
+  React.useEffect(() => {
25
+    console.log('----------->', person, user);
26
+    if (person && !user) {
27
+      const currentPage = Taro.getCurrentPages().slice().pop();      
28
+      if ('pages/login/index' !== currentPage.route) {
29
+        Taro.navigateTo({
30
+          url: '/pages/login/index',
31
+        })
32
+      }
33
+    }
34
+  }, [person, user]);
35
+
15
   return (
36
   return (
16
     <View className={classNames} style={style}>
37
     <View className={classNames} style={style}>
17
       {
38
       {

+ 7
- 2
src/pages/home/components/Head.jsx Целия файл

1
 import React from 'react';
1
 import React from 'react';
2
 import { View } from '@tarojs/components';
2
 import { View } from '@tarojs/components';
3
+import { ROLES, ROLE_CITIZEN } from '@/utils/user';
3
 import style from './head.module.less';
4
 import style from './head.module.less';
4
 
5
 
5
 export default (props) => {
6
 export default (props) => {
7
+  const { user = {} } = props;
8
+  const { dutyList = [] } = user;
9
+  const role = ROLES[dutyList[0] || ROLE_CITIZEN];
10
+
6
   return (
11
   return (
7
     <View className={style.head}>
12
     <View className={style.head}>
8
       <View className={style.profile}>
13
       <View className={style.profile}>
9
-        <View>Hi, 张三!</View>
14
+        <View style={{ letterSpacing: '2px' }}>Hi, {user.name}!</View>
10
         <View className={style.badge}>
15
         <View className={style.badge}>
11
           <View className={style.icon}></View>
16
           <View className={style.icon}></View>
12
-          <View>督察员</View>
17
+          <View>{role}</View>
13
         </View>
18
         </View>
14
       </View>
19
       </View>
15
       <View className={style.avatar}>
20
       <View className={style.avatar}>

+ 23
- 8
src/pages/home/components/head.module.less Целия файл

14
     font-size: 42px;
14
     font-size: 42px;
15
 
15
 
16
     .badge {
16
     .badge {
17
+      display: inline-block;
17
       position: relative;
18
       position: relative;
18
-      padding-left: 64px;
19
+      padding-right: 24px;
20
+      padding-left: 72px;
19
       margin-top: var(--main-space);
21
       margin-top: var(--main-space);
20
       height: 48px;
22
       height: 48px;
21
-      line-height: 48px;
23
+      line-height: 46px; // 向上偏移2像素
22
       background: linear-gradient(0, #E36A00, #FFA658);
24
       background: linear-gradient(0, #E36A00, #FFA658);
23
       border-radius: 22px;
25
       border-radius: 22px;
24
       font-size: 24px;
26
       font-size: 24px;
27
+      text-align: center;
25
 
28
 
26
       .icon {
29
       .icon {
27
-        top: -8px;
28
-        left: -8px;
30
+        top: -12px;
31
+        left: -12px;
29
         position: absolute;
32
         position: absolute;
30
-        width: 64px;
31
-        height: 64px;
32
-        background: linear-gradient(0, #E36A00, #FFA658);
33
+        width: 56px;
34
+        height: 56px;
35
+        border: 8px solid rgba(251, 239, 121, 0.6);
33
         border-radius: 50%;
36
         border-radius: 50%;
34
-        border: 8px solid rgba(251, 239, 121, 0.2);
37
+        box-sizing: content-box;
38
+
39
+        &::before {
40
+          content: '';
41
+          position: absolute;
42
+          top: 0;
43
+          left: 0;
44
+          width: 56px;
45
+          height: 56px;
46
+          background: linear-gradient(0, #E36A00, #FFA658);
47
+          border-radius: 50%;
48
+          overflow: hidden;
49
+        }
35
       }
50
       }
36
     }
51
     }
37
   }
52
   }

+ 6
- 2
src/pages/home/index.jsx Целия файл

1
 import React from 'react'
1
 import React from 'react'
2
 import { View, Text, Image } from '@tarojs/components'
2
 import { View, Text, Image } from '@tarojs/components'
3
 import Page from '@/layouts/index';
3
 import Page from '@/layouts/index';
4
+import { useModel } from '@/store';
4
 import Head from './components/Head';
5
 import Head from './components/Head';
5
 import BannerCard from './components/BannerCard';
6
 import BannerCard from './components/BannerCard';
6
 import MenuCard from './components/MenuCard';
7
 import MenuCard from './components/MenuCard';
7
 import './index.less';
8
 import './index.less';
8
 
9
 
9
 export default (props) => {
10
 export default (props) => {
11
+
12
+  const { user } = useModel('user');
13
+
10
   return (
14
   return (
11
-    <Page className='index'>
12
-      <Head />
15
+    <Page showTabBar className='index'>
16
+      <Head user={user} />
13
       <BannerCard />
17
       <BannerCard />
14
       <MenuCard />
18
       <MenuCard />
15
     </Page>
19
     </Page>

+ 70
- 24
src/pages/login/components/Form.jsx Целия файл

1
 import React from 'react';
1
 import React from 'react';
2
-import { View, Image, Input } from '@tarojs/components';
3
-import { Form, Button } from '@antmjs/vantui'
4
-import user from '../../../assets/image/user.png';
5
-import password from '../../../assets/image/password.png';
6
-import style from './form.module.less';
2
+import { View } from '@tarojs/components';
3
+import { Form, FormItem, Field, Button } from '@antmjs/vantui'
4
+import { useModel } from '@/store';
5
+import user from '@/assets/image/user.png';
6
+import password from '@/assets/image/password.png';
7
+import './form.less';
7
 
8
 
8
 export default (props) => {
9
 export default (props) => {
10
+  const { onSuccess } = props;
11
+
12
+  const { signin } = useModel('user');
13
+  const form = Form.useForm();
14
+  const [accErr, setAccErr] = React.useState();
15
+  const [pwdErr, setPwdErr] = React.useState();
16
+
17
+  const onFinish = (errs, res) => {
18
+    if (!res.account) {
19
+      setAccErr('账户不能为空');
20
+      return;
21
+    } else {
22
+      setAccErr();
23
+    }
24
+    if (!res.password) {
25
+      setPwdErr('密码不能为空');
26
+      return;
27
+    } else {
28
+      setPwdErr();
29
+    }
30
+
31
+    signin(res).then(onSuccess);
32
+  }
33
+
9
   return (
34
   return (
10
-    <Form className={style.form}>
11
-      <View className={style['input-box']}>
12
-        <Image src={user} className={style['img-icon']} />账号<Input className={style.input} placeholder='请输入您的登录账号' />
13
-      </View>
14
-      <View className={style['input-box']}>
15
-        <Image src={password} className={style['img-icon']} />密码<Input className={style.input} placeholder='请输入您的登录密码' />
16
-      </View>
17
-      <View
18
-        className={style['forget-pwd']}
19
-      >
20
-        忘记密码?
21
-      </View>
22
-      <Button
23
-        type='primary'
24
-        className={style.submit}
25
-      >
26
-        登录
27
-      </Button>
28
-    </Form>
35
+    <View className="login-form">
36
+      <Form form={form} onFinish={onFinish}>
37
+        <FormItem
38
+          name="account"
39
+          valueFormat={(e) => e.detail}
40
+        >
41
+          <Field
42
+            border
43
+            label="账号"
44
+            leftIcon={user}
45
+            errorMessage={accErr}
46
+            placeholder="请输入您的登录账号"
47
+          ></Field>
48
+        </FormItem>
49
+        <FormItem
50
+          name="password"
51
+          valueFormat={(e) => e.detail}
52
+        >
53
+          <Field
54
+            password
55
+            label="密码"
56
+            leftIcon={password}
57
+            errorMessage={pwdErr}
58
+            placeholder="请输入您的登录密码"
59
+          ></Field>
60
+        </FormItem>
61
+        <View className="forget-password">
62
+          忘记密码?
63
+        </View>
64
+        <View>
65
+          <Button
66
+            block
67
+            type="primary"
68
+            formType="submit"
69
+          >
70
+            登录
71
+          </Button>
72
+        </View>
73
+      </Form>
74
+    </View>
29
   )
75
   )
30
 }
76
 }

+ 63
- 0
src/pages/login/components/form.less Целия файл

1
+.login-form {
2
+  width: 100%;
3
+  box-sizing: border-box;
4
+  padding: 0 var(--main-space);
5
+
6
+  .vant-form-formItem,
7
+  .vant-form-formItem-wrapper,
8
+  .vant-form-formItem-controll {
9
+    margin: 0;
10
+    padding: 0;
11
+    background-color: transparent;
12
+  }
13
+
14
+  .vant-form-formItem-wrapper {
15
+    & + .vant-form-formItem-wrapper {
16
+      margin-top: var(--main-space);
17
+    }
18
+  }
19
+
20
+  .vant-form-label {
21
+    width: 0;
22
+  }
23
+
24
+  .field-wrapper {
25
+    width: 100%;
26
+    padding: 0 var(--main-space);
27
+  }
28
+
29
+  .van-cell {
30
+    background-color: transparent;
31
+
32
+    &::after {
33
+      border-bottom-color: rgba(0,0,0,0.12);
34
+    }
35
+  }
36
+
37
+  .van-icon__image {
38
+    width: 42px;
39
+    height: 42px;
40
+    vertical-align: middle;
41
+  }
42
+
43
+  .van-cell__title {
44
+    margin-left: 20px;
45
+    font-size: 16px;
46
+    vertical-align: middle;
47
+    border-right: 1px solid #000;
48
+  }
49
+
50
+  .van-field__label {
51
+    font-size: 32px;
52
+  }
53
+
54
+  .forget-password {
55
+    text-align: right;
56
+    font-size: 28px;
57
+    font-weight: 400;
58
+    color: var(--main-bg-color);
59
+    height: 148px;
60
+    line-height: 148px;
61
+    padding: 0 var(--main-space);
62
+  }
63
+}

+ 0
- 36
src/pages/login/components/form.module.less Целия файл

1
-.form {
2
-  width: 620px;
3
-  .input-box {
4
-    display: flex;
5
-    border-bottom: 1px solid #e9eaea;
6
-    width: 600px;
7
-    margin: 26px auto;
8
-    padding-bottom: 30px;
9
-    margin-top: 60px;
10
-    .img-icon {
11
-      margin-right: 30px;
12
-      width: 42px;
13
-      height: 44px;
14
-    }
15
-    .input {
16
-      color: rgb(174, 174, 174);
17
-      margin-left: 15px;
18
-      padding-left: 20px;
19
-      flex-direction: column;
20
-      border-left: 1px solid black;
21
-    }
22
-  }
23
-  .forget-pwd {
24
-    font-size: 28px;
25
-    color: var(--main-bg-color);
26
-    float: right;
27
-    margin-right: 72px;
28
-    margin-bottom: 104px;
29
-  }
30
-  .submit {
31
-    width: 666px;
32
-    margin: 80px auto;
33
-    background-color: var(--main-bg-color);
34
-    color: #fff;
35
-  }
36
-}

+ 22
- 5
src/pages/login/index.jsx Целия файл

1
-import Page from '@/layouts/index';
1
+import React from 'react';
2
+import Taro from '@tarojs/taro';
2
 import { View } from '@tarojs/components';
3
 import { View } from '@tarojs/components';
4
+import Page from '@/layouts/index';
3
 import Head from "./components/Head";
5
 import Head from "./components/Head";
4
 import Form from "./components/Form";
6
 import Form from "./components/Form";
5
 import Bottom from "./components/Bottom";
7
 import Bottom from "./components/Bottom";
6
 import './index.less'
8
 import './index.less'
7
 
9
 
8
 export default (props) => {
10
 export default (props) => {
11
+
12
+  React.useMemo(() => {  
13
+    Taro.hideTabBar();
14
+  }, []);
15
+
16
+  const onSuccess = () => {
17
+    Taro.navigateBack({
18
+      delta: 1,
19
+      fail: () => {
20
+        Taro.reLaunch({
21
+          url: '/pages/home/index'
22
+        })
23
+      }
24
+    });
25
+  }
26
+
9
   return (
27
   return (
10
-    <Page className='index'>
11
-      <View className='login-box'>
28
+    <Page className="index">
29
+      <View className="login-box">
12
         <Head />
30
         <Head />
13
-        <Form />
31
+        <Form onSuccess={onSuccess} />
14
         <Bottom />
32
         <Bottom />
15
       </View>
33
       </View>
16
     </Page>
34
     </Page>
17
-
18
   )
35
   )
19
 }
36
 }

+ 10
- 0
src/services/wxma.js Целия файл

14
  * 小程序登录
14
  * 小程序登录
15
  */
15
  */
16
 export const login = (code) => request(`/api/ma/login?code=${code}`, { method: 'post', silent: true });
16
 export const login = (code) => request(`/api/ma/login?code=${code}`, { method: 'post', silent: true });
17
+
18
+/*
19
+ * 小程序登录
20
+ */
21
+export const signin = (data) => request(`/api/ma/signin`, { method: 'post', data });
22
+
23
+/*
24
+ * 获取当前人员
25
+ */
26
+export const currentUser = () => request(`/api/ma/current`);

+ 24
- 4
src/store/user.js Целия файл

1
 import React from 'react';
1
 import React from 'react';
2
 import Taro from '@tarojs/taro';
2
 import Taro from '@tarojs/taro';
3
-import { login } from '@/services/wxma';
3
+import md5 from 'md5';
4
+import { login, signin, currentUser } from '@/services/wxma';
4
 
5
 
5
 export default function useUser() {
6
 export default function useUser() {
6
-  const [person, setPerson] = React.useState({});
7
-  const [user, setUser] = React.useState({});
7
+  const [person, setPerson] = React.useState();
8
+  const [user, setUser] = React.useState();
8
 
9
 
9
   const maLogin = (code) => {
10
   const maLogin = (code) => {
10
     login(code).then(res => {
11
     login(code).then(res => {
11
       setPerson(res.person);
12
       setPerson(res.person);
12
-      setUser(res.user);
13
+      Taro.setStorage({ key: 'personId', data: res.person.personId })
13
       Taro.setStorage({ key: 'sessionKey', data: res.sessionKey })
14
       Taro.setStorage({ key: 'sessionKey', data: res.sessionKey })
14
     });
15
     });
15
   }
16
   }
16
 
17
 
18
+  const maSignIn = (params) => {
19
+    const data = {
20
+      ...params,
21
+      password: md5(params.password)
22
+    }
23
+
24
+    return signin(data).then(res => {
25
+      setUser(res.user);
26
+    })
27
+  }
28
+
29
+  const current = () => {
30
+    currentUser().then(res => {
31
+      setUser(res.user);
32
+    })
33
+  }
34
+
17
   return {
35
   return {
18
     user,
36
     user,
19
     person,
37
     person,
38
+    current,
39
+    signin: maSignIn,
20
     login: maLogin,
40
     login: maLogin,
21
   }
41
   }
22
 }
42
 }

+ 3
- 1
src/utils/request.js Целия файл

16
     const { method = 'GET', params, data = {}, header = {}, silent = false, ...cfgs } = options;
16
     const { method = 'GET', params, data = {}, header = {}, silent = false, ...cfgs } = options;
17
     const queryStr = params ? getQueryStrByParams(params) : undefined;
17
     const queryStr = params ? getQueryStrByParams(params) : undefined;
18
     // eslint-disable-next-line no-undef
18
     // eslint-disable-next-line no-undef
19
-    const url = queryStr ? `${HOST}${api}?${queryStr}` : `${HOST}${api}`
19
+    const url = queryStr ? `${HOST}${api}?${queryStr}` : `${HOST}${api}`;
20
+    const personId = Taro.getStorageSync('personId');
20
     
21
     
21
     const onError = (err) => {
22
     const onError = (err) => {
22
       console.error(err);
23
       console.error(err);
39
       data,
40
       data,
40
       method,
41
       method,
41
       header: {
42
       header: {
43
+        'x-personId': personId,
42
         'content-type': 'application/json',
44
         'content-type': 'application/json',
43
         'authorization': getToken(),
45
         'authorization': getToken(),
44
         ...header,
46
         ...header,

+ 9
- 0
src/utils/user.js Целия файл

13
 
13
 
14
 // 市民
14
 // 市民
15
 export const ROLE_CITIZEN = 'citizen';
15
 export const ROLE_CITIZEN = 'citizen';
16
+
17
+
18
+export const ROLES = {
19
+  [ROLE_INSPECTOR]: '督察员',
20
+  [ROLE_MANAGER]: '管理员',
21
+  [ROLE_ORG_USER]: '单位人员',
22
+  [ROLE_QUERY_PERSON]: '查询员',
23
+  [ROLE_CITIZEN]: '市民',
24
+}

+ 1
- 1
yarn.lock Целия файл

8180
 
8180
 
8181
 md5@^2.3.0:
8181
 md5@^2.3.0:
8182
   version "2.3.0"
8182
   version "2.3.0"
8183
-  resolved "https://registry.npmmirror.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
8183
+  resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
8184
   integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
8184
   integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
8185
   dependencies:
8185
   dependencies:
8186
     charenc "0.0.2"
8186
     charenc "0.0.2"