refactor: 用户信息重构(Description)
This commit is contained in:
parent
123f234971
commit
542407dcd6
1
apps/web-antd/src/api/system/user/model.d.ts
vendored
1
apps/web-antd/src/api/system/user/model.d.ts
vendored
@ -66,6 +66,7 @@ export interface User {
|
|||||||
roleIds?: string[];
|
roleIds?: string[];
|
||||||
postIds?: number[];
|
postIds?: number[];
|
||||||
roleId: string;
|
roleId: string;
|
||||||
|
deptName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Post {
|
export interface Post {
|
||||||
|
@ -1,129 +0,0 @@
|
|||||||
import type { DescItem } from '#/components/description';
|
|
||||||
|
|
||||||
import { DictEnum } from '@vben/constants';
|
|
||||||
|
|
||||||
import { Tag } from 'ant-design-vue';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import duration from 'dayjs/plugin/duration';
|
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
|
||||||
|
|
||||||
import { renderDict } from '#/utils/render';
|
|
||||||
|
|
||||||
dayjs.extend(duration);
|
|
||||||
dayjs.extend(relativeTime);
|
|
||||||
|
|
||||||
function renderTags(list: string[]) {
|
|
||||||
return (
|
|
||||||
<div class="flex flex-row flex-wrap gap-0.5">
|
|
||||||
{list.map((item) => (
|
|
||||||
<Tag key={item}>{item}</Tag>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const descSchema: DescItem[] = [
|
|
||||||
{
|
|
||||||
field: 'userId',
|
|
||||||
label: '用户ID',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'status',
|
|
||||||
label: '用户状态',
|
|
||||||
render(value) {
|
|
||||||
return renderDict(value, DictEnum.SYS_NORMAL_DISABLE);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'nickName',
|
|
||||||
label: '用户信息',
|
|
||||||
render(_, data) {
|
|
||||||
const { deptName = '暂无部门信息', nickName, userName } = data;
|
|
||||||
// 为了兼容新版本和旧版本
|
|
||||||
let currentDept = deptName;
|
|
||||||
if (data.dept && data.dept.deptName) {
|
|
||||||
currentDept = data.dept.deptName;
|
|
||||||
}
|
|
||||||
return `${userName} / ${nickName} / ${currentDept}`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'phonenumber',
|
|
||||||
label: '手机号',
|
|
||||||
render(value) {
|
|
||||||
return value || '未设置手机号码';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'email',
|
|
||||||
label: '邮箱',
|
|
||||||
render(value) {
|
|
||||||
return value || '未设置邮箱地址';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'postNames',
|
|
||||||
label: '岗位',
|
|
||||||
render(value) {
|
|
||||||
if (Array.isArray(value) && value.length === 0) {
|
|
||||||
return '暂无信息';
|
|
||||||
}
|
|
||||||
return renderTags(value);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'roleNames',
|
|
||||||
label: '权限',
|
|
||||||
render(value) {
|
|
||||||
if (Array.isArray(value) && value.length === 0) {
|
|
||||||
return '暂无信息';
|
|
||||||
}
|
|
||||||
return renderTags(value);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'createTime',
|
|
||||||
label: '创建时间',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'loginIp',
|
|
||||||
label: '上次登录IP',
|
|
||||||
render(value) {
|
|
||||||
return value || <span class="text-orange-500">从未登录过</span>;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'loginDate',
|
|
||||||
label: '上次登录时间',
|
|
||||||
render(value) {
|
|
||||||
if (!value) {
|
|
||||||
return <span class="text-orange-500">从未登录过</span>;
|
|
||||||
}
|
|
||||||
// 默认en显示
|
|
||||||
dayjs.locale('zh-cn');
|
|
||||||
// 计算相差秒数
|
|
||||||
const diffSeconds = dayjs().diff(dayjs(value), 'second');
|
|
||||||
/**
|
|
||||||
* 转为时间显示(x月 x天)
|
|
||||||
* https://dayjs.fenxianglu.cn/category/duration.html#%E4%BA%BA%E6%80%A7%E5%8C%96
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
const diffText = dayjs.duration(diffSeconds, 'seconds').humanize();
|
|
||||||
return (
|
|
||||||
<div class="flex gap-2">
|
|
||||||
{value}
|
|
||||||
<Tag bordered={false} color="cyan">
|
|
||||||
{diffText}前
|
|
||||||
</Tag>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'remark',
|
|
||||||
label: '备注',
|
|
||||||
render(value) {
|
|
||||||
return value || '无';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
@ -1,25 +1,34 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { User } from '#/api/system/user/model';
|
import type { User } from '#/api/system/user/model';
|
||||||
|
|
||||||
|
import { computed, shallowRef } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
import { DictEnum } from '@vben/constants';
|
||||||
|
|
||||||
|
import { Descriptions, DescriptionsItem, Tag } from 'ant-design-vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import duration from 'dayjs/plugin/duration';
|
||||||
|
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||||
|
|
||||||
import { findUserInfo } from '#/api/system/user';
|
import { findUserInfo } from '#/api/system/user';
|
||||||
import { Description, useDescription } from '#/components/description';
|
import { renderDict } from '#/utils/render';
|
||||||
|
|
||||||
import { descSchema } from './info';
|
dayjs.extend(duration);
|
||||||
|
dayjs.extend(relativeTime);
|
||||||
|
|
||||||
const [BasicModal, modalApi] = useVbenModal({
|
const [BasicModal, modalApi] = useVbenModal({
|
||||||
onOpenChange: handleOpenChange,
|
onOpenChange: handleOpenChange,
|
||||||
|
onClosed() {
|
||||||
|
currentUser.value = null;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const [registerDescription, { setDescProps }] = useDescription({
|
interface UserWithNames extends User {
|
||||||
column: 1,
|
postNames: string[];
|
||||||
labelStyle: {
|
roleNames: string[];
|
||||||
minWidth: '150px',
|
}
|
||||||
width: '150px',
|
const currentUser = shallowRef<null | UserWithNames>(null);
|
||||||
},
|
|
||||||
schema: descSchema,
|
|
||||||
});
|
|
||||||
|
|
||||||
async function handleOpenChange(open: boolean) {
|
async function handleOpenChange(open: boolean) {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
@ -41,22 +50,103 @@ async function handleOpenChange(open: boolean) {
|
|||||||
.filter((item) => roleIds.includes(item.roleId))
|
.filter((item) => roleIds.includes(item.roleId))
|
||||||
.map((item) => item.roleName);
|
.map((item) => item.roleName);
|
||||||
|
|
||||||
interface UserWithNames extends User {
|
|
||||||
postNames: string[];
|
|
||||||
roleNames: string[];
|
|
||||||
}
|
|
||||||
(user as UserWithNames).postNames = postNames;
|
(user as UserWithNames).postNames = postNames;
|
||||||
(user as UserWithNames).roleNames = roleNames;
|
(user as UserWithNames).roleNames = roleNames;
|
||||||
|
|
||||||
// 赋值
|
// 赋值
|
||||||
setDescProps({ data: user });
|
currentUser.value = user as UserWithNames;
|
||||||
|
|
||||||
modalApi.modalLoading(false);
|
modalApi.modalLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mixInfo = computed(() => {
|
||||||
|
if (!currentUser.value) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
const { deptName, nickName, userName } = currentUser.value;
|
||||||
|
return `${userName} / ${nickName} / ${deptName ?? '-'}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const diffLoginTime = computed(() => {
|
||||||
|
if (!currentUser.value) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
const { loginDate } = currentUser.value;
|
||||||
|
// 默认en显示
|
||||||
|
dayjs.locale('zh-cn');
|
||||||
|
// 计算相差秒数
|
||||||
|
const diffSeconds = dayjs().diff(dayjs(loginDate), 'second');
|
||||||
|
/**
|
||||||
|
* 转为时间显示(x月 x天)
|
||||||
|
* https://dayjs.fenxianglu.cn/category/duration.html#%E4%BA%BA%E6%80%A7%E5%8C%96
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const diffText = dayjs.duration(diffSeconds, 'seconds').humanize();
|
||||||
|
return diffText;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<BasicModal :footer="false" :fullscreen-button="false" title="用户信息">
|
<BasicModal :footer="false" :fullscreen-button="false" title="用户信息">
|
||||||
<Description @register="registerDescription" />
|
<Descriptions v-if="currentUser" size="small" :column="1" bordered>
|
||||||
|
<DescriptionsItem label="userId">
|
||||||
|
{{ currentUser.userId }}
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="用户状态">
|
||||||
|
<component
|
||||||
|
:is="renderDict(currentUser.status, DictEnum.SYS_NORMAL_DISABLE)"
|
||||||
|
/>
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="用户信息">
|
||||||
|
{{ mixInfo }}
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="手机号">
|
||||||
|
{{ currentUser.phonenumber || '-' }}
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="邮箱">
|
||||||
|
{{ currentUser.email || '-' }}
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="岗位">
|
||||||
|
<div
|
||||||
|
v-if="currentUser.postNames.length > 0"
|
||||||
|
class="flex flex-wrap gap-0.5"
|
||||||
|
>
|
||||||
|
<Tag v-for="item in currentUser.postNames" :key="item">
|
||||||
|
{{ item }}
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="权限">
|
||||||
|
<div
|
||||||
|
v-if="currentUser.roleNames.length > 0"
|
||||||
|
class="flex flex-wrap gap-0.5"
|
||||||
|
>
|
||||||
|
<Tag v-for="item in currentUser.roleNames" :key="item">
|
||||||
|
{{ item }}
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="创建时间">
|
||||||
|
{{ currentUser.createTime }}
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="上次登录IP">
|
||||||
|
{{ currentUser.loginIp ?? '-' }}
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="上次登录时间">
|
||||||
|
<span>{{ currentUser.loginDate ?? '-' }}</span>
|
||||||
|
<Tag
|
||||||
|
class="ml-2"
|
||||||
|
v-if="diffLoginTime"
|
||||||
|
:bordered="false"
|
||||||
|
color="processing"
|
||||||
|
>
|
||||||
|
{{ diffLoginTime }}前
|
||||||
|
</Tag>
|
||||||
|
</DescriptionsItem>
|
||||||
|
<DescriptionsItem label="备注">
|
||||||
|
{{ currentUser.remark ?? '-' }}
|
||||||
|
</DescriptionsItem>
|
||||||
|
</Descriptions>
|
||||||
</BasicModal>
|
</BasicModal>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user