123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- <template>
- <div class="Sign">
- <div class="wrap" :class="{ 'wrap--error': error }">
- <Form>
- <FormItem>
- <Input
- prefix="ios-contact-outline"
- v-model="username"
- placeholder="用户"
- :disabled="loading"
- @on-enter="submit" />
- </FormItem>
- <FormItem>
- <Input
- type="password"
- prefix="ios-lock-outline"
- v-model="password"
- placeholder="密码"
- :disabled="loading"
- @on-enter="submit" />
- </FormItem>
- <FormItem>
- <Button
- type="primary"
- long
- :disabled="!username || !password"
- :loading="loading"
- @click="submit">登录</Button>
- </FormItem>
- </Form>
- </div>
- </div>
- </template>
- <script>
- import { mapActions } from 'vuex'
- export default {
- data () {
- return {
- loading: false,
- error: false,
- username: null,
- password: null,
- }
- },
- methods: {
- ...mapActions('user', [
- 'login',
- ]),
- async submit () {
- this.loading = true
- try {
- await this.login({ username: this.username, password: this.password })
- this.$router.replace({ name: 'root' })
- } catch {
- this.error = true
- setTimeout(() => {
- this.error = false
- this.loading = false
- }, 300)
- }
- },
- },
- }
- </script>
- <style lang="scss" scoped>
- .Sign {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 100vh;
- width: 100vw;
- background: #fafafa;
- }
- .wrap {
- width: 320px;
- padding: 24px;
- padding-bottom: 0;
- background: #fff;
- border-radius: 4px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, .08);
- &--error {
- @keyframes shake {
- 0%, 100% {
- transform: translate(0, 0);
- }
- 20%, 60% {
- transform: translate(-8px, 0);
- }
- 40%, 80% {
- transform: translate(8px, 0);
- }
- }
- animation: shake .3s linear forwards;
- }
- }
- </style>
|