|
|
@@ -1,20 +1,15 @@
|
|
|
<template>
|
|
|
- <wrapper
|
|
|
- class="c-profile"
|
|
|
- fill
|
|
|
- margin
|
|
|
- background
|
|
|
- >
|
|
|
+ <div class="l-flex--col c-profile">
|
|
|
<div class="l-flex__none l-flex--col center c-profile__header has-padding">
|
|
|
<div
|
|
|
- class="o-avatar u-pointer"
|
|
|
+ class="c-sibling-item--v o-avatar u-pointer"
|
|
|
@click="onAvatarClick"
|
|
|
>
|
|
|
<i
|
|
|
class="o-avatar__img"
|
|
|
:style="avatarStyle"
|
|
|
/>
|
|
|
- <i class="o-avatar__upload el-icon-camera" />
|
|
|
+ <i class="o-avatar__upload o-icon sm el-icon-camera" />
|
|
|
<input
|
|
|
ref="upload"
|
|
|
type="file"
|
|
|
@@ -23,19 +18,23 @@
|
|
|
@change="onUpload"
|
|
|
>
|
|
|
</div>
|
|
|
- <div class="u-font-size--lg has-top-padding">{{ name }}</div>
|
|
|
- <div class="u-relative has-top-padding">
|
|
|
+ <div class="c-sibling-item--v u-font-size--md">{{ name }}</div>
|
|
|
+ <div class="c-sibling-item--v u-relative">
|
|
|
<i class="el-icon-user" />
|
|
|
- {{ role }}
|
|
|
+ <span class="u-font-size--sm">{{ role }}</span>
|
|
|
</div>
|
|
|
+ <i
|
|
|
+ class="c-profile__close o-icon el-icon-close u-bold u-pointer"
|
|
|
+ @click="onClose"
|
|
|
+ />
|
|
|
</div>
|
|
|
<div
|
|
|
v-loading="loading"
|
|
|
- class="l-flex__fill l-flex--col center"
|
|
|
+ class="l-flex__fill l-flex--col"
|
|
|
>
|
|
|
<el-tabs
|
|
|
v-model="active"
|
|
|
- class="c-tabs has-padding u-align-self--stretch"
|
|
|
+ class="c-tabs has-padding"
|
|
|
stretch
|
|
|
>
|
|
|
<el-tab-pane
|
|
|
@@ -51,67 +50,62 @@
|
|
|
</el-tabs>
|
|
|
<warning
|
|
|
v-if="error"
|
|
|
+ class=" u-align-self--center"
|
|
|
@click="getUserInfo"
|
|
|
/>
|
|
|
<div
|
|
|
v-else
|
|
|
- class="has-padding l-flex--col"
|
|
|
+ class="l-flex__fill l-flex--col center has-padding u-overflow-y--auto"
|
|
|
>
|
|
|
<template v-if="active === 'settings'">
|
|
|
- <div class="l-flex--row has-bottom-padding">
|
|
|
- <user-info-item
|
|
|
- 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">
|
|
|
- <user-info-item
|
|
|
- v-if="user"
|
|
|
- key="email"
|
|
|
- v-model="email"
|
|
|
- type="email"
|
|
|
- :initial="user.email"
|
|
|
- @update="updateUser({email}, '更新邮箱')"
|
|
|
- />
|
|
|
- </div>
|
|
|
+ <user-info-item
|
|
|
+ v-if="user"
|
|
|
+ key="phone"
|
|
|
+ class="c-sibling-item--v"
|
|
|
+ type="phone"
|
|
|
+ :initial="phone"
|
|
|
+ @update="onChangePhone"
|
|
|
+ />
|
|
|
+ <user-info-item
|
|
|
+ v-if="user"
|
|
|
+ key="email"
|
|
|
+ class="c-sibling-item--v"
|
|
|
+ type="email"
|
|
|
+ :initial="email"
|
|
|
+ @update="onChangeEmail"
|
|
|
+ />
|
|
|
<div
|
|
|
v-if="__WECHAT__"
|
|
|
- class="l-flex--row center has-top-padding"
|
|
|
+ class="l-flex--row center c-sibling-item--v farther"
|
|
|
>
|
|
|
<div
|
|
|
- class="o-app u-pointer"
|
|
|
+ class="o-app has-active u-pointer"
|
|
|
@click="onClickWechat"
|
|
|
>
|
|
|
- <i class="o-icon wechat has-bg" />
|
|
|
- <div
|
|
|
- v-if="wechat"
|
|
|
- class="l-flex--row"
|
|
|
- >
|
|
|
- <div class="c-sibling-item u-color--info light">已绑定</div>
|
|
|
- <div class="c-sibling-item u-pointer">解绑</div>
|
|
|
- </div>
|
|
|
- <div v-else>
|
|
|
- 绑定微信
|
|
|
+ <i class="c-sibling-item--v o-icon md wechat" />
|
|
|
+ <div class="l-flex--row c-sibling-item--v far">
|
|
|
+ <template v-if="wechat">
|
|
|
+ <div class="c-sibling-item u-color--info light">已绑定</div>
|
|
|
+ <div class="c-sibling-item">解绑</div>
|
|
|
+ </template>
|
|
|
+ <div v-else>
|
|
|
+ 绑定微信
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div
|
|
|
- class="o-app u-pointer"
|
|
|
+ class="o-app has-active u-pointer"
|
|
|
@click="onClickApplet"
|
|
|
>
|
|
|
- <i class="o-icon applet has-bg" />
|
|
|
- <div
|
|
|
- v-if="applet"
|
|
|
- class="l-flex--row"
|
|
|
- >
|
|
|
- <div class="c-sibling-item u-color--info light">已绑定</div>
|
|
|
- <div class="c-sibling-item u-pointer">解绑</div>
|
|
|
- </div>
|
|
|
- <div v-else>
|
|
|
- 绑定小程序
|
|
|
+ <i class="c-sibling-item--v o-icon md applet" />
|
|
|
+ <div class="l-flex--row c-sibling-item--v far">
|
|
|
+ <template v-if="applet">
|
|
|
+ <div class="c-sibling-item u-color--info light">已绑定</div>
|
|
|
+ <div class="c-sibling-item">解绑</div>
|
|
|
+ </template>
|
|
|
+ <div v-else>
|
|
|
+ 绑定小程序
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -125,13 +119,14 @@
|
|
|
:visible.sync="showQr"
|
|
|
custom-class="c-dialog--transparent"
|
|
|
:close-on-click-modal="false"
|
|
|
+ append-to-body
|
|
|
>
|
|
|
<div class="c-wechat has-padding">
|
|
|
<div class="l-flex--row center c-sibling-item--v u-relative">
|
|
|
- <i class="c-sibling-item o-icon medium wechat has-bg" />
|
|
|
+ <i class="c-sibling-item o-icon wechat" />
|
|
|
<span class="c-sibling-item u-color--black u-bold">请使用微信扫一扫</span>
|
|
|
<i
|
|
|
- class="c-wechat__close o-icon medium el-icon-close has-active u-bold u-pointer"
|
|
|
+ class="c-wechat__close el-icon-close o-icon has-active u-bold u-pointer"
|
|
|
@click="onCloseQr"
|
|
|
/>
|
|
|
</div>
|
|
|
@@ -148,7 +143,7 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
- </wrapper>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
@@ -160,10 +155,6 @@ import {
|
|
|
getQrcode
|
|
|
} from '@/api/user'
|
|
|
import { GATEWAY } from '@/constant'
|
|
|
-import {
|
|
|
- validPhone,
|
|
|
- validEmail
|
|
|
-} from '@/utils/validate'
|
|
|
import UserInfoItem from './components/UserInfoItem'
|
|
|
import ResetPassword from './components/ResetPassword'
|
|
|
|
|
|
@@ -180,15 +171,8 @@ export default {
|
|
|
active: 'settings',
|
|
|
user: {
|
|
|
email: '',
|
|
|
- attributes: {
|
|
|
- phone: ['']
|
|
|
- }
|
|
|
+ attributes: {}
|
|
|
},
|
|
|
- avatar: '',
|
|
|
- phone: '',
|
|
|
- email: '',
|
|
|
- wechat: '',
|
|
|
- applet: '',
|
|
|
showQr: false,
|
|
|
qrType: 'wechatOptions',
|
|
|
wechatOptions: {
|
|
|
@@ -200,7 +184,8 @@ export default {
|
|
|
loading: false,
|
|
|
retry: false,
|
|
|
qr: null
|
|
|
- }
|
|
|
+ },
|
|
|
+ avatar: null
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -214,6 +199,18 @@ export default {
|
|
|
const avatar = this.avatar
|
|
|
return avatar ? { backgroundImage: `url("${avatar}")` } : null
|
|
|
},
|
|
|
+ phone () {
|
|
|
+ return this.getOrCreateAttribute(this.user, 'phone')
|
|
|
+ },
|
|
|
+ email () {
|
|
|
+ return this.user.email
|
|
|
+ },
|
|
|
+ wechat () {
|
|
|
+ return this.getOrCreateAttribute(this.user, 'wechat')
|
|
|
+ },
|
|
|
+ applet () {
|
|
|
+ return this.getOrCreateAttribute(this.user, 'wechat-applet-openid')
|
|
|
+ },
|
|
|
qrOptions () {
|
|
|
return this[this.qrType]
|
|
|
},
|
|
|
@@ -240,6 +237,9 @@ export default {
|
|
|
clearInterval(this.$checkTimer)
|
|
|
},
|
|
|
methods: {
|
|
|
+ onClose () {
|
|
|
+ this.$emit('close')
|
|
|
+ },
|
|
|
onAvatarClick () {
|
|
|
this.$refs.upload.click()
|
|
|
},
|
|
|
@@ -256,6 +256,7 @@ export default {
|
|
|
const reader = new FileReader()
|
|
|
reader.onload = () => {
|
|
|
this.avatar = reader.result
|
|
|
+ // this.changeAttribute('avatar', reader.result, '更新头像')
|
|
|
}
|
|
|
reader.readAsDataURL(file)
|
|
|
},
|
|
|
@@ -275,12 +276,7 @@ export default {
|
|
|
if (!data.attributes) {
|
|
|
data.attributes = {}
|
|
|
}
|
|
|
- this.avatar = this.getOrCreateAttribute(data, 'avatar', '')
|
|
|
- this.phone = this.getOrCreateAttribute(data, 'phone', '')
|
|
|
- this.email = data.email ?? ''
|
|
|
- this.wechat = this.getOrCreateAttribute(data, 'wechat', '')
|
|
|
this.user = data
|
|
|
- this.applet = this.getOrCreateAttribute(data, 'wechat-applet-openid', '')
|
|
|
},
|
|
|
getOrCreateAttribute (user, key, defaults = '') {
|
|
|
if (!user.attributes[key]) {
|
|
|
@@ -294,72 +290,18 @@ export default {
|
|
|
})
|
|
|
},
|
|
|
changeAttribute (key, value, meesage) {
|
|
|
- if (this.user.attributes[key][0] !== value) {
|
|
|
- this.updateUser({
|
|
|
- attributes: {
|
|
|
- ...this.user.attributes,
|
|
|
- [key]: [value]
|
|
|
- }
|
|
|
- }, meesage).then(
|
|
|
- () => {
|
|
|
- this.user.attributes[key][0] = value
|
|
|
- },
|
|
|
- () => {
|
|
|
- this.resetAttribute(key)
|
|
|
- }
|
|
|
- )
|
|
|
- }
|
|
|
- },
|
|
|
- resetAttribute (key) {
|
|
|
- this[key] = this.user.attributes[key][0]
|
|
|
- },
|
|
|
- resetProp (key) {
|
|
|
- this[key] = this.user[key] ?? ''
|
|
|
+ return this.updateUser({
|
|
|
+ attributes: {
|
|
|
+ ...this.user.attributes,
|
|
|
+ [key]: [value]
|
|
|
+ }
|
|
|
+ }, meesage)
|
|
|
},
|
|
|
- onPhoneChange () {
|
|
|
- if (!this.phone) {
|
|
|
- this.$message({
|
|
|
- type: 'warning',
|
|
|
- message: '手机号不能为空'
|
|
|
- })
|
|
|
- this.resetAttribute('phone')
|
|
|
- return
|
|
|
- }
|
|
|
- if (!validPhone(this.phone)) {
|
|
|
- this.$message({
|
|
|
- type: 'warning',
|
|
|
- message: '手机号格式错误'
|
|
|
- })
|
|
|
- this.resetAttribute('phone')
|
|
|
- return
|
|
|
- }
|
|
|
- this.changeAttribute('phone', this.phone, '更新手机号')
|
|
|
+ onChangePhone (value) {
|
|
|
+ this.changeAttribute('phone', value, '更新手机号')
|
|
|
},
|
|
|
- onEmailChange () {
|
|
|
- if (!this.email) {
|
|
|
- this.$message({
|
|
|
- type: 'warning',
|
|
|
- message: '邮箱不能为空'
|
|
|
- })
|
|
|
- this.resetProp('email')
|
|
|
- return
|
|
|
- }
|
|
|
- if (!validEmail(this.email)) {
|
|
|
- this.$message({
|
|
|
- type: 'warning',
|
|
|
- message: '邮箱格式错误'
|
|
|
- })
|
|
|
- this.resetProp('email')
|
|
|
- return
|
|
|
- }
|
|
|
- this.updateUser({ email: this.email }, '更新邮箱').then(
|
|
|
- () => {
|
|
|
- this.user.email = this.email
|
|
|
- },
|
|
|
- () => {
|
|
|
- this.resetProp('email')
|
|
|
- }
|
|
|
- )
|
|
|
+ onChangeEmail (value) {
|
|
|
+ this.updateUser({ email: value }, '更新邮箱')
|
|
|
},
|
|
|
onClickWechat () {
|
|
|
if (this.wechat) {
|
|
|
@@ -367,9 +309,7 @@ export default {
|
|
|
'解除绑定后将无法再收到消息推送',
|
|
|
'解绑微信',
|
|
|
{ type: 'warning' }
|
|
|
- ).then(() => {
|
|
|
- this.changeAttribute('wechat', this.wechat = '', '解绑公众号')
|
|
|
- })
|
|
|
+ ).then(() => this.changeAttribute('wechat', '', '解绑公众号'))
|
|
|
} else {
|
|
|
this.qrType = 'wechatOptions'
|
|
|
this.showQr = true
|
|
|
@@ -382,11 +322,7 @@ export default {
|
|
|
'解除绑定后将无法使用小程序的功能',
|
|
|
'解绑小程序',
|
|
|
{ type: 'warning' }
|
|
|
- ).then(
|
|
|
- () => {
|
|
|
- this.changeAttribute('wechat-applet-openid', this.applet = '', '解绑小程序')
|
|
|
- }
|
|
|
- )
|
|
|
+ ).then(() => this.changeAttribute('wechat-applet-openid', '', '解绑小程序'))
|
|
|
} else {
|
|
|
this.qrType = 'appletOptions'
|
|
|
this.showQr = true
|
|
|
@@ -450,7 +386,7 @@ export default {
|
|
|
const options = this.appletOptions
|
|
|
options.loading = true
|
|
|
options.retry = false
|
|
|
- getQrcode({ page: 'pages/device/device', sourceUrl: GATEWAY }).then(
|
|
|
+ getQrcode({ page: process.env.VUE_APP_APPLET_PAGE, sourceUrl: GATEWAY }).then(
|
|
|
({ data }) => {
|
|
|
options.checking = true
|
|
|
options.qr = `data:image/png;base64,${data}`
|
|
|
@@ -473,7 +409,7 @@ export default {
|
|
|
let bound = false
|
|
|
let needCheck = false
|
|
|
if (this.wechatOptions.checking) {
|
|
|
- const wechat = data.attributes.wechat?.[0]
|
|
|
+ const wechat = data.attributes?.wechat?.[0]
|
|
|
if (wechat) {
|
|
|
bound = true
|
|
|
this.wechatOptions.checking = false
|
|
|
@@ -491,7 +427,7 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
if (this.appletOptions.checking) {
|
|
|
- const applet = data.attributes['wechat-applet-openid']?.[0]
|
|
|
+ const applet = data.attributes?.['wechat-applet-openid']?.[0]
|
|
|
if (applet) {
|
|
|
bound = true
|
|
|
this.appletOptions.checking = false
|
|
|
@@ -522,13 +458,22 @@ export default {
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.c-profile {
|
|
|
- overflow: hidden;
|
|
|
-
|
|
|
&__header {
|
|
|
+ position: relative;
|
|
|
color: #fff;
|
|
|
line-height: 1;
|
|
|
background-color: $blue;
|
|
|
}
|
|
|
+
|
|
|
+ &__close {
|
|
|
+ position: absolute;
|
|
|
+ top: $spacing--xs;
|
|
|
+ right: $spacing--sm;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: $primary;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.o-avatar {
|
|
|
@@ -549,14 +494,9 @@ export default {
|
|
|
}
|
|
|
|
|
|
&__upload {
|
|
|
- display: inline-flex;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
position: absolute;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
- width: 26px;
|
|
|
- height: 26px;
|
|
|
color: $blue;
|
|
|
border-radius: 50%;
|
|
|
background-color: #fff;
|
|
|
@@ -565,7 +505,8 @@ export default {
|
|
|
|
|
|
.el-icon-user {
|
|
|
position: absolute;
|
|
|
- left: -32px;
|
|
|
+ left: -$spacing--xs;
|
|
|
+ transform: translateX(-100%);
|
|
|
}
|
|
|
|
|
|
.o-app {
|
|
|
@@ -575,11 +516,7 @@ export default {
|
|
|
align-items: center;
|
|
|
width: 128px;
|
|
|
color: $blue;
|
|
|
- font-size: 16px;
|
|
|
-
|
|
|
- .o-icon {
|
|
|
- margin-bottom: $spacing;
|
|
|
- }
|
|
|
+ font-size: $font-size--sm;
|
|
|
}
|
|
|
|
|
|
.o-icon {
|