소스 검색

添加已登录用户资料的更新页面和接口

reghao 2 년 전
부모
커밋
82a2567695

+ 5 - 0
src/api/account.js

@@ -12,6 +12,7 @@ const accountApi = {
   accountVipApi: '/api/account/vip/basic',
   registerApi: '/api/account/user/register',
   resetPasswordApi: '/api/account/user/reset',
+  updateAvatarApi: '/api/account/profile/avatar',
   loginApi: '/api/auth/signin',
   logoutApi: '/api/auth/signout'
 }
@@ -69,3 +70,7 @@ export function logout() {
 export function vip() {
   return post(accountApi.accountVipApi)
 }
+
+export function updateAvatar(userAvatar) {
+  return post(accountApi.updateAvatarApi, userAvatar)
+}

+ 2 - 4
src/components/layout/NavBar.vue

@@ -174,11 +174,9 @@
 </template>
 
 <script>
-import Vue from 'vue'
 import { userMixin } from 'assets/js/mixin'
-import { getMyInfo } from '@/api/user'
 import { keywordSuggest } from '@/api/search'
-import {getUserInfo} from "@/utils/auth";
+import { getAuthedUser } from '@/utils/auth'
 
 export default {
   name: 'NavBar',
@@ -197,7 +195,7 @@ export default {
   created() {
     /* const userdata = Vue.$cookies.get('USERDATA')
     const userId = userdata.split(':')[0]*/
-    const userInfo = getUserInfo()
+    const userInfo = getAuthedUser()
     if (userInfo !== null) {
       this.user = userInfo
     }

+ 3 - 3
src/store/modules/user.js

@@ -1,4 +1,4 @@
-import { setUserInfo, getUserInfo, getAccessToken } from '@/utils/auth'
+import { setAuthedUser, getAuthedUser, getAccessToken } from '@/utils/auth'
 
 const state = {
   userId: 0,
@@ -8,7 +8,7 @@ const state = {
 
 // 判断用户是否登录
 if (getAccessToken()) {
-  const userInfo = getUserInfo()
+  const userInfo = getAuthedUser()
   state.userId = userInfo.uid
   state.username = userInfo.screenName
   state.avatarUrl = userInfo.avatarUrl ? userInfo.avatarUrl : state.avatarUrl
@@ -20,7 +20,7 @@ const User = {
     // 更新用户信息
     UPDATE_USER_INFO(state, userInfo) {
       // 保存用户信息到缓存
-      setUserInfo(userInfo)
+      setAuthedUser(userInfo)
     },
     // 用户退出登录
     USER_LOGOUT(state) {

+ 18 - 9
src/utils/auth.js

@@ -1,9 +1,9 @@
 const USER_ACCESS_TOKEN = 'ACCESS-TOKEN'
 const USER_REFRESH_TOKEN = 'REFRESH-TOKEN'
-const USER_INFO = 'LUMNEIM-USERINFO'
+const USER_INFO = 'TNB-USERINFO'
 
 /**
- * 设置用户 token
+ * 设置已登录用户 token
  *
  * @param {Object} userToken
  */
@@ -28,7 +28,7 @@ export function setUserToken(userToken) {
 }
 
 /**
- * 获取访问令牌
+ * 获取已登录用户的访问令牌
  */
 export function getAccessToken() {
   const result = localStorage.getItem(USER_ACCESS_TOKEN)
@@ -45,7 +45,7 @@ export function getAccessToken() {
 }
 
 /**
- * 获取刷新令牌
+ * 获取已登录的刷新令牌
  */
 export function getRefreshToken() {
   const result = localStorage.getItem(USER_REFRESH_TOKEN)
@@ -62,24 +62,33 @@ export function getRefreshToken() {
 }
 
 /**
- * 设置用户信息
+ * 设置已登录用户信息
  *
  * @param {Object} data
  */
-export function setUserInfo(data) {
+export function setAuthedUser(data) {
   localStorage.setItem(USER_INFO, JSON.stringify(data))
 }
 
 /**
- * 获取用户信息
+ * 更新已登录用户信息
+ *
+ * @param {Object} data
+ */
+export function updateAuthedUser(data) {
+  localStorage.setItem(USER_INFO, JSON.stringify(data))
+}
+
+/**
+ * 获取已登录用户信息
  */
-export function getUserInfo() {
+export function getAuthedUser() {
   const data = localStorage.getItem(USER_INFO) || null
   return data !== null ? JSON.parse(data) : null
 }
 
 /**
- * 删除用户相关缓存信息
+ * 删除已登录用户相关缓存信息
  */
 export function removeAll() {
   localStorage.removeItem(USER_ACCESS_TOKEN)

+ 1 - 1
src/utils/request.js

@@ -1,7 +1,7 @@
 import axios from 'axios'
 import store from '@/store'
 import Vue from 'vue'
-import {getAccessToken, removeAll} from '@/utils/auth'
+import { getAccessToken, removeAll } from '@/utils/auth'
 
 const instance = axios.create({
   // 域名

+ 3 - 6
src/views/home/Status.vue

@@ -12,7 +12,7 @@
 
 <script>
 import StatusCard from '@/components/card/StatusCard'
-import { getUserInfo } from '@/utils/auth'
+import { getAuthedUser } from '@/utils/auth'
 import { getUserStatus } from '@/api/status'
 
 export default {
@@ -31,7 +31,7 @@ export default {
     const arr = path.split('/')
     const statusId = parseInt(arr[3])
 
-    const userInfo = getUserInfo()
+    const userInfo = getAuthedUser()
     if (userInfo != null) {
       document.title = userInfo.screenName + '的状态'
     }
@@ -53,10 +53,7 @@ export default {
   },
   methods: {
     statusTimelineWrapper(nextId) {
-      statusTimeline(nextId).then(res => {
-        if (res.code === 0) {
-        }
-      })
+      console.log('get timeline')
     }
   }
 }

+ 5 - 6
src/views/home/Timeline.vue

@@ -47,8 +47,7 @@ import SideVideoCard from '@/components/card/SideVideoCard'
 import UserAvatarCard from '@/components/card/UserAvatarCard'
 
 import { statusTimeline, videoTimeline } from '@/api/timeline'
-import { getUserInfo } from '@/api/user'
-import Vue from 'vue'
+import { getAuthedUser } from '@/utils/auth'
 
 export default {
   name: 'Timeline',
@@ -65,13 +64,13 @@ export default {
     }
   },
   created() {
-    const userInfo = getUserInfo()
-    if (userInfo === null) {
+    const loginUser = getAuthedUser()
+    if (loginUser === null) {
       return null
     }
 
-    this.userInfo = userInfo
-    document.title = userInfo.screenName + '的时间线'
+    this.userInfo = loginUser
+    document.title = loginUser.screenName + '的时间线'
     this.videoTimelineWrapper(this.nextId)
   },
   mounted() {

+ 16 - 4
src/views/home/VideoPage.vue

@@ -120,6 +120,7 @@
                 />
                 <el-pagination
                   :small="screenWidth <= 768"
+                  hide-on-single-page
                   layout="prev, pager, next"
                   :page-size="pageSize"
                   :current-page="currentPage"
@@ -222,6 +223,7 @@ import { collectItem } from '@/api/collect'
 import { getUserInfo } from '@/api/user'
 import { submitAccessCode } from '@/api/content'
 import { publishComment, getComment } from '@/api/comment'
+import { getAuthedUser } from '@/utils/auth'
 
 export default {
   name: 'VideoPage',
@@ -254,8 +256,8 @@ export default {
         }
       ],
       currentUser: {
-        userId: 10002,
-        name: '草莓',
+        userId: 9999,
+        name: '芒果',
         avatar: '//picx.zhimg.com/v2-a2c89378a6332cbfed3e28b5ab84feb7.jpg',
         author: true
       },
@@ -304,6 +306,16 @@ export default {
     }
   },
   created() {
+    const loginUser = getAuthedUser()
+    if (loginUser != null) {
+      this.currentUser = {
+        userId: loginUser.userId,
+        name: loginUser.screenName,
+        avatar: loginUser.avatarUrl,
+        author: true
+      }
+    }
+
     this.videoId = this.$route.params.id
     this.accessCodeForm.contentId = this.videoId
     this.getVideoInfo(this.videoId)
@@ -553,7 +565,7 @@ export default {
       }
 
       // console.log('addComment: ', res)
-      /* publishComment(res).then(resp => {
+      publishComment(res).then(resp => {
         if (resp.code === 0) {
           this.$notify.success({
             message: '评论已发布',
@@ -565,7 +577,7 @@ export default {
             duration: 3000
           })
         }
-      })*/
+      })
     },
     async like(comment) {
       const res = await new Promise((resolve) => {

+ 162 - 4
src/views/my/MyProfile.vue

@@ -1,25 +1,183 @@
 <template>
-  <el-row>
-    <span>我的资料</span>
+  <el-row class="movie-list">
+    <el-col :md="12" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
+      <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
+        <el-card class="box-card">
+          <div slot="header" class="clearfix">
+            <span>更新我的头像</span>
+          </div>
+          <div class="text item">
+            <el-tooltip class="item" effect="dark" content="点击更新我的头像" placement="top-end">
+              <el-upload
+                class="avatar-uploader"
+                action="//oss.reghao.cn/"
+                :headers="imgHeaders"
+                :data="imgData"
+                :with-credentials="true"
+                :show-file-list="false"
+                :before-upload="beforeAvatarUpload"
+                :on-success="handleAvatarSuccess"
+              >
+                <img v-if="loginUser" :src="loginUser.avatarUrl" class="avatar">
+                <i v-else class="el-icon-plus avatar-uploader-icon" />
+              </el-upload>
+            </el-tooltip>
+          </div>
+        </el-card>
+      </el-row>
+    </el-col>
+    <el-col :md="12" style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
+      <el-row style="padding-right: 5px; padding-left: 5px; padding-bottom: 5px">
+        <el-card class="box-card">
+          <div slot="header" class="clearfix">
+            <span>我的资料</span>
+          </div>
+          <div class="text item">
+            <el-form ref="form" :model="loginUser" label-width="80px">
+              <el-form-item label="ID">
+                <el-input v-model="loginUser.userId" style="padding-right: 1px" readonly />
+              </el-form-item>
+              <el-form-item label="显示名">
+                <el-input v-model="loginUser.screenName" style="padding-right: 1px" readonly />
+              </el-form-item>
+              <el-form-item label="签名">
+                <el-input v-model="loginUser.signature" style="padding-right: 1px" readonly />
+              </el-form-item>
+            </el-form>
+          </div>
+        </el-card>
+      </el-row>
+    </el-col>
   </el-row>
 </template>
 
 <script>
+import { getServerInfo } from '@/api/content'
+import { updateAvatar } from '@/api/account'
+import { getAuthedUser, updateAuthedUser } from '@/utils/auth'
+
 export default {
   name: 'MyProfile',
   data() {
     return {
+      imgOssUrl: null,
+      imgHeaders: {
+        Authorization: ''
+      },
+      imgData: {
+        channelId: 4
+      },
+      coverUrl: null,
+      // ****************************************************************************************************************
+      loginUser: null
     }
   },
   created() {
-    document.title = '我的资料'
+    this.loginUser = getAuthedUser()
+
+    getServerInfo(this.imgData.channelId).then(res => {
+      if (res.code === 0) {
+        const resData = res.data
+        this.imgOssUrl = resData.ossUrl
+        this.imgHeaders.Authorization = 'Bearer ' + resData.token
+      } else {
+        this.$notify({
+          title: '提示',
+          message: '获取 OSS 服务器地址失败, 暂时无法上传文件',
+          type: 'error',
+          duration: 3000
+        })
+      }
+    }).catch(error => {
+      this.$notify({
+        title: '提示',
+        message: error.message,
+        type: 'warning',
+        duration: 3000
+      })
+    })
   },
   mounted() {
   },
   methods: {
+    // ****************************************************************************************************************
+    beforeAvatarUpload(file) {
+      const isJPG = file.type === 'image/jpeg'
+      const isLt2M = file.size / 1024 / 1024 < 2
+      if (!isJPG) {
+        this.$message.error('头像文件只能是 JPG 格式!')
+      }
+      if (!isLt2M) {
+        this.$message.error('头像文件大小不能超过 2MB!')
+      }
+      return isJPG && isLt2M
+    },
+    handleAvatarSuccess(res, file) {
+      if (res.code === 0) {
+        const resData = res.data
+        this.coverUrl = URL.createObjectURL(file.raw)
+
+        const avatar = {}
+        avatar.avatarUrl = resData.url
+        updateAvatar(avatar).then(resp => {
+          if (resp.code === 0) {
+            this.loginUser.avatarUrl = resData.url
+            updateAuthedUser(this.loginUser)
+          } else {
+            this.$notify({
+              title: '头像更新失败',
+              message: resp.msg,
+              type: 'warning',
+              duration: 3000
+            })
+          }
+        })
+      } else {
+        this.$notify({
+          title: '提示',
+          message: '视频封面上传失败,请重试!' + res.msg,
+          type: 'warning',
+          duration: 3000
+        })
+      }
+    }
+    // ****************************************************************************************************************
   }
 }
 </script>
 
-<style scoped>
+<style>
+.uploader-example .uploader-btn {
+  margin-right: 4px;
+}
+.uploader-example .uploader-list {
+  max-height: 440px;
+  overflow: auto;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+.avatar-uploader .el-upload:hover {
+  border-color: #409EFF;
+}
+.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 256px;
+  height: 256px;
+  line-height: 178px;
+  text-align: center;
+}
+.avatar {
+  width: 256px;
+  height: 256px;
+  display: block;
+}
 </style>