Explorar o código

用户修改个人资料

chao %!s(int64=3) %!d(string=hai) anos
pai
achega
d0b1a76dc4

+ 16 - 0
src/api/user.js

@@ -59,3 +59,19 @@ export function deleteUser(id) {
     method: 'post'
     method: 'post'
   })
   })
 }
 }
+
+export function updateProfile(data) {
+  return request({
+    url: '/sys/user/update/profile',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updatePassword(data) {
+  return request({
+    url: '/sys/user/update/password',
+    method: 'post',
+    data: data
+  })
+}

+ 5 - 2
src/store/getters.js

@@ -6,9 +6,12 @@ const getters = {
   cachedViews: state => state.tagsView.cachedViews,
   cachedViews: state => state.tagsView.cachedViews,
   token: state => state.user.token,
   token: state => state.user.token,
   avatar: state => state.user.avatar,
   avatar: state => state.user.avatar,
-  name: state => state.user.name,
-  introduction: state => state.user.introduction,
+  username: state => state.user.username,
+  userId: state => state.user.userId,
   roles: state => state.user.roles,
   roles: state => state.user.roles,
+  roleDesc: state => state.user.roleDesc,
+  fullName: state => state.user.fullName,
+  phone: state => state.user.phone,
   permission_routes: state => state.permission.routes,
   permission_routes: state => state.permission.routes,
   errorLogs: state => state.errorLog.logs
   errorLogs: state => state.errorLog.logs
 }
 }

+ 69 - 51
src/store/modules/user.js

@@ -4,7 +4,7 @@ import router, { resetRouter } from '@/router'
 
 
 const state = {
 const state = {
   token: getToken(),
   token: getToken(),
-  name: '',
+  username: '',
   avatar: '',
   avatar: '',
   introduction: '',
   introduction: '',
   roles: [],
   roles: [],
@@ -15,11 +15,11 @@ const mutations = {
   SET_TOKEN: (state, token) => {
   SET_TOKEN: (state, token) => {
     state.token = token
     state.token = token
   },
   },
-  SET_INTRODUCTION: (state, introduction) => {
-    state.introduction = introduction
+  SET_USERID: (state, userId) => {
+    state.userId = userId
   },
   },
-  SET_NAME: (state, name) => {
-    state.name = name
+  SET_USERNAME: (state, username) => {
+    state.username = username
   },
   },
   SET_AVATAR: (state, avatar) => {
   SET_AVATAR: (state, avatar) => {
     state.avatar = avatar
     state.avatar = avatar
@@ -29,6 +29,15 @@ const mutations = {
   },
   },
   SET_MENUS: (state, menus) => {
   SET_MENUS: (state, menus) => {
     state.menus = menus
     state.menus = menus
+  },
+  SET_ROLEDESC: (state, roleDesc) => {
+    state.roleDesc = roleDesc
+  },
+  SET_FULLNAME: (state, fullName) => {
+    state.fullName = fullName
+  },
+  SET_PHONE: (state, phone) => {
+    state.phone = phone
   }
   }
 }
 }
 
 
@@ -37,64 +46,73 @@ const actions = {
   login({ commit }, userInfo) {
   login({ commit }, userInfo) {
     const { username, password } = userInfo
     const { username, password } = userInfo
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
-      login({ username: username.trim(), password: password }).then(response => {
-        const { data } = response
-        commit('SET_TOKEN', data.token)
-        setToken(data.token)
-        resolve()
-      }).catch(error => {
-        reject(error)
-      })
+      login({ username: username.trim(), password: password })
+        .then(response => {
+          const { data } = response
+          commit('SET_TOKEN', data.token)
+          setToken(data.token)
+          resolve()
+        })
+        .catch(error => {
+          reject(error)
+        })
     })
     })
   },
   },
 
 
   // get user info
   // get user info
   getInfo({ commit, state }) {
   getInfo({ commit, state }) {
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
-      getInfo().then(response => {
-        const { data } = response
-
-        if (!data) {
-          reject('Verification failed, please Login again.')
-        }
-
-        const { roles, menus, name, avatar, introduction } = data
-
-        // roles must be a non-empty array
-        if (!roles || roles.length <= 0) {
-          reject('getInfo: roles must be a non-null array!')
-        }
-
-        commit('SET_ROLES', roles)
-        commit('SET_MENUS', menus)
-        commit('SET_NAME', name)
-        commit('SET_AVATAR', avatar)
-        commit('SET_INTRODUCTION', introduction)
-
-        resolve(data)
-      }).catch(error => {
-        reject(error)
-      })
+      getInfo()
+        .then(response => {
+          const { data } = response
+
+          if (!data) {
+            reject('Verification failed, please Login again.')
+          }
+
+          const { roles, menus, id, username, avatar, roleDesc, fullName, phone } = data
+
+          // roles must be a non-empty array
+          if (!roles || roles.length <= 0) {
+            reject('getInfo: roles must be a non-null array!')
+          }
+
+          commit('SET_ROLES', roles)
+          commit('SET_MENUS', menus)
+          commit('SET_USERID', id)
+          commit('SET_USERNAME', username)
+          commit('SET_AVATAR', avatar)
+          commit('SET_ROLEDESC', roleDesc)
+          commit('SET_FULLNAME', fullName)
+          commit('SET_PHONE', phone)
+
+          resolve(data)
+        })
+        .catch(error => {
+          reject(error)
+        })
     })
     })
   },
   },
 
 
   // user logout
   // user logout
   logout({ commit, state, dispatch }) {
   logout({ commit, state, dispatch }) {
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
-      logout(state.token).then(() => {
-        commit('SET_TOKEN', '')
-        commit('SET_ROLES', [])
-        removeToken()
-        resetRouter()
-
-        // reset visited views and cached views
-        // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
-        dispatch('tagsView/delAllViews', null, { root: true })
-
-        resolve()
-      }).catch(error => {
-        reject(error)
-      })
+      logout(state.token)
+        .then(() => {
+          commit('SET_TOKEN', '')
+          commit('SET_ROLES', [])
+          removeToken()
+          resetRouter()
+
+          // reset visited views and cached views
+          // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
+          dispatch('tagsView/delAllViews', null, { root: true })
+
+          resolve()
+        })
+        .catch(error => {
+          reject(error)
+        })
     })
     })
   },
   },
 
 

+ 120 - 128
src/views/login/index.vue

@@ -1,8 +1,6 @@
 <template>
 <template>
   <div class="login-container" :style="'background-image:' + bgImage">
   <div class="login-container" :style="'background-image:' + bgImage">
-    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on"
-             label-position="left"
-    >
+    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" label-position="left">
 
 
       <div class="title-container">
       <div class="title-container">
         <h3 class="title">采美后台登录</h3>
         <h3 class="title">采美后台登录</h3>
@@ -11,9 +9,7 @@
         <span class="svg-container">
         <span class="svg-container">
           <svg-icon icon-class="user" />
           <svg-icon icon-class="user" />
         </span>
         </span>
-        <el-input ref="username" v-model="loginForm.username" placeholder="Username" name="username" type="text"
-                  tabindex="1" autocomplete="on"
-        />
+        <el-input ref="username" v-model="loginForm.username" placeholder="Username" name="username" type="text" tabindex="1" autocomplete="on" />
       </el-form-item>
       </el-form-item>
 
 
       <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual>
       <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual>
@@ -21,19 +17,14 @@
           <span class="svg-container">
           <span class="svg-container">
             <svg-icon icon-class="password" />
             <svg-icon icon-class="password" />
           </span>
           </span>
-          <el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType"
-                    placeholder="Password" name="password" tabindex="2" autocomplete="on" @keyup.native="checkCapslock"
-                    @blur="capsTooltip = false" @keyup.enter.native="handleLogin"
-          />
+          <el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType" placeholder="Password" name="password" tabindex="2" autocomplete="on" @keyup.native="checkCapslock" @blur="capsTooltip = false" @keyup.enter.native="handleLogin" />
           <span class="show-pwd" @click="showPwd">
           <span class="show-pwd" @click="showPwd">
             <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
             <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
           </span>
           </span>
         </el-form-item>
         </el-form-item>
       </el-tooltip>
       </el-tooltip>
 
 
-      <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;"
-                 @click.native.prevent="handleLogin"
-      >登录</el-button>
+      <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登录</el-button>
     </el-form>
     </el-form>
 
 
     <el-dialog title="Or connect with" :visible.sync="showDialog">
     <el-dialog title="Or connect with" :visible.sync="showDialog">
@@ -46,9 +37,7 @@
 </template>
 </template>
 
 
 <script>
 <script>
-import {
-  validUsername
-} from '@/utils/validate'
+import { validUsername } from '@/utils/validate'
 
 
 export default {
 export default {
   name: 'Login',
   name: 'Login',
@@ -69,20 +58,24 @@ export default {
     }
     }
     return {
     return {
       loginForm: {
       loginForm: {
-        username: 'charles',
+        username: 'sysadmin',
         password: '123456'
         password: '123456'
       },
       },
       loginRules: {
       loginRules: {
-        username: [{
-          required: true,
-          trigger: 'blur',
-          validator: validateUsername
-        }],
-        password: [{
-          required: true,
-          trigger: 'blur',
-          validator: validatePassword
-        }]
+        username: [
+          {
+            required: true,
+            trigger: 'blur',
+            validator: validateUsername
+          }
+        ],
+        password: [
+          {
+            required: true,
+            trigger: 'blur',
+            validator: validatePassword
+          }
+        ]
       },
       },
       passwordType: 'password',
       passwordType: 'password',
       capsTooltip: false,
       capsTooltip: false,
@@ -95,7 +88,7 @@ export default {
   },
   },
   watch: {
   watch: {
     $route: {
     $route: {
-      handler: function(route) {
+      handler: function (route) {
         const query = route.query
         const query = route.query
         if (query) {
         if (query) {
           this.redirect = query.redirect
           this.redirect = query.redirect
@@ -120,10 +113,8 @@ export default {
   },
   },
   methods: {
   methods: {
     checkCapslock(e) {
     checkCapslock(e) {
-      const {
-        key
-      } = e
-      this.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z')
+      const { key } = e
+      this.capsTooltip = key && key.length === 1 && key >= 'A' && key <= 'Z'
     },
     },
     showPwd() {
     showPwd() {
       if (this.passwordType === 'password') {
       if (this.passwordType === 'password') {
@@ -139,7 +130,8 @@ export default {
       this.$refs.loginForm.validate(valid => {
       this.$refs.loginForm.validate(valid => {
         if (valid) {
         if (valid) {
           this.loading = true
           this.loading = true
-          this.$store.dispatch('user/login', this.loginForm)
+          this.$store
+            .dispatch('user/login', this.loginForm)
             .then(() => {
             .then(() => {
               this.$router.push({
               this.$router.push({
                 path: this.redirect || '/',
                 path: this.redirect || '/',
@@ -187,127 +179,127 @@ export default {
 </script>
 </script>
 
 
 <style lang="scss">
 <style lang="scss">
-  /* 修复input 背景不协调 和光标变色 */
-  /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
+/* 修复input 背景不协调 和光标变色 */
+/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
 
 
-  $bg:#283443;
-  $light_gray:#fff;
-  $cursor: #fff;
+$bg: #283443;
+$light_gray: #fff;
+$cursor: #fff;
 
 
-  @supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
-    .login-container .el-input input {
-      color: $cursor;
-    }
+@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
+  .login-container .el-input input {
+    color: $cursor;
   }
   }
+}
 
 
-  /* reset element-ui css */
-  .login-container {
-    background-repeat: no-repeat;
-    background-position: center top;
-    background-size: cover;
-    .el-input {
-      display: inline-block;
-      height: 47px;
-      width: 85%;
+/* reset element-ui css */
+.login-container {
+  background-repeat: no-repeat;
+  background-position: center top;
+  background-size: cover;
+  .el-input {
+    display: inline-block;
+    height: 47px;
+    width: 85%;
 
 
-      input {
-        background: transparent;
-        border: 0px;
-        -webkit-appearance: none;
-        border-radius: 0px;
-        padding: 12px 5px 12px 15px;
-        color: $light_gray;
-        height: 47px;
-        caret-color: $cursor;
+    input {
+      background: transparent;
+      border: 0px;
+      -webkit-appearance: none;
+      border-radius: 0px;
+      padding: 12px 5px 12px 15px;
+      color: $light_gray;
+      height: 47px;
+      caret-color: $cursor;
 
 
-        &:-webkit-autofill {
-          box-shadow: 0 0 0px 1000px $bg inset !important;
-          -webkit-text-fill-color: $cursor !important;
-        }
+      &:-webkit-autofill {
+        box-shadow: 0 0 0px 1000px $bg inset !important;
+        -webkit-text-fill-color: $cursor !important;
       }
       }
     }
     }
+  }
 
 
-    .el-form-item {
-      border: 1px solid rgba(255, 255, 255, 0.1);
-      background: rgba(0, 0, 0, 0.1);
-      border-radius: 5px;
-      color: #454545;
-    }
+  .el-form-item {
+    border: 1px solid rgba(255, 255, 255, 0.1);
+    background: rgba(0, 0, 0, 0.1);
+    border-radius: 5px;
+    color: #454545;
   }
   }
+}
 </style>
 </style>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-  $bg:#2d3a4b;
-  $dark_gray:#889aa4;
-  $light_gray:#eee;
+$bg: #2d3a4b;
+$dark_gray: #889aa4;
+$light_gray: #eee;
 
 
-  .login-container {
-    min-height: 100%;
-    width: 100%;
-    background-color: $bg;
-    overflow: hidden;
+.login-container {
+  min-height: 100%;
+  width: 100%;
+  background-color: $bg;
+  overflow: hidden;
 
 
-    .login-form {
-      position: relative;
-      width: 400px;
-      max-width: 100%;
-      padding: 160px 35px 0;
-      margin: 0 auto;
-      overflow: hidden;
-    }
+  .login-form {
+    position: relative;
+    width: 400px;
+    max-width: 100%;
+    padding: 160px 35px 0;
+    margin: 0 auto;
+    overflow: hidden;
+  }
 
 
-    .tips {
-      font-size: 14px;
-      color: #fff;
-      margin-bottom: 10px;
+  .tips {
+    font-size: 14px;
+    color: #fff;
+    margin-bottom: 10px;
 
 
-      span {
-        &:first-of-type {
-          margin-right: 16px;
-        }
+    span {
+      &:first-of-type {
+        margin-right: 16px;
       }
       }
     }
     }
+  }
 
 
-    .svg-container {
-      padding: 6px 5px 6px 15px;
-      color: $dark_gray;
-      vertical-align: middle;
-      width: 30px;
-      display: inline-block;
-    }
+  .svg-container {
+    padding: 6px 5px 6px 15px;
+    color: $dark_gray;
+    vertical-align: middle;
+    width: 30px;
+    display: inline-block;
+  }
 
 
-    .title-container {
-      position: relative;
+  .title-container {
+    position: relative;
 
 
-      .title {
-        font-size: 26px;
-        color: $light_gray;
-        margin: 0px auto 40px auto;
-        text-align: center;
-        font-weight: bold;
-      }
+    .title {
+      font-size: 26px;
+      color: $light_gray;
+      margin: 0px auto 40px auto;
+      text-align: center;
+      font-weight: bold;
     }
     }
+  }
 
 
-    .show-pwd {
-      position: absolute;
-      right: 10px;
-      top: 7px;
-      font-size: 16px;
-      color: $dark_gray;
-      cursor: pointer;
-      user-select: none;
-    }
+  .show-pwd {
+    position: absolute;
+    right: 10px;
+    top: 7px;
+    font-size: 16px;
+    color: $dark_gray;
+    cursor: pointer;
+    user-select: none;
+  }
 
 
-    .thirdparty-button {
-      position: absolute;
-      right: 0;
-      bottom: 6px;
-    }
+  .thirdparty-button {
+    position: absolute;
+    right: 0;
+    bottom: 6px;
+  }
 
 
-    @media only screen and (max-width: 470px) {
-      .thirdparty-button {
-        display: none;
-      }
+  @media only screen and (max-width: 470px) {
+    .thirdparty-button {
+      display: none;
     }
     }
   }
   }
+}
 </style>
 </style>

+ 64 - 13
src/views/profile/components/Account.vue

@@ -1,36 +1,87 @@
 <template>
 <template>
-  <el-form>
-    <el-form-item label="Name">
-      <el-input v-model.trim="user.name" />
+  <el-form ref="sysUserForm" :model="user" :rules="rules">
+    <el-form-item label="用户头像">
+      <single-upload v-model="user.avatar" />
     </el-form-item>
     </el-form-item>
-    <el-form-item label="Email">
-      <el-input v-model.trim="user.email" />
+    <el-form-item label="登录名:" prop="username">
+      <el-input v-model.trim="user.username" />
+    </el-form-item>
+    <el-form-item label="姓名:" prop="fullName">
+      <el-input v-model.trim="user.fullName" />
+    </el-form-item>
+    <el-form-item label="手机:">
+      <el-input v-model.trim="user.phone" />
     </el-form-item>
     </el-form-item>
     <el-form-item>
     <el-form-item>
-      <el-button type="primary" @click="submit">Update</el-button>
+      <el-button type="primary" @click="onSubmit('sysUserForm')">保存修改</el-button>
     </el-form-item>
     </el-form-item>
   </el-form>
   </el-form>
 </template>
 </template>
 
 
 <script>
 <script>
+import { updateProfile } from '@/api/user'
+import SingleUpload from '@/components/Upload/singleUpload'
 export default {
 export default {
+  components: { SingleUpload },
   props: {
   props: {
     user: {
     user: {
       type: Object,
       type: Object,
       default: () => {
       default: () => {
         return {
         return {
-          name: '',
-          email: ''
+          userId: 0,
+          username: '',
+          fullName: '',
+          phone: '',
+          avatar: ''
+        }
+      }
+    },
+    rules: {
+      type: Object,
+      default: () => {
+        return {
+          username: [
+            { required: true, message: '请输入登录名', trigger: 'blur' },
+            { min: 2, max: 15, message: '长度在 2 到 15 个字符', trigger: 'blur' }
+          ],
+          password: [
+            { required: true, message: '请输入密码', trigger: 'blur' },
+            { min: 6, max: 30, message: '长度在 6 到 30 个字符', trigger: 'blur' }
+          ],
+          fullName: [
+            { required: true, message: '请输入姓名', trigger: 'blur' },
+            { min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }
+          ]
         }
         }
       }
       }
     }
     }
   },
   },
   methods: {
   methods: {
-    submit() {
-      this.$message({
-        message: 'User information has been updated successfully',
-        type: 'success',
-        duration: 5 * 1000
+    onSubmit(formName) {
+      this.$refs[formName].validate(valid => {
+        if (valid) {
+          this.$confirm('是否提交数据', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+            updateProfile(this.user).then(response => {
+              this.$message({
+                message: '修改成功',
+                type: 'success',
+                duration: 1000
+              })
+              this.$router.back()
+            })
+          })
+        } else {
+          this.$message({
+            message: '验证失败',
+            type: 'error',
+            duration: 1000
+          })
+          return false
+        }
       })
       })
     }
     }
   }
   }

+ 0 - 185
src/views/profile/components/Activity.vue

@@ -1,185 +0,0 @@
-<template>
-  <div class="user-activity">
-    <div class="post">
-      <div class="user-block">
-        <img class="img-circle" :src="'https://wpimg.wallstcn.com/57ed425a-c71e-4201-9428-68760c0537c4.jpg'+avatarPrefix">
-        <span class="username text-muted">Iron Man</span>
-        <span class="description">Shared publicly - 7:30 PM today</span>
-      </div>
-      <p>
-        Lorem ipsum represents a long-held tradition for designers,
-        typographers and the like. Some people hate it and argue for
-        its demise, but others ignore the hate as they create awesome
-        tools to help create filler text for everyone from bacon lovers
-        to Charlie Sheen fans.
-      </p>
-      <ul class="list-inline">
-        <li>
-          <span class="link-black text-sm">
-            <i class="el-icon-share" />
-            Share
-          </span>
-        </li>
-        <li>
-          <span class="link-black text-sm">
-            <svg-icon icon-class="like" />
-            Like
-          </span>
-        </li>
-      </ul>
-    </div>
-    <div class="post">
-      <div class="user-block">
-        <img class="img-circle" :src="'https://wpimg.wallstcn.com/9e2a5d0a-bd5b-457f-ac8e-86554616c87b.jpg'+avatarPrefix">
-        <span class="username text-muted">Captain American</span>
-        <span class="description">Sent you a message - yesterday</span>
-      </div>
-      <p>
-        Lorem ipsum represents a long-held tradition for designers,
-        typographers and the like. Some people hate it and argue for
-        its demise, but others ignore the hate as they create awesome
-        tools to help create filler text for everyone from bacon lovers
-        to Charlie Sheen fans.
-      </p>
-      <ul class="list-inline">
-        <li>
-          <span class="link-black text-sm">
-            <i class="el-icon-share" />
-            Share
-          </span>
-        </li>
-        <li>
-          <span class="link-black text-sm">
-            <svg-icon icon-class="like" />
-            Like
-          </span>
-        </li>
-      </ul>
-    </div>
-    <div class="post">
-      <div class="user-block">
-        <img class="img-circle" :src="'https://wpimg.wallstcn.com/fb57f689-e1ab-443c-af12-8d4066e202e2.jpg'+avatarPrefix">
-        <span class="username">Spider Man</span>
-        <span class="description">Posted 4 photos - 2 days ago</span>
-      </div>
-      <div class="user-images">
-        <el-carousel :interval="6000" type="card" height="220px">
-          <el-carousel-item v-for="item in carouselImages" :key="item">
-            <img :src="item+carouselPrefix" class="image">
-          </el-carousel-item>
-        </el-carousel>
-      </div>
-      <ul class="list-inline">
-        <li><span class="link-black text-sm"><i class="el-icon-share" /> Share</span></li>
-        <li>
-          <span class="link-black text-sm">
-            <svg-icon icon-class="like" /> Like</span>
-        </li>
-      </ul>
-    </div>
-  </div>
-</template>
-
-<script>
-const avatarPrefix = '?imageView2/1/w/80/h/80'
-const carouselPrefix = '?imageView2/2/h/440'
-
-export default {
-  data() {
-    return {
-      carouselImages: [
-        'https://wpimg.wallstcn.com/9679ffb0-9e0b-4451-9916-e21992218054.jpg',
-        'https://wpimg.wallstcn.com/bcce3734-0837-4b9f-9261-351ef384f75a.jpg',
-        'https://wpimg.wallstcn.com/d1d7b033-d75e-4cd6-ae39-fcd5f1c0a7c5.jpg',
-        'https://wpimg.wallstcn.com/50530061-851b-4ca5-9dc5-2fead928a939.jpg'
-      ],
-      avatarPrefix,
-      carouselPrefix
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.user-activity {
-  .user-block {
-
-    .username,
-    .description {
-      display: block;
-      margin-left: 50px;
-      padding: 2px 0;
-    }
-
-    .username{
-      font-size: 16px;
-      color: #000;
-    }
-
-    :after {
-      clear: both;
-    }
-
-    .img-circle {
-      border-radius: 50%;
-      width: 40px;
-      height: 40px;
-      float: left;
-    }
-
-    span {
-      font-weight: 500;
-      font-size: 12px;
-    }
-  }
-
-  .post {
-    font-size: 14px;
-    border-bottom: 1px solid #d2d6de;
-    margin-bottom: 15px;
-    padding-bottom: 15px;
-    color: #666;
-
-    .image {
-      width: 100%;
-      height: 100%;
-
-    }
-
-    .user-images {
-      padding-top: 20px;
-    }
-  }
-
-  .list-inline {
-    padding-left: 0;
-    margin-left: -5px;
-    list-style: none;
-
-    li {
-      display: inline-block;
-      padding-right: 5px;
-      padding-left: 5px;
-      font-size: 13px;
-    }
-
-    .link-black {
-
-      &:hover,
-      &:focus {
-        color: #999;
-      }
-    }
-  }
-
-}
-
-.box-center {
-  margin: 0 auto;
-  display: table;
-}
-
-.text-muted {
-  color: #777;
-}
-</style>

+ 83 - 0
src/views/profile/components/Password.vue

@@ -0,0 +1,83 @@
+<template>
+  <el-form ref="passwordForm" :model="user" :rules="rules">
+    <el-form-item label="旧密码:" prop="oldPassword">
+      <el-input v-model.trim="user.oldPassword" />
+    </el-form-item>
+    <el-form-item label="新密码:" prop="password">
+      <el-input v-model.trim="user.password" />
+    </el-form-item>
+    <el-form-item label="确认新密码:" prop="confirmPassword">
+      <el-input v-model.trim="user.confirmPassword" />
+    </el-form-item>
+    <el-form-item>
+      <el-button type="primary" @click="onSubmit('passwordForm')">保存修改</el-button>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script>
+import { updatePassword } from '@/api/user'
+export default {
+  props: {
+    user: {
+      type: Object,
+      default: () => {
+        return {
+          userId: 0,
+          oldPassword: '',
+          password: '',
+          confirmPassword: ''
+        }
+      }
+    },
+    rules: {
+      type: Object,
+      default: () => {
+        return {
+          oldPassword: [
+            { required: true, message: '请输入旧密码', trigger: 'blur' },
+            { min: 2, max: 15, message: '长度在 6 到 30 个字符', trigger: 'blur' }
+          ],
+          password: [
+            { required: true, message: '请输入新密码', trigger: 'blur' },
+            { min: 6, max: 30, message: '长度在 6 到 30 个字符', trigger: 'blur' }
+          ],
+          confirmPassword: [
+            { required: true, message: '请确认新密码', trigger: 'blur' },
+            { min: 2, max: 10, message: '长度在 6 到 30 个字符', trigger: 'blur' }
+          ]
+        }
+      }
+    }
+  },
+  methods: {
+    onSubmit(formName) {
+      this.$refs[formName].validate(valid => {
+        if (valid) {
+          this.$confirm('是否提交数据', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }).then(() => {
+            updatePassword(this.user).then(response => {
+              this.$message({
+                message: '修改成功',
+                type: 'success',
+                duration: 1000
+              })
+              this.$router.back()
+            })
+          })
+        } else {
+          this.$message({
+            message: '验证失败',
+            type: 'error',
+            duration: 1000
+          })
+          return false
+        }
+      })
+    }
+  }
+}
+</script>

+ 0 - 43
src/views/profile/components/Timeline.vue

@@ -1,43 +0,0 @@
-<template>
-  <div class="block">
-    <el-timeline>
-      <el-timeline-item v-for="(item,index) of timeline" :key="index" :timestamp="item.timestamp" placement="top">
-        <el-card>
-          <h4>{{ item.title }}</h4>
-          <p>{{ item.content }}</p>
-        </el-card>
-      </el-timeline-item>
-    </el-timeline>
-  </div>
-</template>
-
-<script>
-export default {
-  data() {
-    return {
-      timeline: [
-        {
-          timestamp: '2019/4/20',
-          title: 'Update Github template',
-          content: 'PanJiaChen committed 2019/4/20 20:46'
-        },
-        {
-          timestamp: '2019/4/21',
-          title: 'Update Github template',
-          content: 'PanJiaChen committed 2019/4/21 20:46'
-        },
-        {
-          timestamp: '2019/4/22',
-          title: 'Build Template',
-          content: 'PanJiaChen committed 2019/4/22 20:46'
-        },
-        {
-          timestamp: '2019/4/23',
-          title: 'Release New Version',
-          content: 'PanJiaChen committed 2019/4/23 20:46'
-        }
-      ]
-    }
-  }
-}
-</script>

+ 37 - 26
src/views/profile/components/UserCard.vue

@@ -1,50 +1,59 @@
 <template>
 <template>
   <el-card style="margin-bottom:20px;">
   <el-card style="margin-bottom:20px;">
     <div slot="header" class="clearfix">
     <div slot="header" class="clearfix">
-      <span>About me</span>
+      <span>个人资料</span>
     </div>
     </div>
 
 
     <div class="user-profile">
     <div class="user-profile">
       <div class="box-center">
       <div class="box-center">
         <pan-thumb :image="user.avatar" :height="'100px'" :width="'100px'" :hoverable="false">
         <pan-thumb :image="user.avatar" :height="'100px'" :width="'100px'" :hoverable="false">
           <div>Hello</div>
           <div>Hello</div>
-          {{ user.role }}
+          {{ user.username }}
         </pan-thumb>
         </pan-thumb>
       </div>
       </div>
       <div class="box-center">
       <div class="box-center">
-        <div class="user-name text-center">{{ user.name }}</div>
-        <div class="user-role text-center text-muted">{{ user.role | uppercaseFirst }}</div>
+        <div class="user-name text-center">{{ user.username }}</div>
       </div>
       </div>
     </div>
     </div>
 
 
     <div class="user-bio">
     <div class="user-bio">
       <div class="user-education user-bio-section">
       <div class="user-education user-bio-section">
-        <div class="user-bio-section-header"><svg-icon icon-class="education" /><span>Education</span></div>
+        <div class="user-bio-section-header">
+          <span>角色</span>
+        </div>
         <div class="user-bio-section-body">
         <div class="user-bio-section-body">
           <div class="text-muted">
           <div class="text-muted">
-            JS in Computer Science from the University of Technology
+            {{ user.roleName | uppercaseFirst }}
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
-
-      <div class="user-skills user-bio-section">
-        <div class="user-bio-section-header"><svg-icon icon-class="skill" /><span>Skills</span></div>
+      <div class="user-education user-bio-section">
+        <div class="user-bio-section-header">
+          <span>角色描述</span>
+        </div>
         <div class="user-bio-section-body">
         <div class="user-bio-section-body">
-          <div class="progress-item">
-            <span>Vue</span>
-            <el-progress :percentage="70" />
-          </div>
-          <div class="progress-item">
-            <span>JavaScript</span>
-            <el-progress :percentage="18" />
+          <div class="text-muted">
+            {{ user.roleDesc }}
           </div>
           </div>
-          <div class="progress-item">
-            <span>Css</span>
-            <el-progress :percentage="12" />
+        </div>
+      </div>
+      <div class="user-education user-bio-section">
+        <div class="user-bio-section-header">
+          <span>姓名</span>
+        </div>
+        <div class="user-bio-section-body">
+          <div class="text-muted">
+            {{ user.fullName }}
           </div>
           </div>
-          <div class="progress-item">
-            <span>ESLint</span>
-            <el-progress :percentage="100" status="success" />
+        </div>
+      </div>
+      <div class="user-education user-bio-section">
+        <div class="user-bio-section-header">
+          <span>手机号</span>
+        </div>
+        <div class="user-bio-section-body" phone>
+          <div class="text-muted">
+            {{ user.phone }}
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
@@ -62,10 +71,12 @@ export default {
       type: Object,
       type: Object,
       default: () => {
       default: () => {
         return {
         return {
-          name: '',
-          email: '',
-          avatar: '',
-          role: ''
+          username: '',
+          roleName: '',
+          roleDesc: '',
+          fullName: '',
+          phone: '',
+          avatar: ''
         }
         }
       }
       }
     }
     }

+ 14 - 19
src/views/profile/index.vue

@@ -10,15 +10,12 @@
         <el-col :span="18" :xs="24">
         <el-col :span="18" :xs="24">
           <el-card>
           <el-card>
             <el-tabs v-model="activeTab">
             <el-tabs v-model="activeTab">
-              <el-tab-pane label="Activity" name="activity">
-                <activity />
-              </el-tab-pane>
-              <el-tab-pane label="Timeline" name="timeline">
-                <timeline />
-              </el-tab-pane>
-              <el-tab-pane label="Account" name="account">
+              <el-tab-pane label="修改资料" name="account">
                 <account :user="user" />
                 <account :user="user" />
               </el-tab-pane>
               </el-tab-pane>
+              <el-tab-pane label="修改密码" name="password">
+                <password :user="user" />
+              </el-tab-pane>
             </el-tabs>
             </el-tabs>
           </el-card>
           </el-card>
         </el-col>
         </el-col>
@@ -31,25 +28,20 @@
 <script>
 <script>
 import { mapGetters } from 'vuex'
 import { mapGetters } from 'vuex'
 import UserCard from './components/UserCard'
 import UserCard from './components/UserCard'
-import Activity from './components/Activity'
-import Timeline from './components/Timeline'
+import Password from './components/Password'
 import Account from './components/Account'
 import Account from './components/Account'
 
 
 export default {
 export default {
   name: 'Profile',
   name: 'Profile',
-  components: { UserCard, Activity, Timeline, Account },
+  components: { UserCard, Password, Account },
   data() {
   data() {
     return {
     return {
       user: {},
       user: {},
-      activeTab: 'activity'
+      activeTab: 'account'
     }
     }
   },
   },
   computed: {
   computed: {
-    ...mapGetters([
-      'name',
-      'avatar',
-      'roles'
-    ])
+    ...mapGetters(['userId', 'username', 'avatar', 'roles', 'roleDesc', 'fullName', 'phone'])
   },
   },
   created() {
   created() {
     this.getUser()
     this.getUser()
@@ -57,9 +49,12 @@ export default {
   methods: {
   methods: {
     getUser() {
     getUser() {
       this.user = {
       this.user = {
-        name: this.name,
-        role: this.roles.join(' | '),
-        email: 'admin@test.com',
+        userId: this.userId,
+        username: this.username,
+        roleName: this.roles.join(' | '),
+        roleDesc: this.roleDesc,
+        fullName: this.fullName,
+        phone: this.phone,
         avatar: this.avatar
         avatar: this.avatar
       }
       }
     }
     }

+ 3 - 3
src/views/sys/users/form.vue

@@ -4,6 +4,9 @@
     <el-page-header :content="isEdit?'编辑用户':'添加用户'" @back="goBack" />
     <el-page-header :content="isEdit?'编辑用户':'添加用户'" @back="goBack" />
     <el-card class="form-container" shadow="never">
     <el-card class="form-container" shadow="never">
       <el-form ref="sysUserForm" :model="sysUser" :rules="rules" label-width="150px">
       <el-form ref="sysUserForm" :model="sysUser" :rules="rules" label-width="150px">
+        <el-form-item label="用户头像">
+          <single-upload v-model="sysUser.avatar" />
+        </el-form-item>
         <el-form-item label="登录名:" prop="username">
         <el-form-item label="登录名:" prop="username">
           <el-input v-model="sysUser.username" />
           <el-input v-model="sysUser.username" />
         </el-form-item>
         </el-form-item>
@@ -27,9 +30,6 @@
             <el-checkbox v-for="item in roleSelect" :key="item.id" :label="item.id" class="littleMarginLeft">{{ item.roleDesc }}</el-checkbox>
             <el-checkbox v-for="item in roleSelect" :key="item.id" :label="item.id" class="littleMarginLeft">{{ item.roleDesc }}</el-checkbox>
           </el-checkbox-group>
           </el-checkbox-group>
         </el-form-item>
         </el-form-item>
-        <el-form-item label="用户头像">
-          <single-upload v-model="sysUser.avatar" />
-        </el-form-item>
         <el-form-item>
         <el-form-item>
           <el-button type="primary" size="medium" @click="onSubmit('sysUserForm')">保存</el-button>
           <el-button type="primary" size="medium" @click="onSubmit('sysUserForm')">保存</el-button>
         </el-form-item>
         </el-form-item>