Yansen 2 år sedan
förälder
incheckning
080d7a9156

+ 55
- 0
src/pages/check/loc/edit/components/Footer/index.jsx Visa fil

@@ -0,0 +1,55 @@
1
+import React from 'react';
2
+import Taro from '@tarojs/taro';
3
+import { View } from '@tarojs/components';
4
+import { Button } from '@antmjs/vantui';
5
+import QuSelect from '../QuSelect';
6
+import style from './style.module.less';
7
+
8
+export default (props) => {
9
+  const { value, list, readonly, onChange, onSubmit } = props;
10
+
11
+  const [isPrev, isFinished] = React.useMemo(() => {
12
+    const total = list?.length || 0;
13
+
14
+    return [
15
+      value > 0,
16
+      value >= total - 1,
17
+    ]
18
+  }, [value, list]);
19
+
20
+  const onPrev = () => {
21
+    onChange(value - 1);
22
+  }
23
+
24
+  const onNext = () => {
25
+    if (isFinished) {
26
+      onSubmit()
27
+    } else {
28
+      onChange(value + 1);
29
+    }
30
+  }
31
+  
32
+  return (
33
+    <View className={style['qu-footer-wrapper']}>
34
+      {
35
+        !readonly && value > -1 && (
36
+          <View className={style['qu-footer-sel']}>
37
+            <QuSelect
38
+              value={value}
39
+              list={list}
40
+              onChange={onChange}
41
+            />
42
+          </View>
43
+        )
44
+      }
45
+      <View className={style['qu-footer-act']}>
46
+        {
47
+          isPrev && <Button type="primary" block plain hairline style={{flex: 1}} onClick={onPrev}>上一题</Button>
48
+        }
49
+        <Button type="primary" block style={{flex: 1, marginLeft: isPrev ? '1em' : 0 }} onClick={onNext}>
50
+          {isFinished ? '提交' : (value == -1 ? '开始测评' : '下一题')}
51
+        </Button>
52
+      </View>
53
+    </View>
54
+  )
55
+}

+ 21
- 0
src/pages/check/loc/edit/components/Footer/style.module.less Visa fil

@@ -0,0 +1,21 @@
1
+
2
+.qu-footer-wrapper {
3
+  width: 100%;
4
+  overflow: hidden;
5
+  padding: var(--main-space) 0;
6
+  background: #fff;
7
+  display: flex;
8
+  align-items: center;
9
+
10
+  .qu-footer-sel {
11
+    flex: none;
12
+    margin-right: 2em;
13
+  }
14
+
15
+  .qu-footer-act {
16
+    flex: 1;
17
+    display: flex;
18
+    overflow: hidden;
19
+    padding: 0 var(--main-space);
20
+  }
21
+}

+ 0
- 20
src/pages/check/loc/edit/components/FormTpl/index.jsx Visa fil

@@ -1,20 +0,0 @@
1
-import React from 'react';
2
-import Taro from '@tarojs/taro';
3
-import { View, ScrollView } from '@tarojs/components';
4
-import VABC from '@/components/VABC';
5
-
6
-export default (props) => {
7
-  const { action } = props;
8
-  
9
-  return (
10
-    <VABC
11
-      footer={(
12
-        <View style={{padding: 'var(--main-space)'}}>{action}</View>
13
-      )}
14
-    >
15
-      <ScrollView scrollY style={{ height: '100%' }}>
16
-        {props.children}
17
-      </ScrollView>
18
-    </VABC>
19
-  )
20
-}

+ 28
- 22
src/pages/check/loc/edit/components/LocForm.jsx Visa fil

@@ -1,52 +1,58 @@
1 1
 import React from 'react';
2 2
 import Taro from '@tarojs/taro';
3 3
 import { View } from '@tarojs/components';
4
-import { CellGroup, Cell, Field, Button } from '@antmjs/vantui';
4
+import { CellGroup, Cell, Field } from '@antmjs/vantui';
5 5
 import Map from '@/components/map';
6
+import { getTaCheckItemAnswer } from '@/services/tacheckitem';
6 7
 import mapIcon from '@/assets/icons/marker.png';
7
-import FormTpl from './FormTpl/index';
8 8
 
9 9
 export default (props) => {
10
+  const { checkItemInfo, answer, readonly, onChange, onLoadingChange } = props;
10 11
 
11
-  const { detail, onDetailChange, onClick } = props;
12
-
13
-  const [loc, setLoc] = React.useState();
12
+  const setLoading = (v) => {
13
+    if (onLoadingChange) {
14
+      onLoadingChange(v)
15
+    }
16
+  }
14 17
   
15 18
   const setFieldChange = (key, val) => {
16
-    onDetailChange({
17
-      ...(detail || {}),
19
+    onChange({
20
+      ...answer || {},
18 21
       [key]: val,
19 22
     })
20 23
   }
21 24
 
25
+  // 获取答题主记录信息
22 26
   React.useEffect(() => {
23
-    if (detail && loc) {
24
-      onDetailChange({
25
-        ...detail,
26
-        location: loc,
27
-      })
27
+    if (checkItemInfo?.itemId) {
28
+      setLoading(true);
29
+      getTaCheckItemAnswer(checkItemInfo?.itemId).then((res) => {
30
+        if (res) {
31
+          onChange(res);
32
+        }
33
+        setLoading(false);
34
+      }).catch(() => {
35
+        setLoading(false);
36
+      });
28 37
     }
29
-  }, [detail, loc]);
38
+  }, [checkItemInfo?.itemId])
30 39
   
31 40
   return (
32
-    <FormTpl
33
-      action={(
34
-        <Button block type="primary" onClick={onClick}>下一步</Button>
35
-      )}
36
-    >
37
-      <Map onLocChange={setLoc} />
41
+    <View>
42
+      <Map location={answer?.location} onLocChange={e => !readonly && setFieldChange('location', e)} />
38 43
       <CellGroup>
39 44
         <Cell
40 45
           title="点位"
41
-          value={detail?.name}
46
+          value={checkItemInfo?.name}
42 47
         />
43 48
         <Field
49
+          readonly={readonly}
44 50
           placeholder="请输入地址"
45
-          value={detail?.addr}
51
+          value={answer?.addr}
46 52
           leftIcon={mapIcon}
47 53
           onChange={e => setFieldChange('addr', e.detail)}
48 54
         />
49 55
       </CellGroup>
50
-    </FormTpl>
56
+    </View>
51 57
   )
52 58
 }

+ 7
- 9
src/pages/check/loc/edit/components/QuSelect/index.jsx Visa fil

@@ -15,14 +15,12 @@ const Bar = (props) => {
15 15
   }
16 16
 
17 17
   return (
18
-    <Cell onClick={handleClick}>
19
-      <View className={style['qu-board-title']}>
20
-        <Icon name="weapp-nav" size={60} color="var(--main-bg-color)" />
21
-        <Text>{cursor + 1}</Text>
22
-        <Text> / </Text>
23
-        <Text>{total}</Text>
24
-      </View>
25
-    </Cell>
18
+    <View className={style['qu-board-title']} onClick={handleClick}>
19
+      <Icon name="weapp-nav" size={60} color="var(--main-bg-color)" />
20
+      <Text>{cursor + 1}</Text>
21
+      <Text> / </Text>
22
+      <Text>{total}</Text>
23
+    </View>
26 24
   )
27 25
 }
28 26
 
@@ -53,7 +51,7 @@ export default (props) => {
53 51
                 const cls = [
54 52
                   style['qu-board-bd-item'],
55 53
                   it?.finished ? style['qu-board-bd-active'] : false,
56
-                ].filter(Boolean).join('-')
54
+                ].filter(Boolean).join(' ')
57 55
 
58 56
                 return (
59 57
                   <RatioView key={inx}>

+ 3
- 3
src/pages/check/loc/edit/components/QuSelect/style.module.less Visa fil

@@ -1,6 +1,5 @@
1 1
 .qu-board-bar {
2
-  background: #fff;
3
-  border-top: 1px solid rgba(0, 0, 0, 0.12);
2
+  display: inline-block;
4 3
 }
5 4
 
6 5
 .qu-board-title {
@@ -8,10 +7,11 @@
8 7
   color: #999;
9 8
   font-weight: bold;
10 9
   display: flex;
11
-  justify-content: flex-end;
12 10
   align-items: center;
11
+  padding: 0 var(--main-space);
13 12
 
14 13
   & > text {
14
+    line-height: 3em;
15 15
     &:first-of-type {
16 16
       margin-left: 0.6em;
17 17
     }

+ 39
- 49
src/pages/check/loc/edit/components/Question.jsx Visa fil

@@ -4,77 +4,67 @@ import { View, RichText, Text } from '@tarojs/components';
4 4
 import { CellGroup, Cell, Field, Radio, RadioGroup, Button } from '@antmjs/vantui';
5 5
 import Uploader from '@/components/Uploader/index';
6 6
 import { getTaCheckAnswerItem } from '@/services/tacheckansweritem';
7
-import FormTpl from './FormTpl/index';
8 7
 
9
-const actStyle = {
10
-  display: 'flex',
11
-  width: '100%',
12
-}
13 8
 
14 9
 export default (props) => {
10
+  const { quInfo, answerItem, readonly, onChange, onLoadingChange } = props;
15 11
 
16
-  const { detail, readonly, cursor, total , onChange, onPrev, onNext } = props;
17
-
18
-  const [isPrev, isFinished] = React.useMemo(() => {
19
-    return [
20
-      cursor > 0,
21
-      cursor >= total - 1,
22
-    ]
23
-  }, [cursor, total])
24
-
25
-  const [answer, setAnswer] = React.useState();
26
-
27
-  const onSubmit = () => {
28
-    onChange(answer);
29
-    onNext();
12
+  const setLoading = (v) => {
13
+    if (onLoadingChange) {
14
+      onLoadingChange(v);
15
+    }
30 16
   }
31 17
 
32 18
   const setFieldChange = (key, val) => {
33 19
     if (readonly) return;
34 20
 
35
-    setAnswer({
36
-      ...(answer || {}),
21
+    onChange({
22
+      ...(answerItem || {}),
23
+      quId: quInfo.quId,
37 24
       [key]: val,
38 25
     })
39 26
   }
40 27
 
41 28
   React.useEffect(() => {
42
-    if (detail?.quId) {
43
-      getTaCheckAnswerItem({ quId: detail.quId, isMine: true }).then(res => {
44
-        setAnswer(res && res.length ? res[0] : undefined)
45
-      })
46
-    } else {
47
-      setAnswer(undefined)
29
+    if (quInfo?.quId) {
30
+      setLoading(true);
31
+      getTaCheckAnswerItem({ quId: quInfo.quId, isMine: true }).then(res => {
32
+        onChange(res && res.length ? res[0] : {});
33
+        setLoading(false);
34
+      }).catch(() => {
35
+        setLoading(false);
36
+      });
48 37
     }
49
-  }, [detail]);
38
+  }, [quInfo?.quId]);
50 39
   
51 40
   return (
52
-    <FormTpl
53
-      action={(
54
-        <View style={actStyle}>
55
-          {
56
-            isPrev && <Button type="default" block style={{flex: 1}} onClick={onPrev}>上一题</Button>
57
-          }
58
-          <Button type="primary" block style={{flex: 1, marginLeft: isPrev ? '1em' : 0 }} onClick={onSubmit}>
59
-            {isFinished ? '提交' : '下一题'}
60
-          </Button>
61
-        </View>
62
-      )}
63
-    >
64
-      <RadioGroup value={answer?.answerCode}>
41
+    <View>
42
+      <RadioGroup value={answerItem?.answerCode}>
65 43
         <CellGroup>
66
-          <Cell title="测评内容" />
67 44
           <Cell
68 45
             border={false}
69 46
             renderTitle={(
70
-              <View>
71
-                <Text>{detail?.sortNo}</Text>
72
-                <Text>{detail?.title}</Text>
47
+              <View style={{fontWeight: 'bold'}}>
48
+                <Text>{quInfo?.sortNo}、</Text>
49
+                <Text>{quInfo?.title}</Text>
73 50
               </View>
74 51
             )}
75 52
           />
76 53
           {
77
-            (detail?.answerList || []).map((it) => {              
54
+            quInfo?.quType == 'fill' && (
55
+              <Field
56
+                label="答案:"
57
+                clearable
58
+                readonly={readonly}
59
+                value={answerItem?.answer}
60
+                placeholder="填写数字"
61
+                renderButton={quInfo?.fillUnit}
62
+                onChange={(e) => setFieldChange('answer', e.detail - 0)}
63
+              />
64
+            )
65
+          }
66
+          {
67
+            (quInfo?.answerList || []).map((it) => {              
78 68
               return (
79 69
                 <Cell
80 70
                   key={it.answerId}
@@ -93,7 +83,7 @@ export default (props) => {
93 83
         <Cell title="测评标准" />
94 84
         <Cell
95 85
           renderTitle={
96
-            <RichText nodes={detail?.stand} />
86
+            <RichText nodes={quInfo?.stand} />
97 87
           }
98 88
         />
99 89
       </CellGroup>
@@ -104,12 +94,12 @@ export default (props) => {
104 94
           renderTitle={
105 95
             <Uploader
106 96
               disabled={readonly}
107
-              value={answer?.attachList}
97
+              value={answerItem?.attachList}
108 98
               onChange={e => setFieldChange('attachList',e)}
109 99
             />
110 100
           }
111 101
         />
112 102
       </CellGroup>
113
-    </FormTpl>
103
+    </View>
114 104
   )
115 105
 }

+ 128
- 32
src/pages/check/loc/edit/index.jsx Visa fil

@@ -1,13 +1,15 @@
1 1
 import React from 'react';
2 2
 import Taro from '@tarojs/taro';
3 3
 import { View } from '@tarojs/components';
4
+import { Notify } from '@antmjs/vantui';
4 5
 import Page from '@/layouts/index';
5
-import { getTaCheckItemById, preCheck } from '@/services/tacheckitem';
6
+import { getTaCheckItemById, preCheck, getTaCheckItemAnswer } from '@/services/tacheckitem';
6 7
 import { getTaCheckItemQu } from '@/services/tacheckitemqu';
7 8
 import VABC from '@/components/VABC';
9
+import { ROLE_INSPECTOR } from '@/utils/user';
8 10
 import LocForm from './components/LocForm';
9 11
 import Question from './components/Question';
10
-import QuSelect from './components/QuSelect';
12
+import Footer from './components/Footer/index';
11 13
 
12 14
 export default (props) => {
13 15
 
@@ -15,30 +17,108 @@ export default (props) => {
15 17
   const { id } = router.params;
16 18
 
17 19
   const [loading, setLoading] = React.useState(false);
20
+  const [readonly, setReadonly] = React.useState(false);
18 21
   const [checkItemInfo, setCheckItemInfo] = React.useState();
19 22
   const [quList, setQuList] = React.useState([]);
20 23
   const [index, setIndex] = React.useState(-1);
24
+  const [answer, setAnswer] = React.useState();
21 25
 
22
-  const onPreFormSubmit = () => {
23
-    setIndex(0);
26
+  const onIndexChange = (n) => {
27
+    if (index == -1 && n != -1) {
28
+      if (!readonly) {
29
+        if (!answer?.addr) {
30
+          Notify.show({
31
+            message: '请填写地址',
32
+            type: 'warning',
33
+          })
34
+          return;
35
+        }
36
+        if (!answer?.location) {
37
+          Notify.show({
38
+            message: '未能获取定位信息, 请重试',
39
+            type: 'warning',
40
+          })
41
+          return;
42
+        }
43
+      }
44
+    }
45
+
46
+    setIndex(n);
24 47
   }
25 48
 
26
-  const onIndexChange = (t, n) => {
27
-    // eslint-disable-next-line no-restricted-globals
28
-    if (isNaN(t)) {
29
-      setIndex(index + n);
49
+  const onAnswerItemChange = (answerItem, quInfo) => {
50
+    const an = {...(answer || {})}
51
+    const answerItemList = an.answerItemList || []
52
+
53
+    if ((answerItem.answerCode || answerItem.answer) &&
54
+      answerItem.attachList?.length) {
55
+        // 说明这一题已经回答完毕
56
+        quInfo.finished = true
57
+      } else {
58
+        quInfo.finished = false
59
+      }
60
+    
61
+    // 更新问题列表中是否作答的标志位
62
+    setQuList(quList.map(x => x.quId == quInfo.quId ? quInfo : x));
63
+
64
+    if (answerItemList.length) {
65
+      let found = false;
66
+      an.answerItemList = answerItemList.map(x => {
67
+        if (x.quId == answerItem.quId) {
68
+          found = true;
69
+          return answerItem;
70
+        } else {
71
+          return x;
72
+        }
73
+      });
74
+
75
+      if (!found) {
76
+        answerItemList.push(answerItem);
77
+        an.answerItemList = answerItemList;
78
+      }
30 79
     } else {
31
-      setIndex(t);
80
+      answerItemList.push(answerItem);
81
+      an.answerItemList = answerItemList;
32 82
     }
83
+
84
+    setAnswer(an);
85
+  }
86
+
87
+  // 作答
88
+  const onSubmit = () => {
89
+
33 90
   }
34 91
 
35 92
   React.useEffect(() => {
36 93
     setLoading(true);
37
-    preCheck(id, { noSuccesTip: true }).then(() => {
94
+    preCheck(id, { noSuccesTip: true }).then((checkRes) => {
95
+      if (checkRes.errorCode < 0) {
96
+        Notify.show({
97
+          message: checkRes.message,
98
+          type: 'warning',
99
+        })
100
+
101
+        Taro.navigateBack({delta: 1})
102
+        return;
103
+      }
104
+
105
+      if (checkRes.errorCode > 0) {
106
+        setReadonly(true);
107
+        // Notify.show({
108
+        //   message: checkRes.message,
109
+        //   type: 'warning',
110
+        // })
111
+      }
112
+
113
+      // 查询当前测评点位(问卷)主记录
38 114
       getTaCheckItemById(id).then(res => {
39 115
         setCheckItemInfo(res);
40 116
       });
117
+      
118
+      // 查询我的答案
119
+      getTaCheckItemAnswer(id).then(setAnswer);
41 120
   
121
+      // 查询当前测评主记录的所有问题
42 122
       getTaCheckItemQu({pageSize: 200, itemId: id}).then(res => {
43 123
         setLoading(false);
44 124
         setQuList(res.records || []);
@@ -51,34 +131,50 @@ export default (props) => {
51 131
   }, [id]);
52 132
   
53 133
   return (
54
-    <Page loading={loading}>
134
+    <Page loading={loading} roles={[ROLE_INSPECTOR]}>
55 135
       <VABC
56
-        footer={
57
-          index > -1 && (
58
-            <QuSelect
59
-              value={index}
60
-              list={quList}
61
-              onChnage={onIndexChange}
62
-            />
63
-          )
64
-        }
136
+        footer={(
137
+          <Footer
138
+            value={index}
139
+            readonly={readonly}
140
+            list={quList}
141
+            onChange={onIndexChange}
142
+            onSubmit={onSubmit}
143
+          />
144
+        )}
65 145
       >
66 146
       {
67
-        index == -1 && <LocForm detail={checkItemInfo} onDetailChange={setCheckItemInfo} onClick={onPreFormSubmit} />
147
+        index == -1 && (
148
+          <LocForm
149
+            readonly={readonly}
150
+            checkItemInfo={checkItemInfo}
151
+            answer={answer}
152
+            onChange={setAnswer}
153
+            onLoadingChange={setLoading}
154
+          />
155
+        )
68 156
       }
69 157
       {
70
-        quList.map((x, inx) => (
71
-          index == inx && (
72
-            <Question
73
-              key={x.quId}
74
-              detail={x}
75
-              cursor={inx}
76
-              total={quList?.length}
77
-              onPrev={() => onIndexChange(null, -1)}
78
-              onNext={() => onIndexChange(null, 1)}
79
-            />
158
+        quList.map((x, inx) => {
159
+          const answerItem = answer?.answerItemList?.filter(y => y.quId == x.quId)[0];
160
+
161
+          return (
162
+            index == inx && (
163
+              <Question
164
+                key={x.quId}
165
+                cursor={inx}
166
+                readonly={readonly}
167
+                quInfo={x}
168
+                answerItem={answerItem}
169
+                total={quList?.length}
170
+                onChange={e => onAnswerItemChange(e, x)}
171
+                onPrev={() => onIndexChange(null, -1)}
172
+                onNext={() => onIndexChange(null, 1)}
173
+                onLoadingChange={setLoading}
174
+              />
175
+            )
80 176
           )
81
-        ))
177
+        })
82 178
       }
83 179
       </VABC>
84 180
     </Page>

+ 5
- 0
src/services/tacheckitem.js Visa fil

@@ -29,3 +29,8 @@ export const putTaCheckItem = (id, data) => request(`/api/taCheckItem/${id}`, {
29 29
 export const deleteTaCheckItem = (id) => request(`/api/taCheckItem/${id}`, { method: 'delete' });
30 30
 
31 31
 export const preCheck = (id, opts = {}) => request(`/api/taCheckItem/${id}/answer/pre-check`, { method: 'put', ...opts });
32
+
33
+/*
34
+ * 获取当前答案
35
+ */
36
+export const getTaCheckItemAnswer = (id) => request(`/api/taCheckItem/${id}/answer`);