mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-11-04 08:06:12 +08:00 
			
		
		
		
	refactor: profile
This commit is contained in:
		
							
								
								
									
										77
									
								
								yudao-ui-admin-vue3/src/api/system/user/profile.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								yudao-ui-admin-vue3/src/api/system/user/profile.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					import request from '@/config/axios'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ProfileDept {
 | 
				
			||||||
 | 
					  id: number
 | 
				
			||||||
 | 
					  name: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export interface ProfileRole {
 | 
				
			||||||
 | 
					  id: number
 | 
				
			||||||
 | 
					  name: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export interface ProfilePost {
 | 
				
			||||||
 | 
					  id: number
 | 
				
			||||||
 | 
					  name: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export interface SocialUser {
 | 
				
			||||||
 | 
					  id: number
 | 
				
			||||||
 | 
					  type: number
 | 
				
			||||||
 | 
					  openid: string
 | 
				
			||||||
 | 
					  token: string
 | 
				
			||||||
 | 
					  rawTokenInfo: string
 | 
				
			||||||
 | 
					  nickname: string
 | 
				
			||||||
 | 
					  avatar: string
 | 
				
			||||||
 | 
					  rawUserInfo: string
 | 
				
			||||||
 | 
					  code: string
 | 
				
			||||||
 | 
					  state: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export interface ProfileVO {
 | 
				
			||||||
 | 
					  id: number
 | 
				
			||||||
 | 
					  username: string
 | 
				
			||||||
 | 
					  nickname: string
 | 
				
			||||||
 | 
					  dept: ProfileDept
 | 
				
			||||||
 | 
					  roles: ProfileRole[]
 | 
				
			||||||
 | 
					  posts: ProfilePost[]
 | 
				
			||||||
 | 
					  socialUsers: SocialUser[]
 | 
				
			||||||
 | 
					  email: string
 | 
				
			||||||
 | 
					  mobile: string
 | 
				
			||||||
 | 
					  sex: number
 | 
				
			||||||
 | 
					  avatar: string
 | 
				
			||||||
 | 
					  status: number
 | 
				
			||||||
 | 
					  remark: string
 | 
				
			||||||
 | 
					  loginIp: string
 | 
				
			||||||
 | 
					  loginDate: Date
 | 
				
			||||||
 | 
					  createTime: Date
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface UserProfileUpdateReqVO {
 | 
				
			||||||
 | 
					  nickname: string
 | 
				
			||||||
 | 
					  email: string
 | 
				
			||||||
 | 
					  mobile: string
 | 
				
			||||||
 | 
					  sex: number
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 查询用户个人信息
 | 
				
			||||||
 | 
					export const getUserProfileApi = () => {
 | 
				
			||||||
 | 
					  return request.get({ url: '/system/user/profile/get' })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 修改用户个人信息
 | 
				
			||||||
 | 
					export const updateUserProfileApi = (data: UserProfileUpdateReqVO) => {
 | 
				
			||||||
 | 
					  return request.put({ url: '/system/user/profile/update', data })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 用户密码重置
 | 
				
			||||||
 | 
					export const updateUserPwdApi = (oldPassword: string, newPassword: string) => {
 | 
				
			||||||
 | 
					  return request.put({
 | 
				
			||||||
 | 
					    url: '/system/user/profile/update-password',
 | 
				
			||||||
 | 
					    data: {
 | 
				
			||||||
 | 
					      oldPassword: oldPassword,
 | 
				
			||||||
 | 
					      newPassword: newPassword
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 用户头像上传
 | 
				
			||||||
 | 
					export const uploadAvatarApi = (data) => {
 | 
				
			||||||
 | 
					  return request.upload({ url: '/system/user/profile/update-avatar', data: data })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,27 +0,0 @@
 | 
				
			|||||||
import request from '@/config/axios'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 查询用户个人信息
 | 
					 | 
				
			||||||
export const getUserProfileApi = () => {
 | 
					 | 
				
			||||||
  return request.get({ url: '/system/user/profile/get' })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 修改用户个人信息
 | 
					 | 
				
			||||||
export const updateUserProfileApi = (params) => {
 | 
					 | 
				
			||||||
  return request.put({ url: '/system/user/profile/update', params })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 用户密码重置
 | 
					 | 
				
			||||||
export const updateUserPwdApi = (oldPassword: string, newPassword: string) => {
 | 
					 | 
				
			||||||
  return request.put({
 | 
					 | 
				
			||||||
    url: '/system/user/profile/update-password',
 | 
					 | 
				
			||||||
    data: {
 | 
					 | 
				
			||||||
      oldPassword: oldPassword,
 | 
					 | 
				
			||||||
      newPassword: newPassword
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 用户头像上传
 | 
					 | 
				
			||||||
export const uploadAvatarApi = (data) => {
 | 
					 | 
				
			||||||
  return request.upload({ url: '/system/user/profile/update-avatar', data: data })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,42 +0,0 @@
 | 
				
			|||||||
export type ProfileDept = {
 | 
					 | 
				
			||||||
  id: number
 | 
					 | 
				
			||||||
  name: string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export type ProfileRole = {
 | 
					 | 
				
			||||||
  id: number
 | 
					 | 
				
			||||||
  name: string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export type ProfilePost = {
 | 
					 | 
				
			||||||
  id: number
 | 
					 | 
				
			||||||
  name: string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export type SocialUser = {
 | 
					 | 
				
			||||||
  id: number
 | 
					 | 
				
			||||||
  type: number
 | 
					 | 
				
			||||||
  openid: string
 | 
					 | 
				
			||||||
  token: string
 | 
					 | 
				
			||||||
  rawTokenInfo: string
 | 
					 | 
				
			||||||
  nickname: string
 | 
					 | 
				
			||||||
  avatar: string
 | 
					 | 
				
			||||||
  rawUserInfo: string
 | 
					 | 
				
			||||||
  code: string
 | 
					 | 
				
			||||||
  state: string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
export type ProfileVO = {
 | 
					 | 
				
			||||||
  id: number
 | 
					 | 
				
			||||||
  username: string
 | 
					 | 
				
			||||||
  nickname: string
 | 
					 | 
				
			||||||
  dept: ProfileDept
 | 
					 | 
				
			||||||
  roles: ProfileRole[]
 | 
					 | 
				
			||||||
  posts: ProfilePost[]
 | 
					 | 
				
			||||||
  socialUsers: SocialUser[]
 | 
					 | 
				
			||||||
  email: string
 | 
					 | 
				
			||||||
  mobile: string
 | 
					 | 
				
			||||||
  sex: number
 | 
					 | 
				
			||||||
  avatar: string
 | 
					 | 
				
			||||||
  status: number
 | 
					 | 
				
			||||||
  remark: string
 | 
					 | 
				
			||||||
  loginIp: string
 | 
					 | 
				
			||||||
  loginDate: Date
 | 
					 | 
				
			||||||
  createTime: Date
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										31
									
								
								yudao-ui-admin-vue3/src/api/system/user/socialUser.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								yudao-ui-admin-vue3/src/api/system/user/socialUser.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					import request from '@/config/axios'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 社交绑定,使用 code 授权码
 | 
				
			||||||
 | 
					export const socialBind = (type, code, state) => {
 | 
				
			||||||
 | 
					  return request.post({
 | 
				
			||||||
 | 
					    url: '/system/social-user/bind',
 | 
				
			||||||
 | 
					    data: {
 | 
				
			||||||
 | 
					      type,
 | 
				
			||||||
 | 
					      code,
 | 
				
			||||||
 | 
					      state
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 取消社交绑定
 | 
				
			||||||
 | 
					export const socialUnbind = (type, openid) => {
 | 
				
			||||||
 | 
					  return request.delete({
 | 
				
			||||||
 | 
					    url: '/system/social-user/unbind',
 | 
				
			||||||
 | 
					    data: {
 | 
				
			||||||
 | 
					      type,
 | 
				
			||||||
 | 
					      openid
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 社交授权的跳转
 | 
				
			||||||
 | 
					export const socialAuthRedirect = (type, redirectUri) => {
 | 
				
			||||||
 | 
					  return request.get({
 | 
				
			||||||
 | 
					    url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,11 +1,3 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					 | 
				
			||||||
import { ref } from 'vue'
 | 
					 | 
				
			||||||
import { useI18n } from '@/hooks/web/useI18n'
 | 
					 | 
				
			||||||
import { ElCard, ElTabs, ElTabPane } from 'element-plus'
 | 
					 | 
				
			||||||
import { BasicInfo, ProfileUser, ResetPwd, UserSocial } from './components/'
 | 
					 | 
				
			||||||
const { t } = useI18n()
 | 
					 | 
				
			||||||
const activeName = ref('basicInfo')
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="flex">
 | 
					  <div class="flex">
 | 
				
			||||||
    <el-card class="w-1/3 user" shadow="hover">
 | 
					    <el-card class="w-1/3 user" shadow="hover">
 | 
				
			||||||
@ -38,6 +30,15 @@ const activeName = ref('basicInfo')
 | 
				
			|||||||
    </el-card>
 | 
					    </el-card>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import { ref } from 'vue'
 | 
				
			||||||
 | 
					import { useI18n } from '@/hooks/web/useI18n'
 | 
				
			||||||
 | 
					import { ElCard, ElTabs, ElTabPane } from 'element-plus'
 | 
				
			||||||
 | 
					import { BasicInfo, ProfileUser, ResetPwd, UserSocial } from './components/'
 | 
				
			||||||
 | 
					const { t } = useI18n()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const activeName = ref('basicInfo')
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
<style scoped>
 | 
					<style scoped>
 | 
				
			||||||
.user {
 | 
					.user {
 | 
				
			||||||
  max-height: 960px;
 | 
					  max-height: 960px;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,30 +1,28 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <Form ref="formRef" :rules="rules" :schema="schema" :labelWidth="80">
 | 
				
			||||||
 | 
					    <template #sex>
 | 
				
			||||||
 | 
					      <el-radio-group v-model="sexVlue">
 | 
				
			||||||
 | 
					        <el-radio :label="1">{{ t('profile.user.man') }}</el-radio>
 | 
				
			||||||
 | 
					        <el-radio :label="2">{{ t('profile.user.woman') }}</el-radio>
 | 
				
			||||||
 | 
					      </el-radio-group>
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
 | 
					  </Form>
 | 
				
			||||||
 | 
					  <el-button type="primary" @click="submit()">{{ t('common.save') }}</el-button>
 | 
				
			||||||
 | 
					  <el-button type="danger" @click="init()">{{ t('common.reset') }}</el-button>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { ref, reactive, onMounted } from 'vue'
 | 
					import { reactive, onMounted, unref, ref } from 'vue'
 | 
				
			||||||
import type { FormRules, FormInstance } from 'element-plus'
 | 
					import type { FormRules } from 'element-plus'
 | 
				
			||||||
import { ElForm, ElFormItem, ElInput, ElRadioGroup, ElRadio, ElMessage } from 'element-plus'
 | 
					import { ElMessage, ElRadioGroup, ElRadio } from 'element-plus'
 | 
				
			||||||
import { useI18n } from '@/hooks/web/useI18n'
 | 
					import { useI18n } from '@/hooks/web/useI18n'
 | 
				
			||||||
import { getUserProfileApi, updateUserProfileApi } from '@/api/system/user/profile'
 | 
					import {
 | 
				
			||||||
 | 
					  getUserProfileApi,
 | 
				
			||||||
 | 
					  updateUserProfileApi,
 | 
				
			||||||
 | 
					  UserProfileUpdateReqVO
 | 
				
			||||||
 | 
					} from '@/api/system/user/profile'
 | 
				
			||||||
 | 
					import { FormSchema } from '@/types/form'
 | 
				
			||||||
 | 
					import { FormExpose } from '@/components/Form'
 | 
				
			||||||
const { t } = useI18n()
 | 
					const { t } = useI18n()
 | 
				
			||||||
const formRef = ref<FormInstance>()
 | 
					 | 
				
			||||||
interface BasicUserInfoVO {
 | 
					 | 
				
			||||||
  id: number
 | 
					 | 
				
			||||||
  nickname: string
 | 
					 | 
				
			||||||
  email: string
 | 
					 | 
				
			||||||
  mobile: string
 | 
					 | 
				
			||||||
  sex: number
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
interface userInfoType {
 | 
					 | 
				
			||||||
  basicUserInfo: BasicUserInfoVO
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const user = reactive<userInfoType>({
 | 
					 | 
				
			||||||
  basicUserInfo: {
 | 
					 | 
				
			||||||
    id: 0,
 | 
					 | 
				
			||||||
    nickname: '',
 | 
					 | 
				
			||||||
    mobile: '',
 | 
					 | 
				
			||||||
    email: '',
 | 
					 | 
				
			||||||
    sex: 0
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
// 表单校验
 | 
					// 表单校验
 | 
				
			||||||
const rules = reactive<FormRules>({
 | 
					const rules = reactive<FormRules>({
 | 
				
			||||||
  nickname: [{ required: true, message: t('profile.rules.nickname'), trigger: 'blur' }],
 | 
					  nickname: [{ required: true, message: t('profile.rules.nickname'), trigger: 'blur' }],
 | 
				
			||||||
@ -45,47 +43,49 @@ const rules = reactive<FormRules>({
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
const submit = (formEl: FormInstance | undefined) => {
 | 
					const schema = reactive<FormSchema[]>([
 | 
				
			||||||
  if (!formEl) return
 | 
					  {
 | 
				
			||||||
  formEl.validate(async (valid) => {
 | 
					    field: 'nickname',
 | 
				
			||||||
 | 
					    label: t('profile.user.nickname'),
 | 
				
			||||||
 | 
					    component: 'Input'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    field: 'mobile',
 | 
				
			||||||
 | 
					    label: t('profile.user.mobile'),
 | 
				
			||||||
 | 
					    component: 'Input'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    field: 'email',
 | 
				
			||||||
 | 
					    label: t('profile.user.email'),
 | 
				
			||||||
 | 
					    component: 'Input'
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    field: 'sex',
 | 
				
			||||||
 | 
					    label: t('profile.user.sex'),
 | 
				
			||||||
 | 
					    component: 'InputNumber'
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					const sexVlue = ref<number>()
 | 
				
			||||||
 | 
					const formRef = ref<FormExpose>() // 表单 Ref
 | 
				
			||||||
 | 
					const submit = () => {
 | 
				
			||||||
 | 
					  const elForm = unref(formRef)?.getElFormRef()
 | 
				
			||||||
 | 
					  if (!elForm) return
 | 
				
			||||||
 | 
					  elForm.validate(async (valid) => {
 | 
				
			||||||
    if (valid) {
 | 
					    if (valid) {
 | 
				
			||||||
      await updateUserProfileApi({ params: user.basicUserInfo })
 | 
					      const data = unref(formRef)?.formModel as UserProfileUpdateReqVO
 | 
				
			||||||
 | 
					      data.sex = sexVlue.value as unknown as number
 | 
				
			||||||
 | 
					      await updateUserProfileApi(data)
 | 
				
			||||||
      ElMessage.success(t('common.updateSuccess'))
 | 
					      ElMessage.success(t('common.updateSuccess'))
 | 
				
			||||||
 | 
					      await init()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const reset = async (formEl: FormInstance | undefined) => {
 | 
					const init = async () => {
 | 
				
			||||||
  if (!formEl) return
 | 
					  const res = await getUserProfileApi()
 | 
				
			||||||
  await getUserInfo()
 | 
					  sexVlue.value = res.sex
 | 
				
			||||||
}
 | 
					  unref(formRef)?.setValues(res)
 | 
				
			||||||
const getUserInfo = async () => {
 | 
					 | 
				
			||||||
  const users = await getUserProfileApi()
 | 
					 | 
				
			||||||
  user.basicUserInfo = users
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
  await getUserInfo()
 | 
					  await init()
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<template>
 | 
					 | 
				
			||||||
  <el-form ref="form" :model="user.basicUserInfo" :rules="rules" label-width="80px">
 | 
					 | 
				
			||||||
    <el-form-item :label="t('profile.user.nickname')" prop="nickname">
 | 
					 | 
				
			||||||
      <el-input v-model="user.basicUserInfo.nickname" />
 | 
					 | 
				
			||||||
    </el-form-item>
 | 
					 | 
				
			||||||
    <el-form-item :label="t('profile.user.mobile')" prop="mobile">
 | 
					 | 
				
			||||||
      <el-input v-model="user.basicUserInfo.mobile" maxlength="11" />
 | 
					 | 
				
			||||||
    </el-form-item>
 | 
					 | 
				
			||||||
    <el-form-item :label="t('profile.user.email')" prop="email">
 | 
					 | 
				
			||||||
      <el-input v-model="user.basicUserInfo.email" maxlength="50" />
 | 
					 | 
				
			||||||
    </el-form-item>
 | 
					 | 
				
			||||||
    <el-form-item :label="t('profile.user.sex')" prop="sex">
 | 
					 | 
				
			||||||
      <el-radio-group v-model="user.basicUserInfo.sex">
 | 
					 | 
				
			||||||
        <el-radio :label="1">{{ t('profile.user.man') }}</el-radio>
 | 
					 | 
				
			||||||
        <el-radio :label="2">{{ t('profile.user.woman') }}</el-radio>
 | 
					 | 
				
			||||||
      </el-radio-group>
 | 
					 | 
				
			||||||
    </el-form-item>
 | 
					 | 
				
			||||||
    <el-form-item>
 | 
					 | 
				
			||||||
      <el-button type="primary" @click="submit(formRef)">{{ t('common.save') }}</el-button>
 | 
					 | 
				
			||||||
      <el-button type="danger" @click="reset(formRef)">{{ t('common.reset') }}</el-button>
 | 
					 | 
				
			||||||
    </el-form-item>
 | 
					 | 
				
			||||||
  </el-form>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,86 +1,61 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <div>
 | 
				
			||||||
 | 
					    <div class="text-center">
 | 
				
			||||||
 | 
					      <UserAvatar :img="userInfo?.avatar" />
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <ul class="list-group list-group-striped">
 | 
				
			||||||
 | 
					      <li class="list-group-item">
 | 
				
			||||||
 | 
					        <Icon icon="ep:user" class="mr-5px" />{{ t('profile.user.username') }}
 | 
				
			||||||
 | 
					        <div class="pull-right">{{ userInfo?.username }}</div>
 | 
				
			||||||
 | 
					      </li>
 | 
				
			||||||
 | 
					      <li class="list-group-item">
 | 
				
			||||||
 | 
					        <Icon icon="ep:phone" class="mr-5px" />{{ t('profile.user.mobile') }}
 | 
				
			||||||
 | 
					        <div class="pull-right">{{ userInfo?.mobile }}</div>
 | 
				
			||||||
 | 
					      </li>
 | 
				
			||||||
 | 
					      <li class="list-group-item">
 | 
				
			||||||
 | 
					        <Icon icon="fontisto:email" class="mr-5px" />{{ t('profile.user.email') }}
 | 
				
			||||||
 | 
					        <div class="pull-right">{{ userInfo?.email }}</div>
 | 
				
			||||||
 | 
					      </li>
 | 
				
			||||||
 | 
					      <li class="list-group-item">
 | 
				
			||||||
 | 
					        <Icon icon="carbon:tree-view-alt" class="mr-5px" />{{ t('profile.user.dept') }}
 | 
				
			||||||
 | 
					        <div class="pull-right" v-if="userInfo?.dept">{{ userInfo?.dept.name }}</div>
 | 
				
			||||||
 | 
					      </li>
 | 
				
			||||||
 | 
					      <li class="list-group-item">
 | 
				
			||||||
 | 
					        <Icon icon="ep:suitcase" class="mr-5px" />{{ t('profile.user.posts') }}
 | 
				
			||||||
 | 
					        <div class="pull-right" v-if="userInfo?.posts">
 | 
				
			||||||
 | 
					          {{ userInfo?.posts.map((post) => post.name).join(',') }}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </li>
 | 
				
			||||||
 | 
					      <li class="list-group-item">
 | 
				
			||||||
 | 
					        <Icon icon="icon-park-outline:peoples" class="mr-5px" />{{ t('profile.user.roles') }}
 | 
				
			||||||
 | 
					        <div class="pull-right" v-if="userInfo?.roles">
 | 
				
			||||||
 | 
					          {{ userInfo?.roles.map((role) => role.name).join(',') }}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </li>
 | 
				
			||||||
 | 
					      <li class="list-group-item">
 | 
				
			||||||
 | 
					        <Icon icon="ep:calendar" class="mr-5px" />{{ t('profile.user.createTime') }}
 | 
				
			||||||
 | 
					        <div class="pull-right">{{ dayjs(userInfo?.createTime).format('YYYY-MM-DD') }}</div>
 | 
				
			||||||
 | 
					      </li>
 | 
				
			||||||
 | 
					    </ul>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { getUserProfileApi } from '@/api/system/user/profile'
 | 
					import { getUserProfileApi, ProfileVO } from '@/api/system/user/profile'
 | 
				
			||||||
import { onMounted, reactive } from 'vue'
 | 
					import { onMounted, ref } from 'vue'
 | 
				
			||||||
import dayjs from 'dayjs'
 | 
					import dayjs from 'dayjs'
 | 
				
			||||||
import UserAvatar from './UserAvatar.vue'
 | 
					import UserAvatar from './UserAvatar.vue'
 | 
				
			||||||
import { ProfileVO } from '@/api/system/user/profile/types'
 | 
					 | 
				
			||||||
import { useI18n } from '@/hooks/web/useI18n'
 | 
					import { useI18n } from '@/hooks/web/useI18n'
 | 
				
			||||||
const { t } = useI18n()
 | 
					const { t } = useI18n()
 | 
				
			||||||
interface userInfoType {
 | 
					const userInfo = ref<ProfileVO>()
 | 
				
			||||||
  user: ProfileVO
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const userInfo = reactive<userInfoType>({
 | 
					 | 
				
			||||||
  user: {
 | 
					 | 
				
			||||||
    id: 0,
 | 
					 | 
				
			||||||
    username: '',
 | 
					 | 
				
			||||||
    nickname: '',
 | 
					 | 
				
			||||||
    dept: {
 | 
					 | 
				
			||||||
      id: 0,
 | 
					 | 
				
			||||||
      name: ''
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    roles: [],
 | 
					 | 
				
			||||||
    posts: [],
 | 
					 | 
				
			||||||
    socialUsers: [],
 | 
					 | 
				
			||||||
    email: '',
 | 
					 | 
				
			||||||
    mobile: '',
 | 
					 | 
				
			||||||
    sex: 0,
 | 
					 | 
				
			||||||
    avatar: '',
 | 
					 | 
				
			||||||
    status: 0,
 | 
					 | 
				
			||||||
    remark: '',
 | 
					 | 
				
			||||||
    loginIp: '',
 | 
					 | 
				
			||||||
    loginDate: new Date(),
 | 
					 | 
				
			||||||
    createTime: new Date()
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
const getUserInfo = async () => {
 | 
					const getUserInfo = async () => {
 | 
				
			||||||
  const users = await getUserProfileApi()
 | 
					  const users = await getUserProfileApi()
 | 
				
			||||||
  userInfo.user = users
 | 
					  userInfo.value = users
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
  await getUserInfo()
 | 
					  await getUserInfo()
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<template>
 | 
					
 | 
				
			||||||
  <div>
 | 
					 | 
				
			||||||
    <div class="text-center">
 | 
					 | 
				
			||||||
      <UserAvatar :img="userInfo.user.avatar" />
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <ul class="list-group list-group-striped">
 | 
					 | 
				
			||||||
      <li class="list-group-item">
 | 
					 | 
				
			||||||
        <Icon icon="ep:user" class="mr-5px" />{{ t('profile.user.username') }}
 | 
					 | 
				
			||||||
        <div class="pull-right">{{ userInfo.user.username }}</div>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
      <li class="list-group-item">
 | 
					 | 
				
			||||||
        <Icon icon="ep:phone" class="mr-5px" />{{ t('profile.user.mobile') }}
 | 
					 | 
				
			||||||
        <div class="pull-right">{{ userInfo.user.mobile }}</div>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
      <li class="list-group-item">
 | 
					 | 
				
			||||||
        <Icon icon="fontisto:email" class="mr-5px" />{{ t('profile.user.email') }}
 | 
					 | 
				
			||||||
        <div class="pull-right">{{ userInfo.user.email }}</div>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
      <li class="list-group-item">
 | 
					 | 
				
			||||||
        <Icon icon="carbon:tree-view-alt" class="mr-5px" />{{ t('profile.user.dept') }}
 | 
					 | 
				
			||||||
        <div class="pull-right" v-if="userInfo.user.dept">{{ userInfo.user.dept.name }}</div>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
      <li class="list-group-item">
 | 
					 | 
				
			||||||
        <Icon icon="ep:suitcase" class="mr-5px" />{{ t('profile.user.posts') }}
 | 
					 | 
				
			||||||
        <div class="pull-right" v-if="userInfo.user.posts">
 | 
					 | 
				
			||||||
          {{ userInfo.user.posts.map((post) => post.name).join(',') }}
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
      <li class="list-group-item">
 | 
					 | 
				
			||||||
        <Icon icon="icon-park-outline:peoples" class="mr-5px" />{{ t('profile.user.roles') }}
 | 
					 | 
				
			||||||
        <div class="pull-right" v-if="userInfo.user.roles">
 | 
					 | 
				
			||||||
          {{ userInfo.user.roles.map((role) => role.name).join(',') }}
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
      <li class="list-group-item">
 | 
					 | 
				
			||||||
        <Icon icon="ep:calendar" class="mr-5px" />{{ t('profile.user.createTime') }}
 | 
					 | 
				
			||||||
        <div class="pull-right">{{ dayjs(userInfo.user.createTime).format('YYYY-MM-DD') }}</div>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
    </ul>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
<style scoped>
 | 
					<style scoped>
 | 
				
			||||||
.text-center {
 | 
					.text-center {
 | 
				
			||||||
  text-align: center;
 | 
					  text-align: center;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,20 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <el-form ref="formRef" :model="password" :rules="rules" label-width="80px">
 | 
				
			||||||
 | 
					    <el-form-item :label="t('profile.password.oldPassword')">
 | 
				
			||||||
 | 
					      <InputPassword v-model="password.oldPassword" />
 | 
				
			||||||
 | 
					    </el-form-item>
 | 
				
			||||||
 | 
					    <el-form-item :label="t('profile.password.newPassword')">
 | 
				
			||||||
 | 
					      <InputPassword v-model="password.newPassword" strength />
 | 
				
			||||||
 | 
					    </el-form-item>
 | 
				
			||||||
 | 
					    <el-form-item :label="t('profile.password.confirmPassword')">
 | 
				
			||||||
 | 
					      <InputPassword v-model="password.confirmPassword" strength />
 | 
				
			||||||
 | 
					    </el-form-item>
 | 
				
			||||||
 | 
					    <el-form-item>
 | 
				
			||||||
 | 
					      <XButton type="primary" @click="submit(formRef)" :title="t('common.save')" />
 | 
				
			||||||
 | 
					      <XButton type="danger" :title="t('common.reset')" @click="reset(formRef)" />
 | 
				
			||||||
 | 
					    </el-form-item>
 | 
				
			||||||
 | 
					  </el-form>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { InputPassword } from '@/components/InputPassword'
 | 
					import { InputPassword } from '@/components/InputPassword'
 | 
				
			||||||
import { ElForm, ElFormItem, ElMessage } from 'element-plus'
 | 
					import { ElForm, ElFormItem, ElMessage } from 'element-plus'
 | 
				
			||||||
@ -49,20 +66,3 @@ const reset = (formEl: FormInstance | undefined) => {
 | 
				
			|||||||
  formEl.resetFields()
 | 
					  formEl.resetFields()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<template>
 | 
					 | 
				
			||||||
  <el-form ref="formRef" :model="password" :rules="rules" label-width="80px">
 | 
					 | 
				
			||||||
    <el-form-item :label="t('profile.password.oldPassword')">
 | 
					 | 
				
			||||||
      <InputPassword v-model="password.oldPassword" />
 | 
					 | 
				
			||||||
    </el-form-item>
 | 
					 | 
				
			||||||
    <el-form-item :label="t('profile.password.newPassword')">
 | 
					 | 
				
			||||||
      <InputPassword v-model="password.newPassword" strength />
 | 
					 | 
				
			||||||
    </el-form-item>
 | 
					 | 
				
			||||||
    <el-form-item :label="t('profile.password.confirmPassword')">
 | 
					 | 
				
			||||||
      <InputPassword v-model="password.confirmPassword" strength />
 | 
					 | 
				
			||||||
    </el-form-item>
 | 
					 | 
				
			||||||
    <el-form-item>
 | 
					 | 
				
			||||||
      <el-button type="primary" @click="submit(formRef)">{{ t('common.save') }}</el-button>
 | 
					 | 
				
			||||||
      <el-button type="danger" @click="reset(formRef)">{{ t('common.reset') }}</el-button>
 | 
					 | 
				
			||||||
    </el-form-item>
 | 
					 | 
				
			||||||
  </el-form>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,54 +1,70 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					 | 
				
			||||||
import { ElTable, ElTableColumn } from 'element-plus'
 | 
					 | 
				
			||||||
import { onMounted, reactive } from 'vue'
 | 
					 | 
				
			||||||
interface sociaType {
 | 
					 | 
				
			||||||
  title: string
 | 
					 | 
				
			||||||
  type: string
 | 
					 | 
				
			||||||
  source: string
 | 
					 | 
				
			||||||
  img: string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
interface socialUserType {
 | 
					 | 
				
			||||||
  socialUser: {
 | 
					 | 
				
			||||||
    socia: sociaType[]
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const state = reactive<socialUserType>({
 | 
					 | 
				
			||||||
  socialUser: {
 | 
					 | 
				
			||||||
    socia: []
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
const initSocial = () => {
 | 
					 | 
				
			||||||
  console.info(1)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const bind = () => {
 | 
					 | 
				
			||||||
  console.info(1)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const unbind = () => {
 | 
					 | 
				
			||||||
  console.info(1)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
onMounted(async () => {
 | 
					 | 
				
			||||||
  await initSocial()
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <el-table :data="state.socialUser.socia" :show-header="false">
 | 
					  <el-table :data="socialUsers" :show-header="false">
 | 
				
			||||||
    <el-table-column label="社交平台" align="left" width="120" prop="socia">
 | 
					    <el-table-column type="seq" title="序号" width="60" fixed="left" />
 | 
				
			||||||
      <template #socia="{ row }">
 | 
					    <el-table-column label="社交平台" align="left" width="120">
 | 
				
			||||||
 | 
					      <template #default="{ row }">
 | 
				
			||||||
        <img style="height: 20px; vertical-align: middle" :src="row.img" alt="" />
 | 
					        <img style="height: 20px; vertical-align: middle" :src="row.img" alt="" />
 | 
				
			||||||
        {{ row.title }}
 | 
					        {{ row.title }}
 | 
				
			||||||
      </template>
 | 
					      </template>
 | 
				
			||||||
    </el-table-column>
 | 
					    </el-table-column>
 | 
				
			||||||
    <el-table-column label="操作" align="left" prop="action">
 | 
					    <el-table-column label="操作" align="center">
 | 
				
			||||||
      <template #action="{ row }">
 | 
					      <template #default="{ row }">
 | 
				
			||||||
        <div v-if="row.openid">
 | 
					        <template v-if="row.openid">
 | 
				
			||||||
          已绑定
 | 
					          已绑定
 | 
				
			||||||
          <el-button link type="primary" @click="unbind()">(解绑)</el-button>
 | 
					          <XTextButton type="primary" @click="unbind(row)" title="(解绑)" />
 | 
				
			||||||
        </div>
 | 
					        </template>
 | 
				
			||||||
        <div v-else>
 | 
					        <template v-else>
 | 
				
			||||||
          未绑定
 | 
					          未绑定
 | 
				
			||||||
          <el-button link type="primary" @click="bind()">(绑定)</el-button>
 | 
					          <XTextButton type="primary" @click="bind(row)" title="(绑定)" />
 | 
				
			||||||
        </div>
 | 
					        </template>
 | 
				
			||||||
      </template>
 | 
					      </template>
 | 
				
			||||||
    </el-table-column>
 | 
					    </el-table-column>
 | 
				
			||||||
  </el-table>
 | 
					  </el-table>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import { onMounted, ref } from 'vue'
 | 
				
			||||||
 | 
					import { ElTable, ElTableColumn } from 'element-plus'
 | 
				
			||||||
 | 
					import { SystemUserSocialTypeEnum } from '@/utils/constants'
 | 
				
			||||||
 | 
					import { getUserProfileApi, ProfileVO } from '@/api/system/user/profile'
 | 
				
			||||||
 | 
					import { socialAuthRedirect, socialUnbind } from '@/api/system/user/socialUser'
 | 
				
			||||||
 | 
					import { ElMessage } from 'element-plus'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const socialUsers = ref<any[]>([])
 | 
				
			||||||
 | 
					const userInfo = ref<ProfileVO>()
 | 
				
			||||||
 | 
					const initSocial = async () => {
 | 
				
			||||||
 | 
					  const res = await getUserProfileApi()
 | 
				
			||||||
 | 
					  userInfo.value = res
 | 
				
			||||||
 | 
					  for (const i in SystemUserSocialTypeEnum) {
 | 
				
			||||||
 | 
					    const socialUser = { ...SystemUserSocialTypeEnum[i] }
 | 
				
			||||||
 | 
					    socialUsers.value.push(socialUser)
 | 
				
			||||||
 | 
					    if (userInfo.value?.socialUsers) {
 | 
				
			||||||
 | 
					      for (const j in userInfo.value.socialUsers) {
 | 
				
			||||||
 | 
					        if (socialUser.type === userInfo.value.socialUsers[j].type) {
 | 
				
			||||||
 | 
					          socialUser.openid = userInfo.value.socialUsers[j].openid
 | 
				
			||||||
 | 
					          break
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  console.info(socialUsers.value)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const bind = (row) => {
 | 
				
			||||||
 | 
					  const redirectUri = location.origin + '/user/profile?type=' + row.type
 | 
				
			||||||
 | 
					  // 进行跳转
 | 
				
			||||||
 | 
					  socialAuthRedirect(row.type, encodeURIComponent(redirectUri)).then((res) => {
 | 
				
			||||||
 | 
					    console.log(res.url)
 | 
				
			||||||
 | 
					    window.location.href = res.data
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const unbind = async (row) => {
 | 
				
			||||||
 | 
					  const res = await socialUnbind(row.type, row.openid)
 | 
				
			||||||
 | 
					  if (res) {
 | 
				
			||||||
 | 
					    row.openid = undefined
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ElMessage.success('解绑成功')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					onMounted(async () => {
 | 
				
			||||||
 | 
					  await initSocial()
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user