fangmingyue 2 лет назад
Родитель
Сommit
f770a04b4c
34 измененных файлов: 531 добавлений и 214 удалений
  1. 1
    0
      config/dev.js
  2. 1
    0
      config/prod.js
  3. 2
    2
      src/app.config.js
  4. 5
    2
      src/components/Icon.jsx
  5. 14
    2
      src/components/MenuIcon.jsx
  6. 9
    2
      src/components/PowerList/index.jsx
  7. 81
    41
      src/components/map/index.jsx
  8. 2
    2
      src/components/map/style.module.less
  9. 2
    1
      src/layouts/index.jsx
  10. 17
    11
      src/pages/check/edit/components/LocForm.jsx
  11. 1
    1
      src/pages/check/edit/index.jsx
  12. 5
    4
      src/pages/check/loc/edit/components/LocForm.jsx
  13. 2
    1
      src/pages/feedback/issue/index.jsx
  14. 17
    6
      src/pages/home/index.jsx
  15. 2
    1
      src/pages/issue/components/Issue/index.jsx
  16. 35
    2
      src/pages/my/components/Head/index.jsx
  17. 82
    0
      src/pages/my/components/ResetPwd/index.jsx
  18. 7
    5
      src/pages/my/index.jsx
  19. 0
    20
      src/pages/reporting/detail/components/Issue.jsx
  20. 0
    17
      src/pages/reporting/detail/components/Map.jsx
  21. 0
    21
      src/pages/reporting/detail/components/issue.module.less
  22. 0
    16
      src/pages/reporting/detail/components/map.module.less
  23. 0
    3
      src/pages/reporting/detail/index.config.js
  24. 0
    41
      src/pages/reporting/detail/index.jsx
  25. 0
    3
      src/pages/reporting/index.config.js
  26. 0
    9
      src/pages/reporting/index.jsx
  27. 112
    0
      src/pages/user/add/index.jsx
  28. 4
    0
      src/pages/user/list/index.config.js
  29. 82
    0
      src/pages/user/list/index.jsx
  30. 12
    0
      src/pages/user/list/index.module.less
  31. 21
    0
      src/services/sysuser.js
  32. 2
    0
      src/services/taissueapply.js
  33. 11
    0
      src/store/user.js
  34. 2
    1
      src/utils/authorize.js

+ 1
- 0
config/dev.js Просмотреть файл

@@ -6,6 +6,7 @@ module.exports = {
6 6
     // HOST: '"http://127.0.0.1:9087"',
7 7
     HOST: '"http://localhost:9087"',
8 8
     AD_IMAGE: '"https://h5.njyunzhi.com/images/citizen_banner.png"',
9
+    DEFAULT_POS: '"116.3476917447715,31.409912844296578"', // 霍山县人民政府 gcj02
9 10
   },
10 11
   mini: {},
11 12
   h5: {},

+ 1
- 0
config/prod.js Просмотреть файл

@@ -5,6 +5,7 @@ module.exports = {
5 5
   defineConstants: {
6 6
     HOST: '"https://t.njyz.tech"',
7 7
     AD_IMAGE: '"https://h5.njyunzhi.com/images/citizen_banner.png"',
8
+    DEFAULT_POS: '"116.3476917447715,31.409912844296578"', // 霍山县人民政府 gcj02
8 9
   },
9 10
   mini: {},
10 11
   h5: {

+ 2
- 2
src/app.config.js Просмотреть файл

@@ -16,8 +16,6 @@ export default defineAppConfig({
16 16
     // 'pages/checkStand/index',
17 17
     "pages/checkStand/list/index",
18 18
     "pages/checkStand/detail/index",
19
-    "pages/reporting/index",
20
-    "pages/reporting/detail/index",
21 19
     "pages/reset-password/index",
22 20
     "pages/check/list/index",
23 21
     "pages/check/loc/list/index",
@@ -28,6 +26,8 @@ export default defineAppConfig({
28 26
     "pages/my/edit/index",
29 27
     "pages/feedback/issue/index",
30 28
     "pages/feedback/issuelist/index",
29
+    "pages/user/list/index",
30
+    "pages/user/add/index",
31 31
   ],
32 32
   subpackages: [
33 33
     {

+ 5
- 2
src/components/Icon.jsx Просмотреть файл

@@ -1,6 +1,7 @@
1 1
 import React from 'react';
2 2
 import Taro from '@tarojs/taro';
3 3
 import { Image } from '@tarojs/components';
4
+import { Icon } from '@antmjs/vantui';
4 5
 import icon1 from '@/assets/icons/icon1.png';
5 6
 import icon2 from '@/assets/icons/icon2.png';
6 7
 import icon3 from '@/assets/icons/icon3.png';
@@ -13,6 +14,7 @@ import icon9 from '@/assets/icons/icon9.png';
13 14
 import icon10 from '@/assets/icons/icon10.png';
14 15
 import icon11 from '@/assets/icons/icon11.png';
15 16
 import icon12 from '@/assets/icons/icon12.png';
17
+import person from '@/assets/icons/peopleicon.png';
16 18
 
17 19
 const icons = {
18 20
   icon1,
@@ -27,12 +29,13 @@ const icons = {
27 29
   icon10,
28 30
   icon11,
29 31
   icon12,
32
+  person,
30 33
 }
31 34
 
32 35
 export default (props) => {
33
-  const { className, style, name } = props;
36
+  const { className, style, name, info } = props;
34 37
   
35 38
   return (
36
-    <Image src={icons[name]} className={className} style={style} />
39
+    <Icon name={icons[name]} className={className} style={style} info={info} />
37 40
   )
38 41
 }

+ 14
- 2
src/components/MenuIcon.jsx Просмотреть файл

@@ -27,7 +27,9 @@ const txtStyle = {
27 27
 
28 28
 export default (props) => {
29 29
   
30
-  const { icon, text, link } = props;
30
+  const { icon, text, link, request } = props;
31
+
32
+  const [info, setInfo] = React.useState();
31 33
 
32 34
   const onClick = () => {
33 35
     Taro.navigateTo({
@@ -35,11 +37,21 @@ export default (props) => {
35 37
     })
36 38
   }
37 39
 
40
+  React.useEffect(() => {
41
+    if (request) {
42
+      request().then(res => {
43
+        if (res) {
44
+          res > 99 ? setInfo('99+') : setInfo(res);
45
+        }
46
+      });
47
+    }
48
+  }, [request]);
49
+
38 50
   return (
39 51
     <RatioView>
40 52
       <View style={wrapperStyle} onClick={onClick}>
41 53
         <View>
42
-          <Icon name={icon} style={iconStyle} />
54
+          <Icon name={icon} style={iconStyle} info={info} />
43 55
           <View style={txtStyle}>{text}</View>
44 56
         </View>
45 57
       </View>

+ 9
- 2
src/components/PowerList/index.jsx Просмотреть файл

@@ -3,7 +3,7 @@ import Taro from '@tarojs/taro';
3 3
 import { View } from '@tarojs/components';
4 4
 import { PowerScrollView } from '@antmjs/vantui';
5 5
 
6
-export default (props) => {
6
+export default React.forwardRef((props, ref) => {
7 7
   const { request, params, renderItem, onLoadingChange } = props;
8 8
 
9 9
   const pageSize = 20;
@@ -56,6 +56,13 @@ export default (props) => {
56 56
     pageNumRef.current = 1;
57 57
     queryData({pageNum : pageNumRef.current});
58 58
   }, [queryData]);
59
+
60
+  React.useImperativeHandle(ref, () => ({
61
+    refresh: () => {
62
+      pageNumRef.current = 1;
63
+      queryData({pageNum : pageNumRef.current});
64
+    }
65
+  }));
59 66
   
60 67
   return (
61 68
     <PowerScrollView
@@ -72,4 +79,4 @@ export default (props) => {
72 79
       }
73 80
     </PowerScrollView>
74 81
   )
75
-}
82
+})

+ 81
- 41
src/components/map/index.jsx Просмотреть файл

@@ -6,66 +6,106 @@ import { getLocation } from '@/utils/authorize';
6 6
 import iconPath from '@/assets/icons/marker.png';
7 7
 import style from './style.module.less';
8 8
 
9
-// location 逻辑
10
-// 如果 props.location 有值, 那么放弃地图定位的点, 使用 props.location
11
-// 否则使用 地图定位的点
12
-// 如果地图定位失败 或者 props.location 为空, 那么不产生数据交互
13
-// 但是地图上默认使用 霍山县人民政府 的定位
14 9
 export default (props) => {
15
-  const { location, onLocChange } = props;
10
+  const { readOnly, location, onChange } = props;
11
+
12
+  const id = React.useMemo(() => `map-${Math.random().toString(36).substring(2, 10)}`, []);
13
+  const mapCtxRef = React.useRef();
16 14
 
17
-  const [currentPos, setCurPos] = React.useState();
18 15
   const [
19
-    markers,
20
-    lngLat,
16
+    // markers,
17
+    center,
21 18
   ] = React.useMemo(() => {
22
-    const loc = location || currentPos || '116.354259,31.415587';
19
+    // eslint-disable-next-line no-undef
20
+    const loc = location || DEFAULT_POS;
23 21
     const [longitude, latitude] = loc.split(',');
24 22
 
25
-    const mks = [{
26
-      id: 1,
27
-      longitude,
28
-      latitude,
29
-      iconPath,
30
-      width: 17,
31
-      height: 20
32
-    }];
23
+    // const mks = [{
24
+    //   id: 1,
25
+    //   longitude,
26
+    //   latitude,
27
+    //   iconPath,
28
+    //   width: 17,
29
+    //   height: 20
30
+    // }];
33 31
 
34 32
     return [
35
-      mks,
36
-      [longitude, latitude]
33
+      // mks,
34
+      { longitude, latitude }
37 35
     ]
38
-  }, [location, currentPos]);
36
+  }, [location]);
39 37
 
40
-  React.useEffect(() => {
41
-    getLocation().then((res) => {
42
-      setCurPos([res.longitude, res.latitude].join(','));
43
-    }).catch((err) => {
44
-      console.error(err);
45
-      Taro.showToast({
46
-        title: '定位失败',
47
-        icon: 'none',
38
+  const moveTo = (ctx, point) => {
39
+    ctx.moveToLocation({
40
+      ...point,
41
+      fail: console.error,
42
+    })
43
+  }
44
+
45
+  const getContext = React.useCallback(() => {
46
+    const query = Taro.createSelectorQuery();
47
+    query.select(`#${id}`).context(res => {
48
+      mapCtxRef.current = res.context;
49
+
50
+      // 修改中心图标 - 暂时不起作用, wx bug
51
+      mapCtxRef.current.setLocMarkerIcon({
52
+        iconPath,
53
+        fail: console.error,
48 54
       })
55
+    }).exec();
56
+  }, [id]);
57
+
58
+  const fixedLocation = () => {
59
+    return new Promise((resolve) => {
60
+      getLocation({ type: 'gcj02' }).then((res) => {
61
+        resolve(res);
62
+      }).catch((err) => {
63
+        console.error(err);
64
+        Taro.showToast({
65
+          title: '定位失败',
66
+          icon: 'none',
67
+        })
68
+      });
49 69
     });
50
-  }, []);
51
-  // console.log('markers latitude', mks)
52
-  React.useEffect(() => {
53
-    if (!location && !currentPos) return;
70
+  }
54 71
 
55
-    const loc = location || currentPos;
56
-    if (loc) {
57
-      onLocChange(loc);
72
+  const onRefresh = () => {
73
+    if (mapCtxRef.current) {
74
+      fixedLocation().then((res) => {
75
+        const { longitude, latitude } = res;
76
+        onChange([res.longitude, res.latitude].join(','));
77
+        moveTo(mapCtxRef.current, { longitude, latitude });
78
+      })
58 79
     }
59
-  }, [location, currentPos]);
80
+  }
81
+
82
+  React.useEffect(() => {
83
+    if (!readOnly) {
84
+      fixedLocation().then((res) => {
85
+        const { longitude, latitude } = res;
86
+        onChange([longitude, latitude].join(','));
87
+      })
88
+    }
89
+  }, [readOnly]);
90
+
91
+  React.useEffect(() => {
92
+    getContext();
93
+  }, [getContext]);
60 94
 
61 95
   return (
62 96
     <View className={style['map-wrapper']}>
63 97
       <Map
64
-        longitude={lngLat[0]}
65
-        latitude={lngLat[1]}
66
-        markers={markers}
98
+        id={id}
99
+        showLocation
100
+        longitude={center.longitude}
101
+        latitude={center.latitude}
102
+      // markers={markers}
67 103
       >
68
-        <CoverView className={style['control']}><Icon name="aim" size="26px" color="rgb(18,183,245)" /></CoverView>
104
+        {!readOnly && (
105
+          <CoverView className={style['control']} onClick={onRefresh}>
106
+            <Icon name="aim" size="24px" color="#1A7565" />
107
+          </CoverView>
108
+        )}
69 109
       </Map>
70 110
     </View>
71 111
   )

+ 2
- 2
src/components/map/style.module.less Просмотреть файл

@@ -12,8 +12,8 @@
12 12
     left: 0;
13 13
     .control {
14 14
       position: absolute;
15
-      bottom: 14%;
16
-      right: 4%;
15
+      bottom: var(--main-space);
16
+      right: var(--main-space);
17 17
     }
18 18
   }
19 19
 }

+ 2
- 1
src/layouts/index.jsx Просмотреть файл

@@ -2,7 +2,7 @@ import React from 'react';
2 2
 import Taro from '@tarojs/taro';
3 3
 import { View, Image } from '@tarojs/components';
4 4
 import { useModel } from '@/store';
5
-import { Loading, Notify } from '@antmjs/vantui';
5
+import { Loading, Notify, Dialog } from '@antmjs/vantui';
6 6
 import NavLoading from '@/components/NavLoading';
7 7
 import Auth from '@/components/Auth';
8 8
 import TabBar from './TabBar';
@@ -35,6 +35,7 @@ export default (props) => {
35 35
   return (
36 36
     <View className={laySty['page-wrapper']}>
37 37
       <Notify id="vanNotify" />
38
+      <Dialog id="vanDialog" />
38 39
       <NavLoading loading={loading} />
39 40
       <View className={containerClass} style={style}>
40 41
         {

+ 17
- 11
src/pages/check/edit/components/LocForm.jsx Просмотреть файл

@@ -10,7 +10,6 @@ import AgePicker from './AgePicker';
10 10
 export default (props) => {
11 11
   const { checkItemInfo, checkType, answer, readonly, onChange, onLoadingChange } = props;
12 12
 
13
-  const [loc, setLoc] = React.useState();
14 13
   const [showAgePicker, setShowAgePicker] = React.useState(false);
15 14
 
16 15
   const setLoading = (v) => {
@@ -21,7 +20,6 @@ export default (props) => {
21 20
 
22 21
   const setFieldChange = (key, val) => {
23 22
     onChange({
24
-      location: loc,
25 23
       ...answer || {},
26 24
       [key]: val,
27 25
     })
@@ -46,7 +44,11 @@ export default (props) => {
46 44
 
47 45
   return (
48 46
     <View>
49
-      <Map location={answer?.location} onLocChange={setLoc} />
47
+      <Map
48
+        readOnly={readonly}
49
+        location={answer?.location}
50
+        onChange={e => setFieldChange('location', e)}
51
+      />
50 52
       <CellGroup>
51 53
         {
52 54
           checkType == 'loc' && (
@@ -56,18 +58,22 @@ export default (props) => {
56 58
             />
57 59
           )
58 60
         }
61
+        {
62
+          checkType == 'survey' && (
63
+            <Field
64
+              label="社区"
65
+              placeholder="请填写社区名称"
66
+              readonly={readonly}
67
+              value={answer?.communityName}
68
+              onChange={e => setFieldChange('communityName', e.detail)}
69
+            />
70
+          )
71
+        }
59 72
         <Field
60 73
           readonly={readonly}
61
-          placeholder={checkType == 'loc' ? '请输入地址' : '请填写社区名称'}
62
-          // value={answer}
63
-          leftIcon={mapIcon}
64
-        // onChange={e => setFieldChange('', e.detail)}
65
-        />
66
-        <Field
67
-          readonly={readonly}
74
+          label={checkType == 'loc' ? '地址' : '小区'}
68 75
           placeholder={checkType == 'loc' ? '请输入地址' : '请填写小区名称'}
69 76
           value={answer?.addr}
70
-          leftIcon={mapIcon}
71 77
           onChange={e => setFieldChange('addr', e.detail)}
72 78
         />
73 79
       </CellGroup>

+ 1
- 1
src/pages/check/edit/index.jsx Просмотреть файл

@@ -44,8 +44,8 @@ export default (props) => {
44 44
     if (index == -1 && n != -1) {
45 45
       if (!readonly) {
46 46
         try {
47
+          warn(typ == 'survey' && !answer?.communityName, '请填写社区名称');
47 48
           warn(!answer?.addr, typ == 'loc' ? '请填写地址' : '请填写小区名称');
48
-          // warn(!answer, typ == 'loc' ? '请填写地址' : '请填写社区名称');
49 49
           warn(!answer?.location, '未能获取定位信息, 请重试');
50 50
           warn(typ == 'survey' && !answer?.sex, '请选择性别');
51 51
           warn(typ == 'survey' && !answer?.age, '请选择年龄段');

+ 5
- 4
src/pages/check/loc/edit/components/LocForm.jsx Просмотреть файл

@@ -9,8 +9,6 @@ import mapIcon from '@/assets/icons/marker.png';
9 9
 export default (props) => {
10 10
   const { checkItemInfo, answer, readonly, onChange, onLoadingChange } = props;
11 11
 
12
-  const [loc, setLoc] = React.useState();
13
-
14 12
   const setLoading = (v) => {
15 13
     if (onLoadingChange) {
16 14
       onLoadingChange(v)
@@ -19,7 +17,6 @@ export default (props) => {
19 17
   
20 18
   const setFieldChange = (key, val) => {
21 19
     onChange({
22
-      location: loc,
23 20
       ...answer || {},
24 21
       [key]: val,
25 22
     })
@@ -42,7 +39,11 @@ export default (props) => {
42 39
   
43 40
   return (
44 41
     <View>
45
-      <Map location={answer?.location} onLocChange={setLoc} />
42
+      <Map
43
+        readOnly={readonly}
44
+        location={answer?.location}
45
+        onChange={(e) => setFieldChange('location', e)}
46
+      />
46 47
       <CellGroup>
47 48
         <Cell
48 49
           title="点位"

+ 2
- 1
src/pages/feedback/issue/index.jsx Просмотреть файл

@@ -64,8 +64,9 @@ export default (props) => {
64 64
   return (
65 65
     <Page tabBar="feedback">
66 66
       <Map
67
+        readOnly={readOnly}
67 68
         location={formData.location}
68
-        onLocChange={e => !formData.location && setFieldChange('location', e)}
69
+        onChange={e => !formData.location && setFieldChange('location', e)}
69 70
       />
70 71
 
71 72
       <CellGroup>

+ 17
- 6
src/pages/home/index.jsx Просмотреть файл

@@ -5,11 +5,17 @@ import { useModel } from '@/store';
5 5
 import MenuIcon from '@/components/MenuIcon';
6 6
 import { ROLE_CITIZEN, ROLE_INSPECTOR, ROLE_MANAGER, ROLE_ORG_MANAGER, ROLE_ORG_USER, ROLE_QUERY_PERSON } from '@/utils/user';
7 7
 import { PROCESS_APPLY_DELAY, PROCESS_APPLY_END, PROCESS_APPLY_REJECT, PROCESS_APPLY_VERIFY, PROCESS_ASSIGNED, PROCESS_END, PROCESS_START } from '@/utils/biz';
8
+import { getApplyNum } from '@/services/taissueapply';
8 9
 import Head from './components/Head';
9 10
 import Banner from './components/Banner';
10 11
 import StatCard from './components/StatCard';
11 12
 import './index.less';
12 13
 
14
+const getRejctApply = () => getApplyNum({ applyType: PROCESS_APPLY_REJECT });
15
+const getDelayApply = () => getApplyNum({ applyType: PROCESS_APPLY_DELAY });
16
+const getVerifyApply = () => getApplyNum({ applyType: PROCESS_APPLY_VERIFY });
17
+const getEdnApply = () => getApplyNum({ applyType: PROCESS_APPLY_END });
18
+
13 19
 const menus = {
14 20
   // 督查员
15 21
   [ROLE_INSPECTOR]: [
@@ -23,10 +29,10 @@ const menus = {
23 29
     { icon: 'icon1', text: '待 交 办', link: `/pages/issue/list2/index?title=待交办&bizStatus=${PROCESS_START}` },
24 30
     { icon: 'icon2', text: '已 交 办', link: `/pages/issue/list2/index?title=已交办&bizStatus=${PROCESS_ASSIGNED}`, },
25 31
     { icon: 'icon3', text: '已 办 结', link: `/pages/issue/list2/index?title=已办结&bizStatus=${PROCESS_END}` },
26
-    { icon: 'icon4', text: '消单申请', link: `/pages/apply/list/index?title=消单申请&applyType=${PROCESS_APPLY_END}` },
32
+    { icon: 'icon4', text: '消单申请', request: getEdnApply, link: `/pages/apply/list/index?title=消单申请&applyType=${PROCESS_APPLY_END}` },
27 33
     { icon: 'icon5', text: '逾期警告', link: `/pages/issue/list2/index?title=逾期警告&bizStatus=expired` },
28
-    { icon: 'icon6', text: '延期申请', link: `/pages/apply/list/index?title=延期申请&applyType=${PROCESS_APPLY_DELAY}` },
29
-    { icon: 'icon12', text: '驳回申请', link: `/pages/apply/list/index?title=驳回申请&applyType=${PROCESS_APPLY_REJECT}` },
34
+    { icon: 'icon6', text: '延期申请', request: getDelayApply, link: `/pages/apply/list/index?title=延期申请&applyType=${PROCESS_APPLY_DELAY}` },
35
+    { icon: 'icon12', text: '驳回申请', request: getRejctApply, link: `/pages/apply/list/index?title=驳回申请&applyType=${PROCESS_APPLY_REJECT}` },
30 36
     { icon: 'icon7', text: '统计查询', link: '/subpkg1/pages/statistics/index' },
31 37
     { icon: 'icon9', text: '我的上报', link: '/pages/issue/list2/index?title=我的上报&mine=true' },
32 38
     { icon: 'icon11', text: '消息通知', link: '/pages/message/list/index' },
@@ -45,8 +51,9 @@ const menus = {
45 51
     { icon: 'icon2', text: '处 理 中', link: `/pages/org/issue/list/index?title=处理中&bizStatus=${PROCESS_ASSIGNED}` },
46 52
     { icon: 'icon3', text: '已 办 结', link: `/pages/org/issue/list/index?title=已办结&bizStatus=${PROCESS_END}` },
47 53
     { icon: 'icon5', text: '已 逾 期', link: '/pages/org/issue/list/index?title=已办结&bizStatus=expired' },
48
-    { icon: 'icon9', text: '审核申请', link: `/pages/apply/list/index?title=审核申请&applyType=${PROCESS_APPLY_VERIFY}` },
54
+    { icon: 'icon9', text: '审核申请', request: getVerifyApply, link: `/pages/apply/list/index?title=审核申请&applyType=${PROCESS_APPLY_VERIFY}` },
49 55
     { icon: 'icon11', text: '消息通知', link: '/pages/message/list/index' },
56
+    { icon: 'person', text: '人员管理', link: '/pages/user/list/index' },
50 57
   ],
51 58
 
52 59
   // 查询人员
@@ -68,7 +75,7 @@ const menus = {
68 75
 export default (props) => {
69 76
 
70 77
   const userModel = useModel('user');
71
-  const { user, duty } = userModel || {};
78
+  const { user, duty, signOut, changePwd } = userModel || {};
72 79
 
73 80
   const menuArr = React.useMemo(() => {
74 81
     if (!duty) return [];
@@ -78,7 +85,11 @@ export default (props) => {
78 85
 
79 86
   return (
80 87
     <Page tabBar="home" className="home-page">
81
-      <Head userModel={userModel} />
88
+      <Head
89
+        userModel={userModel}
90
+        onChangePwd={changePwd}
91
+        onExit={signOut}
92
+      />
82 93
       <Banner duty={duty} />
83 94
       <StatCard duty={duty} />
84 95
 

+ 2
- 1
src/pages/issue/components/Issue/index.jsx Просмотреть файл

@@ -144,8 +144,9 @@ export default (props) => {
144 144
       />
145 145
 
146 146
       <Map
147
+        readOnly={readOnly}
147 148
         location={formData.location}
148
-        onLocChange={e => !formData.location && setFieldChange('location', e)}
149
+        onChange={e => !formData.location && setFieldChange('location', e)}
149 150
       />
150 151
 
151 152
       <CellGroup>

+ 35
- 2
src/pages/my/components/Head/index.jsx Просмотреть файл

@@ -1,20 +1,53 @@
1 1
 import React from 'react';
2 2
 import Taro from '@tarojs/taro';
3 3
 import { View, Image } from '@tarojs/components';
4
+import { ActionSheet } from '@antmjs/vantui';
5
+import ResetPwd from '../ResetPwd';
4 6
 import styles from './style.module.less';
5 7
 
6 8
 export default (props) => {
7 9
 
8
-  const { name, avatar } = props;
10
+  const { name, avatar, onChangePwd, onExit } = props;
11
+  const [show, setShow] = React.useState(false);
12
+  const [show2, setShow2] = React.useState(false);
13
+
14
+  const actions =[
15
+    { name: '重置密码', value: 'reset-pwd' },
16
+    { name: '退出', value: 'exit' },
17
+  ]
18
+
19
+  const onAction = (e) => {
20
+    const { value } = e.detail;
21
+
22
+    if (value === 'reset-pwd') {
23
+      setShow(false);
24
+      setShow2(true);
25
+    }
26
+
27
+    if (value === 'exit') {
28
+      onExit();
29
+    }
30
+  }
9 31
   
10 32
   return (
11 33
     <View className={styles['my-head-box']}>
12 34
       <View className={styles['profile-box']}>
13
-        <View className={styles['profile-avatar']}>
35
+        <View className={styles['profile-avatar']} onClick={() => setShow(true)}>
14 36
           <Image src={avatar} />
15 37
         </View>
16 38
         <View className={styles['profile-name']}>{name}</View>
17 39
       </View>
40
+      <ActionSheet
41
+        show={show}
42
+        actions={actions}
43
+        onClose={() => setShow(false)}
44
+        onSelect={onAction}
45
+      />
46
+      <ResetPwd
47
+        show={show2}
48
+        onClose={() => setShow2(false)}
49
+        onSubmit={onChangePwd}
50
+      />
18 51
     </View>
19 52
   )
20 53
 }

+ 82
- 0
src/pages/my/components/ResetPwd/index.jsx Просмотреть файл

@@ -0,0 +1,82 @@
1
+import React from 'react';
2
+import Taro from '@tarojs/taro';
3
+import { View } from '@tarojs/components';
4
+import { Dialog, CellGroup, Field, Button } from '@antmjs/vantui';
5
+import { warn } from '@/utils/message';
6
+
7
+export default (props) => {
8
+
9
+  const { show, onClose, onSubmit } = props;
10
+  const id = React.useMemo(() => {
11
+    return `dialog-${Math.random().toString(36).substring(2, 10)}`
12
+  }, []);
13
+
14
+  const [formData, setFormData] = React.useState({});
15
+
16
+  const setField = (name, value) => {
17
+    setFormData({
18
+      ...formData,
19
+      [name]: value,
20
+    })
21
+  }
22
+
23
+  const onConfirm = () => {
24
+    console.log(formData.newPassword)
25
+    try {
26
+      warn(formData.newPassword != formData.newPassword2, '两次新密码不一致');
27
+      warn(!formData.originPassword, '请输入原始密码');
28
+      warn(!formData.newPassword, '请输入新密码');
29
+    } catch (er) {
30
+      return ;
31
+    }
32
+
33
+    onClose();
34
+    onSubmit(formData);
35
+  }
36
+  
37
+  return (
38
+    <Dialog
39
+      showConfirmButton={false}
40
+      showCancelButton={false}
41
+      id={id}
42
+      show={show}
43
+      onClose={onClose}
44
+    >
45
+      <View style={{ padding: 'var(--main-space)', textAlign: 'center' }}>修改密码</View>
46
+      <CellGroup style={{ padding: 'var(--main-space)' }}>
47
+        <Field
48
+          required
49
+          label="原始密码"
50
+          type="password"
51
+          placeholder="请输入原始密码"
52
+          value={formData.originPassword}
53
+          onChange={(e) => setField('originPassword', e.detail)}
54
+        />
55
+        <Field
56
+          required
57
+          label="新密码"
58
+          type="password"
59
+          placeholder="请输入新密码"
60
+          value={formData.newPassword}
61
+          onChange={(e) => setField('newPassword', e.detail)}
62
+        />
63
+        <Field
64
+          required
65
+          label="确认密码"
66
+          type="password"
67
+          placeholder="请再次输入新密码"
68
+          value={formData.newPassword2}
69
+          onChange={(e) => setField('newPassword2', e.detail)}
70
+        />
71
+      </CellGroup>
72
+      <View style={{ display: 'flex', justifyContent: "space-around", alignItems: 'center' }}>
73
+        <View style={{ flex: 'none' }}>
74
+          <Button plain onClick={onClose}>取消</Button>
75
+        </View>
76
+        <View style={{ flex: 'none' }}>
77
+          <Button plain type="primary" onClick={onConfirm}>确定</Button>
78
+        </View>
79
+      </View>
80
+    </Dialog>
81
+  )
82
+}

+ 7
- 5
src/pages/my/index.jsx Просмотреть файл

@@ -14,7 +14,7 @@ import styles from './style.module.less';
14 14
 
15 15
 export default (props) => {
16 16
 
17
-  const { user, person, duty, signOut } = useModel('user');
17
+  const { user, person, duty, signOut, changePwd } = useModel('user');
18 18
   const [org, setOrg] = React.useState();
19 19
 
20 20
   const [
@@ -51,6 +51,10 @@ export default (props) => {
51 51
     })
52 52
   }
53 53
 
54
+  const onChangePwd = (data) => {
55
+    changePwd(data);
56
+  }
57
+
54 58
   React.useEffect(() => {
55 59
     if (user) {
56 60
       getSysOrgById(user.orgId).then(setOrg);
@@ -62,6 +66,8 @@ export default (props) => {
62 66
       <Head
63 67
         avatar={user?.avatar || person?.avatar || logo}
64 68
         name={user?.name || person?.name || '市民先生'}
69
+        onChangePwd={onChangePwd}
70
+        onExit={onExit}
65 71
       />
66 72
       <View className={styles['bg-menu-box']}>
67 73
         {
@@ -82,10 +88,6 @@ export default (props) => {
82 88
           )
83 89
         }
84 90
       </View>
85
-      <View className={styles.exit} onClick={onExit}>
86
-        退出
87
-        <Image src={iconExit} />
88
-      </View>
89 91
     </Page>
90 92
   )
91 93
 }

+ 0
- 20
src/pages/reporting/detail/components/Issue.jsx Просмотреть файл

@@ -1,20 +0,0 @@
1
-import React from 'react';
2
-import { View } from '@tarojs/components';
3
-import style from './issue.module.less';
4
-
5
-export default (props) => {
6
-  
7
-  return (
8
-    <View className={style['issue-container']}>
9
-      <View class={style.card}>
10
-        <View className={style.title}>状态</View>
11
-      </View>
12
-      <View class={style.card}>
13
-        <View className={style.title}>问题描述</View>
14
-      </View>
15
-      <View class={style.card}>
16
-        <View className={style.title}>拍照</View>
17
-      </View>
18
-    </View>
19
-  )
20
-}

+ 0
- 17
src/pages/reporting/detail/components/Map.jsx Просмотреть файл

@@ -1,17 +0,0 @@
1
-import React from 'react';
2
-import { View } from '@tarojs/components';
3
-import Map from '@/components/map';
4
-import style from './map.module.less';
5
-
6
-export default (props) => {
7
-  const { location } = props;
8
-  
9
-  return (
10
-    <View className={style['map-box']}>
11
-      <Map location={location} />
12
-      <View className={style.address}>
13
-        阳光丽景小区
14
-      </View>
15
-    </View>
16
-  )
17
-}

+ 0
- 21
src/pages/reporting/detail/components/issue.module.less Просмотреть файл

@@ -1,21 +0,0 @@
1
-
2
-.issue-container {
3
-  margin-top: var(--main-space);
4
-
5
-  .card {
6
-    background: #fff;
7
-    padding: 0 var(--main-space);
8
-
9
-    & + .card {
10
-      margin-top: 2.67vw;
11
-    }
12
-  }
13
-
14
-  .title {
15
-    height: 90px;
16
-    font-size: 32px;
17
-    font-weight: bold;
18
-    color: #202020;
19
-    line-height: 90px;
20
-  }
21
-}

+ 0
- 16
src/pages/reporting/detail/components/map.module.less Просмотреть файл

@@ -1,16 +0,0 @@
1
-
2
-.map-box {
3
-  width: 100vw;
4
-
5
-  .address {
6
-    width: 100%;
7
-    background: #fff;
8
-    height: 90px;
9
-    font-size: 24px;
10
-    font-weight: 500;
11
-    color: #202020;
12
-    line-height: 90px;
13
-    padding: 0 var(--main-space);
14
-  }
15
-  
16
-}

+ 0
- 3
src/pages/reporting/detail/index.config.js Просмотреть файл

@@ -1,3 +0,0 @@
1
-export default definePageConfig({
2
-  navigationBarTitleText: '详情'
3
-})

+ 0
- 41
src/pages/reporting/detail/index.jsx Просмотреть файл

@@ -1,41 +0,0 @@
1
-import React from 'react';
2
-import Taro from '@tarojs/taro';
3
-import { View } from '@tarojs/components';
4
-import { Notify } from '@antmjs/vantui';
5
-import Page from '@/layouts/index';
6
-import getAuthorize from '@/utils/authorize';
7
-import Map from './components/Map';
8
-import Issue from './components/Issue';
9
-
10
-export default (props) => {
11
-
12
-  const [loc, setLoc] = React.useState();
13
-
14
-  React.useMemo(() => {
15
-    getAuthorize('scope.userLocation').then(() => {
16
-      Taro.getLocation({
17
-        success(res) {
18
-          setLoc(`${res.longitude},${res.latitude}`);
19
-        },
20
-        fail() {
21
-          Notify.show({
22
-            message: '获取位置失败, 请退出重试',
23
-            type: 'warning',
24
-          })
25
-        }
26
-      });
27
-    }).catch((err) => {
28
-      Notify.show({
29
-        message: '未能获取位置, 程序部分功能将不能正常使用',
30
-        type: 'warning',
31
-      })
32
-    });
33
-  }, []);
34
-
35
-  return (
36
-    <Page>
37
-      <Map location={loc} />
38
-      <Issue />
39
-    </Page>
40
-  )
41
-}

+ 0
- 3
src/pages/reporting/index.config.js Просмотреть файл

@@ -1,3 +0,0 @@
1
-export default definePageConfig({
2
-  navigationBarTitleText: '我的上报'
3
-})

+ 0
- 9
src/pages/reporting/index.jsx Просмотреть файл

@@ -1,9 +0,0 @@
1
-import React from 'react';
2
-import { View } from '@tarojs/components';
3
-
4
-export default (props) => {
5
-  
6
-  return (
7
-    <View></View>
8
-  )
9
-}

+ 112
- 0
src/pages/user/add/index.jsx Просмотреть файл

@@ -0,0 +1,112 @@
1
+import React from "react";
2
+import Taro from "@tarojs/taro";
3
+import { View } from "@tarojs/components";
4
+import Page from "@/layouts/index";
5
+import {
6
+  Button,
7
+  Field,
8
+  Cell,
9
+  CellGroup,
10
+  CheckboxGroup,
11
+  Checkbox,
12
+} from "@antmjs/vantui";
13
+import { ROLE_ORG_MANAGER, ROLE_ORG_USER } from "@/utils/user";
14
+
15
+import { warn } from "@/utils/message";
16
+import { postSysUser } from "@/services/sysuser";
17
+
18
+export default (props) => {
19
+  const [loading, setLoading] = React.useState(false);
20
+  const [identity, setIdentity] = React.useState([]);
21
+  const [formData, setFormData] = React.useState({});
22
+
23
+  const setField = (name, value) => {
24
+    setFormData((data) => ({
25
+      ...data,
26
+      [name]: value,
27
+    }));
28
+  };
29
+  const onSubmit = () => {
30
+    try {
31
+      warn(!formData.name, "请填写姓名");
32
+      warn(!formData.phone, "请填写手机号");
33
+      warn(identity.length < 1, "请选择身份");
34
+    } catch (e) {
35
+      return;
36
+    }
37
+
38
+    setLoading(true);
39
+    postSysUser({ ...formData, dutyList: identity })
40
+      .then(() => {
41
+        setLoading(false);
42
+        Taro.navigateBack({
43
+          delta: 1,
44
+          fail: () => {
45
+            Taro.reLaunch({
46
+              url: "/pages/user/list/index",
47
+            });
48
+          },
49
+        });
50
+      })
51
+      .catch(() => {
52
+        setLoading(false);
53
+      });
54
+  };
55
+
56
+  return (
57
+    <Page>
58
+      <CellGroup>
59
+        <Field
60
+          required
61
+          label="姓名"
62
+          placeholder="请输入姓名"
63
+          value={formData.name}
64
+          onChange={(e) => setField("name", e.detail)}
65
+        />
66
+        <Field
67
+          required
68
+          label="手机号"
69
+          placeholder="请输入手机号"
70
+          value={formData.phone}
71
+          onChange={(e) => setField("phone", e.detail)}
72
+        />
73
+        <Cell
74
+          title="身份"
75
+          required
76
+          titleWidth="100px"
77
+          titleStyle={{
78
+            maxWidth: "6.2em",
79
+            minWidth: "6.2em",
80
+            marginRight: "12px",
81
+          }}
82
+        >
83
+          <View style={{ display: "flex" }}>
84
+            <CheckboxGroup
85
+              direction="horizontal"
86
+              value={identity}
87
+              onChange={(e) => {
88
+                console.info(e);
89
+                setIdentity([...e.detail]);
90
+              }}
91
+            >
92
+              <Checkbox name={ROLE_ORG_USER}>单位人员</Checkbox>
93
+              <Checkbox name={ROLE_ORG_MANAGER}>单位管理员</Checkbox>
94
+            </CheckboxGroup>
95
+          </View>
96
+        </Cell>
97
+
98
+        {/* // 单位人员
99
+export const ROLE_ORG_USER = 'org_user';
100
+
101
+// 单位管理员
102
+export const ROLE_ORG_MANAGER = 'org_manager'; */}
103
+      </CellGroup>
104
+
105
+      <View style={{ padding: "var(--main-space)", background: "#fff" }}>
106
+        <Button block type="primary" loading={loading} onClick={onSubmit}>
107
+          提交
108
+        </Button>
109
+      </View>
110
+    </Page>
111
+  );
112
+};

+ 4
- 0
src/pages/user/list/index.config.js Просмотреть файл

@@ -0,0 +1,4 @@
1
+// eslint-disable-next-line no-undef
2
+export default definePageConfig({
3
+  navigationBarTitleText: '人员列表'
4
+})

+ 82
- 0
src/pages/user/list/index.jsx Просмотреть файл

@@ -0,0 +1,82 @@
1
+import React from "react";
2
+import Taro from "@tarojs/taro";
3
+import { View } from "@tarojs/components";
4
+import { Cell, Button, Dialog } from "@antmjs/vantui";
5
+import Page from "@/layouts/index";
6
+import PowerList from "@/components/PowerList";
7
+import { getSysUser, deleteSysUser } from "@/services/sysuser";
8
+import styles from "./index.module.less";
9
+
10
+export default (props) => {
11
+  const [loading, setLoading] = React.useState(false);
12
+  const listRef = React.useRef();
13
+
14
+  const onAdd = () => {
15
+    Taro.navigateTo({
16
+      url: "/pages/user/add/index",
17
+    });
18
+  };
19
+
20
+  const onDelete = (user) => {
21
+    Dialog.confirm({
22
+      title: "确认删除用户?",
23
+    }).then((e) => {
24
+      const { action } = e.detail;
25
+      if (action === "confirm") {
26
+        setLoading(true);
27
+        deleteSysUser(user.id)
28
+          .then(() => {
29
+            setLoading(false);
30
+
31
+            // 刷新列表
32
+            listRef.current.refresh();
33
+          })
34
+          .catch(() => {
35
+            setLoading(false);
36
+          });
37
+      }
38
+    });
39
+  };
40
+
41
+  return (
42
+    <Page loading={loading}>
43
+      <view className={styles["user-warpper"]}>
44
+        <view className={styles["user-warpper-list"]}>
45
+          <PowerList
46
+            ref={listRef}
47
+            request={getSysUser}
48
+            onLoadingChange={setLoading}
49
+            renderItem={(item) => (
50
+              <Cell
51
+                key={item.userId}
52
+                title={item.name}
53
+                label={item.createDate.substring(0, 10)}
54
+              >
55
+                <Button
56
+                  plain
57
+                  type="danger"
58
+                  size="small"
59
+                  onClick={() => onDelete(item)}
60
+                >
61
+                  删除
62
+                </Button>
63
+              </Cell>
64
+            )}
65
+          />
66
+        </view>
67
+
68
+        <Button
69
+          type="primary"
70
+          size="large"
71
+          onClick={() => onAdd()}
72
+          style={{
73
+            margin: "var(--main-space)",
74
+            width: "calc(100% - var(--main-space) * 2)",
75
+          }}
76
+        >
77
+          添加
78
+        </Button>
79
+      </view>
80
+    </Page>
81
+  );
82
+};

+ 12
- 0
src/pages/user/list/index.module.less Просмотреть файл

@@ -0,0 +1,12 @@
1
+// height: calc(100% - env(safe-area-inset-bottom));
2
+.user-warpper {
3
+  height: 100%;
4
+  display: flex;
5
+  flex-direction: column;
6
+  .user-warpper-list {
7
+    height: calc(100% - 78px);
8
+  }
9
+  .user-warpper-btn {
10
+    width: 100%;
11
+  }
12
+}

+ 21
- 0
src/services/sysuser.js Просмотреть файл

@@ -0,0 +1,21 @@
1
+import request from '@/utils/request';
2
+
3
+/*
4
+ * 分页查询
5
+ */
6
+export const getSysUser = (params) => request('/api/ma/sysUser', { params });
7
+
8
+/*
9
+ * 新增数据
10
+ */
11
+export const postSysUser = (data) => request('/api/ma/sysUser', { data, method: 'post' });
12
+
13
+/*
14
+ * 通过主键删除数据
15
+ */
16
+export const deleteSysUser = (id) => request(`/api/ma/sysUser/${id}`, { method: 'delete' });
17
+
18
+/*
19
+ * 修改密码
20
+ */
21
+export const changePassword = (data) => request('/api/ma/sysUser/change-password', { method: 'put', data });

+ 2
- 0
src/services/taissueapply.js Просмотреть файл

@@ -27,3 +27,5 @@ export const putTaIssueApply = (id, data) => request(`/api/taIssueApply/${id}`,
27 27
  * 通过主键删除数据
28 28
  */
29 29
 export const deleteTaIssueApply = (id) => request(`/api/taIssueApply/${id}`, { method: 'delete' });
30
+
31
+export const getApplyNum = params => request('/api/taIssueApply/nums', { params });

+ 11
- 0
src/store/user.js Просмотреть файл

@@ -2,6 +2,7 @@ import React from 'react';
2 2
 import Taro from '@tarojs/taro';
3 3
 import md5 from 'md5';
4 4
 import { login, signin, currentUser, authPhone, authUser } from '@/services/wxma';
5
+import { changePassword } from '@/services/sysuser';
5 6
 import { ROLE_CITIZEN } from '@/utils/user';
6 7
 
7 8
 export default function useUser() {
@@ -75,6 +76,15 @@ export default function useUser() {
75 76
     initDuty([]);
76 77
   }
77 78
 
79
+  const changePwd = (params) => {
80
+    const data = {
81
+      originPassword: md5(params.originPassword),
82
+      newPassword: md5(params.newPassword),
83
+    }
84
+
85
+    changePassword(data);
86
+  }
87
+
78 88
   return {
79 89
     user,
80 90
     person,
@@ -86,5 +96,6 @@ export default function useUser() {
86 96
     signinByPhone,
87 97
     authProfile,
88 98
     signOut,
99
+    changePwd,
89 100
   }
90 101
 }

+ 2
- 1
src/utils/authorize.js Просмотреть файл

@@ -25,10 +25,11 @@ export default function getAuthorize(scope) {
25 25
   });
26 26
 }
27 27
 
28
-export const getLocation = () => {
28
+export const getLocation = (options) => {
29 29
   return new Promise((resolve, reject) => {
30 30
     getAuthorize('scope.userLocation').then(() => {
31 31
       Taro.getLocation({
32
+        ...options || {},
32 33
         success(res) {
33 34
           resolve(res);
34 35
         },