张延森 5 anos atrás
pai
commit
1ceb0c3e9d

+ 8
- 50
config/config.js Ver arquivo

@@ -1,4 +1,5 @@
1 1
 import defaultSettings from './defaultSettings'; // https://umijs.org/config/
2
+import routes from './routes';
2 3
 
3 4
 import slash from 'slash2';
4 5
 import webpackPlugin from './plugin.config';
@@ -82,50 +83,7 @@ export default {
82 83
   },
83 84
   devtool: isAntDesignProPreview ? 'source-map' : false,
84 85
   // umi routes: https://umijs.org/zh/guide/router.html
85
-  routes: [
86
-    {
87
-      path: '/user',
88
-      component: '../layouts/UserLayout',
89
-      routes: [
90
-        {
91
-          name: 'login',
92
-          path: '/user/login',
93
-          component: './user/login',
94
-        },
95
-      ],
96
-    },
97
-    {
98
-      path: '/',
99
-      component: '../layouts/SecurityLayout',
100
-      routes: [
101
-        {
102
-          path: '/',
103
-          component: '../layouts/BasicLayout',
104
-          authority: ['admin', 'user'],
105
-          routes: [
106
-            {
107
-              path: '/',
108
-              redirect: '/org',
109
-            },
110
-            {
111
-              path: '/org',
112
-              name: '账户管理',
113
-              component: './UserManage',
114
-            },
115
-            {
116
-              component: './404',
117
-            },
118
-          ],
119
-        },
120
-        {
121
-          component: './404',
122
-        },
123
-      ],
124
-    },
125
-    {
126
-      component: './404',
127
-    },
128
-  ],
86
+  routes,
129 87
   // Theme for antd: https://ant.design/docs/react/customize-theme-cn
130 88
   theme: {
131 89
     'primary-color': primaryColor,
@@ -168,13 +126,13 @@ export default {
168 126
     basePath: '/',
169 127
   },
170 128
   chainWebpack: webpackPlugin,
171
-  /*
129
+
172 130
   proxy: {
173
-    '/server/api/': {
174
-      target: 'https://preview.pro.ant.design/',
131
+    '/api': {
132
+      target: 'http://localhost:8080/',
175 133
       changeOrigin: true,
176
-      pathRewrite: { '^/server': '' },
134
+      // pathRewrite: { '^/server': '' },
177 135
     },
178
-  },
179
-  */
136
+  }
137
+  
180 138
 };

+ 54
- 0
config/routes.js Ver arquivo

@@ -0,0 +1,54 @@
1
+export default [
2
+  {
3
+    path: '/user',
4
+    component: '../layouts/UserLayout',
5
+    routes: [
6
+      {
7
+        name: 'login',
8
+        path: '/user/login',
9
+        component: './user/login',
10
+      },
11
+    ],
12
+  },
13
+  {
14
+    path: '/',
15
+    component: '../layouts/SecurityLayout',
16
+    routes: [
17
+      {
18
+        path: '/',
19
+        component: '../layouts/BasicLayout',
20
+        authority: ['admin', 'user'],
21
+        routes: [
22
+          {
23
+            path: '/',
24
+            redirect: '/member',
25
+          },
26
+          {
27
+            path: '/member',
28
+            name: '账户管理',
29
+            component: './UserManage',
30
+          },
31
+          {
32
+            path: '/member/new',
33
+            name: '账户新增',
34
+            component: './UserManage/Editor',
35
+          },
36
+          {
37
+            path: '/member/edit/:id',
38
+            name: '账户编辑',
39
+            component: './UserManage/Editor',
40
+          },
41
+          {
42
+            component: './404',
43
+          },
44
+        ],
45
+      },
46
+      {
47
+        component: './404',
48
+      },
49
+    ],
50
+  },
51
+  {
52
+    component: './404',
53
+  },
54
+];

+ 1
- 0
package.json Ver arquivo

@@ -52,6 +52,7 @@
52 52
     "classnames": "^2.2.6",
53 53
     "dva": "^2.4.1",
54 54
     "lodash": "^4.17.11",
55
+    "md5": "^2.2.1",
55 56
     "moment": "^2.24.0",
56 57
     "omit.js": "^1.0.2",
57 58
     "path-to-regexp": "^3.0.0",

+ 8
- 0
src/app.js Ver arquivo

@@ -0,0 +1,8 @@
1
+export const dva = {
2
+  config: {
3
+    onError(e) {
4
+      e.preventDefault();
5
+      console.error(e.message);
6
+    },
7
+  },
8
+};

BIN
src/components/XForm.rar Ver arquivo


+ 56
- 0
src/components/XForm/ImageUpload.jsx Ver arquivo

@@ -0,0 +1,56 @@
1
+import React from 'react';
2
+import { Upload, Icon, message } from 'antd';
3
+import './style.less';
4
+
5
+class ImageUpload extends React.Component {
6
+  state = {
7
+    loading: false
8
+  };
9
+
10
+  handleChange = info => {
11
+    if (info.file.status === "uploading") {
12
+      this.setState({ loading: true });
13
+      return;
14
+    }
15
+
16
+    if (info.file.status === "done") {
17
+      const imageUrl = info.response.url
18
+
19
+      this.setState({
20
+        loading: false
21
+      })
22
+
23
+      this.props.onChange(imageUrl)
24
+    }
25
+  };
26
+
27
+  render () {
28
+    const uploadButton = (
29
+      <div>
30
+        <Icon style={{ fontSize: '2em', color: '#aaa' }} type={this.state.loading ? "loading" : "plus"} />        
31
+      </div>
32
+    );
33
+
34
+    const value = this.props.value;
35
+
36
+    return (
37
+      <Upload
38
+        name="avatar"
39
+        listType="picture-card"
40
+        className="avatar-uploader"
41
+        showUploadList={false}
42
+        action={this.props.action}
43
+        beforeUpload={this.props.beforeUpload}
44
+        onChange={this.handleChange}
45
+      >
46
+        {value ? (
47
+          <img src={value} alt="avatar" style={{ width: "100%" }} />
48
+        ) : (
49
+          uploadButton
50
+        )}
51
+      </Upload>
52
+    );
53
+  }
54
+}
55
+
56
+export default ImageUpload;

+ 31
- 0
src/components/XForm/README.md Ver arquivo

@@ -0,0 +1,31 @@
1
+# XForm
2
+Antd Form 扩展
3
+
4
+## 使用说明
5
+
6
+```jsx
7
+import XForm, { FieldTypes } from '/path/to/XForm';
8
+
9
+const tplJSON = [
10
+  {},
11
+  {}
12
+]
13
+
14
+```
15
+
16
+通过 `json` 对象来实现自动构造 form 表单
17
+
18
+计划支持的属性
19
+
20
+[] label      显示的文字
21
+
22
+[] name       form name, 用于表单提交
23
+
24
+[] type       组件类型, 参见 FieldTypes
25
+
26
+[] rules      校验规则
27
+
28
+[] element    函数, 用于生成组件. (props) => <></> . 其中 props 包含 ...
29
+
30
+[] value      绑定的数据
31
+

+ 81
- 0
src/components/XForm/WrapperForm.jsx Ver arquivo

@@ -0,0 +1,81 @@
1
+import React from 'react';
2
+import PropTypes from 'prop-types';
3
+import { Form, Button } from 'antd';
4
+import WrapperItem from './WrapperItem';
5
+
6
+const formItemLayout = {
7
+  labelCol: {
8
+    xs: { span: 24 },
9
+    sm: { span: 8 },
10
+  },
11
+  wrapperCol: {
12
+    xs: { span: 24 },
13
+    sm: { span: 16 },
14
+  },
15
+};
16
+
17
+class WrapperForm extends React.Component {
18
+  constructor(props) {
19
+    super(props);
20
+
21
+    this.state = {}
22
+  }
23
+
24
+  handleSubmit = e => {
25
+    e.preventDefault();
26
+    this.props.form.validateFieldsAndScroll((err, values) => {
27
+      if (err) {
28
+        if (typeof this.props.onError === 'function') {
29
+          typeof this.props.onError(err)
30
+        } else {
31
+          window.console.error(err)
32
+        }
33
+      } else {
34
+        if (typeof this.props.onSubmit === 'function') {
35
+          typeof this.props.onSubmit(values)
36
+        }
37
+      }
38
+    });
39
+  }
40
+
41
+  handleCancel = e => {
42
+    e.preventDefault();
43
+
44
+    if (typeof this.props.onCancel === 'function') {
45
+      typeof this.props.onCancel()
46
+    }
47
+  }
48
+
49
+  renderDefaultAction = (submitBtn, cancelBtn) => {
50
+    let FieldSubmit = null
51
+    let FieldCancel = null
52
+    if (submitBtn !== false) {
53
+      FieldSubmit = <Button htmlType="submit" type="primary">提交</Button>
54
+    }
55
+    if (cancelBtn !== false) {
56
+      FieldCancel = <Button htmlType="button" onClick={this.handleCancel} style={{ marginLeft: '48px' }}>取消</Button>
57
+    }
58
+
59
+    return FieldSubmit || FieldCancel ? <WrapperItem action render={<>{FieldSubmit}{FieldCancel}</>} /> : null
60
+  }
61
+
62
+  render () {
63
+    const {fields, form, children, submitBtn, cancelBtn, ...formProps} = this.props;
64
+
65
+    const FeildItems = (fields || []).map((props, inx) => (<WrapperItem key={inx} {...props} form={form} />))
66
+    
67
+    return (
68
+      <Form {...formItemLayout} {...formProps} onSubmit={this.handleSubmit}>
69
+        {FeildItems}
70
+        {this.renderDefaultAction(submitBtn, cancelBtn)}
71
+        {children}
72
+      </Form>
73
+    );
74
+  }
75
+}
76
+
77
+WrapperForm.propTypes = {
78
+  fields: PropTypes.array.isRequired
79
+}
80
+
81
+export default WrapperForm;

+ 141
- 0
src/components/XForm/WrapperItem.jsx Ver arquivo

@@ -0,0 +1,141 @@
1
+import React from 'react';
2
+import {
3
+  Form,
4
+  Input,
5
+  InputNumber,
6
+  Checkbox,
7
+  Radio,
8
+  DatePicker,
9
+  TimePicker,
10
+  Select,
11
+} from 'antd';
12
+import ImageUploader from './ImageUpload';
13
+
14
+const Item = Form.Item
15
+const { Option } = Select;
16
+const { MonthPicker, RangePicker } = DatePicker
17
+
18
+const FieldTypes = {
19
+  Text: 'Text',
20
+  Password: 'Password',
21
+  Number: 'Number',
22
+  Switch: 'Switch',
23
+  TimePicker: 'TimePicker',
24
+  DatePicker: 'DatePicker',
25
+  RangePicker: 'RangePicker',
26
+  MonthPicker: 'MonthPicker',
27
+  Select: 'Select',
28
+  ImageUploader: 'ImageUploader',
29
+}
30
+
31
+const tailFormItemLayout = {
32
+  wrapperCol: {
33
+    xs: {
34
+      span: 24,
35
+      offset: 0,
36
+    },
37
+    sm: {
38
+      span: 16,
39
+      offset: 8,
40
+    },
41
+  },
42
+};
43
+
44
+const WrapperItem = (props) => {
45
+  const {
46
+    form,
47
+    label,
48
+    name,
49
+    type,
50
+    placeholder,
51
+    render,
52
+    rules,
53
+    value,
54
+    dict,
55
+    action,
56
+    props: fieldProps,
57
+    ...restProps
58
+  } = props;
59
+
60
+  const { getFieldDecorator } = form || {};
61
+
62
+  let config = {
63
+    rules,
64
+    initialValue: value
65
+  }
66
+
67
+  if (type === FieldTypes.Switch) {
68
+    config = {
69
+      ...config,
70
+      valuePropName: 'checked',
71
+    };
72
+  }
73
+  
74
+  if (type === FieldTypes.ImageUploader) {
75
+    config = {
76
+      ...config,
77
+      getValueFromEvent: x => x,
78
+    };
79
+  }
80
+
81
+  // 没有类型与组件, 生成隐藏字段
82
+  if (!type && !render) {
83
+    getFieldDecorator(name, config);
84
+    return <></>;
85
+  }
86
+
87
+  const SelectOpts = (dict || []).map((item, index) => (<Option value={item.value}>{item.name}</Option>))
88
+
89
+  let Field = <></>;
90
+  if (render) {
91
+    Field = typeof render === 'function' ? render(props) : render
92
+  } else {
93
+    switch (type) {
94
+      case FieldTypes.Text:
95
+        Field = <Input placeholder={placeholder} style={{ width: '100%' }} {...fieldProps}/>;
96
+        break;
97
+      case FieldTypes.Password:
98
+        Field = <Input.Password placeholder={placeholder} style={{ width: '100%' }} {...fieldProps}/>;
99
+        break;
100
+      case FieldTypes.Number:
101
+        Field = <InputNumber placeholder={placeholder} style={{ width: '100%' }} {...fieldProps}/>;
102
+        break;
103
+      case FieldTypes.Switch:
104
+        Field = <Switch {...fieldProps} />;
105
+        break;
106
+      case FieldTypes.TimePicker:
107
+        Field = <TimePicker {...fieldProps} style={{ width: '100%' }}/>;
108
+        break;
109
+      case FieldTypes.DatePicker:
110
+        Field = <DatePicker {...fieldProps} style={{ width: '100%' }}/>;
111
+        break;
112
+      case FieldTypes.RangePicker:
113
+        Field = <RangePicker {...fieldProps} style={{ width: '100%' }}/>;
114
+        break;
115
+      case FieldTypes.MonthPicker:
116
+        Field = <MonthPicker {...fieldProps} style={{ width: '100%' }}/>;
117
+        break;
118
+      case FieldTypes.Select:
119
+        Field = <Select placeholder={placeholder} style={{ width: '100%' }} {...fieldProps}>{SelectOpts}</Select>
120
+        break;
121
+      case FieldTypes.ImageUploader:
122
+        Field = <ImageUploader {...fieldProps}/>
123
+        break;
124
+      default:
125
+        throw new Error(`暂时不支持的组件类型: ${type}`)
126
+    }
127
+  }
128
+
129
+  if (!label && !name && !action) return Field;
130
+  
131
+  const itemProps = action ? { ...restProps, ...tailFormItemLayout } : restProps
132
+
133
+  return (
134
+    <Item label={label} {...itemProps}>
135
+      {action ? Field : getFieldDecorator(name, config)(Field)}
136
+    </Item>
137
+  )
138
+};
139
+
140
+export default WrapperItem;
141
+export { FieldTypes };

+ 7
- 0
src/components/XForm/index.jsx Ver arquivo

@@ -0,0 +1,7 @@
1
+import React from 'react';
2
+import { Form } from 'antd';
3
+import WrapperForm from './WrapperForm';
4
+import { FieldTypes } from './WrapperItem';
5
+
6
+export default Form.create()(WrapperForm);
7
+export { FieldTypes };

+ 8
- 0
src/components/XForm/style.less Ver arquivo

@@ -0,0 +1,8 @@
1
+:global {
2
+  .avatar-uploader {
3
+    & > .ant-upload {
4
+      width: 128px;
5
+      height: 128px;
6
+    }
7
+  }
8
+}

+ 1
- 1
src/layouts/BasicLayout.jsx Ver arquivo

@@ -113,7 +113,7 @@ const BasicLayout = props => {
113 113
       }}
114 114
       footerRender={footerRender}
115 115
       menuDataRender={menuDataRender}
116
-      formatMessage={formatMessage}
116
+      // formatMessage={formatMessage}
117 117
       rightContentRender={rightProps => <RightContent {...rightProps} />}
118 118
       {...props}
119 119
       {...settings}

+ 2
- 2
src/layouts/SecurityLayout.jsx Ver arquivo

@@ -25,11 +25,11 @@ class SecurityLayout extends React.Component {
25 25
     const { isReady } = this.state;
26 26
     const { children, loading, currentUser } = this.props;
27 27
 
28
-    if ((!currentUser.userid && loading) || !isReady) {
28
+    if ((!currentUser.userName && loading) || !isReady) {
29 29
       return <PageLoading />;
30 30
     }
31 31
 
32
-    if (!currentUser.userid) {
32
+    if (!currentUser.userName) {
33 33
       return <Redirect to="/user/login"></Redirect>;
34 34
     }
35 35
 

+ 22
- 19
src/models/login.js Ver arquivo

@@ -1,8 +1,11 @@
1 1
 import { routerRedux } from 'dva/router';
2 2
 import { stringify } from 'querystring';
3
-import { fakeAccountLogin, getFakeCaptcha } from '@/services/login';
4 3
 import { setAuthority } from '@/utils/authority';
5 4
 import { getPageQuery } from '@/utils/utils';
5
+
6
+import request from '../utils/request';
7
+import apis from '../services/apis';
8
+
6 9
 const Model = {
7 10
   namespace: 'login',
8 11
   state: {
@@ -10,34 +13,34 @@ const Model = {
10 13
   },
11 14
   effects: {
12 15
     *login({ payload }, { call, put }) {
13
-      const response = yield call(fakeAccountLogin, payload);
16
+      const response = yield call(request, { ...apis.user.login, data: payload });
14 17
       yield put({
15 18
         type: 'changeLoginStatus',
16 19
         payload: response,
17 20
       }); // Login successfully
18 21
 
19
-      if (response.status === 'ok') {
20
-        const urlParams = new URL(window.location.href);
21
-        const params = getPageQuery();
22
-        let { redirect } = params;
22
+      const urlParams = new URL(window.location.href);
23
+      const params = getPageQuery();
24
+      let { redirect } = params;
23 25
 
24
-        if (redirect) {
25
-          const redirectUrlParams = new URL(redirect);
26
+      if (redirect) {
27
+        const redirectUrlParams = new URL(redirect);
26 28
 
27
-          if (redirectUrlParams.origin === urlParams.origin) {
28
-            redirect = redirect.substr(urlParams.origin.length);
29
+        if (redirectUrlParams.origin === urlParams.origin) {
30
+          redirect = redirect.substr(urlParams.origin.length);
29 31
 
30
-            if (redirect.match(/^\/.*#/)) {
31
-              redirect = redirect.substr(redirect.indexOf('#') + 1);
32
-            }
33
-          } else {
34
-            window.location.href = redirect;
35
-            return;
32
+          if (redirect.match(/^\/.*#/)) {
33
+            redirect = redirect.substr(redirect.indexOf('#') + 1);
36 34
           }
35
+        } else {
36
+          window.location.href = redirect;
37
+          return;
37 38
         }
38
-
39
-        yield put(routerRedux.replace(redirect || '/'));
40 39
       }
40
+
41
+      console.log('----------> redirect ')
42
+
43
+      yield put(routerRedux.replace(redirect || '/'));
41 44
     },
42 45
 
43 46
     *getCaptcha({ payload }, { call }) {
@@ -62,7 +65,7 @@ const Model = {
62 65
   reducers: {
63 66
     changeLoginStatus(state, { payload }) {
64 67
       setAuthority(payload.currentAuthority);
65
-      return { ...state, status: payload.status, type: payload.type };
68
+      return { ...state, status: 'ok', type: payload.type };
66 69
     },
67 70
   },
68 71
 };

+ 5
- 10
src/models/user.js Ver arquivo

@@ -1,20 +1,15 @@
1
-import { queryCurrent, query as queryUsers } from '@/services/user';
1
+import request from '../utils/request';
2
+import apis from '../services/apis';
3
+
2 4
 const UserModel = {
3 5
   namespace: 'user',
4 6
   state: {
5 7
     currentUser: {},
6 8
   },
7 9
   effects: {
8
-    *fetch(_, { call, put }) {
9
-      const response = yield call(queryUsers);
10
-      yield put({
11
-        type: 'save',
12
-        payload: response,
13
-      });
14
-    },
15
-
16 10
     *fetchCurrent(_, { call, put }) {
17
-      const response = yield call(queryCurrent);
11
+      const response = yield call(request, apis.user.current);
12
+
18 13
       yield put({
19 14
         type: 'saveCurrentUser',
20 15
         payload: response,

+ 49
- 0
src/pages/UserManage/Editor/User.jsx Ver arquivo

@@ -0,0 +1,49 @@
1
+import React from 'react';
2
+import { Button } from 'antd';
3
+import XForm, { FieldTypes } from '../../../components/XForm';
4
+
5
+export default (props) => {
6
+  const fields = [
7
+    {
8
+      label: '公司名称',
9
+      name: 'orgName',
10
+      type: FieldTypes.Text
11
+    },
12
+    {
13
+      label: '用户名称',
14
+      name: 'name',
15
+      type: FieldTypes.Text
16
+    },
17
+    {
18
+      label: '登录名称',
19
+      name: 'loginName',
20
+      type: FieldTypes.Text,
21
+      placeholder: '不填, 默认使用手机号'
22
+    },
23
+    {
24
+      label: '手机号',
25
+      name: 'phone',
26
+      type: FieldTypes.Text,
27
+      rules: [
28
+        {required: true, message: '请填写手机号'}
29
+      ]
30
+    },
31
+    {
32
+      label: '头像',
33
+      name: 'avatar',
34
+      type: FieldTypes.ImageUploader,
35
+      extra: '建议图片大小 128 * 128'
36
+    },
37
+    {
38
+      label: '有效期',
39
+      name: 'expDate',
40
+      type: FieldTypes.DatePicker,
41
+    },
42
+  ]
43
+
44
+  const handleSubmit = val => {
45
+    window.console.log('submit data --->', val)
46
+  }
47
+
48
+  return (<XForm onSubmit={handleSubmit} fields={fields}></XForm>)
49
+}

+ 29
- 0
src/pages/UserManage/Editor/index.jsx Ver arquivo

@@ -0,0 +1,29 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { PageHeaderWrapper } from '@ant-design/pro-layout';
3
+import { Radio } from 'antd';
4
+import User from './User';
5
+
6
+import request from '../../../utils/request';
7
+import apis from '../../../services/apis';
8
+
9
+export default (props) => {
10
+  const [ tab, changeTab ] = useState(1);
11
+
12
+  // useEffect(() => {
13
+  //   request({ ...apis.user.current }).then()
14
+  // })
15
+
16
+  return (
17
+    <PageHeaderWrapper>
18
+      <div>
19
+        <Radio.Group value={tab} buttonStyle="solid" onChange={e => changeTab(e.target.value)}>
20
+          <Radio.Button value={1}>主信息</Radio.Button>
21
+          <Radio.Button value={2}>小程序</Radio.Button>
22
+        </Radio.Group>
23
+      </div>
24
+      <div>
25
+        { tab === 1 ? <User /> : null}
26
+      </div>
27
+    </PageHeaderWrapper>
28
+  );
29
+}

+ 0
- 4
src/pages/user/login/components/Login/index.jsx Ver arquivo

@@ -39,10 +39,6 @@ class Login extends Component {
39 39
 
40 40
     if (form) {
41 41
       form.validateFields(
42
-        activeFields,
43
-        {
44
-          force: true,
45
-        },
46 42
         (err, values) => {
47 43
           if (onSubmit) {
48 44
             onSubmit(err, values);

+ 3
- 3
src/pages/user/login/index.jsx Ver arquivo

@@ -3,6 +3,7 @@ import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
3 3
 import React, { Component } from 'react';
4 4
 import Link from 'umi/link';
5 5
 import { connect } from 'dva';
6
+import md5 from 'md5';
6 7
 import LoginComponents from './components/Login';
7 8
 import styles from './style.less';
8 9
 const { Tab, UserName, Password, Mobile, Captcha, Submit } = LoginComponents;
@@ -23,13 +24,12 @@ class Login extends Component {
23 24
     });
24 25
   };
25 26
   handleSubmit = (err, values) => {
26
-    const { type } = this.state;
27
-
27
+    // const { type } = this.state;
28 28
     if (!err) {
29 29
       const { dispatch } = this.props;
30 30
       dispatch({
31 31
         type: 'login/login',
32
-        payload: { ...values, type },
32
+        payload: { ...values, password: md5(values.password) },
33 33
       });
34 34
     }
35 35
   };

+ 20
- 0
src/services/apis.js Ver arquivo

@@ -0,0 +1,20 @@
1
+const prefix = '/api/center'
2
+
3
+const apis = {
4
+  user: {
5
+    current: {
6
+      url: `${prefix}/current`,
7
+      method: 'GET',
8
+    },
9
+    login: {
10
+      url: `${prefix}/signin`,
11
+      method: 'POST',
12
+    },
13
+    logoff: {
14
+      url: `${prefix}/signout`,
15
+      method: 'POST',
16
+    },
17
+  }
18
+}
19
+
20
+export default apis;

+ 40
- 37
src/utils/request.js Ver arquivo

@@ -22,29 +22,6 @@ const codeMessage = {
22 22
   504: '网关超时。',
23 23
 };
24 24
 
25
-/**
26
- * 异常处理程序
27
- */
28
-const errorHandler = error => {
29
-  const { response } = error;
30
-
31
-  if (response && response.status) {
32
-    const errorText = codeMessage[response.status] || response.statusText;
33
-    const { status, url } = response;
34
-    notification.error({
35
-      message: `请求错误 ${status}: ${url}`,
36
-      description: errorText,
37
-    });
38
-  } else if (!response) {
39
-    notification.error({
40
-      description: '您的网络发生异常,无法连接服务器',
41
-      message: '网络异常',
42
-    });
43
-  }
44
-
45
-  return response;
46
-};
47
-
48 25
 const replaceURLParams = (url, params = {}) => {
49 26
   return Object.keys(params).reduce((acc, k) => { // 此方法对每个元素进行处理
50 27
     const re = new RegExp(`:${k}(?!w)`, 'i')
@@ -53,7 +30,7 @@ const replaceURLParams = (url, params = {}) => {
53 30
 }
54 31
 
55 32
 request.interceptors.request.use((url, options) => {
56
-  const { urlData, headers = {}, logout = false, ...opts } = options
33
+  const { urlData, headers = {}, logout = false, data, ...opts } = options
57 34
   const apiURL = urlData ? replaceURLParams(url, urlData) : url
58 35
   const token = window.localStorage.getItem('x-token')
59 36
   const authHeader = token ? { Authorization: `Bearer ${token}` } : {}
@@ -71,7 +48,8 @@ request.interceptors.request.use((url, options) => {
71 48
           ...authHeader,
72 49
           ...headers,
73 50
         },
74
-        errorHandler,
51
+        data,
52
+        requestType: data instanceof FormData ? 'form' : 'json',
75 53
         credentials: 'include', // 带 cookie
76 54
         interceptors: true
77 55
       },
@@ -80,20 +58,45 @@ request.interceptors.request.use((url, options) => {
80 58
 });
81 59
 
82 60
 request.interceptors.response.use(async (response, options) => {
83
-  const { code, data, message } = await response.clone().json();
84
-  if (code != 0 && code != 200) {
61
+  
62
+  if (response && response.status) {
63
+    if (response.status != 200) {
64
+      const errorText = codeMessage[response.status] || response.statusText;
65
+      const { status, url } = response;
66
+      notification.error({
67
+        message: `请求错误 ${status}: ${url}`,
68
+        description: errorText,
69
+      });
70
+      throw new Error(response.statusText);
71
+    } else {
72
+      const { code, data, message } = await response.clone().json();
73
+      if (code != 1000) {
74
+        notification.error({
75
+          message: `请求错误`,
76
+          description: message,
77
+        });
78
+        throw new Error(message);
79
+      }
80
+
81
+      if (data.token) {
82
+        window.localStorage.setItem('x-token', data.token)
83
+      }
84
+
85
+      return data;
86
+    }
87
+  } else if (!response) {
85 88
     notification.error({
86
-      message: `请求错误`,
87
-      description: message,
89
+      description: '您的网络发生异常,无法连接服务器',
90
+      message: '网络异常',
88 91
     });
89
-    throw new Error(message);
90
-  }
91
-
92
-  if (data.token) {
93
-    window.localStorage.setItem('x-token', token)
94 92
   }
95
-
96
-  return response;
97 93
 });
98 94
 
99
-export default request;
95
+export default config => {
96
+  if (typeof config === 'string') {
97
+    return request(config);
98
+  } else {
99
+    const {url, ...options} = config;
100
+    return request(url, options);
101
+  }
102
+};