|
|
@@ -0,0 +1,458 @@
|
|
|
+<template>
|
|
|
+ <wrapper
|
|
|
+ class="c-profile"
|
|
|
+ fill
|
|
|
+ margin
|
|
|
+ background
|
|
|
+ >
|
|
|
+ <div class="l-flex__none l-flex--col center c-profile__header has-padding">
|
|
|
+ <div
|
|
|
+ class="o-avatar u-pointer"
|
|
|
+ @click="onAvatarClick"
|
|
|
+ >
|
|
|
+ <i
|
|
|
+ class="o-avatar__img"
|
|
|
+ :style="avatarStyle"
|
|
|
+ />
|
|
|
+ <i class="o-avatar__upload el-icon-camera" />
|
|
|
+ <input
|
|
|
+ ref="upload"
|
|
|
+ type="file"
|
|
|
+ accept="image/*"
|
|
|
+ style="display: none;"
|
|
|
+ @change="onUpload"
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div class="u-bold">{{ name }}</div>
|
|
|
+ <div class="u-relative">
|
|
|
+ <i class="c-profile__icon el-icon-user" />
|
|
|
+ {{ roleTip }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="l-flex__fill u-overflow-y--auto">
|
|
|
+ <el-result
|
|
|
+ v-if="error"
|
|
|
+ icon="warning"
|
|
|
+ >
|
|
|
+ <template #extra>
|
|
|
+ <el-link
|
|
|
+ class="u-pointer"
|
|
|
+ type="warning"
|
|
|
+ @click="getUserInfo"
|
|
|
+ >
|
|
|
+ 出错了,点击重试
|
|
|
+ </el-link>
|
|
|
+ </template>
|
|
|
+ </el-result>
|
|
|
+ <div
|
|
|
+ v-else
|
|
|
+ class="c-form"
|
|
|
+ >
|
|
|
+ <div class="c-form__section">
|
|
|
+ <span class="c-form__label">手机:</span>
|
|
|
+ <el-input
|
|
|
+ v-model="phone"
|
|
|
+ class="c-form__item"
|
|
|
+ @change="onPhoneChange"
|
|
|
+ @keydown.enter="$event.target.blur()"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="c-form__section has-bottom-padding">
|
|
|
+ <span class="c-form__label">邮箱:</span>
|
|
|
+ <el-input
|
|
|
+ v-model="email"
|
|
|
+ class="c-form__item"
|
|
|
+ @change="onEmailChange"
|
|
|
+ @keydown.enter="$event.target.blur()"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="c-form__section">
|
|
|
+ <i class="o-wechat" />
|
|
|
+ <div
|
|
|
+ class="has-padding u-pointer"
|
|
|
+ :class="color"
|
|
|
+ @click="onClickWechat"
|
|
|
+ >
|
|
|
+ {{ tip }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-dialog
|
|
|
+ :visible.sync="showQr"
|
|
|
+ custom-class="c-preview"
|
|
|
+ width="0"
|
|
|
+ @close="onCloseQr"
|
|
|
+ >
|
|
|
+ <div class="c-wechat has-padding">
|
|
|
+ <div class="l-flex--row center has-bottom-padding">
|
|
|
+ <i class="c-sibling-item o-wechat" />
|
|
|
+ <span class="c-sibling-item u-color--black u-bold">请使用微信扫一扫</span>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ v-loading="loading"
|
|
|
+ class="c-wechat__wrapper"
|
|
|
+ :class="{ retry }"
|
|
|
+ @click="getQr"
|
|
|
+ >
|
|
|
+ <img
|
|
|
+ class="c-wechat__qr"
|
|
|
+ :src="qr"
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </wrapper>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { mapState } from 'vuex'
|
|
|
+import {
|
|
|
+ userinfo,
|
|
|
+ updateUser
|
|
|
+} from '@/api/user'
|
|
|
+import { Role } from '@/constant'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'Profile',
|
|
|
+ data () {
|
|
|
+ return {
|
|
|
+ error: false,
|
|
|
+ user: null,
|
|
|
+ avatar: '',
|
|
|
+ phone: '',
|
|
|
+ email: '',
|
|
|
+ wechat: '',
|
|
|
+ showQr: false,
|
|
|
+ qr: '',
|
|
|
+ loading: false,
|
|
|
+ retry: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ ...mapState('user', ['name', 'roles']),
|
|
|
+ avatarStyle () {
|
|
|
+ const avatar = this.avatar
|
|
|
+ return avatar ? {
|
|
|
+ backgroundImage: `url("${avatar}")`
|
|
|
+ } : null
|
|
|
+ },
|
|
|
+ roleTip () {
|
|
|
+ if (this.roles.includes(Role.ADMIN)) {
|
|
|
+ return '超级管理员'
|
|
|
+ }
|
|
|
+ if (this.roles.includes(Role.SUPERVISOR)) {
|
|
|
+ return '主管'
|
|
|
+ }
|
|
|
+ if (this.roles.includes(Role.STAFF)) {
|
|
|
+ return '员工'
|
|
|
+ }
|
|
|
+ return '游客'
|
|
|
+ },
|
|
|
+ tip () {
|
|
|
+ return this.wechat ? '解除绑定' : '绑定微信'
|
|
|
+ },
|
|
|
+ color () {
|
|
|
+ return this.wechat ? 'u-color--error' : 'u-color--primary'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created () {
|
|
|
+ this.$timer = null
|
|
|
+ this.$checkTimer = null
|
|
|
+ this.getUserInfo()
|
|
|
+ },
|
|
|
+ beforeDestroy () {
|
|
|
+ this.onCloseQr()
|
|
|
+ clearInterval(this.$checkTimer)
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ onAvatarClick () {
|
|
|
+ this.$refs.upload.click()
|
|
|
+ },
|
|
|
+ onUpload (e) {
|
|
|
+ const file = e.target.files[0]
|
|
|
+ e.target.value = null
|
|
|
+ if (file.size >= 1024 * 1024) {
|
|
|
+ this.$message({
|
|
|
+ type: 'warning',
|
|
|
+ message: '请选择1M以下的图片'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const reader = new FileReader()
|
|
|
+ reader.onload = () => {
|
|
|
+ this.avatar = reader.result
|
|
|
+ }
|
|
|
+ reader.readAsDataURL(file)
|
|
|
+ },
|
|
|
+ getUserInfo () {
|
|
|
+ this.error = false
|
|
|
+ userinfo().then(data => {
|
|
|
+ // 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.error = true
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getOrCreateAttribute (user, key, defaults = '') {
|
|
|
+ if (!user.attributes[key]) {
|
|
|
+ user.attributes[key] = [defaults]
|
|
|
+ }
|
|
|
+ return user.attributes[key][0]
|
|
|
+ },
|
|
|
+ updateUser (data, meesage) {
|
|
|
+ return updateUser(this.user.id, data, meesage)
|
|
|
+ },
|
|
|
+ changeAttribute (key, value, meesage) {
|
|
|
+ if (this.user.attributes[key][0] !== value) {
|
|
|
+ return this.updateUser({
|
|
|
+ attributes: {
|
|
|
+ ...this.user.attributes,
|
|
|
+ [key]: [value]
|
|
|
+ }
|
|
|
+ }, meesage).then(
|
|
|
+ () => {
|
|
|
+ this.user.attributes[key][0] = value
|
|
|
+ },
|
|
|
+ e => {
|
|
|
+ this.resetAttribute(key)
|
|
|
+ return Promise.reject(e)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }
|
|
|
+ return Promise.resolve()
|
|
|
+ },
|
|
|
+ resetAttribute (key) {
|
|
|
+ this[key] = this.user.attributes[key][0]
|
|
|
+ },
|
|
|
+ onPhoneChange () {
|
|
|
+ if (!this.phone) {
|
|
|
+ this.$message({
|
|
|
+ type: 'warning',
|
|
|
+ message: '手机号不能为空'
|
|
|
+ })
|
|
|
+ this.resetAttribute('phone')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!(/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(this.phone))) {
|
|
|
+ this.$message({
|
|
|
+ type: 'warning',
|
|
|
+ message: '手机号格式错误'
|
|
|
+ })
|
|
|
+ this.resetAttribute('phone')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.changeAttribute('phone', this.phone, '更新手机号')
|
|
|
+ },
|
|
|
+ onEmailChange () {
|
|
|
+ if (!this.email) {
|
|
|
+ this.$message({
|
|
|
+ type: 'warning',
|
|
|
+ message: '邮箱不能为空'
|
|
|
+ })
|
|
|
+ this.resetAttribute('email')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!(/^([a-zA-Z0-9]+[_|.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/.test(this.email))) {
|
|
|
+ this.$message({
|
|
|
+ type: 'warning',
|
|
|
+ message: '邮箱格式错误'
|
|
|
+ })
|
|
|
+ this.resetAttribute('email')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.updateUser({ email: this.email }, '更新邮箱').then(
|
|
|
+ () => {
|
|
|
+ this.user.email = this.email
|
|
|
+ },
|
|
|
+ () => {
|
|
|
+ this.email = this.user.email
|
|
|
+ }
|
|
|
+ )
|
|
|
+ },
|
|
|
+ onClickWechat () {
|
|
|
+ if (this.wechat) {
|
|
|
+ this.$confirm('解除绑定后将无法再收到消息推送', '确定解绑微信?', { type: 'warning' }).then(
|
|
|
+ () => {
|
|
|
+ this.changeAttribute('wechat', '', '解绑微信').then(() => {
|
|
|
+ this.wechat = ''
|
|
|
+ this.user.attributes.wechat[0] = ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ this.showQr = true
|
|
|
+ this.getQr()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onCloseQr () {
|
|
|
+ this.showQr = false
|
|
|
+ clearTimeout(this.$timer)
|
|
|
+ },
|
|
|
+ getQr () {
|
|
|
+ if (this.loading || this.qr && !this.retry) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.fetchQr()
|
|
|
+ },
|
|
|
+ resetQr () {
|
|
|
+ clearInterval(this.$checkTimer)
|
|
|
+ this.$checkTimer = null
|
|
|
+ this.qr = ''
|
|
|
+ this.retry = false
|
|
|
+ },
|
|
|
+ fetchQr () {
|
|
|
+ if (!this.showQr) {
|
|
|
+ this.qr = ''
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!this.qr || this.retry) {
|
|
|
+ this.loading = true
|
|
|
+ }
|
|
|
+ this.retry = false
|
|
|
+ clearTimeout(this.$timer)
|
|
|
+ new Promise((resolve, reject) => {
|
|
|
+ setTimeout(Math.random() + 0.5 | 0 ? resolve : reject, 1000)
|
|
|
+ }).then(
|
|
|
+ () => {
|
|
|
+ if (!this.wechat) {
|
|
|
+ this.qr = Math.random()
|
|
|
+ this.$timer = setTimeout(this.fetchQr, 5000)
|
|
|
+ this.checkBind()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ () => {
|
|
|
+ if (!this.wechat) {
|
|
|
+ this.retry = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ).finally(() => {
|
|
|
+ this.loading = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ checkBind () {
|
|
|
+ if (!this.wechat && !this.$checkTimer) {
|
|
|
+ this.$checkTimer = setInterval(this.check, 2000)
|
|
|
+ setTimeout(() => {
|
|
|
+ this.updateUser({
|
|
|
+ attributes: {
|
|
|
+ ...this.user.attributes,
|
|
|
+ wechat: ['9999']
|
|
|
+ }
|
|
|
+ }, null)
|
|
|
+ }, 5000)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ check () {
|
|
|
+ userinfo(true).then(data => {
|
|
|
+ const wechat = data.attributes.wechat?.[0]
|
|
|
+ if (wechat) {
|
|
|
+ this.$message({
|
|
|
+ type: 'success',
|
|
|
+ message: '绑定微信成功'
|
|
|
+ })
|
|
|
+ this.wechat = wechat
|
|
|
+ this.user.attributes.wechat[0] = wechat
|
|
|
+ this.onCloseQr()
|
|
|
+ this.resetQr()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.c-profile {
|
|
|
+ overflow: hidden;
|
|
|
+
|
|
|
+ &__header {
|
|
|
+ justify-content: space-between;
|
|
|
+ height: 176px;
|
|
|
+ color: #fff;
|
|
|
+ line-height: 1;
|
|
|
+ background-color: $blue;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__icon {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ transform: translate(calc(-100% - 16px), -50%);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.o-avatar {
|
|
|
+ display: inline-block;
|
|
|
+ position: relative;
|
|
|
+ width: 80px;
|
|
|
+ height: 80px;
|
|
|
+ padding: 2px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background-color: #fff;
|
|
|
+
|
|
|
+ &__img {
|
|
|
+ display: inline-block;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: url("~@/assets/icon_avatar.png") 0 0 / 100% 100% no-repeat;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__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;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.o-wechat {
|
|
|
+ display: inline-block;
|
|
|
+ width: 32px;
|
|
|
+ height: 32px;
|
|
|
+ background: url("~@/assets/icon_wechat.png") 0 0 / 100% 100% no-repeat;
|
|
|
+}
|
|
|
+
|
|
|
+.c-wechat {
|
|
|
+ border-radius: $radius;
|
|
|
+ background-color: #fff;
|
|
|
+
|
|
|
+ &__wrapper {
|
|
|
+ position: relative;
|
|
|
+ width: 240px;
|
|
|
+ height: 240px;
|
|
|
+
|
|
|
+ &.retry::after {
|
|
|
+ content: "点击重试";
|
|
|
+ display: inline-flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ color: $black;
|
|
|
+ font-weight: bold;
|
|
|
+ background-color: rgba(#fff, 0.8);
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &__qr {
|
|
|
+ display: inline-block;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|