Browse Source

登录注册界面

zhuth 7 years ago
parent
commit
34c45fba5e

+ 67 - 0
src/components/common/login.jsx

@@ -0,0 +1,67 @@
+import React from 'react'
+import Login from 'ant-design-pro/lib/Login'
+import { Alert, Checkbox } from 'antd'
+import { Link } from 'dva/router';
+import './login.less'
+
+const { Tab, UserName, Password, Mobile, Captcha, Submit } = Login;
+
+class LoginDemo extends React.Component {
+    state = {
+        notice: '',
+        autoLogin: true,
+    }
+    onSubmit = (err, values) => {
+        console.log('value collected ->', { ...values, autoLogin: this.state.autoLogin });
+        this.setState({
+            notice: '',
+        }, () => {
+            if (!err && (values.username !== 'admin' || values.password !== '888888')) {
+                setTimeout(() => {
+                    this.setState({
+                        notice: '账号名或密码错误!',
+                    });
+                }, 500);
+            }
+        });
+    }
+    changeAutoLogin = (e) => {
+        this.setState({
+            autoLogin: e.target.checked,
+        });
+    }
+    render() {
+        return (
+            <div className='container'>
+                <div className='content'>
+                    <div className='main'>
+                        <h3>登录</h3>
+                        <Login
+                            className='login'
+                            onSubmit={this.onSubmit}
+                        >
+                            {
+                                this.state.notice &&
+                                <Alert style={{ marginBottom: 24 }} message={this.state.notice} type="error" showIcon closable />
+                            }
+                            <UserName name="username" />
+                            <Password name="password" />
+                            <div>
+                                <Checkbox checked={this.state.autoLogin} onChange={this.changeAutoLogin}>记住密码</Checkbox>
+                                <a style={{ float: 'right' }} href="">忘记密码</a>
+                            </div>
+                            <Submit>登录</Submit>
+                            <div>
+                                <Link to="/register">
+                                    <a style={{ float: 'right' }} href="">注册</a>
+                                </Link>
+                            </div>
+                        </Login>
+                    </div>
+                </div>
+            </div>
+        );
+    }
+}
+
+export default LoginDemo;

+ 15 - 0
src/components/common/login.less

@@ -0,0 +1,15 @@
+.container {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    overflow: auto;
+    background: #f0f2f5;
+    .content {
+        padding: 112px 0 24px;
+        flex: 1 1;
+        .main {
+            width: 368px;
+            margin: 0 auto;
+        }
+    }
+}

+ 293 - 0
src/components/common/register.jsx

@@ -0,0 +1,293 @@
+import React, { Component } from 'react';
+import { connect } from 'dva';
+import { Link } from 'dva/router';
+import { Form, Input, Button, Select, Row, Col, Popover, Progress } from 'antd';
+import './register.less';
+
+const FormItem = Form.Item;
+const { Option } = Select;
+const InputGroup = Input.Group;
+
+const passwordStatusMap = {
+    ok: <div className='success'>强度:强</div>,
+    pass: <div className='warning'>强度:中</div>,
+    poor: <div className='error'>强度:太短</div>,
+};
+
+const passwordProgressMap = {
+    ok: 'success',
+    pass: 'normal',
+    poor: 'exception',
+};
+
+class Register extends Component {
+    state = {
+        count: 0,
+        confirmDirty: false,
+        visible: false,
+        help: '',
+        prefix: '86',
+    };
+
+    // componentWillReceiveProps(nextProps) {
+    //     const { form, dispatch } = this.props;
+    //     const account = form.getFieldValue('mail');
+    //     if (nextProps.register.status === 'ok') {
+    //         dispatch(
+    //             routerRedux.push({
+    //                 pathname: '/user/register-result',
+    //                 state: {
+    //                     account,
+    //                 },
+    //             })
+    //         );
+    //     }
+    // }
+
+    componentWillUnmount() {
+        clearInterval(this.interval);
+    }
+
+    onGetCaptcha = () => {
+        let count = 59;
+        this.setState({ count });
+        this.interval = setInterval(() => {
+            count -= 1;
+            this.setState({ count });
+            if (count === 0) {
+                clearInterval(this.interval);
+            }
+        }, 1000);
+    };
+
+    getPasswordStatus = () => {
+        const { form } = this.props;
+        const value = form.getFieldValue('password');
+        if (value && value.length > 9) {
+            return 'ok';
+        }
+        if (value && value.length > 5) {
+            return 'pass';
+        }
+        return 'poor';
+    };
+
+    handleSubmit = e => {
+        // e.preventDefault();
+        // const { form, dispatch } = this.props;
+        // form.validateFields({ force: true }, (err, values) => {
+        //     const { prefix } = this.state;
+        //     if (!err) {
+        //         dispatch({
+        //             type: 'register/submit',
+        //             payload: {
+        //                 ...values,
+        //                 prefix,
+        //             },
+        //         });
+        //     }
+        // });
+    };
+
+    handleConfirmBlur = e => {
+        const { value } = e.target;
+        const { confirmDirty } = this.state;
+        this.setState({ confirmDirty: confirmDirty || !!value });
+    };
+
+    checkConfirm = (rule, value, callback) => {
+        const { form } = this.props;
+        if (value && value !== form.getFieldValue('password')) {
+            callback('两次输入的密码不匹配!');
+        } else {
+            callback();
+        }
+    };
+
+    checkPassword = (rule, value, callback) => {
+        if (!value) {
+            this.setState({
+                help: '请输入密码!',
+                visible: !!value,
+            });
+            callback('error');
+        } else {
+            this.setState({
+                help: '',
+            });
+            const { visible, confirmDirty } = this.state;
+            if (!visible) {
+                this.setState({
+                    visible: !!value,
+                });
+            }
+            if (value.length < 6) {
+                callback('error');
+            } else {
+                const { form } = this.props;
+                if (value && confirmDirty) {
+                    form.validateFields(['confirm'], { force: true });
+                }
+                callback();
+            }
+        }
+    };
+
+    changePrefix = value => {
+        this.setState({
+            prefix: value,
+        });
+    };
+
+    renderPasswordProgress = () => {
+        const { form } = this.props;
+        const value = form.getFieldValue('password');
+        const passwordStatus = this.getPasswordStatus();
+        return value && value.length ? (
+            <div className={`progress-${passwordStatus}`}>
+                <Progress
+                    status={passwordProgressMap[passwordStatus]}
+                    className='progress'
+                    strokeWidth={6}
+                    percent={value.length * 10 > 100 ? 100 : value.length * 10}
+                    showInfo={false}
+                />
+            </div>
+        ) : null;
+    };
+
+    render() {
+        const { form, submitting } = this.props;
+        const { getFieldDecorator } = form;
+        const { count, prefix, help, visible } = this.state;
+        return (
+            <div className='container'>
+                <div className='content'>
+                    <div className='main'>
+                        <h3>注册</h3>
+                        <Form onSubmit={this.handleSubmit}>
+                            <FormItem>
+                                {getFieldDecorator('mail', {
+                                    rules: [
+                                        {
+                                            required: true,
+                                            message: '请输入邮箱地址!',
+                                        },
+                                        {
+                                            type: 'email',
+                                            message: '邮箱地址格式错误!',
+                                        },
+                                    ],
+                                })(<Input size="large" placeholder="邮箱" />)}
+                            </FormItem>
+                            <FormItem help={help}>
+                                <Popover
+                                    content={
+                                        <div style={{ padding: '4px 0' }}>
+                                            {passwordStatusMap[this.getPasswordStatus()]}
+                                            {this.renderPasswordProgress()}
+                                            <div style={{ marginTop: 10 }}>
+                                                请至少输入 6 个字符。请不要使用容易被猜到的密码。
+                                            </div>
+                                        </div>
+                                    }
+                                    overlayStyle={{ width: 240 }}
+                                    placement="right"
+                                    visible={visible}
+                                >
+                                    {getFieldDecorator('password', {
+                                        rules: [
+                                            {
+                                                validator: this.checkPassword,
+                                            },
+                                        ],
+                                    })(<Input size="large" type="password" placeholder="至少6位密码,区分大小写" />)}
+                                </Popover>
+                            </FormItem>
+                            <FormItem>
+                                {getFieldDecorator('confirm', {
+                                    rules: [
+                                        {
+                                            required: true,
+                                            message: '请确认密码!',
+                                        },
+                                        {
+                                            validator: this.checkConfirm,
+                                        },
+                                    ],
+                                })(<Input size="large" type="password" placeholder="确认密码" />)}
+                            </FormItem>
+                            <FormItem>
+                                <InputGroup compact>
+                                    <Select
+                                        size="large"
+                                        value={prefix}
+                                        onChange={this.changePrefix}
+                                        style={{ width: '20%' }}
+                                    >
+                                        <Option value="86">+86</Option>
+                                        <Option value="87">+87</Option>
+                                    </Select>
+                                    {getFieldDecorator('mobile', {
+                                        rules: [
+                                            {
+                                                required: true,
+                                                message: '请输入手机号!',
+                                            },
+                                            {
+                                                pattern: /^1\d{10}$/,
+                                                message: '手机号格式错误!',
+                                            },
+                                        ],
+                                    })(<Input size="large" style={{ width: '80%' }} placeholder="11位手机号" />)}
+                                </InputGroup>
+                            </FormItem>
+                            <FormItem>
+                                <Row gutter={8} style={{ marginLeft: '-4px', marginRight: '-4px' }}>
+                                    <Col span={16} style={{ paddingLeft: '4px', paddingRight: '4px' }}>
+                                        {getFieldDecorator('captcha', {
+                                            rules: [
+                                                {
+                                                    required: true,
+                                                    message: '请输入验证码!',
+                                                },
+                                            ],
+                                        })(<Input size="large" placeholder="验证码" />)}
+                                    </Col>
+                                    <Col span={8} style={{ paddingLeft: '4px', paddingRight: '4px' }}>
+                                        <Button
+                                            size="large"
+                                            disabled={count}
+                                            className='btn-getcaptcha'
+                                            onClick={this.onGetCaptcha}
+                                        >
+                                            {count ? `${count} s` : '获取验证码'}
+                                        </Button>
+                                    </Col>
+                                </Row>
+                            </FormItem>
+                            <FormItem>
+                                <Button
+                                    size="large"
+                                    loading={submitting}
+                                    className='btn-submit'
+                                    type="primary"
+                                    htmlType="submit"
+                                >
+                                    注册
+                                </Button>
+                                <Link className='tologin' to="/login">
+                                    使用已有账户登录
+                                </Link>
+                            </FormItem>
+                        </Form>
+                    </div>
+                </div>
+            </div>
+        );
+    }
+}
+
+export default connect(({ present: { register } }) => ({
+    register,
+}))(Form.create()(Register))

+ 41 - 0
src/components/common/register.less

@@ -0,0 +1,41 @@
+.container {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    overflow: auto;
+    background: #f0f2f5;
+    .content {
+        padding: 112px 0 24px;
+        flex: 1 1;
+        .main {
+            width: 368px;
+            margin: 0 auto;
+            h3 {
+                font-size: 16px;
+                margin-bottom: 20px;
+            }
+            .ant-form-item {
+                margin-bottom: 24px;
+                .ant-form-item-control {
+                    line-height: 39.9999px;
+                    position: relative;
+                    zoom: 1;
+                    .ant-form-item-children {
+                        position: relative;
+                    }
+                }
+            }
+            .btn-getcaptcha {
+                display: block;
+                width: 100%;
+            }
+            .btn-submit {
+                width: 50%;
+            }
+            .tologin {
+                float: right;
+                line-height: 40px;
+            }
+        }
+    }
+}

+ 1 - 1
src/components/dashboard/dashboard.jsx

@@ -40,7 +40,7 @@ class Dashboard extends React.Component {
 
 
     render() {
     render() {
         const { dispatch } = this.props;
         const { dispatch } = this.props;
-
+        return <div>null</div>
         return (
         return (
             <Tabs
             <Tabs
                 className='dashboard-tabs'
                 className='dashboard-tabs'

+ 1 - 1
src/components/datasource/columnConfig.jsx

@@ -1,5 +1,5 @@
 import React from 'react'
 import React from 'react'
-import { Form, Input, Button, Select, Table, Checkbox, Switch, Divider, Icon, Popconfirm } from 'antd'
+import { Form, Input, Button, Select, Table, Checkbox, Divider, Icon, Popconfirm } from 'antd'
 import { connect } from 'dva'
 import { connect } from 'dva'
 import COLUMN_TYPE from './columnType.json'
 import COLUMN_TYPE from './columnType.json'
 import { Resizable } from 'react-resizable';
 import { Resizable } from 'react-resizable';

+ 4 - 2
src/index.js

@@ -7,9 +7,10 @@ import dataSource from './models/dataSource'
 import dataConnect from './models/dataConnect'
 import dataConnect from './models/dataConnect'
 import dashboard from './models/dashboard'
 import dashboard from './models/dashboard'
 import chart from './models/chart'
 import chart from './models/chart'
+import dashboardDesigner from './models/dashboardDesigner';
+import user from './models/user'
 import './utils/baseUtils'
 import './utils/baseUtils'
 import './index.less'
 import './index.less'
-import dashboardDesigner from './models/dashboardDesigner';
 import createLoading from 'dva-loading';
 import createLoading from 'dva-loading';
 
 
 // 1. Initialize
 // 1. Initialize
@@ -33,7 +34,8 @@ app.model(dataSource); // 数据源
 app.model(dataConnect); // 数据连接
 app.model(dataConnect); // 数据连接
 app.model(dashboard);  //报告与看板
 app.model(dashboard);  //报告与看板
 app.model(chart);  // 图表
 app.model(chart);  // 图表
-app.model(dashboardDesigner)
+app.model(dashboardDesigner); // 看板设计
+app.model(user); // 用户
 
 
 // 4. Router
 // 4. Router
 app.router(indexRouter);
 app.router(indexRouter);

+ 1 - 5
src/models/dataConnect.js

@@ -1,7 +1,6 @@
 import { message } from 'antd'
 import { message } from 'antd'
 import * as service from '../services/index'
 import * as service from '../services/index'
 import URLS from '../constants/url'
 import URLS from '../constants/url'
-import RULE from './validRule.js'
 
 
 export default {
 export default {
     namespace: 'dataConnect',
     namespace: 'dataConnect',
@@ -58,14 +57,11 @@ export default {
             return Object.assign({}, state, { filterLabel: label });
             return Object.assign({}, state, { filterLabel: label });
         },
         },
         setNewModelField(state, action) {
         setNewModelField(state, action) {
-            const { name, value, rules } = action;
+            const { name, value } = action;
             let newOne = state.newOne;
             let newOne = state.newOne;
             let validInfo = state.validInfo;
             let validInfo = state.validInfo;
             newOne[name] = value;
             newOne[name] = value;
             delete newOne.invalid;
             delete newOne.invalid;
-            (rules && (Object.prototype.toString.call(rules) === '[object Array]')) && rules.map((r) => {
-                return validInfo[name] = RULE[r](value);
-            });
             
             
             return Object.assign({}, state, { newOne, validInfo });
             return Object.assign({}, state, { newOne, validInfo });
         },
         },

+ 0 - 0
src/models/mapRule.js


+ 61 - 0
src/models/user.js

@@ -0,0 +1,61 @@
+import { message } from 'antd'
+
+export default {
+    namespace: 'user',
+    state: {
+        list: [],
+        currentUser: {}
+    },
+    reducers: {
+        setCurrentUser(state, { action }) {
+            return {
+                ...state,
+                currentUser: action.user
+            };
+        },
+    },
+    effects: {
+        *login (action, { select, call, put }) {
+            // const user = yield select(state => state.present.user);
+            try {
+                /*
+                let body = {
+                }
+                const res = yield call(service.fetch, {
+                    url: '',
+                    body: body
+                });
+
+                console.log('登录', body, res);
+
+                if(!res.err && res.data.code > 0) {
+                }else {
+                }
+                */
+                const user = {
+                    code: 'u001',
+                    name: 'zhuth',
+                    expireTime: new Date().getTime() + 1 * 60 * 1000,
+                    authority: 'admin',
+                };
+                yield put({ type: 'setCurrentUser', user });
+            }catch(e) {
+                console.log(e);
+                message.error('登录失败');
+            }
+        },
+    },
+    subscriptions: {
+        setup({ dispatch, history }) {
+            message.config({
+                top: 60,
+                duration: 2,
+                maxCount: 3,
+            });
+            return history.listen(({ pathname, query }) => {
+                let page = pathname.match(/\/(\w*)/)[1];
+                dispatch({ type: 'setPage', page });
+            })
+        }
+    }
+};

+ 0 - 45
src/models/validRule.js

@@ -1,45 +0,0 @@
-const STATE = {
-    VALIDATING: 'validating', // 校验中
-    SUCCESS: 'success', // 校验通过
-    ERROR: 'error', // 校验不通过
-    WARNING: 'warning' // 存在问题但通过校验
-}
-const RULE = {
-    // 默认校验信息
-    validInfo: {
-        validateStatus: STATE.SUCCESS,
-        help: ''
-    },
-    // 必填
-    required: function(value) {
-        if(!value) {
-            this.validInfo.validateStatus = STATE.ERROR;
-            this.validInfo.help = '不能为空';
-        }else {
-            this.validInfo.validateStatus = STATE.SUCCESS
-        }
-        return this.validInfo;
-    },
-    // 长度
-    length: function(value, maxLen, minLen) {
-        let str = value + '';
-        if(maxLen < minLen) {
-            return this.validInfo;
-        }
-        if(maxLen > 0) {
-            if(str.length > maxLen) {
-                this.validInfo.validateStatus = STATE.ERROR;
-                this.validInfo.help = '长度不能大于' + maxLen;
-            }
-        }
-        if(minLen >= 0) {
-            if(str.length < minLen) {
-                this.validInfo.validateStatus = STATE.ERROR;
-                this.validInfo.help = '长度不能小于' + minLen;
-            }
-        }
-        return this.validInfo;
-    },
-};
-
-export default RULE;

+ 9 - 9
src/routes/mainLayout.js

@@ -4,9 +4,9 @@ import { Route, Switch } from 'dva/router'
 import Navigator from '../components/common/navigator'
 import Navigator from '../components/common/navigator'
 import Welcome from '../components/myPage/welcome'
 import Welcome from '../components/myPage/welcome'
 import Loading from '../components/common/loading'
 import Loading from '../components/common/loading'
-import DataSource from '../components/datasource/dataSource'
 import DataSourceDetail from '../components/datasource/dataSourceDetail'
 import DataSourceDetail from '../components/datasource/dataSourceDetail'
-// import Dashboard from '../components/dashboard/dashboard'
+import DataSource from '../components/datasource/dataSource'
+import Dashboard from '../components/dashboard/dashboard'
 import Chart from '../components/chart/list'
 import Chart from '../components/chart/list'
 import './mainLayout.less';
 import './mainLayout.less';
 import Demo from '../demo';
 import Demo from '../demo';
@@ -21,13 +21,13 @@ const MainLayout = (history) => {
             </Header>
             </Header>
             <Content className='main-content'>
             <Content className='main-content'>
                 <Switch>
                 <Switch>
-                    <Route exact path='/demo' component={Demo}/>
-                    <Route exact path='/' component={Welcome}/>
-                    <Route exact path='/home' component={Welcome}/>
-                    <Route exact sensitive path='/datasource' component={DataSource}/>
-                    <Route sensitive path='/datasource/:type/:code/:tab' component={DataSourceDetail}/>
-                    {/* <Route exact sensitive path='/dashboard' component={Dashboard} /> */}
-                    <Route exact sensitive path='/chart' component={Chart} />
+                    <Route path='/demo' component={Demo}/>
+                    <Route path='/home' component={Welcome}/>
+                    <Route path='/datasource/:type/:code/:tab' component={DataSourceDetail}/>
+                    <Route sensitive path='/datasource' component={DataSource}/>
+                    <Route sensitive path='/dashboard' component={Dashboard} />
+                    <Route sensitive path='/chart' component={Chart} />
+                    <Route path='/' component={Welcome}/>
                 </Switch>
                 </Switch>
             </Content>
             </Content>
         </Layout>
         </Layout>

+ 4 - 0
src/routes/router.js

@@ -1,6 +1,8 @@
 import React from 'react'
 import React from 'react'
 import { LocaleProvider } from 'antd'
 import { LocaleProvider } from 'antd'
 import { Router, Route, Switch } from 'dva/router'
 import { Router, Route, Switch } from 'dva/router'
+import Login from '../components/common/login'
+import Register from '../components/common/register'
 import MainLayout from './mainLayout'
 import MainLayout from './mainLayout'
 import ChartDesigner from '../components/chartDesigner/layout'
 import ChartDesigner from '../components/chartDesigner/layout'
 import DashboardDesigner from '../components/dashboardDesigner/layout'
 import DashboardDesigner from '../components/dashboardDesigner/layout'
@@ -12,6 +14,8 @@ function RouterConfig({ history }) {
     <LocaleProvider locale={zhCN}>
     <LocaleProvider locale={zhCN}>
       <Router history={history}>
       <Router history={history}>
         <Switch>
         <Switch>
+          <Route sensitive path='/login' component={Login}/>
+          <Route sensitive path='/register' component={Register}/>
           <Route sensitive path='/chart/:code' component={ChartDesigner}/>
           <Route sensitive path='/chart/:code' component={ChartDesigner}/>
           <Route sensitive path='/dashboard/:id/' component={DashboardDesigner}/>
           <Route sensitive path='/dashboard/:id/' component={DashboardDesigner}/>
           <Route path='/' component={MainLayout}/>
           <Route path='/' component={MainLayout}/>