财务门户设计

This commit is contained in:
2026-02-19 21:10:43 +08:00
parent fd71143cd2
commit a0244c9afc
15 changed files with 1777 additions and 1335 deletions

View File

@@ -37,57 +37,54 @@
</span>
<span class="trigger-time">{{ item.triggerTime }}</span>
<span class="alert-type">{{ item.alertType }}</span>
<span
class="alert-title"
@mouseenter="showFullContent(item.alertTitle || '', $event)"
@mouseleave="hideFullContent"
<Tooltip
:title="item.alertTitle || '--'"
placement="top"
trigger="hover"
:mouseEnterDelay="0.1"
class="alert-title-tooltip"
>
<a-button type="link" size="small" @click="openModal(true, item)">
<span class="title-text">{{ item.alertTitle || '--' }}</span>
</a-button>
</span>
<span class="alert-title"
@mouseenter="showFullContent(item.alertContent || '', $event)"
@mouseleave="hideFullContent"
>
{{ item.alertContent || '--' }}
</span>
<span class="alert-title" ref="titleRefs">
<a-button type="link" size="small" @click="openModal(true, item)">
<span class="title-text">{{ item.alertTitle || '--' }}</span>
</a-button>
</span>
</Tooltip>
<Tooltip
:title="item.alertContent || '--'"
placement="top"
trigger="hover"
:mouseEnterDelay="0.1"
class="alert-content-tooltip"
>
<span class="alert-title alert-content">
{{ item.alertContent || '--' }}
</span>
</Tooltip>
</div>
</div>
</div>
</Card>
<!-- 新增预警标题悬浮提示框 -->
<div
v-if="showContentTooltip"
class="custom-tooltip"
:style="{
top: `${tooltipTop}px`,
left: `${tooltipLeft}px`,
zIndex: 9999
}"
>
<pre class="tooltip-content">{{ fullContent }}</pre>
<div class="tooltip-arrow"></div>
</div>
<Modal @register="register" @modalClose="fetchAppList(currentStatus)" />
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { Card, Button } from 'ant-design-vue';
import { ref, onMounted, nextTick } from 'vue';
import { useRouter } from 'vue-router';
import { useModal } from '@jeesite/core/components/Modal';
import { Card, Tooltip, Button } from 'ant-design-vue';
import { bizWarningAlertListAll, BizWarningAlert } from '@jeesite/biz/api/biz/warningAlert';
import Modal from './info/WarningInfo.vue';
const [register, { openModal }] = useModal();
const alertList = ref<BizWarningAlert[]>([]);
const loading = ref<boolean>(false); // 新增加载状态
const loading = ref<boolean>(false);
const router = useRouter();
const titleRefs = ref<HTMLElement[]>([]);
// 状态选项配置
const statusOptions = ref([
{ value: '0', label: '未处理' },
{ value: '1', label: '处理中' },
@@ -95,65 +92,33 @@ const statusOptions = ref([
{ value: '3', label: '已忽略' },
{ value: '4', label: '已关闭' },
]);
const currentStatus = ref<string>('0'); // 默认选中未处理
const currentStatus = ref<string>('0');
// 新增:预警标题悬浮提示相关
const showContentTooltip = ref(false);
const fullContent = ref('');
const tooltipTop = ref(0);
const tooltipLeft = ref(0);
// 新增:显示完整标题
const showFullContent = (content: string, event: MouseEvent) => {
// 内容为空或无截断时不显示提示
if (!content) return;
const target = event.target as HTMLElement;
// 判断内容是否被截断(容器宽度 < 内容宽度)
if (target.scrollWidth <= target.clientWidth) return;
// 直接赋值原始内容,不做任何格式化处理
fullContent.value = content;
// 定位提示框(鼠标位置偏移,避免遮挡鼠标)
tooltipTop.value = event.clientY + 10;
tooltipLeft.value = event.clientX + 10;
showContentTooltip.value = true;
};
// 新增:隐藏提示框
const hideFullContent = () => {
showContentTooltip.value = false;
fullContent.value = '';
};
// 处理状态切换(新增方法)
const handleStatusChange = (status: string) => {
if (currentStatus.value === status) return; // 避免重复请求
if (currentStatus.value === status) return;
currentStatus.value = status;
fetchAppList(status); // 切换状态时传递参数
fetchAppList(status);
};
// 获取预警列表数据
const fetchAppList = async (status: string) => {
try {
loading.value = true; // 开始加载
const params = { alertStatus: status }; // 传递状态参数
loading.value = true;
const params = { alertStatus: status };
const result = await bizWarningAlertListAll(params);
alertList.value = result || [];
await nextTick();
} catch (error) {
console.error('获取预警列表失败:', error);
alertList.value = [];
} finally {
loading.value = false; // 结束加载
loading.value = false;
}
};
// 跳转到更多页面(优化:携带当前状态参数)
const goToMorePage = () => {
router.push('/biz/warningAlert/list');
};
// 转换预警级别文本
const getLevelText = (level: number | undefined) => {
if (!level) return '未知';
const levelMap = {
@@ -165,30 +130,26 @@ const getLevelText = (level: number | undefined) => {
return levelMap[level as keyof typeof levelMap] || '未知';
};
// 初始化加载默认状态数据
onMounted(() => {
fetchAppList(currentStatus.value); // 初始化时传递默认状态0
fetchAppList(currentStatus.value);
});
</script>
<style scoped>
/* extra插槽容器状态标签 + 更多按钮 横向排列 */
.status-filter-container {
display: flex;
align-items: center;
gap: 16px;
}
/* 状态筛选栏(非按钮样式) */
.status-filter {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 12px; /* 标签间距 */
gap: 12px;
font-size: 14px;
}
/* 状态项样式(纯文本标签) */
.status-item {
cursor: pointer;
color: #666;
@@ -198,13 +159,11 @@ onMounted(() => {
user-select: none;
}
/* 选中状态样式(下划线 + 高亮色) */
.status-item.active {
color: #1890ff;
font-weight: 500;
}
/* 选中状态下划线 */
.status-item.active::after {
content: '';
position: absolute;
@@ -216,56 +175,50 @@ onMounted(() => {
border-radius: 1px;
}
/* 悬浮效果 */
.status-item:not(.active):hover {
color: #40a9ff;
}
/* 列表外层容器:移除边框 + 滚动核心样式 + 极致紧凑 */
.alert-list-container {
width: 100%;
height: 32vh; /* 限制最大高度,超出滚动 */
overflow-y: auto; /* 垂直滚动 */
overflow-x: hidden; /* 隐藏横向滚动 */
padding: 0; /* 移除内边距 */
margin: 0; /* 移除外边距 */
height: 32vh;
overflow-y: auto;
overflow-x: hidden;
padding: 0;
margin: 0;
background: transparent;
}
/* 空数据/加载提示 */
.empty-tip {
padding: 20px 0; /* 缩减空状态内边距,更紧凑 */
padding: 20px 0;
text-align: center;
color: #999;
font-size: 14px;
}
/* 预警列表 */
.alert-list {
width: 100%;
}
/* 单个预警项flex布局 + 紧凑排列(级别→时间→类型→标题) */
.alert-item {
display: flex;
align-items: center;
padding: 6px 8px;
border-bottom: 1px solid #f0f0f0;
font-size: 14px;
gap: 10px; /* 统一控制元素间基础间距 */
gap: 10px;
width: 100%;
box-sizing: border-box;
}
/* 最后一项去掉底部边框 */
.alert-item:last-child {
border-bottom: none;
}
/* 鼠标悬浮高亮 */
.alert-item:hover {
background-color: #f8f9fa;
}
/* 预警级别标签(固定宽度,不压缩) */
.level-tag {
display: inline-block;
padding: 1px 6px;
@@ -274,51 +227,55 @@ onMounted(() => {
color: #fff;
min-width: 40px;
text-align: center;
flex-shrink: 0; /* 固定宽度,不被压缩 */
flex-shrink: 0;
}
/* 级别颜色 */
.level-1 { background-color: #f5222d; } /* 紧急 */
.level-2 { background-color: #fa8c16; } /* 高 */
.level-3 { background-color: #faad14; } /* 中 */
.level-4 { background-color: #1890ff; } /* 低 */
.level-undefined { background-color: #8c8c8c; } /* 未知 */
.level-1 { background-color: #f5222d; }
.level-2 { background-color: #fa8c16; }
.level-3 { background-color: #faad14; }
.level-4 { background-color: #1890ff; }
.level-undefined { background-color: #8c8c8c; }
/* 预警触发时间(固定宽度,不压缩) */
.trigger-time {
width: 120px;
color: #999;
text-align: left;
white-space: nowrap;
flex-shrink: 0; /* 固定宽度,不被压缩 */
flex-shrink: 0;
font-size: 13px;
}
/* 预警类型(固定宽度,不压缩) */
.alert-type {
width: 60px;
color: #666;
text-align: left;
white-space: nowrap;
flex-shrink: 0; /* 固定宽度,不被压缩 */
flex-shrink: 0;
font-size: 13px;
overflow: hidden;
text-overflow: ellipsis;
}
/* 预警标题(仅修改这部分样式) */
.alert-title {
width: 100px; /* 固定宽度可根据需求调整比如200px/400px */
flex-shrink: 0; /* 关键:禁止宽度被压缩,保证固定宽度生效 */
width: 100px;
flex-shrink: 0;
color: #666;
white-space: nowrap; /* 强制不换行 */
overflow: hidden; /* 隐藏超出宽度的内容 */
text-overflow: ellipsis; /* 超出显示省略号 */
margin-left: 4px; /* 保留与类型的微小间距 */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-left: 4px;
cursor: pointer;
display: inline-block;
box-sizing: border-box;
position: relative;
}
.alert-content {
width: 200px;
flex-grow: 1;
min-width: 150px;
}
/* 新增:标题文本样式 - 确保省略号生效 */
.title-text {
width: 100%;
white-space: nowrap;
@@ -326,71 +283,38 @@ onMounted(() => {
text-overflow: ellipsis;
display: inline-block;
padding: 0 4px;
box-sizing: border-box;
}
/* 新增:自定义提示框样式 */
.custom-tooltip {
position: fixed;
background: #1f2937;
color: #ffffff;
padding: 12px 16px;
border-radius: 8px;
max-width: 500px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
font-size: 14px;
line-height: 1.6;
z-index: 9999;
animation: fadeIn 0.2s ease-in-out;
max-height: 400px;
overflow-y: auto;
}
.tooltip-content {
font-family: "Consolas", "Monaco", "Courier New", monospace;
white-space: pre-wrap;
word-wrap: break-word;
color: #e5e7eb;
margin: 0;
:deep(.alert-title .ant-btn-link) {
padding: 0;
height: auto;
line-height: 1;
background: transparent;
border: none;
}
.custom-tooltip::-webkit-scrollbar {
width: 4px;
:deep(.ant-tooltip) {
z-index: 1070 !important;
}
.custom-tooltip::-webkit-scrollbar-track {
background: #2d3748;
border-radius: 2px;
:deep(.ant-tooltip-inner) {
max-width: 500px !important;
padding: 12px 16px !important;
font-size: 14px !important;
line-height: 1.6 !important;
white-space: pre-wrap !important;
word-wrap: break-word !important;
background: #1f2937 !important;
color: #fff !important;
border-radius: 8px !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
}
.custom-tooltip::-webkit-scrollbar-thumb {
background: #4a5568;
border-radius: 2px;
:deep(.ant-tooltip-arrow-content) {
background: #1f2937 !important;
}
.tooltip-arrow {
position: absolute;
top: -8px;
left: 10px;
width: 0;
height: 0;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-bottom: 8px solid #1f2937;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(5px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 滚动条样式优化 */
.alert-list-container::-webkit-scrollbar {
width: 6px;
height: 6px;
@@ -405,7 +329,6 @@ onMounted(() => {
background-color: #f5f5f5;
}
/* 小屏幕适配 */
@media (max-width: 768px) {
.status-filter-container {
gap: 8px;
@@ -435,5 +358,11 @@ onMounted(() => {
.alert-list-container {
max-height: 200px;
}
.alert-title {
width: 80px;
}
.alert-content {
width: 150px;
}
}
</style>
</style>

View File

@@ -11,6 +11,9 @@
<TabPane key="3" tab="文件管理">
<MyfileInfo />
</TabPane>
<TabPane key="4" tab="便签管理">
<NoteTodo />
</TabPane>
</Tabs>
</div>
</template>
@@ -18,6 +21,7 @@
<script lang="ts" setup name="AboutPage">
import { h, ref, onMounted } from 'vue';
import { Tag, Tabs, TabPane } from 'ant-design-vue';
import NoteTodo from './NoteTodo.vue';
import MySchedule from './MySchedule.vue';
import Calendar from './calendar/list.vue';
import ItemsInfo from './listItem/list.vue';