| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- <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>
|