Procházet zdrojové kódy

feat: authcode check when update phone,email

fenghao před 3 roky
rodič
revize
1980a999e2

+ 15 - 0
src/api/user.js

@@ -369,3 +369,18 @@ function addUserRoles (userId, roles) {
     data: roles
   })
 }
+export function authcodeSend (data) {
+  return request({
+    url: `/authcode/send`,
+    method: 'POST',
+    data
+  })
+}
+
+export function authcodeCheck (data) {
+  return request({
+    url: `/authcode/check`,
+    method: 'POST',
+    data
+  })
+}

+ 261 - 0
src/views/platform/profile/components/UserInfoItem.vue

@@ -0,0 +1,261 @@
+<template>
+  <div class="l-flex--col">
+    <div class="l-flex--row c-line">
+      <div class="c-grid-form__label c-line__left u-color--black u-bold">
+        绑定{{ config.label }}:
+      </div>
+      <div class="c-line__mid">
+        <el-input
+          v-model="cValue"
+          :maxlength="config.maxlength"
+          :placeholder="'请输入'+config.tipText"
+        />
+      </div>
+      <div class="c-line__right has-left-padding">
+        <button
+          v-if="expanded === false"
+          class="o-button"
+          @click="expanded = true"
+        >
+          {{ initial?'更换':'绑定' }}{{ config.label }}
+        </button>
+        <div
+          v-else
+          class="u-pointer u-color--blue"
+          @click="expanded = false"
+        >
+          收起
+        </div>
+      </div>
+    </div>
+    <div
+      v-if="expanded === true"
+      class="l-flex--row c-line"
+    >
+      <div class="c-line__left" />
+      <div class="c-line__mid l-flex--row">
+        <el-input
+          v-model="code"
+          class="c-code"
+          maxlength="6"
+          placeholder="验证码"
+          @keydown.enter="bind"
+        />
+        <el-button
+          class="o-button l-flex__fill c-btn"
+          :disabled="verification"
+          @click="sendCode"
+        >
+          {{ codeText }}
+        </el-button>
+      </div>
+      <div class="c-line__right" />
+    </div>
+    <div
+      v-if="expanded === true"
+      class="l-flex--row c-line"
+    >
+      <div class="c-line__left" />
+      <div class="c-line__mid l-flex--row">
+        <el-button
+          class="o-button l-flex__fill"
+          @click="bind"
+        >绑定</el-button>
+      </div>
+      <div class="c-line__right" />
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  validPhone, validEmail
+} from '@/utils/validate'
+import {
+  authcodeSend, authcodeCheck
+} from '@/api/user'
+const COUNTDOWN = 60
+const config = {
+  phone: {
+    label: '手机',
+    tipText: '手机号',
+    maxlength: 11,
+    valid: validPhone,
+    typeKey: 'phoneNum',
+    codeKey: 'phoneNumAuthCode',
+    checkKey: 'checkPhoneNum'
+  },
+  email: {
+    label: '邮箱',
+    maxlength: 50,
+    valid: validEmail,
+    tipText: '邮箱',
+    typeKey: 'email',
+    codeKey: 'emailAuthCode',
+    checkKey: 'checkEmail'
+  }
+}
+export default {
+  name: 'UserInfoItem',
+  props: {
+    type: {
+      type: String,
+      require: true,
+      default: 'phone'
+    },
+    value: {
+      type: String,
+      default: ''
+    },
+    initial: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      config: {},
+      code: null,
+      expanded: false,
+      verification: false,
+      countDown: COUNTDOWN
+    }
+  },
+  computed: {
+    cValue: {
+      get () {
+        return this.value
+      },
+      set (v) {
+        this.$emit('input', v)
+      }
+    },
+    codeText () {
+      return this.verification ? `${this.countDown} s` : '发送验证码'
+    }
+  },
+  watch: {
+    initial () {
+      this.reset()
+    }
+  },
+  created () {
+    this.config = config[this.type]
+  },
+  beforeDestroy () {
+    clearInterval(this.$timer)
+  },
+  methods: {
+    reset () {
+      this.expanded = false
+      this.code = ''
+      this.verification = false
+      this.countDown = COUNTDOWN
+      clearInterval(this.$timer)
+    },
+    sendCode () {
+      if (this.verification) {
+        return
+      }
+      if (!this.value) {
+        this.$message({
+          type: 'warning',
+          message: `${this.config.tipText}不能为空`
+        })
+        return
+      }
+      if (!this.config.valid(this.value)) {
+        this.$message({
+          type: 'warning',
+          message: `${this.config.tipText}格式错误`
+        })
+        return
+      }
+      authcodeSend({
+        [this.config.typeKey]: this.value
+      })
+        .then(({ success, errMessage }) => {
+          if (success) {
+            this.$message({
+              type: 'success',
+              message: '验证码已发送...'
+            })
+            this.verification = true
+            this.countDown = COUNTDOWN
+            this.$timer = setInterval(() => {
+              this.countDown--
+              if (this.countDown <= 0) {
+                this.verification = false
+                this.countDown = COUNTDOWN
+                clearInterval(this.$timer)
+              }
+            }, 1000)
+          } else {
+            console.log(errMessage)
+          }
+        })
+        .catch(err => {
+          console.log(err)
+        })
+    },
+
+    bind () {
+      if (!this.value) {
+        this.$message({
+          type: 'warning',
+          message: `${this.config.tipText}不能为空`
+        })
+        return
+      }
+      if (!this.code) {
+        this.$message({
+          type: 'warning',
+          message: `验证码不能为空`
+        })
+        return
+      }
+      authcodeCheck({
+        [this.config.typeKey]: this.value,
+        [this.config.codeKey]: this.code
+      }).then(({ success, data }) => {
+        if (success) {
+          if (data[this.config.checkKey]) {
+            this.$emit('update', () => this.reset())
+            return
+          }
+        }
+        this.$message({
+          type: 'error',
+          message: `验证码错误`
+        })
+      }).catch(err => {
+        console.log(err)
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.c-line {
+  padding-bottom: $spacing;
+  width: 420px;
+  &__left {
+    flex: 0 0 80px;
+  }
+  &__mid {
+    flex: 1
+  }
+  &__right {
+    flex: 0 0 120px;
+  }
+}
+.c-code {
+  flex: 0 0 100px;
+  margin-right: 20px;
+}
+::v-deep.el-button.is-disabled {
+  border: 1px solid $blue;
+  color: $blue;
+}
+</style>

+ 30 - 21
src/views/platform/profile/index.vue

@@ -39,29 +39,27 @@
       />
       <div
         v-else
-        class="has-padding"
+        class="has-padding l-flex--col"
       >
         <div class="l-flex--row">
-          <label class="c-grid-form__label">手机:</label>
-          <div>
-            <el-input
-              v-model="phone"
-              maxlength="11"
-              @change="onPhoneChange"
-              @keydown.enter="$event.target.blur()"
-            />
-          </div>
+          <UserInfoItem
+            v-if="user"
+            key="phone"
+            v-model="phone"
+            type="phone"
+            :initial="user.attributes.phone[0]"
+            @update="changeAttribute('phone', phone, '更新手机号')"
+          />
         </div>
         <div class="l-flex--row has-padding--v">
-          <label class="c-grid-form__label">邮箱:</label>
-          <div>
-            <el-input
-              v-model="email"
-              maxlength="50"
-              @change="onEmailChange"
-              @keydown.enter="$event.target.blur()"
-            />
-          </div>
+          <UserInfoItem
+            v-if="user"
+            key="email"
+            v-model="email"
+            type="email"
+            :initial="user.email"
+            @update="updateUser({email}, '更新邮箱')"
+          />
         </div>
         <div class="l-flex--row has-top-padding">
           <div class="o-app">
@@ -138,6 +136,7 @@
 
 <script>
 import { mapGetters } from 'vuex'
+import UserInfoItem from './components/UserInfoItem'
 import {
   userinfo,
   updateUser,
@@ -151,11 +150,19 @@ import {
 
 export default {
   name: 'Profile',
+  components: {
+    UserInfoItem
+  },
   data () {
     return {
       loading: true,
       error: false,
-      user: null,
+      user: {
+        email: '',
+        attributes: {
+          phone: ['']
+        }
+      },
       avatar: '',
       phone: '',
       email: '',
@@ -261,7 +268,9 @@ export default {
       return user.attributes[key][0]
     },
     updateUser (data, meesage) {
-      return updateUser(this.user.id, data, meesage)
+      return updateUser(this.user.id, data, meesage).then(() => {
+        this.user = { ...this.user, ...data }
+      })
     },
     changeAttribute (key, value, meesage) {
       if (this.user.attributes[key][0] !== value) {