ソースを参照

Merge branch 'master' of http://git.ycjcjy.com/nanyang/data-collect-miniapp

fangmingyue 2 年 前
コミット
418f2c6be3
共有12 個のファイルを変更した259 個の追加11 個の削除を含む
  1. 3
    1
      .eslintrc
  2. 1
    1
      project.config.json
  3. 2
    1
      src/app.config.js
  4. 9
    0
      src/app.less
  5. 31
    0
      src/components/Uploader.jsx
  6. 103
    4
      src/pages/index/index.jsx
  7. 30
    0
      src/pages/index/index.less
  8. 3
    0
      src/services/bind.js
  9. 5
    0
      src/services/upload.js
  10. 45
    4
      src/utils/request.js
  11. 7
    0
      src/utils/useForceUpdate.js
  12. 20
    0
      src/utils/useRequest.js

+ 3
- 1
.eslintrc ファイルの表示

2
   "extends": ["taro/react"],
2
   "extends": ["taro/react"],
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
+    "jsx-quotes": "off",
7
+    "no-unused-vars": "warn"
6
   }
8
   }
7
 }
9
 }

+ 1
- 1
project.config.json ファイルの表示

2
   "miniprogramRoot": "./dist",
2
   "miniprogramRoot": "./dist",
3
   "projectname": "myApp",
3
   "projectname": "myApp",
4
   "description": "xiaofang",
4
   "description": "xiaofang",
5
-  "appid": "touristappid",
5
+  "appid": "wx1a0fa56e6d0b78b3",
6
   "setting": {
6
   "setting": {
7
     "urlCheck": true,
7
     "urlCheck": true,
8
     "es6": false,
8
     "es6": false,

+ 2
- 1
src/app.config.js ファイルの表示

5
   ],
5
   ],
6
   window: {
6
   window: {
7
     backgroundTextStyle: 'light',
7
     backgroundTextStyle: 'light',
8
+    backgroundColor: '#F7F8FA',
8
     navigationBarBackgroundColor: '#fff',
9
     navigationBarBackgroundColor: '#fff',
9
     navigationBarTitleText: 'WeChat',
10
     navigationBarTitleText: 'WeChat',
10
-    navigationBarTextStyle: 'black'
11
+    navigationBarTextStyle: 'black'    
11
   },
12
   },
12
   tabBar: {
13
   tabBar: {
13
     list: [{
14
     list: [{

+ 9
- 0
src/app.less ファイルの表示

1
+page {
2
+  width: 100%;
3
+  height: 100%;
4
+  background-color: #F7F8FA;
5
+}
6
+
7
+form {
8
+  display: block;
9
+}

+ 31
- 0
src/components/Uploader.jsx ファイルの表示

1
+import React from 'react';
2
+import { Uploader } from '@antmjs/vantui';
3
+import upload from '@/services/upload';
4
+
5
+export default (props) => {
6
+
7
+  const { value, onChange } = props;
8
+
9
+  const fileList = React.useMemo(() => {
10
+    return value ? [{ url: value }] : []
11
+  }, [value]);
12
+  
13
+  const onAfterRead = (e) => {
14
+    const { file } = e.detail;
15
+    upload(file.url).then(v => onChange({ detail: v }));
16
+  }
17
+
18
+  const onDelete = () => {
19
+    onChange({ detail: undefined });
20
+  }
21
+
22
+  return (
23
+    <Uploader
24
+      multiple={false}
25
+      accept="image"
26
+      fileList={fileList}
27
+      onAfterRead={onAfterRead}
28
+      onDelete={onDelete}
29
+    />
30
+  )
31
+}

+ 103
- 4
src/pages/index/index.jsx ファイルの表示

1
-import { Component } from 'react'
2
-import { View } from '@tarojs/components'
3
-import { Button } from '@antmjs/vantui'
1
+import React from 'react';
2
+import Taro from '@tarojs/taro';
3
+import { View } from '@tarojs/components';
4
+import Uploader from '@/components/Uploader';
5
+import { Button, Form, FormItem, Radio, RadioGroup, Icon, Field } from '@antmjs/vantui';
6
+import { saveBind } from '@/services/bind';
7
+import useRequest from '@/utils/useRequest';
4
 import './index.less'
8
 import './index.less'
5
 
9
 
6
 export default (props) => {
10
 export default (props) => {
11
+  const form = Form.useForm();
12
+
13
+  const [loading, request] = useRequest(saveBind);
14
+
15
+  const onScan = () => {
16
+    Taro.scanCode({
17
+      success: ({ result }) => {
18
+        form.setFieldsValue('deviceNo', result);
19
+      },
20
+      fail: (err) => {
21
+        console.error(err);
22
+      }
23
+    })
24
+  }
25
+
26
+  const onFinish = (errs, values) => {
27
+    console.log(errs, values);
28
+    if (!errs) {
29
+      request(values).then(res => {
30
+        Taro.switchTab({
31
+          url: '/pages/mine/index',
32
+        });
33
+      });
34
+    }
35
+  }
7
 
36
 
8
   return (
37
   return (
9
     <View>
38
     <View>
10
-      <Button type="warning">123</Button>
39
+      <Form className="bind-form" form={form} onFinish={onFinish}>
40
+        <FormItem
41
+          required
42
+          label="设备类型"
43
+          name="deviceType"
44
+          validateTrigger="onBlur"
45
+        >
46
+          <RadioGroup direction="horizontal">
47
+            <Radio name="shensong" checkedColor="#07c160">深松</Radio>
48
+            <Radio name="feifang" checkedColor="#07c160">飞防</Radio>
49
+          </RadioGroup>
50
+        </FormItem>
51
+        <FormItem
52
+          required
53
+          label="设备编号"
54
+          name="deviceNo"
55
+          validateTrigger="onBlur"
56
+          renderRight={<View className='scan-btn' onClick={onScan} ><Icon name="scan" size="18px" /></View>}
57
+        >
58
+          <Field placeholder="请输入" clearable />
59
+        </FormItem>
60
+        <FormItem
61
+          required
62
+          label="农机编号"
63
+          name="machineryName"
64
+          validateTrigger="onBlur"
65
+        >
66
+          <Field placeholder="请输入" clearable />
67
+        </FormItem>
68
+        <FormItem
69
+          required
70
+          label="农机图片"
71
+          name="machineryThumb"
72
+        >
73
+          <Uploader />
74
+        </FormItem>
75
+        <FormItem
76
+          required
77
+          label="归 属 人"
78
+          name="userName"
79
+          validateTrigger="onBlur"
80
+        >
81
+          <Field placeholder="请输入" clearable />
82
+        </FormItem>
83
+        <FormItem
84
+          required
85
+          label="手 机 号"
86
+          name="phone"
87
+          validateTrigger="onBlur"
88
+        >
89
+          <Field placeholder="请输入" clearable />
90
+        </FormItem>
91
+        <FormItem
92
+          required
93
+          label="身 份 证"
94
+          name="idCard"
95
+          validateTrigger="onBlur"
96
+        >
97
+          <Field placeholder="请输入" clearable />
98
+        </FormItem>
99
+        <View className="submit-wrapper">
100
+          <Button
101
+            block
102
+            type="primary"
103
+            formType="submit"
104
+            loading={loading}
105
+          >
106
+            提交
107
+          </Button>
108
+        </View>
109
+      </Form>
11
     </View>
110
     </View>
12
   )
111
   )
13
 }
112
 }

+ 30
- 0
src/pages/index/index.less ファイルの表示

1
+
2
+.bind-form {
3
+  background: #fff;
4
+  border-radius: 16px;
5
+  margin: 0 1em;
6
+  width: calc(100% - 2em);
7
+  overflow: hidden;
8
+
9
+  .scan-btn {
10
+    padding: 0 24px;
11
+  }
12
+
13
+  .submit-wrapper {
14
+    padding: 48px;
15
+  }
16
+  
17
+  .vant-form-formItem {
18
+    border-bottom: 1px solid rgb(235, 237, 240);
19
+  }
20
+
21
+  .van-field {
22
+    padding: 0;
23
+  }
24
+
25
+  .van-cell {
26
+    &::after {
27
+      border: 0;
28
+    }
29
+  }
30
+}

+ 3
- 0
src/services/bind.js ファイルの表示

1
+import request from "@/utils/request";
2
+
3
+export const saveBind = data => request('/tcBind', { method: 'post', data })

+ 5
- 0
src/services/upload.js ファイルの表示

1
+import { upload } from "@/utils/request";
2
+
3
+export default (filePath) => {
4
+  return upload('/image', filePath);
5
+}

+ 45
- 4
src/utils/request.js ファイルの表示

19
   return arr.filter(Boolean).join('&')
19
   return arr.filter(Boolean).join('&')
20
 }
20
 }
21
 
21
 
22
+export function upload(url, tempFilePath) {
23
+  return new Promise((resolve, reject) => {
24
+    Taro.uploadFile({
25
+      // eslint-disable-next-line no-undef
26
+      url: `${HOST}/api/${url}`.replace('api//', 'api/'),
27
+      filePath: tempFilePath,
28
+      name: 'file',
29
+      success: (res) => {
30
+        const { data, code, message } = JSON.parse(res.data);
31
+        if (code === 1000) {
32
+          resolve(data);
33
+        } else {
34
+          reject(message);
35
+          Taro.showToast({
36
+            title: message,
37
+            icon: 'none',
38
+          })
39
+        }
40
+      },
41
+      fail: (err) => {
42
+        console.error(err);
43
+        const errMsg = err.message || err.msg || err.errMsg || err;
44
+        reject(errMsg);
45
+        Taro.showToast({
46
+          title: errMsg,
47
+          icon: 'none',
48
+        })
49
+      }
50
+    });
51
+  });
52
+}
53
+
22
 
54
 
23
 export default (url, options) => {
55
 export default (url, options) => {
24
-  const { params, skipError, header, ...leftOptions } = options || {}
56
+  const { params, skipError, header, method = 'GET', ...leftOptions } = options || {}
25
   const queryStr = getQueryString(params)
57
   const queryStr = getQueryString(params)
26
 
58
 
27
   const urlWithParams = queryStr ? `${url}?${queryStr}` : url;
59
   const urlWithParams = queryStr ? `${url}?${queryStr}` : url;
28
   // eslint-disable-next-line no-undef
60
   // eslint-disable-next-line no-undef
29
-  const nwUrl = `${HOST}/api/${urlWithParams}`
61
+  const nwUrl = `${HOST}/api/${urlWithParams}`.replace('api//', 'api/');
30
 
62
 
31
   const authToken = Taro.getStorageSync('token')
63
   const authToken = Taro.getStorageSync('token')
32
   const tokenHeader = authToken ? { Authorization: authToken } : {}
64
   const tokenHeader = authToken ? { Authorization: authToken } : {}
39
     Taro.request({
71
     Taro.request({
40
       ...leftOptions,
72
       ...leftOptions,
41
       url: nwUrl,
73
       url: nwUrl,
74
+      method,
42
       header: nwHeader,
75
       header: nwHeader,
43
       success: (res) => {
76
       success: (res) => {
44
         const { code, message, data, token } = res.data
77
         const { code, message, data, token } = res.data
48
         }
81
         }
49
 
82
 
50
         if (code === 1000) {
83
         if (code === 1000) {
51
-          resolve(data)
84
+          resolve(data);
85
+
86
+          if (['post', 'put', 'delete'].indexOf(method.toLocaleLowerCase()) > -1) {
87
+            Taro.showToast({
88
+              title: '操作成功',
89
+              icon: 'success',
90
+              duration: 2000
91
+            });            
92
+          }
52
 
93
 
53
         } else {
94
         } else {
54
           if (!skipError) {
95
           if (!skipError) {
64
       fail: (err) => {
105
       fail: (err) => {
65
         console.error(err)
106
         console.error(err)
66
 
107
 
67
-        const message = err.message || err.errMsg || err
108
+        const message = err.message || err.errMsg || err || '服务不存在或异常'
68
 
109
 
69
         if (!skipError) {
110
         if (!skipError) {
70
           Taro.showToast({
111
           Taro.showToast({

+ 7
- 0
src/utils/useForceUpdate.js ファイルの表示

1
+import React from "react";
2
+
3
+export function useForceUpdate() {
4
+  const [, forceUpdate] = React.useReducer(x => x + 1, 0);
5
+
6
+  return forceUpdate;
7
+}

+ 20
- 0
src/utils/useRequest.js ファイルの表示

1
+import React from "react";
2
+
3
+export default function useRequest(api) {
4
+  const [loading, setLoading] = React.useState(false);
5
+
6
+  const request = React.useCallback((...args) => {
7
+    return new Promise((resovle, reject) => {
8
+      setLoading(true);
9
+      api(...args).then(res => {
10
+        setLoading(false);
11
+        resovle(res);
12
+      }).catch(er => {
13
+        reject(er);
14
+        setLoading(false);
15
+      })
16
+    });
17
+  }, [api]);
18
+
19
+  return [loading, request];
20
+}