import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid'; import { OakOperationUnpermittedException } from 'oak-domain/lib/types'; import dayjs from 'dayjs'; import { isMobile } from 'oak-domain/lib/utils/validator'; export default OakComponent({ entity: 'user', projection: { id: 1, name: 1, nickname: 1, birth: 1, gender: 1, idState: 1, userState: 1, refId: 1, mobile$user: { $entity: 'mobile', data: { id: 1, mobile: 1, userId: 1, }, }, user$ref: { $entity: 'user', data: { userState: 1, refId: 1, mobile$user: { $entity: 'mobile', data: { id: 1, mobile: 1, userId: 1, }, }, }, }, extraFile$entity: { $entity: 'extraFile', data: { id: 1, tag1: 1, origin: 1, bucket: 1, objectId: 1, filename: 1, extra1: 1, extension: 1, type: 1, entity: 1, entityId: 1, }, filter: { tag1: 'avatar', }, indexFrom: 0, count: 1, }, wechatUser$user: { $entity: 'wechatUser', data: { id: 1, openId: 1, unionId: 1, userId: 1, origin: 1, nickname: 1, }, }, hasPassword: 1, }, isList: false, formData({ data: user, features, origin }) { const extraFiles = user && this.select('extraFile', { data: { id: 1, tag1: 1, origin: 1, bucket: 1, objectId: 1, filename: 1, extra1: 1, extension: 1, type: 1, entity: 1, entityId: 1, }, filter: { tag1: 'avatar', entityId: user.id, }, }); const avatar = extraFiles?.[0]; const avatarUrl = features.extraFile.getUrl(avatar); const { mobile } = (user?.mobile$user && user?.mobile$user[0]) || (user?.user$ref && user?.user$ref[0] && user?.user$ref[0].mobile$user && user?.user$ref[0].mobile$user[0]) || {}; const genderOption = user?.gender && this.state.genderOptions.find((ele) => ele.value === user?.gender); const isRoot = features.token.isReallyRoot(); // 如果是从微信侧登录,可以同步用户信息 const app = features.application.getApplication(); const token = features.token.getToken(); const canSyncWechat = (token?.wechatUser?.applicationId === app.id) && this.features.token.isSelf(); const editable = user && user.$$createAt$$ === 1 || user['#oakLegalActions']?.includes('update'); const executable = this.tryExecute(); const commitBtnProps = { disabled: executable === true, }; return { id: user?.id, name: user?.name, hasPassword: user?.password || user?.hasPassword, nameDirty: origin && user?.name !== origin?.name, nickname: user?.nickname, nnDirty: origin && user?.nickname !== origin?.nickname, gender: user?.gender, genderStr: genderOption?.label, genderDirty: origin && user?.gender !== origin?.gender, birthText: user?.birth ? dayjs(user.birth).format('YYYY-MM-DD') : '', birth: user?.birth, birthDirty: origin && user?.birth !== origin?.birth, avatar, avatarUrl, mobile, userState: user?.userState, userStateStr: user?.userState && this.t(`user:v.userState.${user.userState}`), userStateColor: user?.userState && features.style.getColor('user', 'userState', user.userState), idState: user?.idState, idStateStr: user?.idState && this.t(`user:v.idState.${user.idState}`), idStateColor: user?.idState && features.style.getColor('user', 'idState', user.idState), wechatUser: user?.wechatUser$user?.[0], isRoot, canSyncWechat, editable, executable, isCreation: this.isCreation(), commitBtnProps, }; }, data: { lastSendAt: undefined, stateColor: { shadow: 'primary', normal: 'success', disabled: 'danger', }, idStateColor: { verifying: 'primary', verified: 'success', unverified: 'warning', }, genderOptions: [ { value: 'male', label: '男', }, { value: 'female', label: '女', }, ], refreshing: false, editAttr: '', mobileInput: '', mobileInputLegal: false, }, actions: ['update'], properties: { changeMobileUrl: '', changePasswordUrl: '', authenticateUrl: '', onConfirm: () => undefined, }, methods: { checkEditable(attr) { const { oakId } = this.props; const { editable } = this.state; if (!editable) { throw new OakOperationUnpermittedException('user', { id: 'dummy', action: 'update', data: { [attr]: '', }, filter: { id: oakId, } }); } }, syncWechatInfoMp() { return this.features.token.syncUserInfoWechatMp(); }, checkIdState() { if (this.state.idState === 'verified') { this.setMessage({ type: 'warning', content: this.t('notAllowUpdate.verified') }); return false; } return true; }, async refreshWechatPublicUserInfo() { this.checkEditable('nickname'); this.setState({ refreshing: true, }); try { await this.features.token.refreshWechatPublicUserInfo(); this.setState({ refreshing: false, }); } catch (err) { this.setState({ refreshing: false, }); throw err; } }, editMobile() { this.checkEditable('nickname'); if (this.state.isCreation) { this.setState({ editAttr: 'mobile', }); return; } const { changeMobileUrl, oakId } = this.props; if (changeMobileUrl) { this.navigateTo({ url: changeMobileUrl, userId: oakId, }); } else if (process.env.NODE_ENV === 'development') { console.warn('changeMobileUrl unset'); } }, editPassword() { this.checkEditable('password'); if (this.state.isCreation) { this.setState({ editAttr: 'password', }); return; } const { changePasswordUrl, oakId } = this.props; if (changePasswordUrl) { this.navigateTo({ url: changePasswordUrl, oakId, }); } else if (process.env.NODE_ENV === 'development') { console.warn('changePasswordUrl unset'); } }, goAuthenticate() { const { authenticateUrl, oakId } = this.props; if (authenticateUrl) { this.navigateTo({ url: authenticateUrl, oakId, }); } else if (process.env.NODE_ENV === 'development') { console.warn('authenticateUrl unset'); } }, editNickname() { this.checkEditable('nickname'); this.setState({ editAttr: 'nickname', }); }, editName() { this.checkEditable('name'); if (this.checkIdState()) { this.setState({ editAttr: 'name', }); } }, editGender() { this.checkEditable('gender'); const { idState } = this.state; if (this.checkIdState()) { this.setState({ editAttr: 'gender', }); } }, editBirth() { this.checkEditable('birth'); if (this.checkIdState()) { this.setState({ editAttr: 'birth', }); } }, cancelEdit() { this.setState({ editAttr: '', }); }, changeGenderMp(e) { const { detail } = e; const { checked, currentKey } = detail; this.update({ gender: currentKey, }); this.cancelEdit(); }, changeBirthMp(e) { const { detail: { value }, } = e; const birth = dayjs(value).startOf('day').valueOf(); this.update({ birth, }); }, changePasswordMp(e) { const { value } = e.detail; this.update({ password: value, hasPassword: !!value, }); }, changeNicknameMp(e) { const { value } = e.detail; this.update({ nickname: value, }); }, changeNameMp(e) { const { value } = e.detail; this.update({ name: value, }); }, inputMobileMp(e) { const { value } = e.detail; const mobileInputLegal = !!isMobile(value); this.setState({ mobileInput: value, mobileInputLegal, }); }, async confirmMobileInputMp() { const { mobileInput } = this.state; this.update({ mobile$user: [ { id: await generateNewIdAsync(), action: 'create', data: { id: await generateNewIdAsync(), mobile: mobileInput, ableState: 'enabled', } }, ], }); }, async unbindingWechat(captcha) { const { mobile, wechatUser } = this.state; try { await this.features.cache.exec('unbindingWechat', { wechatUserId: wechatUser.id, mobile, captcha, }); this.refresh(); this.setMessage({ content: '解绑成功', type: 'success', }); } catch (err) { this.setMessage({ content: '解绑失败', type: 'warning', }); } }, async onChooseAvatar(e) { const { avatarUrl } = e.detail; const { avatar } = this.state; this.update({ extraFile$entity: [ { id: await generateNewIdAsync(), action: 'create', data: { id: await generateNewIdAsync(), origin: 'unknown', type: 'image', uploadState: 'success', extra1: avatarUrl, filename: avatarUrl.slice(avatarUrl.lastIndexOf('/') + 1), tag1: 'avatar', }, } ].concat(avatar?.$$createAt$$ > 1 ? [ { id: await generateNewIdAsync(), action: 'remove', data: {}, filter: { id: avatar.id, } } ] : []) }); }, async onConfirm() { await this.execute(); this.reRender(); const { onConfirm } = this.props; onConfirm && onConfirm(); }, }, });