lcw
This commit is contained in:
346
src/views/backOfficeSystem/luntan copy/components/UserCard.vue
Normal file
346
src/views/backOfficeSystem/luntan copy/components/UserCard.vue
Normal file
@ -0,0 +1,346 @@
|
||||
<template>
|
||||
<div class="user-card">
|
||||
<div class="user-card-head">
|
||||
<div class="user-avatar">
|
||||
<div class="avatar-wrapper" @click="showAvatarDialog = true">
|
||||
<el-avatar :size="56" :src="avatarUrl">
|
||||
<img src="@/assets/images/mr.png" />
|
||||
</el-avatar>
|
||||
<div class="avatar-overlay">
|
||||
<el-icon class="upload-icon">
|
||||
<Camera />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-card-head-text">
|
||||
<div class="name-row">
|
||||
<span class="nickname">{{ userInfo.nickname || '用户信息' }}</span>
|
||||
</div>
|
||||
<div class="sub-stats">内部论坛 · 已登录</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="user-info">
|
||||
<div class="info-item clickable" @click="showNicknameDialog = true">
|
||||
<span class="label">昵称</span>
|
||||
<span class="value">{{ userInfo.nickname || '-' }}</span>
|
||||
<el-icon class="edit-icon">
|
||||
<Edit />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">账号</span>
|
||||
<span class="value">{{ userInfo.account || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">姓名</span>
|
||||
<span class="value">{{ userInfo.name || '-' }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">部门</span>
|
||||
<span class="value">{{ userInfo.department || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 更换头像对话框 -->
|
||||
<ChangeAvatar v-model="showAvatarDialog" title="更换头像" @avatarUpdated="handleAvatarUpdated" />
|
||||
|
||||
<!-- 编辑昵称对话框 -->
|
||||
<el-dialog
|
||||
v-model="showNicknameDialog"
|
||||
class="luntan-tech-dialog"
|
||||
title="编辑昵称"
|
||||
width="400px"
|
||||
center
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form ref="nicknameFormRef" :model="nicknameForm" :rules="nicknameRules" label-width="80px">
|
||||
<el-form-item label="昵称" prop="nickname">
|
||||
<el-input v-model="nicknameForm.nickname" placeholder="请输入昵称" maxlength="20" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showNicknameDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSaveNickname">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Camera, Edit } from '@element-plus/icons-vue'
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage.js'
|
||||
import { setAddress } from '@/utils/tools'
|
||||
import { tbGsxtXxltTxTxQueryBySfzh, tbGsxtXxltTxTxSave } from '@/api/tbGsxtXxltHf.js'
|
||||
import ChangeAvatar from './ChangeAvatar.vue'
|
||||
|
||||
const showAvatarDialog = ref(false)
|
||||
const showNicknameDialog = ref(false)
|
||||
const nicknameFormRef = ref()
|
||||
|
||||
const userInfo = ref({
|
||||
avatar: '',
|
||||
account: '',
|
||||
name: '',
|
||||
department: '',
|
||||
nickname: ''
|
||||
})
|
||||
|
||||
const nicknameForm = reactive({
|
||||
nickname: ''
|
||||
})
|
||||
|
||||
const nicknameRules = {
|
||||
nickname: [
|
||||
{ required: true, message: '请输入昵称', trigger: 'blur' },
|
||||
{ min: 2, max: 20, message: '昵称长度在 2 到 20 个字符', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
const avatarUrl = computed(() => {
|
||||
return userInfo.value.avatar ? setAddress(userInfo.value.avatar) : ''
|
||||
})
|
||||
|
||||
// 加载用户信息
|
||||
const loadUserInfo = async () => {
|
||||
const sfzh = getItem('idEntityCard')
|
||||
let ltmasg = getItem('ltmasg')
|
||||
|
||||
if (!ltmasg) {
|
||||
try {
|
||||
const res = await tbGsxtXxltTxTxQueryBySfzh({ sfzh: sfzh })
|
||||
console.log(res);
|
||||
|
||||
const deptId = getItem('deptId')?.[0]
|
||||
ltmasg = {
|
||||
...res,
|
||||
deptName: deptId?.deptName || ''
|
||||
}
|
||||
setItem('ltmasg', ltmasg)
|
||||
} catch (error) {
|
||||
console.error('加载用户信息失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
if (ltmasg) {
|
||||
userInfo.value = {
|
||||
avatar: ltmasg.tx || '',
|
||||
account: ltmasg.sfzh || '',
|
||||
name: ltmasg.xm || '',
|
||||
department: ltmasg.deptName || ltmasg.bm || '',
|
||||
nickname: ltmasg.nc || ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理头像更新
|
||||
const handleAvatarUpdated = async (newAvatar) => {
|
||||
try {
|
||||
const ltmasg = getItem('ltmasg')
|
||||
const updateData = {
|
||||
...ltmasg,
|
||||
tx: newAvatar
|
||||
}
|
||||
|
||||
await tbGsxtXxltTxTxSave(updateData)
|
||||
removeItem('ltmasg')
|
||||
await loadUserInfo()
|
||||
ElMessage.success('头像更新成功')
|
||||
} catch (error) {
|
||||
console.error('更新头像失败:', error)
|
||||
ElMessage.error('头像更新失败,请重试')
|
||||
}
|
||||
}
|
||||
|
||||
// 处理保存昵称
|
||||
const handleSaveNickname = async () => {
|
||||
if (!nicknameFormRef.value) return
|
||||
|
||||
await nicknameFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
try {
|
||||
const ltmasg = getItem('ltmasg')
|
||||
const updateData = {
|
||||
...ltmasg,
|
||||
nc: nicknameForm.nickname
|
||||
}
|
||||
|
||||
await tbGsxtXxltTxTxSave(updateData)
|
||||
removeItem('ltmasg')
|
||||
await loadUserInfo()
|
||||
showNicknameDialog.value = false
|
||||
ElMessage.success('昵称保存成功')
|
||||
} catch (error) {
|
||||
console.error('保存昵称失败:', error)
|
||||
ElMessage.error('昵称保存失败,请重试')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 监听昵称对话框打开,初始化表单
|
||||
const openNicknameDialog = () => {
|
||||
nicknameForm.nickname = userInfo.value.nickname
|
||||
}
|
||||
|
||||
// 监听对话框显示状态
|
||||
const unwatchNickname = () => {
|
||||
if (showNicknameDialog.value) {
|
||||
openNicknameDialog()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadUserInfo()
|
||||
})
|
||||
|
||||
// 监听昵称对话框
|
||||
const stopWatch = () => {
|
||||
if (showNicknameDialog.value) {
|
||||
nicknameForm.nickname = userInfo.value.nickname
|
||||
}
|
||||
}
|
||||
|
||||
// 使用 watch 监听对话框状态
|
||||
import { watch } from 'vue'
|
||||
watch(showNicknameDialog, (newVal) => {
|
||||
if (newVal) {
|
||||
nicknameForm.nickname = userInfo.value.nickname
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '../styles/luntan-tech.scss';
|
||||
|
||||
.user-card {
|
||||
border-radius: 4px;
|
||||
padding: 18px 16px 16px;
|
||||
@include lt-panel-frame;
|
||||
}
|
||||
|
||||
.user-card-head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 14px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 14px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
flex-shrink: 0;
|
||||
|
||||
.avatar-wrapper {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
border: 2px solid rgba(100, 180, 255, 0.35);
|
||||
|
||||
&:hover .avatar-overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.avatar-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.55);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
border-radius: 50%;
|
||||
|
||||
.upload-icon {
|
||||
font-size: 22px;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-card-head-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.name-row {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.nickname {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #f0f6ff;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.sub-stats {
|
||||
font-size: 12px;
|
||||
color: rgba(180, 200, 230, 0.55);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 10px;
|
||||
font-size: 13px;
|
||||
position: relative;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.clickable {
|
||||
cursor: pointer;
|
||||
padding: 6px 8px;
|
||||
margin-left: -8px;
|
||||
margin-right: -8px;
|
||||
border-radius: 6px;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.06);
|
||||
|
||||
.edit-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
color: rgba(160, 185, 215, 0.55);
|
||||
min-width: 40px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: rgba(220, 230, 245, 0.88);
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
margin-left: 6px;
|
||||
color: #5eb8ff;
|
||||
font-size: 14px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../styles/luntan-dialog-tech.scss';
|
||||
</style>
|
||||
Reference in New Issue
Block a user