Merge pull request #288 from xxyijixx/dev-profile

Dev profile
This commit is contained in:
kuaifan 2025-11-05 17:11:46 +08:00 committed by GitHub
commit 789062e85e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 520 additions and 338 deletions

View File

@ -0,0 +1,131 @@
<template>
<Modal v-model="visibleProxy" :title="$L('共同群组') + ' (' + $L('(*)个', totalCount) + ')'" :footer-hide="true" width="500">
<div class="common-dialog-content">
<div v-if="loading > 0 && list.length === 0" class="loading-wrapper">
<Loading/>
</div>
<div v-else-if="list.length === 0" class="empty-wrapper">
<div class="empty-content">
<Icon type="ios-people-outline" size="48"/>
<p>{{$L('暂无共同群组')}}</p>
</div>
</div>
<div v-else class="dialog-list">
<div
v-for="dialog in list"
:key="dialog.id"
class="dialog-item"
@click="onEnterDialog(dialog)">
<div class="dialog-avatar">
<EAvatar v-if="dialog.avatar" :src="dialog.avatar" :size="42"></EAvatar>
<i v-else-if="dialog.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
<i v-else-if="dialog.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-else-if="dialog.group_type=='task'" class="taskfont icon-avatar task">&#xe6f4;</i>
<i v-else-if="dialog.group_type=='okr'" class="taskfont icon-avatar task">&#xe6f4;</i>
<Icon v-else class="icon-avatar" type="ios-people" />
</div>
<div class="dialog-info">
<div class="dialog-name" v-html="transformEmojiToHtml(dialog.name)"></div>
<div class="dialog-meta">
<span class="member-count">{{$L('(*)人', dialog.people || 0)}}</span>
<span v-if="dialog.last_at" class="last-time">{{$A.timeFormat(dialog.last_at)}}</span>
</div>
</div>
<Icon class="enter-icon" type="ios-arrow-forward" />
</div>
<div v-if="hasMore" class="load-more-wrapper">
<Button type="primary" @click="loadList(true)" :loading="loading > 0">{{$L('加载更多')}}</Button>
</div>
</div>
</div>
</Modal>
</template>
<script>
import transformEmojiToHtml from "../../../utils/emoji";
export default {
name: 'CommonDialogModal',
props: {
value: { // v-model
type: Boolean,
default: false,
},
targetUserId: {
type: [Number, String],
required: true,
},
totalCount: {
type: [Number, String],
default: 0,
},
},
data() {
return {
list: [],
page: 1,
hasMore: false,
loading: 0,
}
},
computed: {
visibleProxy: {
get() { return this.value; },
set(v) { this.$emit('input', v); }
}
},
watch: {
visibleProxy(val) {
if (val && this.list.length === 0) {
this.loadList(false);
}
},
targetUserId() {
// reset when user changes
this.list = [];
this.page = 1;
this.hasMore = false;
}
},
methods: {
transformEmojiToHtml,
loadList(loadMore = false) {
if (!this.targetUserId) return;
this.loading++;
const page = loadMore ? this.page + 1 : 1;
this.$store.dispatch('call', {
url: 'dialog/common/list',
data: {
target_userid: this.targetUserId,
page
}
}).then(({data}) => {
const newList = loadMore ? [...this.list, ...data.data] : data.data;
this.list = Array.isArray(newList) ? newList : [];
this.page = data.current_page || page;
this.hasMore = !!data.next_page_url;
}).catch(({msg}) => {
$A.modalError(msg || this.$L('加载失败'));
}).finally(() => {
this.loading--;
});
},
onEnterDialog(dialog) {
this.$emit('open-chat', dialog);
}
}
}
</script>
<style scoped>
/* 组件自身不引入额外样式,复用全局样式类名 */
</style>

View File

@ -5,149 +5,162 @@
:fullscreen="isFullscreen" :fullscreen="isFullscreen"
:mask-closable="false" :mask-closable="false"
:footer-hide="true" :footer-hide="true"
width="600"> width="420"
>
<div class="user-detail-body"> <div class="user-detail-body">
<UserAvatar <div class="profile-header">
:userid="userData.userid" <div class="cover-photo"></div>
:size="120" <div class="profile-avatar">
:show-state-dot="false" <UserAvatar
@on-click="onOpenAvatar"/> :userid="userData.userid"
<ul class="user-select-auto"> :size="80"
<li class="user-name"> :show-state-dot="false"
<h1>{{userData.nickname}}</h1> @on-click="onOpenAvatar"
<em v-if="userData.delete_at" class="deleted no-dark-content">{{$L('已删除')}}</em> />
<em v-else-if="userData.disable_at" class="disabled no-dark-content">{{$L('已离职')}}</em> </div>
</li> </div>
<li v-if="userData.userid != userId && commonDialog.total !== null"> <div class="profile-content">
<span>{{$L('共同群聊')}}: </span> <div class="user-info-top">
<a href="javascript:void(0)" @click="commonDialogShow=true">{{ $L('(*)', commonDialog.total) }}</a> <span class="username"
</li> >@{{ userData.profession || "管理员" }}</span
<template v-if="!userData.bot"> >
<li> <h1 class="fullname">
<span>{{$L('部门')}}: </span> {{ userData.nickname}}
{{userData.department_name || '-'}} </h1>
</li> <div class="meta">
<li> <!-- <span>{{userData.address || 'Bandung'}}</span> -->
<span>{{$L('职位/职称')}}: </span> <span @click="commonDialogShow = true"
{{userData.profession || '-'}} class="common-dialog"
</li> >{{ $L("共同群组") }}:
<li> {{ $L("(*)个", commonDialog.total) }}</span
<span>{{$L('生日')}}: </span> >
{{userData.birthday ? ($A.newDateString(userData.birthday, 'YYYY-MM-DD') || userData.birthday) : '-'}} <span class="separator">|</span>
</li> <span
<li> >{{ $L("最后在线") }}:
<span>{{$L('地址')}}: </span> {{
{{userData.address || '-'}} $A.newDateString(
</li> userData.line_at,
<li> "YYYY-MM-DD HH:mm"
<span>{{$L('个人简介')}}: </span> ) || "-"
{{userData.introduction || '-'}} }}</span
</li> >
<li class="user-tags-line"> </div>
<span>{{$L('个性标签')}}: </span> </div>
<div class="tags-content" @click="onOpenTagsModal">
<div v-if="displayTags.length" class="tags-list"> <div class="profile-actions">
<Tag <Button
v-for="tag in displayTags" icon="md-chatbubbles"
:key="tag.id" @click="onOpenDialog"
:color="tag.recognized ? 'primary' : 'default'" >{{ $L("开始聊天") }}</Button
class="tag-pill">{{tag.name}}</Tag> >
</div> <Button
<span v-else class="tags-empty">{{$L('暂无个性标签')}}</span> icon="md-people"
<div class="tags-extra"> @click="onCreateGroup"
<span v-if="personalTagTotal > displayTags.length" class="tags-total">{{$L('(*)', personalTagTotal)}}</span> >{{ $L("创建群组") }}</Button
<Button type="text" size="small" class="manage-button" @click.stop="onOpenTagsModal">{{$L('管理')}}</Button> >
</div> </div>
<div class="profile-bio">
<p>{{ userData.introduction }}</p>
</div>
<div class="profile-information">
<h2>{{ $L("个人信息") }}</h2>
<ul>
<li>
<Icon type="ios-person-outline" />
<span class="label">{{ $L("部门") }}</span>
<span class="value">{{
userData.department_name || "-"
}}</span>
</li>
<li>
<Icon type="ios-mail-outline" />
<span class="label">{{ $L("邮箱") }}</span>
<span class="value">{{
userData.email || "-"
}}</span>
</li>
<li>
<Icon type="ios-call-outline" />
<span class="label">{{ $L("电话") }}</span>
<span class="value">{{ userData.tel || "-" }}</span>
</li>
<li>
<Icon type="ios-calendar-outline" />
<span class="label">{{ $L("生日") }}</span>
<span class="value">{{
userData.birthday || "-"
}}</span>
</li>
</ul>
<div class="profile-tags" @click.capture="onOpenTagsModal">
<div v-if="displayTags.length" class="tags-list">
<Button
type="dashed"
class="manage-tags-btn icon"
@click.stop="onOpenTagsModal"
>
<Icon type="ios-settings-outline" /> 管理
</Button>
<Button
v-for="tag in displayTags"
:key="tag.id"
:type="tag.recognized ? 'primary' : 'default'"
>
{{ tag.name }}
</Button>
</div> </div>
</li> <div v-else class="tags-empty">
<li> <Button
<span>{{$L('最后在线')}}: </span> type="dashed"
{{$A.newDateString(userData.line_at, 'YYYY-MM-DD HH:mm') || '-'}} size="small"
</li> icon="md-add"
<li v-if="userData.delete_at"> class="add-tag-btn"
<strong><span>{{$L('删除时间')}}: </span>{{$A.newDateString(userData.delete_at, 'YYYY-MM-DD HH:mm')}}</strong> @click.stop="onOpenTagsModal"
</li> >{{ $L("添加标签") }}</Button
<li v-else-if="userData.disable_at"> >
<strong><span>{{$L('离职时间')}}: </span>{{$A.newDateString(userData.disable_at, 'YYYY-MM-DD HH:mm')}}</strong> </div>
</li> </div>
</template> </div>
</ul>
<div class="user-detail-actions">
<Button icon="md-chatbubbles" :disabled="!!userData.delete_at" @click="onOpenDialog">{{ $L('开始聊天') }}</Button>
<Button icon="md-people" :disabled="!!userData.delete_at" @click="onOpenCreateGroup">{{ $L('创建群组') }}</Button>
</div> </div>
</div> </div>
<!-- 共同群组 -->
<Modal v-model="commonDialogShow" :title="$L('共同群组') + ' (' + $L('(*)个', commonDialog.total) + ')'" :footer-hide="true" width="500">
<div class="common-dialog-content">
<div v-if="commonDialogLoading > 0 && commonDialog.list.length === 0" class="loading-wrapper">
<Loading/>
</div>
<div v-else-if="commonDialogList.length === 0" class="empty-wrapper">
<div class="empty-content">
<Icon type="ios-people-outline" size="48"/>
<p>{{$L('暂无共同群组')}}</p>
</div>
</div>
<div v-else class="dialog-list">
<div
v-for="dialog in commonDialogList"
:key="dialog.id"
class="dialog-item"
@click="onOpenCommonDialogChat(dialog)">
<div class="dialog-avatar">
<EAvatar v-if="dialog.avatar" :src="dialog.avatar" :size="42"></EAvatar>
<i v-else-if="dialog.group_type=='department'" class="taskfont icon-avatar department">&#xe75c;</i>
<i v-else-if="dialog.group_type=='project'" class="taskfont icon-avatar project">&#xe6f9;</i>
<i v-else-if="dialog.group_type=='task'" class="taskfont icon-avatar task">&#xe6f4;</i>
<i v-else-if="dialog.group_type=='okr'" class="taskfont icon-avatar task">&#xe6f4;</i>
<Icon v-else class="icon-avatar" type="ios-people" />
</div>
<div class="dialog-info">
<div class="dialog-name" v-html="transformEmojiToHtml(dialog.name)"></div>
<div class="dialog-meta">
<span class="member-count">{{$L('(*)人', dialog.people || 0)}}</span>
<span v-if="dialog.last_at" class="last-time">{{$A.timeFormat(dialog.last_at)}}</span>
</div>
</div>
<Icon class="enter-icon" type="ios-arrow-forward" />
</div>
<div v-if="commonDialog.has_more" class="load-more-wrapper">
<Button type="primary" @click="loadCommonDialogList(true)" :loading="commonDialogLoading > 0">{{$L('加载更多')}}</Button>
</div>
</div>
</div>
</Modal>
<UserTagsModal <UserTagsModal
v-if="userData.userid" v-if="userData.userid"
v-model="tagModalVisible" v-model="tagModalVisible"
:userid="userData.userid" :userid="userData.userid"
@updated="onTagsUpdated"/> @updated="onTagsUpdated"
/>
<CommonDialogModal
v-model="commonDialogShow"
:target-user-id="userData.userid"
:total-count="commonDialog.total || 0"
@open-chat="onOpenCommonDialogChat"
/>
</ModalAlive> </ModalAlive>
</template> </template>
<script> <script>
import emitter from "../../../store/events"; import emitter from "../../../store/events";
import { mapState } from "vuex";
import transformEmojiToHtml from "../../../utils/emoji"; import transformEmojiToHtml from "../../../utils/emoji";
import {mapState} from "vuex";
import UserTagsModal from "./UserTagsModal.vue"; import UserTagsModal from "./UserTagsModal.vue";
import CommonDialogModal from "./CommonDialogModal.vue";
export default { export default {
name: 'UserDetail', name: "UserDetail",
components: {UserTagsModal}, components: { UserTagsModal, CommonDialogModal },
data() { data() {
return { return {
userData: { userData: {
userid: 0 userid: 0,
}, },
showModal: false, showModal: false,
tagModalVisible: false, tagModalVisible: false,
commonDialog: { commonDialog: {
userid: null, userid: null,
total: null, total: null,
@ -157,105 +170,111 @@ export default {
}, },
commonDialogShow: false, commonDialogShow: false,
commonDialogLoading: 0, commonDialogLoading: 0,
} };
}, },
mounted() { mounted() {
emitter.on('openUser', this.onShow); emitter.on("openUser", this.onShow);
}, },
beforeDestroy() { beforeDestroy() {
emitter.off('openUser', this.onShow); emitter.off("openUser", this.onShow);
}, },
watch: { watch: {
...mapState(['cacheUserBasic']), ...mapState(["cacheUserBasic"]),
commonDialogShow() { commonDialogShow() {
if (!this.commonDialogShow || this.commonDialog.list.length > 0) { if (!this.commonDialogShow || this.commonDialog.list.length > 0) {
return; return;
} }
this.loadCommonDialogList(false); this.loadCommonDialogList(false);
} },
}, },
computed: { computed: {
isFullscreen({windowWidth}) { isFullscreen({ windowWidth }) {
return windowWidth < 576 return windowWidth < 576;
},
displayTags() {
return Array.isArray(this.userData.personal_tags)
? this.userData.personal_tags
: [];
},
personalTagTotal() {
if (typeof this.userData.personal_tags_total === "number") {
return this.userData.personal_tags_total;
}
return this.displayTags.length;
}, },
commonDialogList() { commonDialogList() {
return this.commonDialog.list || []; return this.commonDialog.list || [];
}, },
displayTags() {
return Array.isArray(this.userData.personal_tags) ? this.userData.personal_tags : [];
},
personalTagTotal() {
if (typeof this.userData.personal_tags_total === 'number') {
return this.userData.personal_tags_total;
}
return this.displayTags.length;
}
}, },
methods: { methods: {
transformEmojiToHtml, transformEmojiToHtml,
onShow(userid) { onShow(userid) {
if (!/^\d+$/.test(userid)) { if (!/^\d+$/.test(userid)) {
return return;
} }
this.$store.dispatch("showSpinner", 600) this.$store.dispatch("showSpinner", 600);
this.$store.dispatch('getUserData', userid).then(user => { this.$store
this.userData = user; .dispatch("getUserData", userid)
this.ensureTagDefaults(); .then((user) => {
this.showModal = true; this.userData = user;
this.loadCommonDialogCount() this.ensureTagDefaults();
}).finally(_ => { this.showModal = true;
this.$store.dispatch("hiddenSpinner") this.loadCommonDialogCount();
}); })
.finally((_) => {
this.$store.dispatch("hiddenSpinner");
});
}, },
onHide() { onHide() {
this.commonDialogShow = false;
this.showModal = false; this.showModal = false;
this.tagModalVisible = false; this.tagModalVisible = false;
this.commonDialogShow = false;
}, },
onOpenAvatar() { onOpenAvatar() {
this.$store.dispatch("previewImage", this.userData.userimg) this.$store.dispatch("previewImage", this.userData.userimg);
}, },
onOpenDialog() { onOpenDialog() {
this.$store.dispatch("openDialogUserid", this.userData.userid).then(_ => { this.$store
this.onHide() .dispatch("openDialogUserid", this.userData.userid)
}).catch(({msg}) => { .then((_) => {
$A.modalError(msg) this.onHide();
}); })
.catch(({ msg }) => {
$A.modalError(msg);
});
}, },
onOpenCreateGroup() { onCreateGroup() {
const userids = []; const userids = [this.$store.state.userId];
if (this.userId) { if (this.userData.userid && this.$store.state.userId != this.userData.userid) {
userids.push(this.userId);
}
if (this.userData.userid && this.userData.userid !== this.userId) {
userids.push(this.userData.userid);
}
if (userids.length === 0 && this.userData.userid) {
userids.push(this.userData.userid); userids.push(this.userData.userid);
} }
emitter.emit('createGroup', userids); emitter.emit('createGroup', userids);
this.onHide();
}, },
ensureTagDefaults() { ensureTagDefaults() {
if (!Array.isArray(this.userData.personal_tags)) { if (!Array.isArray(this.userData.personal_tags)) {
this.$set(this.userData, 'personal_tags', []); this.$set(this.userData, "personal_tags", []);
} }
if (typeof this.userData.personal_tags_total !== 'number') { if (typeof this.userData.personal_tags_total !== "number") {
this.$set(this.userData, 'personal_tags_total', this.userData.personal_tags.length); this.$set(
this.userData,
"personal_tags_total",
this.userData.personal_tags.length
);
} }
}, },
@ -266,9 +285,19 @@ export default {
this.tagModalVisible = true; this.tagModalVisible = true;
}, },
onTagsUpdated({top, total}) { onTagsUpdated({ top, total }) {
this.$set(this.userData, 'personal_tags', Array.isArray(top) ? top : []); this.$set(
this.$set(this.userData, 'personal_tags_total', typeof total === 'number' ? total : this.userData.personal_tags.length); this.userData,
"personal_tags",
Array.isArray(top) ? top : []
);
this.$set(
this.userData,
"personal_tags_total",
typeof total === "number"
? total
: this.userData.personal_tags.length
);
}, },
loadCommonDialogCount() { loadCommonDialogCount() {
@ -299,123 +328,90 @@ export default {
const cacheMap = this.$store.state.dialogCommonCountCache || {}; const cacheMap = this.$store.state.dialogCommonCountCache || {};
const cached = cacheMap[String(target_userid)]; const cached = cacheMap[String(target_userid)];
if (cached && typeof cached.total !== 'undefined') { if (cached && typeof cached.total !== "undefined") {
this.commonDialog = { this.commonDialog = {
...this.commonDialog, ...this.commonDialog,
total: cached.total, total: cached.total,
}; };
} }
this.$store.dispatch('call', { this.$store
url: 'dialog/common/list', .dispatch("call", {
data: { url: "dialog/common/list",
target_userid, data: {
only_count: 'yes' target_userid,
} only_count: "yes",
}).then(({data}) => { },
if (target_userid !== this.userData.userid) { })
return .then(({ data }) => {
} if (target_userid !== this.userData.userid) {
const parsedTotal = Number(data.total); return;
const total = Number.isNaN(parsedTotal) ? 0 : parsedTotal; }
this.commonDialog = { const parsedTotal = Number(data.total);
...this.commonDialog, const total = Number.isNaN(parsedTotal) ? 0 : parsedTotal;
userid: target_userid, this.commonDialog = {
total, ...this.commonDialog,
list: [], userid: target_userid,
page: 1, total,
has_more: false, list: [],
}; page: 1,
this.$store.commit('common/dialog/count/save', { has_more: false,
userid: target_userid, };
total, this.$store.commit("common/dialog/count/save", {
userid: target_userid,
total,
});
}); });
});
}, },
loadCommonDialogList(loadMore = false) { loadCommonDialogList(loadMore = false) {
this.commonDialogLoading++; this.commonDialogLoading++;
const target_userid = this.userData.userid; const target_userid = this.userData.userid;
this.$store.dispatch('call', { this.$store
url: 'dialog/common/list', .dispatch("call", {
data: { url: "dialog/common/list",
target_userid, data: {
page: loadMore ? this.commonDialog.page + 1 : 1 target_userid,
} page: loadMore ? this.commonDialog.page + 1 : 1,
}).then(({data}) => { },
if (target_userid !== this.userData.userid) { })
return; .then(({ data }) => {
} if (target_userid !== this.userData.userid) {
this.commonDialog = { return;
...this.commonDialog, }
list: loadMore ? [...this.commonDialog.list, ...data.data] : data.data, this.commonDialog = {
total: data.total, ...this.commonDialog,
page: data.current_page, list: loadMore
has_more: !!data.next_page_url ? [...this.commonDialog.list, ...data.data]
} : data.data,
}).catch(({msg}) => { total: data.total,
$A.modalError(msg || this.$L('加载失败')); page: data.current_page,
}).finally(() => { has_more: !!data.next_page_url,
this.commonDialogLoading--; };
}); })
.catch(({ msg }) => {
$A.modalError(msg || this.$L("加载失败"));
})
.finally(() => {
this.commonDialogLoading--;
});
}, },
onOpenCommonDialogChat(dialog) { onOpenCommonDialogChat(dialog) {
this.$store.dispatch("openDialog", dialog.id).then(() => { this.$store
this.onHide(); .dispatch("openDialog", dialog.id)
}).catch(({msg}) => { .then(() => {
$A.modalError(msg); this.onHide();
}); })
.catch(({ msg }) => {
$A.modalError(msg);
});
}, },
} },
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.user-tags-line { // The styles will be moved to the SCSS file as requested.
display: flex; // This scoped style block can be removed if not needed for specific overrides.
align-items: flex-start;
gap: 8px;
span:first-child {
flex: 0 0 auto;
}
.tags-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 6px;
cursor: pointer;
}
.tags-list {
display: flex;
flex-wrap: wrap;
gap: 6px;
.tag-pill {
cursor: pointer;
}
}
.tags-empty {
color: #909399;
}
.tags-extra {
display: flex;
align-items: center;
gap: 8px;
.tags-total {
color: #909399;
font-size: 12px;
}
.manage-button {
padding: 0;
}
}
}
</style> </style>

View File

@ -43,7 +43,7 @@
:class="{'is-editing': editId === tag.id}"> :class="{'is-editing': editId === tag.id}">
<div class="tag-item-main"> <div class="tag-item-main">
<div class="tag-name" v-if="editId !== tag.id"> <div class="tag-name" v-if="editId !== tag.id">
<Tag :color="tag.recognized ? 'primary' : 'default'" class="tag-pill">{{tag.name}}</Tag> <Tag :color="tag.recognized ? '#84C56A' : 'default'" class="tag-pill">{{tag.name}}</Tag>
</div> </div>
<div class="tag-name edit" v-else> <div class="tag-name edit" v-else>
<Input <Input

View File

@ -50,7 +50,7 @@
<Tag <Tag
v-for="tag in displayTags" v-for="tag in displayTags"
:key="tag.id" :key="tag.id"
:color="tag.recognized ? 'primary' : 'default'" :color="tag.recognized ? '#84C56A' : 'default'"
class="tag-pill">{{tag.name}}</Tag> class="tag-pill">{{tag.name}}</Tag>
</template> </template>
<span v-else class="tags-empty">{{$L('暂无个性标签')}}</span> <span v-else class="tags-empty">{{$L('暂无个性标签')}}</span>

View File

@ -1,89 +1,144 @@
.common-user-detail-modal { .common-user-detail-modal {
.ivu-modal { .ivu-modal-content {
max-width: 90%; border-radius: 16px !important;
margin-top: calc(var(--status-bar-height) + 46px) !important;
&.ivu-modal-fullscreen { }
max-width: none; .ivu-modal-body {
padding: 0 !important;
.ivu-modal-content { }
margin-top: calc(var(--status-bar-height) + 46px); .user-detail-body {
margin-bottom: 0; .profile-header {
border-top-left-radius: 18px !important; position: relative;
border-top-right-radius: 18px !important; height: 160px;
.cover-photo {
.ivu-modal-body { background: $primary-color;
.user-detail-body { height: 120px;
padding-bottom: var(--navigation-bar-height); border-top-left-radius: 16px;
} border-top-right-radius: 16px;
}
.profile-avatar {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
border: 4px solid #fff;
border-radius: 50%;
.user-avatar {
display: block;
} }
} }
} }
.profile-content {
padding: 16px 24px 24px;
text-align: center;
.user-detail-actions { .user-info-top {
display: flex; .username {
gap: 10px; color: $primary-desc-color;
} font-size: 14px;
}
.ivu-modal-content { .fullname {
overflow: hidden; font-size: 20px;
font-weight: bold;
.ivu-modal-body { margin: 4px 0;
padding: 0 !important; }
display: flex; .meta {
flex-direction: column;
.user-detail-body {
display: flex; display: flex;
flex-direction: column; justify-content: center;
align-items: center; align-items: center;
gap: 16px; color: #808695;
padding: 84px 24px; font-size: 12px;
.common-dialog {
.avatar-wrapper {
cursor: pointer; cursor: pointer;
} }
.separator {
margin: 0 8px;
}
}
}
> ul { .profile-actions {
width: 80%; margin: 16px 0;
display: flex;
justify-content: center;
gap: 8px;
}
> li { .profile-bio {
list-style: none; color: $primary-title-color;
display: flex; line-height: 1.5;
justify-content: center; margin: 16px 0;
margin: 12px auto; padding: 0 50px;
font-size: 12px;
}
&.user-name { .profile-information {
align-items: center; text-align: left;
} background-color: #f8f8f9;
padding: 16px;
border-radius: 8px;
> em { h2 {
font-style: normal; font-size: 16px;
&.disabled, margin-bottom: 12px;
&.deleted { }
display: inline-block;
margin-left: 2px;
white-space: nowrap;
font-size: 12px;
height: 20px;
line-height: 20px;
padding: 0 6px;
border-radius: 3px;
transform: scale(0.9);
transform-origin: right center;
color: #ffffff;
background-color: #ED4014;
}
}
> span { ul {
flex-shrink: 0; list-style: none;
opacity: 0.8; padding: 0;
padding-right: 4px; margin: 0;
}
li {
display: flex;
align-items: flex-start; // 避免多行内容导致垂直居中不齐
padding: 8px 0;
font-size: 14px;
.ivu-icon {
font-size: 20px;
margin-right: 12px;
color: $primary-desc-color;
}
.label {
color: #808695;
flex: 0 0 64px;
flex-shrink: 0;
line-height: 22px;
margin-right: 8px;
}
.value {
color: $primary-title-color;
font-weight: 500;
flex: 1 1 auto;
min-width: 0;
margin-left: 0;
text-align: right;
white-space: normal;
word-break: break-word;
overflow-wrap: break-word;
} }
} }
} }
} }
.profile-tags {
margin-top: 12px;
padding-top: 12px;
border-top: 1px solid #80869550;
cursor: pointer;
.tags-list {
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
position: relative;
}
.ivu-tag {
margin: 0;
}
}
} }
} }
} }