完成个人信息设置页面
This commit is contained in:
parent
892f7df54e
commit
aed0856ceb
@ -8,11 +8,11 @@ export function login(data) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInfo(token) {
|
export function getInfo(params) {
|
||||||
return request({
|
return request({
|
||||||
url: 'user/userInfo',
|
url: 'user/userInfo',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: { token }
|
params
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,3 +22,11 @@ export function logout() {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function userUpdate(data) {
|
||||||
|
return request({
|
||||||
|
url: 'user/update',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
190
src/components/Cropper/dialog.vue
Normal file
190
src/components/Cropper/dialog.vue
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="container">
|
||||||
|
<!--<img :src="sourceImg" style="width: 50px; height: 50px;">-->
|
||||||
|
<div class="img-container" v-loading="loading">
|
||||||
|
<div class="img-region">
|
||||||
|
<img :src="sourceImg" ref="image" style="max-width: 100%;" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="button-region">
|
||||||
|
<el-button type="primary" @click="sureSava">保存头像</el-button>
|
||||||
|
<el-button @click="selectImg">重新选择</el-button>
|
||||||
|
<!--<el-upload-->
|
||||||
|
<!--action="https://jsonplaceholder.typicode.com/posts/"-->
|
||||||
|
<!--:auto-upload="false">-->
|
||||||
|
<!--<el-button ref="selectImg">选择</el-button>-->
|
||||||
|
<!--</el-upload>-->
|
||||||
|
<input ref="selectImg" type="file" style="display: none;" accept="image/*" @change="changImg"></input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-divider direction="vertical"></el-divider>
|
||||||
|
<div class="avatar-preview">
|
||||||
|
<h3>头像预览</h3>
|
||||||
|
<div class="before big"></div>
|
||||||
|
<span>大头像100*100</span>
|
||||||
|
<div class="before small margin-top"></div>
|
||||||
|
<span>小头像55*55</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import "@/assets/css/cropper.css"
|
||||||
|
import Cropper from 'cropperjs'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CropperDialog',
|
||||||
|
props: {
|
||||||
|
dialogVisible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
src: {
|
||||||
|
type: String,
|
||||||
|
default: '~@/assets/img/widget-img.jpeg'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
cropper: null,
|
||||||
|
sourceImg: this.src,
|
||||||
|
fileImg: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(()=>{
|
||||||
|
this.initCropper()
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initCropper(){
|
||||||
|
this.cropper = new Cropper(this.$refs.image, {
|
||||||
|
responsive: true,
|
||||||
|
restore: true,
|
||||||
|
checkCrossOrigin: true,
|
||||||
|
checkOrientation: true,
|
||||||
|
modal: true,
|
||||||
|
guides: true,
|
||||||
|
center: true,
|
||||||
|
highlight: true,
|
||||||
|
autoCrop: true,
|
||||||
|
movable: true,
|
||||||
|
rotatable: true,
|
||||||
|
scalable: true,
|
||||||
|
zoomable: true,
|
||||||
|
zoomOnTouch: true,
|
||||||
|
zoomOnWheel: true,
|
||||||
|
cropBoxMovable: true,
|
||||||
|
cropBoxResizable: true,
|
||||||
|
toggleDragModeOnDblclick: true,
|
||||||
|
preview: '.before',
|
||||||
|
aspectRatio: 1,
|
||||||
|
viewMode: 1,
|
||||||
|
// dragMode: 'none',
|
||||||
|
// initialAspectRatio: 1,
|
||||||
|
// background: false,
|
||||||
|
// autoCropArea: 0.6,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
selectImg() {
|
||||||
|
this.$refs.selectImg.click()
|
||||||
|
},
|
||||||
|
changImg(e) {
|
||||||
|
if(e.target.files[0].size/1024/1024 > 2){
|
||||||
|
this.$message({
|
||||||
|
message: '选择的图片不能超过2M',
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
const that = this
|
||||||
|
let reader = new FileReader();
|
||||||
|
this.fileImg = e.target.files[0]
|
||||||
|
reader.readAsDataURL( this.fileImg);
|
||||||
|
reader.onload = function()
|
||||||
|
{
|
||||||
|
that.cropper.replace(reader.result)
|
||||||
|
that.loading = false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
sureSava(){
|
||||||
|
let cro = this.cropper.getCroppedCanvas({
|
||||||
|
maxWidth: 1204 ,
|
||||||
|
maxHeight: 1024,
|
||||||
|
fillColor: '#FFF',
|
||||||
|
imageSmoothingEnabled: true,
|
||||||
|
imageSmoothingQuality: 'high'
|
||||||
|
})
|
||||||
|
let dataURL = cro.toDataURL('image/jpeg');
|
||||||
|
cro.toBlob((blob)=>{
|
||||||
|
this.$emit('croppedCanvas', dataURL, blob)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.big{
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.small{
|
||||||
|
width: 55px;
|
||||||
|
height: 55px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.img-container{
|
||||||
|
height: 450px;
|
||||||
|
line-height: 450px;
|
||||||
|
text-align: center;
|
||||||
|
width: 712px;
|
||||||
|
overflow: hidden;
|
||||||
|
.img-region {
|
||||||
|
height: 350px;
|
||||||
|
line-height: 350px;
|
||||||
|
text-align: center;
|
||||||
|
width: 623px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.button-region {
|
||||||
|
height: 100px;
|
||||||
|
line-height: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.afterCropper{
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 20px;
|
||||||
|
border: 1px solid salmon;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.afterCropper img{
|
||||||
|
width: 150px;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
.avatar-preview {
|
||||||
|
span{
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.margin-top{
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/deep/.el-divider--vertical {
|
||||||
|
height: 450px;
|
||||||
|
margin: 0 20px;
|
||||||
|
}
|
||||||
|
/deep/.el-loading-spinner {
|
||||||
|
top: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -11,9 +11,9 @@
|
|||||||
<i class="el-icon-caret-bottom" />
|
<i class="el-icon-caret-bottom" />
|
||||||
</div>
|
</div>
|
||||||
<el-dropdown-menu slot="dropdown" class="user-dropdown">
|
<el-dropdown-menu slot="dropdown" class="user-dropdown">
|
||||||
<router-link to="/userinfo">
|
<router-link to="/setting">
|
||||||
<el-dropdown-item>
|
<el-dropdown-item>
|
||||||
个人信息
|
<i class="el-icon-setting" />设置
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</router-link>
|
</router-link>
|
||||||
<!--<router-link to="/">-->
|
<!--<router-link to="/">-->
|
||||||
|
|||||||
@ -84,7 +84,7 @@ new Vue({
|
|||||||
el: '#app',
|
el: '#app',
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
render: h => h(App)
|
render: h => h(App),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)) {
|
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)) {
|
||||||
|
|||||||
@ -33,7 +33,6 @@ router.beforeEach(async(to, from, next) => {
|
|||||||
try {
|
try {
|
||||||
// get user info
|
// get user info
|
||||||
await store.dispatch('user/getInfo')
|
await store.dispatch('user/getInfo')
|
||||||
|
|
||||||
next()
|
next()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// remove token and go to login page to re-login
|
// remove token and go to login page to re-login
|
||||||
|
|||||||
@ -87,13 +87,13 @@ export const constantRoutes = [
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/userinfo',
|
path: '/setting',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
name: 'userInfo',
|
name: 'setting',
|
||||||
component: () => import('@/views/userInfo/index'),
|
component: () => import('@/views/setting/index'),
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { login, logout, getInfo } from '@/api/user'
|
import { login, logout, getInfo } from '@/api/user'
|
||||||
import { getToken, setToken, removeToken } from '@/utils/auth'
|
import { getToken, setToken, getConsumerId, setConsumerId, removeToken, removeConsumerId } from '@/utils/auth'
|
||||||
import { resetRouter } from '@/router'
|
import { resetRouter } from '@/router'
|
||||||
|
|
||||||
const getDefaultState = () => {
|
const getDefaultState = () => {
|
||||||
@ -7,7 +7,7 @@ const getDefaultState = () => {
|
|||||||
token: getToken(),
|
token: getToken(),
|
||||||
name: '',
|
name: '',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
userId: ''
|
userId: getConsumerId(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +40,8 @@ const actions = {
|
|||||||
const { data } = response
|
const { data } = response
|
||||||
commit('SET_TOKEN', data.token)
|
commit('SET_TOKEN', data.token)
|
||||||
setToken(data.token)
|
setToken(data.token)
|
||||||
|
commit('SET_USERID', data.userId)
|
||||||
|
setConsumerId(data.userId)
|
||||||
resolve()
|
resolve()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
@ -50,9 +52,11 @@ const actions = {
|
|||||||
// get user info
|
// get user info
|
||||||
getInfo({ commit, state }) {
|
getInfo({ commit, state }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getInfo(state.token).then(response => {
|
getInfo({
|
||||||
|
id: state.userId,
|
||||||
|
token: state.token
|
||||||
|
}).then(response => {
|
||||||
const { data } = response
|
const { data } = response
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
// reject('Verification failed, please Login again.')
|
// reject('Verification failed, please Login again.')
|
||||||
}
|
}
|
||||||
@ -62,6 +66,7 @@ const actions = {
|
|||||||
commit('SET_NAME', username)
|
commit('SET_NAME', username)
|
||||||
commit('SET_AVATAR', avatar)
|
commit('SET_AVATAR', avatar)
|
||||||
commit('SET_USERID', id)
|
commit('SET_USERID', id)
|
||||||
|
sessionStorage.setItem('store', JSON.stringify(state))
|
||||||
resolve(data)
|
resolve(data)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
@ -74,6 +79,7 @@ const actions = {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
logout(state.token).then(() => {
|
logout(state.token).then(() => {
|
||||||
removeToken() // must remove token first
|
removeToken() // must remove token first
|
||||||
|
removeConsumerId()
|
||||||
resetRouter()
|
resetRouter()
|
||||||
commit('RESET_STATE')
|
commit('RESET_STATE')
|
||||||
resolve()
|
resolve()
|
||||||
@ -87,6 +93,7 @@ const actions = {
|
|||||||
resetToken({ commit }) {
|
resetToken({ commit }) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
removeToken() // must remove token first
|
removeToken() // must remove token first
|
||||||
|
removeConsumerId()
|
||||||
commit('RESET_STATE')
|
commit('RESET_STATE')
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
|
|||||||
45
src/styles/setting.scss
Normal file
45
src/styles/setting.scss
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
.img-dialog {
|
||||||
|
|
||||||
|
}
|
||||||
|
.form-item-avatar {
|
||||||
|
.avatar-value{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.avatar-value:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
.avatar-overlay{
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.avatar-overlay:hover{
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1;
|
||||||
|
background: #2f2f2fa8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.form-item-avatar /deep/ .el-form-item__label{
|
||||||
|
padding: 30px 12px;
|
||||||
|
}
|
||||||
|
.dialog-avatar {
|
||||||
|
/deep/.el-dialog {
|
||||||
|
min-width: 800px;
|
||||||
|
margin-top: 5vh!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/deep/.el-input {
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
/deep/.el-textarea {
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
.form-slogan {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
.quota-space {
|
||||||
|
margin-top: 10px;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
|
|
||||||
const TokenKey = 'vue_admin_template_token'
|
const TokenKey = 'jmal_token'
|
||||||
|
const consumerId = 'consumerId'
|
||||||
|
|
||||||
export function getToken() {
|
export function getToken() {
|
||||||
return Cookies.get(TokenKey)
|
return Cookies.get(TokenKey)
|
||||||
@ -13,3 +14,15 @@ export function setToken(token) {
|
|||||||
export function removeToken() {
|
export function removeToken() {
|
||||||
return Cookies.remove(TokenKey)
|
return Cookies.remove(TokenKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getConsumerId() {
|
||||||
|
return Cookies.get(consumerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setConsumerId(userId) {
|
||||||
|
return Cookies.set(consumerId, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeConsumerId() {
|
||||||
|
return Cookies.remove(consumerId)
|
||||||
|
}
|
||||||
|
|||||||
@ -46,6 +46,10 @@ service.interceptors.response.use(
|
|||||||
|
|
||||||
// if the custom code is not 20000, it is judged as an error.
|
// if the custom code is not 20000, it is judged as an error.
|
||||||
if (res.code !== 0) {
|
if (res.code !== 0) {
|
||||||
|
if(res.code === 5) {
|
||||||
|
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
if(res.code === -2){
|
if(res.code === -2){
|
||||||
Message({
|
Message({
|
||||||
message: res.message || '服务器开小差了...',
|
message: res.message || '服务器开小差了...',
|
||||||
|
|||||||
@ -1,47 +1,78 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="hello">
|
||||||
<mavon-editor
|
<p>预览</p>
|
||||||
v-model="content"
|
<div class="before"></div>
|
||||||
ref="md"
|
<button style="margin: 30px auto;" type="error" @click="sureSava">裁剪</button>
|
||||||
@change="change"
|
<div class="container">
|
||||||
style="min-height: 600px"
|
<div class="img-container">
|
||||||
/>
|
<img src="~@/assets/img/back.jpeg" ref="image" alt="">
|
||||||
|
</div>
|
||||||
<button @click="submit">提交</button>
|
<div class="afterCropper">
|
||||||
|
<img :src="afterImg" alt="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mavonEditor } from 'mavon-editor'
|
import Cropper from 'cropperjs'
|
||||||
import 'mavon-editor/dist/css/index.css'
|
|
||||||
export default {
|
export default {
|
||||||
// 注册
|
name: 'HelloWorld',
|
||||||
components: {
|
data () {
|
||||||
mavonEditor,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
return {
|
||||||
content:'', // 输入的markdown
|
cropper: null,
|
||||||
html:'', // 及时转的html
|
afterImg: ''
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 所有操作都会被解析重新渲染
|
|
||||||
change(value, render){
|
|
||||||
console.log(value)
|
|
||||||
// render 为 markdown 解析后的结果[html]
|
|
||||||
this.html = render;
|
|
||||||
},
|
|
||||||
// 提交
|
|
||||||
submit(){
|
|
||||||
console.log(this.content);
|
|
||||||
console.log(this.html);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.init()
|
||||||
}
|
},
|
||||||
|
methods: {
|
||||||
|
init(){
|
||||||
|
this.cropper = new Cropper(this.$refs.image, {
|
||||||
|
viewMode: 1,
|
||||||
|
dragMode: 'none',
|
||||||
|
initialAspectRatio: 1,
|
||||||
|
aspectRatio: 1,
|
||||||
|
preview: '.before',
|
||||||
|
background: false,
|
||||||
|
autoCropArea: 0.6,
|
||||||
|
zoomOnWheel: false,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
sureSava(){
|
||||||
|
this.afterImg = this.cropper.getCroppedCanvas({
|
||||||
|
imageSmoothingQuality: 'high'
|
||||||
|
}).toDataURL('image/jpeg')
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
.container{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.before{
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
overflow: hidden;
|
||||||
|
/* 这个属性可以得到想要的效果 */
|
||||||
|
}
|
||||||
|
.img-container{
|
||||||
|
height: 400px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.afterCropper{
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 20px;
|
||||||
|
border: 1px solid salmon;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.afterCropper img{
|
||||||
|
width: 150px;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -74,8 +74,8 @@ export default {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
loginForm: {
|
loginForm: {
|
||||||
username: '',
|
username: 'jmal',
|
||||||
password: ''
|
password: '123456'
|
||||||
},
|
},
|
||||||
loginRules: {
|
loginRules: {
|
||||||
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
|
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
|
||||||
@ -116,7 +116,6 @@ export default {
|
|||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log('error submit!!')
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
167
src/views/setting/index.vue
Normal file
167
src/views/setting/index.vue
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-tabs type="border-card" :value="tabsDefault" @tab-click="tabClick">
|
||||||
|
<el-tab-pane name="1">
|
||||||
|
<span slot="label"><i class="el-icon-user"></i> 个人信息</span>
|
||||||
|
|
||||||
|
<!--<div class="img-dialog" :v-show="dialogVisible">-->
|
||||||
|
<!--<img id="image" :src="userInfo.avatar"/>-->
|
||||||
|
<!--</div>-->
|
||||||
|
|
||||||
|
<el-dialog class="dialog-avatar" title="修改头像" :visible.sync="dialogVisible">
|
||||||
|
<cropper-dialog :src="userInfo.avatar" @croppedCanvas="saveAvatar"></cropper-dialog>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-form ref="form" :model="form" label-width="120px">
|
||||||
|
<el-form-item label="头像" class="form-item-avatar">
|
||||||
|
<el-avatar class="avatar-value" shape="circle" :size="100" fit="fit" :src="userInfo.avatar" ></el-avatar>
|
||||||
|
<el-avatar class="avatar-overlay" shape="circle" :size="100" @click.native="dialogVisible = true"> 修改头像 </el-avatar>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="username">
|
||||||
|
<el-input readonly="readonly" v-model="form.username" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="昵称">
|
||||||
|
<el-input v-model="form.showName" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="标语">
|
||||||
|
<el-input class="form-slogan" v-model="form.slogan" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="个人简介">
|
||||||
|
<el-input type="textarea" v-model="form.introduction"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="使用情况">
|
||||||
|
<el-progress class="quota-space" :percentage="percentage" :format="progressFormat" :color="customColors"></el-progress>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane name="3" label="消息中心">
|
||||||
|
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane name="4" label="角色管理">
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getInfo, userUpdate} from '@/api/user'
|
||||||
|
import { formatSize } from '@/utils/number'
|
||||||
|
import CropperDialog from '@/components/Cropper/dialog'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CropperDialog
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tabsDefault: '1',
|
||||||
|
userInfo: {},
|
||||||
|
dialogVisible:false,
|
||||||
|
cropper:'',
|
||||||
|
percentage: 0,
|
||||||
|
customColors: [
|
||||||
|
{color: '#f56c6c', percentage: 100},
|
||||||
|
{color: '#e6a23c', percentage: 80},
|
||||||
|
{color: '#5cb87a', percentage: 60},
|
||||||
|
{color: '#1989fa', percentage: 40},
|
||||||
|
{color: '#6f7ad3', percentage: 20}
|
||||||
|
],
|
||||||
|
form: {
|
||||||
|
avatar: '',
|
||||||
|
showName: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if(this.$route.query.tab){
|
||||||
|
this.tabsDefault = this.$route.query.tab
|
||||||
|
}
|
||||||
|
this.getInfo()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getInfo(){
|
||||||
|
getInfo({
|
||||||
|
id: this.$store.state.user.userId,
|
||||||
|
takeUpSpace: true,
|
||||||
|
}).then(res => {
|
||||||
|
console.log(res.data)
|
||||||
|
this.userInfo = res.data
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.form = this.userInfo
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
tabClick(tab) {
|
||||||
|
this.$router.push({path: this.$route.path, query: {tab: tab.name}})
|
||||||
|
},
|
||||||
|
onSubmit() {
|
||||||
|
this.userUpdate(this.setFormData())
|
||||||
|
// this.$message('submit!')
|
||||||
|
},
|
||||||
|
onCancel() {
|
||||||
|
this.$message({
|
||||||
|
message: 'cancel!',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
progressFormat() {
|
||||||
|
const space = this.userInfo.takeUpSpace/1024/1024/1024
|
||||||
|
const quota = this.userInfo.quota
|
||||||
|
if(space && quota > 0){
|
||||||
|
this.percentage = (space/quota * 100).toFixed(1)
|
||||||
|
return `${this.percentage}% (${formatSize(this.userInfo.takeUpSpace)}/${quota}GB)`;
|
||||||
|
// return `${this.percentage}%`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setFormData() {
|
||||||
|
let data = new FormData();
|
||||||
|
for (let formKey in this.form) {
|
||||||
|
if(this.form.hasOwnProperty(formKey)){
|
||||||
|
if(formKey !== 'avatar'){
|
||||||
|
console.log(formKey,this.form[formKey])
|
||||||
|
data.append(formKey,this.form[formKey])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
},
|
||||||
|
// 保存头像
|
||||||
|
saveAvatar(dataURL) {
|
||||||
|
this.dialogVisible = false
|
||||||
|
this.userInfo.avatar = dataURL
|
||||||
|
let data = new FormData();
|
||||||
|
data.append('id', this.$store.state.user.userId)
|
||||||
|
data.append('avatar', dataURL)
|
||||||
|
this.userUpdate(data,dataURL)
|
||||||
|
},
|
||||||
|
userUpdate(data, dataURL){
|
||||||
|
userUpdate(data).then(() => {
|
||||||
|
this.$message({
|
||||||
|
message: '保存成功!',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1000
|
||||||
|
})
|
||||||
|
if(dataURL){
|
||||||
|
this.$store.state.user.avatar = dataURL
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.$message({
|
||||||
|
message: '保存失败!',
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--<style src="@styles/cropper.css"></style>-->
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "src/styles/setting";
|
||||||
|
</style>
|
||||||
@ -1,194 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
|
|
||||||
<div class="img-dialog" :v-show="dialogVisible">
|
|
||||||
<img id="image" :src="form.avater"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<el-form ref="form" :model="form" label-width="120px">
|
|
||||||
<el-form-item label="头像" class="form-item-avatar">
|
|
||||||
<el-upload
|
|
||||||
class="avatar-uploader"
|
|
||||||
:action="UploadAvatarURL"
|
|
||||||
:show-file-list="false"
|
|
||||||
:on-change="addAvatar"
|
|
||||||
:auto-upload="false"
|
|
||||||
:before-upload="beforeAvatarUpload">
|
|
||||||
<img id="imageAvatar" v-if="form.avater" :src="form.avater" class="avatar">
|
|
||||||
<!-- <el-image v-if="form.avater" class="avatar" :src="form.avater" :fit="cover"></el-image>-->
|
|
||||||
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
|
||||||
</el-upload>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="Activity name">
|
|
||||||
<el-input v-model="form.name" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="Activity zone">
|
|
||||||
<el-select v-model="form.region" placeholder="please select your zone">
|
|
||||||
<el-option label="Zone one" value="shanghai" />
|
|
||||||
<el-option label="Zone two" value="beijing" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="Activity time">
|
|
||||||
<el-col :span="11">
|
|
||||||
<el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%;" />
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="2" class="line">-</el-col>
|
|
||||||
<el-col :span="11">
|
|
||||||
<el-time-picker v-model="form.date2" type="fixed-time" placeholder="Pick a time" style="width: 100%;" />
|
|
||||||
</el-col>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="Instant delivery">
|
|
||||||
<el-switch v-model="form.delivery" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="Activity type">
|
|
||||||
<el-checkbox-group v-model="form.type">
|
|
||||||
<el-checkbox label="Online activities" name="type" />
|
|
||||||
<el-checkbox label="Promotion activities" name="type" />
|
|
||||||
<el-checkbox label="Offline activities" name="type" />
|
|
||||||
<el-checkbox label="Simple brand exposure" name="type" />
|
|
||||||
</el-checkbox-group>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="Resources">
|
|
||||||
<el-radio-group v-model="form.resource">
|
|
||||||
<el-radio label="Sponsor" />
|
|
||||||
<el-radio label="Venue" />
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="Activity form">
|
|
||||||
<el-input v-model="form.desc" type="textarea" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="onSubmit">Create</el-button>
|
|
||||||
<el-button @click="onCancel">Cancel</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import "@/assets/css/cropper.css"
|
|
||||||
import Cropper from 'cropperjs'
|
|
||||||
import api from '@/api/upload-api'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogVisible:false,
|
|
||||||
cropper:'',
|
|
||||||
UploadAvatarURL: api.simpleUploadAvatarURL,
|
|
||||||
form: {
|
|
||||||
avater: '',
|
|
||||||
name: '',
|
|
||||||
region: '',
|
|
||||||
date1: '',
|
|
||||||
date2: '',
|
|
||||||
delivery: false,
|
|
||||||
type: [],
|
|
||||||
resource: '',
|
|
||||||
desc: ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
let _this = this;
|
|
||||||
let image = document.getElementById('image');
|
|
||||||
this.cropper = new Cropper(image, {
|
|
||||||
aspectRatio: 1,
|
|
||||||
viewMode: 1,
|
|
||||||
background:false,
|
|
||||||
zoomable:false,
|
|
||||||
ready: function () {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSubmit() {
|
|
||||||
this.$message('submit!')
|
|
||||||
},
|
|
||||||
onCancel() {
|
|
||||||
this.$message({
|
|
||||||
message: 'cancel!',
|
|
||||||
type: 'warning'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addAvatar(file, fileList) {
|
|
||||||
// const isLt2M = file.size / 1024 / 1024 < 2;
|
|
||||||
// if (!isLt2M) {
|
|
||||||
// this.$message.error('上传头像图片大小不能超过 2MB!');
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
let reader = new FileReader();
|
|
||||||
const _this = this
|
|
||||||
reader.onload = function (e) {
|
|
||||||
_this.form.avater = e.target.result
|
|
||||||
_this.dialogVisible = true
|
|
||||||
_this.cropper.replace(e.target.result);
|
|
||||||
};
|
|
||||||
reader.readAsDataURL(file.raw)
|
|
||||||
},
|
|
||||||
beforeAvatarUpload(file) {
|
|
||||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
|
||||||
if (!isLt2M) {
|
|
||||||
this.$message.error('上传头像图片大小不能超过 2MB!');
|
|
||||||
}
|
|
||||||
return isLt2M;
|
|
||||||
},
|
|
||||||
crop () {
|
|
||||||
this.panel = false;
|
|
||||||
var croppedCanvas;
|
|
||||||
var roundedCanvas;
|
|
||||||
|
|
||||||
if (!this.croppable) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Crop
|
|
||||||
croppedCanvas = this.cropper.getCroppedCanvas();
|
|
||||||
console.log(this.cropper)
|
|
||||||
// Round
|
|
||||||
roundedCanvas = this.getRoundedCanvas(croppedCanvas);
|
|
||||||
this.form.avater = roundedCanvas.toDataURL();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!--<style src="@styles/cropper.css"></style>-->
|
|
||||||
<style scoped>
|
|
||||||
.line{
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.img-dialog {
|
|
||||||
|
|
||||||
}
|
|
||||||
/deep/ .avatar-uploader .el-upload {
|
|
||||||
border: 1px dashed #d9d9d9;
|
|
||||||
width: 100px;
|
|
||||||
height: 100px;
|
|
||||||
line-height: 100px;
|
|
||||||
border-radius: 50%;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
/deep/.avatar-uploader .el-upload:hover {
|
|
||||||
border-color: #409EFF;
|
|
||||||
}
|
|
||||||
/deep/.avatar-uploader-icon {
|
|
||||||
font-size: 28px;
|
|
||||||
color: #8c939d;
|
|
||||||
width: 100px;
|
|
||||||
height: 100px;
|
|
||||||
line-height: 100px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
/deep/.avatar {
|
|
||||||
width: 100px;
|
|
||||||
height: 100px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.form-item-avatar {
|
|
||||||
line-height: 100px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Loading…
x
Reference in New Issue
Block a user