Skip to content

Commit

Permalink
实现功能 个人信息 -> 头像上传
Browse files Browse the repository at this point in the history
  • Loading branch information
toplusifer committed Aug 26, 2019
1 parent deb98f1 commit 4db4470
Show file tree
Hide file tree
Showing 12 changed files with 352 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.funtl.myshop.plus.business.dto;

import lombok.Data;

import java.io.Serializable;

/**
* 修改头像参数
* <p>
* Description:
* </p>
*
* @author Lusifer
* @version v1.0.0
* @date 2019-08-26 23:44:42
* @see com.funtl.myshop.plus.business.dto
*/
@Data
public class IconParam implements Serializable {

/**
* 用户名
*/
private String username;

/**
* 头像地址
*/
private String path;

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.funtl.myshop.plus.business.feign;

import com.funtl.myshop.plus.business.dto.IconParam;
import com.funtl.myshop.plus.business.dto.PasswordParam;
import com.funtl.myshop.plus.business.dto.ProfileParam;
import com.funtl.myshop.plus.configuration.FeignRequestConfiguration;
Expand Down Expand Up @@ -49,4 +50,13 @@ public interface ProfileFeign {
*/
@PostMapping(value = "modify/password")
String modifyPassword(@RequestBody PasswordParam passwordParam);

/**
* 修改头像
*
* @param iconParam {@link IconParam}
* @return {@code String} JSON
*/
@PostMapping(value = "modify/icon")
String modifyIcon(@RequestBody IconParam iconParam);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.funtl.myshop.plus.business.controller;

import com.funtl.myshop.plus.business.dto.IconParam;
import com.funtl.myshop.plus.business.dto.PasswordParam;
import com.funtl.myshop.plus.business.dto.ProfileParam;
import com.funtl.myshop.plus.commons.dto.ResponseResult;
Expand Down Expand Up @@ -98,4 +99,25 @@ public ResponseResult<Void> modifyPassword(@RequestBody PasswordParam passwordPa

return new ResponseResult<Void>(ResponseResult.CodeStatus.FAIL, "修改密码失败");
}

/**
* 修改头像
*
* @param iconParam {@link IconParam}
* @return {@link ResponseResult}
*/
@PostMapping(value = "modify/icon")
public ResponseResult<Void> modifyIcon(@RequestBody IconParam iconParam) {
int result = umsAdminService.modifyIcon(iconParam.getUsername(), iconParam.getPath());

// 成功
if (result > 0) {
return new ResponseResult<Void>(ResponseResult.CodeStatus.OK, "更新头像成功");
}

// 失败
else {
return new ResponseResult<Void>(ResponseResult.CodeStatus.FAIL, "更新头像失败");
}
}
}
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"vue": "2.6.10",
"vue-image-crop-upload": "^2.5.0",
"vue-router": "3.0.6",
"vuex": "3.1.0"
},
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/api/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,15 @@ export function modifyPassword(data) {
data
})
}

/**
* 更新头像
* @param data
*/
export function modifyIcon(data) {
return request({
url: '/profile/modify/icon',
method: 'post',
data
})
}
132 changes: 132 additions & 0 deletions frontend/src/components/PanThumb/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<template>
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
<div class="pan-info">
<div class="pan-info-roles-container">
<slot />
</div>
</div>
<!-- eslint-disable-next-line -->
<div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
</div>
</template>

<script>
export default {
name: 'PanThumb',
props: {
image: {
type: String,
required: true
},
zIndex: {
type: Number,
default: 1
},
width: {
type: String,
default: '150px'
},
height: {
type: String,
default: '150px'
}
}
}
</script>

<style scoped>
.pan-item {
width: 200px;
height: 200px;
border-radius: 50%;
display: inline-block;
position: relative;
cursor: default;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.pan-info-roles-container {
padding: 20px;
text-align: center;
}
.pan-thumb {
width: 100%;
height: 100%;
background-position: center center;
background-size: cover;
border-radius: 50%;
overflow: hidden;
position: absolute;
transform-origin: 95% 40%;
transition: all 0.3s ease-in-out;
}
/* .pan-thumb:after {
content: '';
width: 8px;
height: 8px;
position: absolute;
border-radius: 50%;
top: 40%;
left: 95%;
margin: -4px 0 0 -4px;
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
} */
.pan-info {
position: absolute;
width: inherit;
height: inherit;
border-radius: 50%;
overflow: hidden;
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
}
.pan-info h3 {
color: #fff;
text-transform: uppercase;
position: relative;
letter-spacing: 2px;
font-size: 18px;
margin: 0 60px;
padding: 22px 0 0 0;
height: 85px;
font-family: 'Open Sans', Arial, sans-serif;
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
}
.pan-info p {
color: #fff;
padding: 10px 5px;
font-style: italic;
margin: 0 30px;
font-size: 12px;
border-top: 1px solid rgba(255, 255, 255, 0.5);
}
.pan-info p a {
display: block;
color: #333;
width: 80px;
height: 80px;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
color: #fff;
font-style: normal;
font-weight: 700;
text-transform: uppercase;
font-size: 9px;
letter-spacing: 1px;
padding-top: 24px;
margin: 7px auto 0;
font-family: 'Open Sans', Arial, sans-serif;
opacity: 0;
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
transform: translateX(60px) rotate(90deg);
}
.pan-info p a:hover {
background: rgba(255, 255, 255, 0.5);
}
.pan-item:hover .pan-thumb {
transform: rotate(-110deg);
}
.pan-item:hover .pan-info p a {
opacity: 1;
transform: translateX(0px) rotate(0deg);
}
</style>
6 changes: 6 additions & 0 deletions frontend/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ export const constantRoutes = [
name: 'ProfilePassword',
component: () => import('@/views/profile/password'),
meta: { title: '修改密码' }
},
{
path: 'icon',
name: 'ProfileIcon',
component: () => import('@/views/profile/icon'),
meta: { title: '修改头像' }
}
]
},
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/store/modules/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ const actions = {
removeToken()
resolve()
})
},

// 设置头像
setAvatar({ commit }, avatar) {
return new Promise(resolve => {
commit('SET_AVATAR', avatar)
resolve()
})
}
}

Expand Down
5 changes: 5 additions & 0 deletions frontend/src/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,8 @@ div:focus {
.app-container {
padding: 20px;
}

.components-container {
margin: 30px 50px;
position: relative;
}
109 changes: 109 additions & 0 deletions frontend/src/views/profile/icon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<template>
<div class="components-container">
<pan-thumb :image="image" />

<el-button type="primary" icon="upload" style="position: absolute;bottom: 15px;margin-left: 40px;" @click="toggleShow">
上传头像
</el-button>

<image-cropper
v-model="show"
field="multipartFile"
:width="300"
:height="300"
:url="url"
:params="params"
:headers="headers"
img-format="png"
@crop-success="cropSuccess"
@crop-upload-success="cropUploadSuccess"
@crop-upload-fail="cropUploadFail"
/>
</div>
</template>

<script>
import ImageCropper from 'vue-image-crop-upload'
import PanThumb from '@/components/PanThumb'
import { getToken } from '../../utils/auth'
import { modifyIcon } from '@/api/profile'
export default {
name: 'ProfileIcon',
components: { ImageCropper, PanThumb },
data() {
return {
url: process.env.VUE_APP_BASE_API + '/upload',
show: false,
params: {
access_token: getToken()
},
headers: {
smail: '*_~'
},
image: this.$store.getters.avatar
}
},
methods: {
toggleShow() {
this.show = !this.show
},
/**
*
* @param image
* @param field
*/
cropSuccess(image, field) {
console.log('-------- crop success --------')
this.image = image
},
/**
* 上传成功
* @param jsonData 服务器返回数据,已进行 JSON 转码
* @param field
*/
cropUploadSuccess(jsonData, field) {
console.log('-------- upload success --------')
console.log(jsonData)
console.log('path: ', jsonData.data.path)
console.log('field: ' + field)
// 更新头像
modifyIcon({
username: this.$store.getters.name,
path: jsonData.data.path
}).then(response => {
this.$message({
message: response.message,
type: 'success'
})
// 更新 vuex 中的头像
this.$store.dispatch('user/setAvatar', jsonData.data.path)
}).catch(() => {
})
},
/**
* 上传失败
* @param status 服务器返回的失败状态码
* @param field
*/
cropUploadFail(status, field) {
console.log('-------- upload fail --------')
console.log(status)
console.log('field: ' + field)
}
}
}
</script>

<style scoped>
.avatar{
width: 200px;
height: 200px;
border-radius: 50%;
}
</style>
Loading

0 comments on commit 4db4470

Please sign in to comment.