98 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Vue
		
	
	
	
<template>
 | 
						|
  <div class="login-container">
 | 
						|
    <h2>欢迎使用系统</h2>
 | 
						|
    <a-form :form="form" @submit="handleSubmit">
 | 
						|
      <a-form-item :validate-status="usernameError() ? 'error' : ''" :help="usernameError() || ''">
 | 
						|
        <a-input
 | 
						|
          v-decorator="[
 | 
						|
          'username',
 | 
						|
          { rules: [{ required: true, message: '请输入用户名' }] },
 | 
						|
        ]"
 | 
						|
          placeholder="Username"
 | 
						|
        >
 | 
						|
          <a-icon slot="prefix" type="user" style="color:rgba(0,0,0,.25)" />
 | 
						|
        </a-input>
 | 
						|
      </a-form-item>
 | 
						|
      <a-form-item :validate-status="passwordError() ? 'error' : ''" :help="passwordError() || ''">
 | 
						|
        <a-input
 | 
						|
          v-decorator="[
 | 
						|
          'password',
 | 
						|
          { rules: [{ required: true, message: '请输入密码' }] },
 | 
						|
        ]"
 | 
						|
          type="password"
 | 
						|
          placeholder="Password"
 | 
						|
        >
 | 
						|
          <a-icon slot="prefix" type="lock" style="color:rgba(0,0,0,.25)" />
 | 
						|
        </a-input>
 | 
						|
      </a-form-item>
 | 
						|
      <a-form-item>
 | 
						|
        <a-button type="primary" html-type="submit" :disabled="hasErrors(form.getFieldsError())">
 | 
						|
          登录
 | 
						|
        </a-button>
 | 
						|
      </a-form-item>
 | 
						|
    </a-form>
 | 
						|
  </div>
 | 
						|
 | 
						|
 | 
						|
</template>
 | 
						|
 | 
						|
<script>
 | 
						|
import { mapActions } from 'vuex'
 | 
						|
function hasErrors(fieldsError) {
 | 
						|
  return Object.keys(fieldsError).some(field => fieldsError[field]);
 | 
						|
}
 | 
						|
export default {
 | 
						|
  layout: 'LoginLayout',
 | 
						|
  data() {
 | 
						|
    return {
 | 
						|
      hasErrors,
 | 
						|
      form: this.$form.createForm(this, { name: 'horizontal_login' }),
 | 
						|
    };
 | 
						|
  },
 | 
						|
  mounted() {
 | 
						|
    this.$nextTick(() => {
 | 
						|
      // To disabled submit button at the beginning.
 | 
						|
      this.form.validateFields();
 | 
						|
    });
 | 
						|
  },
 | 
						|
  methods: {
 | 
						|
    ...mapActions('user', ['setUserInfo']),
 | 
						|
    // Only show error after a field is touched.
 | 
						|
    usernameError() {
 | 
						|
      const { getFieldError, isFieldTouched } = this.form;
 | 
						|
      return isFieldTouched('username') && getFieldError('username');
 | 
						|
    },
 | 
						|
    // Only show error after a field is touched.
 | 
						|
    passwordError() {
 | 
						|
      const { getFieldError, isFieldTouched } = this.form;
 | 
						|
      return isFieldTouched('password') && getFieldError('password');
 | 
						|
    },
 | 
						|
    handleSubmit(e) {
 | 
						|
      e.preventDefault();
 | 
						|
      this.form.validateFields(async (err, values) => {
 | 
						|
        if (!err) {
 | 
						|
          const { data } = await this.$post('/api/User/login', values)
 | 
						|
          this.setUserInfo({ expire: 1 * 60 * 60 * 1000, userInfo: data, loginTime: Date.now() })
 | 
						|
          this.$router.replace({ path: '/home' })
 | 
						|
        }
 | 
						|
      });
 | 
						|
    },
 | 
						|
  },
 | 
						|
};
 | 
						|
</script>
 | 
						|
 | 
						|
 | 
						|
<style scoped lang="less">
 | 
						|
.login-container {
 | 
						|
  padding: 16px;
 | 
						|
  border-radius: 10px;
 | 
						|
  box-shadow: 0 0 10px rgba(0,0,0,.2);
 | 
						|
  width: 300px;
 | 
						|
  position: absolute;
 | 
						|
  left: 50%;
 | 
						|
  top: 50%;
 | 
						|
  transform: translate(-50%, -50%);
 | 
						|
  text-align: center;
 | 
						|
}
 | 
						|
</style>
 |