refactor(views): 优化组件代码结构,使用tsx和计算属性重构描述列表
重构多个组件中的描述列表,使用tsx语法和计算属性items来简化模板代码 统一调整样式类名顺序,提升代码可读性和维护性
This commit is contained in:
parent
b427a77fc1
commit
5c30bcdefa
@ -1,17 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="tsx">
|
||||||
|
import type { DescriptionsProps } from 'antdv-next';
|
||||||
|
|
||||||
import type { UserProfile } from '#/api/system/profile/model';
|
import type { UserProfile } from '#/api/system/profile/model';
|
||||||
|
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { preferences, usePreferences } from '@vben/preferences';
|
import { preferences, usePreferences } from '@vben/preferences';
|
||||||
|
|
||||||
import {
|
import { Card, Descriptions, Tag, Tooltip } from 'antdv-next';
|
||||||
Card,
|
|
||||||
Descriptions,
|
|
||||||
DescriptionsItem,
|
|
||||||
Tag,
|
|
||||||
Tooltip,
|
|
||||||
} from 'antdv-next';
|
|
||||||
|
|
||||||
import { userUpdateAvatar } from '#/api/system/profile';
|
import { userUpdateAvatar } from '#/api/system/profile';
|
||||||
import { CropperAvatar } from '#/components/cropper';
|
import { CropperAvatar } from '#/components/cropper';
|
||||||
@ -32,6 +28,42 @@ const poetrySrc = computed(() => {
|
|||||||
const color = isDark.value ? 'white' : 'gray';
|
const color = isDark.value ? 'white' : 'gray';
|
||||||
return `https://v2.jinrishici.com/one.svg?font-size=12&color=${color}`;
|
return `https://v2.jinrishici.com/one.svg?font-size=12&color=${color}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const items = computed<DescriptionsProps['items']>(() => {
|
||||||
|
if (!props.profile) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const { profile } = props;
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
content: profile.user.userName,
|
||||||
|
label: '账号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: profile.user.phonenumber || '未绑定手机号',
|
||||||
|
label: '手机号码',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: profile.user.email || '未绑定邮箱',
|
||||||
|
label: '邮箱',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<Tag color="processing">{profile.user.deptName ?? '未分配部门'}</Tag>
|
||||||
|
{profile.postGroup && (
|
||||||
|
<Tag color="processing">{profile.postGroup}</Tag>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
label: '部门',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: profile.user.loginDate,
|
||||||
|
label: '上次登录',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -48,7 +80,7 @@ const poetrySrc = computed(() => {
|
|||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<div class="flex flex-col items-center gap-[8px]">
|
<div class="flex flex-col items-center gap-[8px]">
|
||||||
<span class="text-foreground text-xl font-bold">
|
<span class="text-xl font-bold text-foreground">
|
||||||
{{ profile.user.nickName ?? '未知' }}
|
{{ profile.user.nickName ?? '未知' }}
|
||||||
</span>
|
</span>
|
||||||
<!-- https://www.jinrishici.com/doc/#image -->
|
<!-- https://www.jinrishici.com/doc/#image -->
|
||||||
@ -56,28 +88,7 @@ const poetrySrc = computed(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="px-[24px]">
|
<div class="px-[24px]">
|
||||||
<Descriptions :column="1">
|
<Descriptions :column="1" :items="items" />
|
||||||
<DescriptionsItem label="账号">
|
|
||||||
{{ profile.user.userName }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="手机号码">
|
|
||||||
{{ profile.user.phonenumber || '未绑定手机号' }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="邮箱">
|
|
||||||
{{ profile.user.email || '未绑定邮箱' }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="部门">
|
|
||||||
<Tag color="processing">
|
|
||||||
{{ profile.user.deptName ?? '未分配部门' }}
|
|
||||||
</Tag>
|
|
||||||
<Tag v-if="profile.postGroup" color="processing">
|
|
||||||
{{ profile.postGroup }}
|
|
||||||
</Tag>
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="上次登录">
|
|
||||||
{{ profile.user.loginDate }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
</Descriptions>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@ -31,7 +31,7 @@ const settingList = [
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Tabs class="bg-background rounded-[var(--radius)] px-[16px] lg:flex-1">
|
<Tabs class="rounded-[var(--radius)] bg-background px-[16px] lg:flex-1">
|
||||||
<TabPane v-for="item in settingList" :key="item.key" :tab="item.name">
|
<TabPane v-for="item in settingList" :key="item.key" :tab="item.name">
|
||||||
<component :is="item.component" v-bind="$attrs" />
|
<component :is="item.component" v-bind="$attrs" />
|
||||||
</TabPane>
|
</TabPane>
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import {
|
|||||||
UsergroupAddOutlined,
|
UsergroupAddOutlined,
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
import { Avatar, TimelineItem } from 'antdv-next';
|
import { Avatar } from 'antdv-next';
|
||||||
|
|
||||||
import { ossInfo } from '#/api/system/oss';
|
import { ossInfo } from '#/api/system/oss';
|
||||||
import { renderDict } from '#/utils/render';
|
import { renderDict } from '#/utils/render';
|
||||||
@ -51,8 +51,8 @@ const isMultiplePerson = computed(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<TimelineItem>
|
<div>
|
||||||
<template #dot>
|
<template>
|
||||||
<div class="relative rounded-full border">
|
<div class="relative rounded-full border">
|
||||||
<Avatar
|
<Avatar
|
||||||
class="bg-primary-400"
|
class="bg-primary-400"
|
||||||
@ -63,7 +63,7 @@ const isMultiplePerson = computed(
|
|||||||
<VbenAvatar
|
<VbenAvatar
|
||||||
v-else
|
v-else
|
||||||
:alt="item?.approveName ?? 'unknown'"
|
:alt="item?.approveName ?? 'unknown'"
|
||||||
class="bg-primary size-[36px] rounded-full text-white"
|
class="size-[36px] rounded-full bg-primary text-white"
|
||||||
src=""
|
src=""
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
@ -86,12 +86,12 @@ const isMultiplePerson = computed(
|
|||||||
<div :class="cn('mt-2 flex flex-wrap gap-2')" v-if="isMultiplePerson">
|
<div :class="cn('mt-2 flex flex-wrap gap-2')" v-if="isMultiplePerson">
|
||||||
<!-- 如果昵称中带, 这里的处理是不准确的 -->
|
<!-- 如果昵称中带, 这里的处理是不准确的 -->
|
||||||
<div
|
<div
|
||||||
:class="cn('bg-foreground/5 flex items-center rounded-full', 'p-1')"
|
:class="cn('flex items-center rounded-full bg-foreground/5', 'p-1')"
|
||||||
v-for="(name, index) in item.approveName.split(',')"
|
v-for="(name, index) in item.approveName.split(',')"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
class="bg-primary-400 flex items-center justify-center"
|
class="flex items-center justify-center bg-primary-400"
|
||||||
:size="24"
|
:size="24"
|
||||||
:icon="h(UserOutlined)"
|
:icon="h(UserOutlined)"
|
||||||
/>
|
/>
|
||||||
@ -107,7 +107,7 @@ const isMultiplePerson = computed(
|
|||||||
:class="cn('flex gap-2')"
|
:class="cn('flex gap-2')"
|
||||||
>
|
>
|
||||||
<MessageOutlined />
|
<MessageOutlined />
|
||||||
<div class="text-foreground/75 break-all">{{ item.message }}</div>
|
<div class="break-all text-foreground/75">{{ item.message }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="attachmentInfo.length > 0" class="flex flex-wrap gap-2">
|
<div v-if="attachmentInfo.length > 0" class="flex flex-wrap gap-2">
|
||||||
<!-- 这里下载的文件名不是原始文件名 -->
|
<!-- 这里下载的文件名不是原始文件名 -->
|
||||||
@ -125,5 +125,5 @@ const isMultiplePerson = computed(
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TimelineItem>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="tsx">
|
||||||
|
import type { TimelineProps } from 'antdv-next';
|
||||||
|
|
||||||
import type { Flow } from '#/api/workflow/instance/model';
|
import type { Flow } from '#/api/workflow/instance/model';
|
||||||
|
|
||||||
|
import { computed, h } from 'vue';
|
||||||
|
|
||||||
import { Empty, Timeline } from 'antdv-next';
|
import { Empty, Timeline } from 'antdv-next';
|
||||||
|
|
||||||
import ApprovalTimelineItem from './approval-timeline-item.vue';
|
import ApprovalTimelineItem from './approval-timeline-item.vue';
|
||||||
@ -9,12 +13,18 @@ interface Props {
|
|||||||
list: Flow[];
|
list: Flow[];
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const items = computed<TimelineProps['items']>(() => {
|
||||||
|
const { list } = props;
|
||||||
|
return list.map((item) => ({
|
||||||
|
key: item.id,
|
||||||
|
content: h(ApprovalTimelineItem, { item }),
|
||||||
|
}));
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Timeline v-if="list.length > 0">
|
<Timeline v-if="list.length > 0" :items="items" />
|
||||||
<ApprovalTimelineItem v-for="item in list" :key="item.id" :item="item" />
|
|
||||||
</Timeline>
|
|
||||||
<Empty v-else />
|
<Empty v-else />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="tsx">
|
||||||
|
import type { DescriptionsProps } from 'antdv-next';
|
||||||
|
|
||||||
import type { User } from '#/api/system/user/model';
|
import type { User } from '#/api/system/user/model';
|
||||||
import type { TaskInfo } from '#/api/workflow/task/model';
|
import type { TaskInfo } from '#/api/workflow/task/model';
|
||||||
|
|
||||||
@ -6,7 +8,7 @@ import { computed, ref } from 'vue';
|
|||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Descriptions, DescriptionsItem, Modal } from 'antdv-next';
|
import { Descriptions, Modal } from 'antdv-next';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getTaskByTaskId,
|
getTaskByTaskId,
|
||||||
@ -127,30 +129,50 @@ function handleReductionSignature(userList: User[]) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const items = computed<DescriptionsProps['items']>(() => {
|
||||||
|
if (!taskInfo.value) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const data = taskInfo.value;
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
content: data.nodeName,
|
||||||
|
label: '任务名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: data.nodeCode,
|
||||||
|
label: '节点编码',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: data.createTime,
|
||||||
|
label: '开始时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: data.instanceId,
|
||||||
|
label: '流程实例ID',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: data.version,
|
||||||
|
label: '版本号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: data.businessId,
|
||||||
|
label: '业务ID',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<BasicModal>
|
<BasicModal>
|
||||||
<Descriptions v-if="taskInfo" :column="2" bordered size="small">
|
<Descriptions
|
||||||
<DescriptionsItem label="任务名称">
|
v-if="taskInfo"
|
||||||
{{ taskInfo.nodeName }}
|
:column="2"
|
||||||
</DescriptionsItem>
|
:items="items"
|
||||||
<DescriptionsItem label="节点编码">
|
bordered
|
||||||
{{ taskInfo.nodeCode }}
|
size="small"
|
||||||
</DescriptionsItem>
|
/>
|
||||||
<DescriptionsItem label="开始时间">
|
|
||||||
{{ taskInfo.createTime }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="流程实例ID">
|
|
||||||
{{ taskInfo.instanceId }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="版本号">
|
|
||||||
{{ taskInfo.version }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="业务ID">
|
|
||||||
{{ taskInfo.businessId }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
</Descriptions>
|
|
||||||
<TransferModal mode="single" @finish="handleTransfer" />
|
<TransferModal mode="single" @finish="handleTransfer" />
|
||||||
<AddSignatureModal mode="multiple" @finish="handleAddSignature" />
|
<AddSignatureModal mode="multiple" @finish="handleAddSignature" />
|
||||||
<ReductionSignatureModal
|
<ReductionSignatureModal
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="tsx">
|
||||||
|
import type { DescriptionsProps } from 'antdv-next';
|
||||||
|
|
||||||
import type { LeaveVO } from '../leave/api/model';
|
import type { LeaveVO } from '../leave/api/model';
|
||||||
|
|
||||||
import { computed, onMounted, shallowRef } from 'vue';
|
import { computed, onMounted, shallowRef } from 'vue';
|
||||||
|
|
||||||
import { Descriptions, DescriptionsItem, Skeleton } from 'antdv-next';
|
import { Descriptions, Skeleton } from 'antdv-next';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
import { leaveInfo } from './api';
|
import { leaveInfo } from './api';
|
||||||
@ -32,25 +34,37 @@ const leaveType = computed(() => {
|
|||||||
function formatDate(date: string) {
|
function formatDate(date: string) {
|
||||||
return dayjs(date).format('YYYY-MM-DD');
|
return dayjs(date).format('YYYY-MM-DD');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const items = computed<DescriptionsProps['items']>(() => {
|
||||||
|
if (!data.value) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const info = data.value;
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
content: leaveType.value,
|
||||||
|
label: '请假类型',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: `${formatDate(info.startDate)} - ${formatDate(info.endDate)}`,
|
||||||
|
label: '请假时间',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: `${info.leaveDays}天`,
|
||||||
|
label: '请假时长',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
content: info.remark || '无',
|
||||||
|
label: '请假原因',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="rounded-[6px] border p-2">
|
<div class="rounded-[6px] border p-2">
|
||||||
<Descriptions v-if="data" :column="1" size="middle">
|
<Descriptions v-if="data" :column="1" :items="items" size="middle" />
|
||||||
<DescriptionsItem label="请假类型">
|
|
||||||
{{ leaveType }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="请假时间">
|
|
||||||
{{ formatDate(data.startDate) }} - {{ formatDate(data.endDate) }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="请假时长">
|
|
||||||
{{ data.leaveDays }}天
|
|
||||||
</DescriptionsItem>
|
|
||||||
<DescriptionsItem label="请假原因">
|
|
||||||
{{ data.remark || '无' }}
|
|
||||||
</DescriptionsItem>
|
|
||||||
</Descriptions>
|
|
||||||
|
|
||||||
<Skeleton active v-else />
|
<Skeleton v-else active />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user