fix(notice): 待办中心左列表改滚动分页追加/表格列宽与幻影省略号修正/流程图弹窗收窄至740
build / build (push) Successful in 2m35s

- NoticeAccept 左侧列表:改为每页50滚动触底预取并追加(hasNext 驱动,加载中/没有更多提示),
  已读状态改本地置位(markRead),不再整页重拉列表(重拉会丢已追加分页与滚动位置)
- NoticeList 附件列 70→80:图标外包 Tooltip 后内容宽不足,cell ellipsis 会在图标后画出「...」
- NoticeApproval 办件表格:状态/提交人/时间列 width→minWidth 参与余量分配,避免通知列独占宽屏余量;操作列固定150居中
- 流程图弹窗/抽屉 860→740(NewNotice / NoticeSetting / NoticeDetails)
- 回退 main.scss 中操作列裸 .ivu-tooltip 的 display:block(会以更高特异性顶掉横排规则致图标竖排),改由 .ivu-table-cell-tooltip 恢复 flex
- .gitignore 忽略 vite 配置 bundle 临时产物 vite.config.*.timestamp-*
This commit is contained in:
chenxing
2026-10-10 16:57:07 +08:00
parent 690d329371
commit 46710cd18e
8 changed files with 96 additions and 50 deletions
+3
View File
@@ -27,3 +27,6 @@ yarn.lock
# scratch
.temp
# vite 配置 bundle 临时产物
vite.config.*.timestamp-*
+6 -9
View File
@@ -116,15 +116,12 @@ h4.subtitle {
margin-bottom: 2px;
}
/* 修复表格幻影省略号(2026-10-10):.ivu-table-cell 基础样式自带 text-overflow:ellipsis,
tooltip 列(.ivu-tooltip 行内块包装 + width:100%)与操作列(图标外包 Tooltip)未溢出也常显「...」。
恢复组件预期的块级/flex 渲染层级即可;内层 .ivu-table-cell-tooltip-content 的真省略号与
悬浮 tooltip 不受影响(已在 dev:mock 实测:短内容无省略号、长标题正常截断+悬浮提示)。 */
/* 两条同为 3 类特异性(0,3,0):后者居后胜出 → tooltip 列(.ivu-table-cell-tooltip)最终 flex
(组件预期布局),操作列裸 .ivu-tooltip 包装取 block。 */
.ivu-table .ivu-table-cell > .ivu-tooltip {
display: block;
}
/* 修复表格幻影省略号(2026-10-10):.ivu-table-cell 自带 overflow:hidden + text-overflow:ellipsis,
tooltip 列的包装层(.ivu-tooltip 行内块 + width:100%)未溢出也会被画出「...」;
恢复组件预期的 flex 层级即可,内层 .ivu-table-cell-tooltip-content 的真省略号与悬浮 tooltip 不受影响。
注意:不要再给操作列的裸 .ivu-tooltip 加 display:block——那会以更高特异性顶掉 App.vue 的横排规则,
使 operatingHandle 渲染的图标按钮竖排(2026-10-10 踩过,已回退)。 */
/* tooltip 列的包装层同时挂 .ivu-tooltip{display:inline-block},靠声明顺序顶掉了组件预期的 flex,这里恢复 */
.ivu-table .ivu-table-cell > .ivu-table-cell-tooltip {
display: flex;
}
+1 -1
View File
@@ -421,7 +421,7 @@ async function saveEditAndLeave(data: NoticeRequest) {
</Modal>
<!-- 流程图 Drawer(后端 DiagramDef 同源 PNG;竖版长图容器内纵向滚动) -->
<Drawer v-model="flowDiagramVisible" title="流程示意图" :width="860" :transfer="false"
<Drawer v-model="flowDiagramVisible" title="流程示意图" :width="740" :transfer="false"
:styles="{ body: { padding: '0' } }">
<div class="flow-diagram-frame">
<img ref="flowDiagramEl" v-if="flowDiagramSrc" :src="flowDiagramSrc" alt="流程示意图" @load="fitDiagram(flowDiagramEl)" @error="onFlowDiagramError" />
+73 -32
View File
@@ -8,41 +8,76 @@ import FilePreviewModal from "@/components/FilePreviewModal.vue";
import SvgIcon from "@/components/SvgIcon.vue";
import Utils from "@/utils";
/* ============ 左侧列表 ============ */
/* ============ 左侧列表(每页 50,滚动到底部加载下一页并追加) ============ */
const keyword = ref("");
const pageNum = ref(1);
const pageSize = ref(50);
const PAGE_SIZE = 50;
const pageIndex = ref(1);
const list = ref<NoticeVo[]>([]);
const unreadCount = ref(0);
const hasNext = ref(false);
const loadingMore = ref(false);
const selected = ref(0);
const { data: page, loading, send: reload } = useRequest(
(params: NoticeQuery) => noticeApi.list(params),
{
immediate: false,
initialData: { content: [], total: 0, pageIndex: 1, pageSize: 50, totalPages: 0, hasNext: false, unreadCount: 0 },
}
);
const { send: reload } = useRequest((params: NoticeQuery) => noticeApi.list(params), { immediate: false });
async function run() {
async function fetchList(append: boolean) {
const data: NoticePageResult<NoticeVo> = await reload({
keyword: keyword.value || "",
pageIndex: pageNum.value,
pageSize: pageSize.value,
pageIndex: append ? pageIndex.value + 1 : 1,
pageSize: PAGE_SIZE,
orderByTime: "1",
});
const content = data?.content || [];
if (append) {
list.value = list.value.concat(content);
pageIndex.value += 1;
} else {
list.value = content;
pageIndex.value = 1;
}
unreadCount.value = data?.unreadCount || 0;
hasNext.value = !!data?.hasNext;
}
async function run() {
await fetchList(false);
// 默认选中第一条(同旧版进入页面即展示最新通知)
const list = data?.content || [];
if (!detail.value && list.length) {
const first = list.value[0];
if (!detail.value && first) {
selected.value = 0;
await loadDetail(list[0].id, true);
await loadDetail(first.id, true);
markRead(first);
}
}
function onSearch() {
pageNum.value = 1;
run();
/* 触底预取:距底部 60px 即发下一页请求,避免滑到尽头才出现内容 */
function onListScroll(e: Event) {
const el = e.target as HTMLElement;
if (!hasNext.value || loadingMore.value) return;
if (el.scrollTop + el.clientHeight < el.scrollHeight - 60) return;
loadMore();
}
async function loadMore() {
loadingMore.value = true;
try {
await fetchList(true);
} catch (e: any) {
Message.error(e?.message || "加载更多失败");
} finally {
loadingMore.value = false;
}
}
/** 已读状态本地置位:标读接口已改库,无需重拉列表(重拉会丢掉已追加的分页与滚动位置) */
function markRead(item: NoticeVo) {
if (item.read) return;
item.read = true;
unreadCount.value = Math.max(0, unreadCount.value - 1);
}
function onClear() {
keyword.value = "";
onSearch();
run();
}
/* 一键已读(旧版 icon-saoba 清除按钮) */
@@ -50,7 +85,8 @@ async function allRead() {
try {
await noticeApi.initializeRed().send();
Message.success("操作成功!");
run();
list.value.forEach(markRead);
unreadCount.value = 0;
if (detail.value) loadDetail(detail.value.serid, false);
} catch (e: any) {
Message.error(e.message || "操作失败");
@@ -68,16 +104,13 @@ onMounted(async () => {
async function checkNotice(item: NoticeVo, index: number) {
selected.value = index;
await loadDetail(item.id, true);
markRead(item);
}
async function loadDetail(serid: number, markRead: boolean) {
async function loadDetail(serid: number, markAsRead: boolean) {
detailLoading.value = true;
try {
detail.value = await noticeApi.modify(serid, markRead ? 1 : 0).send();
if (markRead) {
// 标读后刷新左侧未读状态
run();
}
detail.value = await noticeApi.modify(serid, markAsRead ? 1 : 0).send();
} catch (e: any) {
Message.error(e.message || "加载通知失败");
} finally {
@@ -171,7 +204,7 @@ function shortDate(date: string) {
<!-- 左侧通知列表 -->
<div class="title-list">
<div class="total">
<span>未读<span class="num">{{ page.unreadCount || 0 }}</span>条</span>
<span>未读<span class="num">{{ unreadCount }}</span>条</span>
<Tooltip content="一键已读" placement="top" transfer>
<SvgIcon class="clear-icon" name="read-all" :size="18" color="var(--text-3)" hover-color="var(--brand)" @click="allRead" />
</Tooltip>
@@ -182,13 +215,13 @@ function shortDate(date: string) {
clearable
search
placeholder="搜索发布人,标题,部门......"
@on-search="onSearch"
@on-search="run"
@on-clear="onClear"
></Input>
</div>
<div class="notice-items">
<div class="notice-items" @scroll="onListScroll">
<div
v-for="(item, index) in page.content"
v-for="(item, index) in list"
:key="item.id"
:class="{ list_item: true, readed: item.read, active: index == selected }"
@click="checkNotice(item, index)"
@@ -199,7 +232,9 @@ function shortDate(date: string) {
<span>{{ shortDate(item.createTime) }}</span>
</div>
</div>
<div v-if="!page.content.length" class="empty">暂无通知</div>
<div v-if="loadingMore" class="load-more">加载中...</div>
<div v-else-if="list.length && !hasNext" class="load-more">没有更多了</div>
<div v-if="!list.length" class="empty">暂无通知</div>
</div>
</div>
@@ -381,6 +416,12 @@ function shortDate(date: string) {
color: var(--text-3);
padding: 40px 0;
}
.load-more {
padding: 10px 0 4px;
text-align: center;
font-size: 11.5px;
color: var(--text-3);
}
}
}
+8 -5
View File
@@ -123,13 +123,16 @@ const todoCols = [
{ title: "操作", slot: "action", width: 190, align: "center" },
];
/* 列宽:iView 把表格的剩余宽度全部分给「未设 width」的列(table.vue handleResize),
原先只有通知列可变 → 宽屏下通知列独占全部余量。改为各列都给 minWidth 参与分配,
通知列不再被拉宽;操作列固定 150 且居中。 */
const instCols = [
{ title: "通知", key: "bizTitle", minWidth: 240, ellipsis: true, tooltip: true },
{ title: "状态", slot: "status", width: 100 },
{ title: "提交人", key: "submitterName", width: 100 },
{ title: "提交时间", key: "submitTime", width: 170, render: fmtTime },
{ title: "办结时间", key: "finishTime", width: 170, render: fmtTime },
{ title: "操作", slot: "instAction", width: 100 },
{ title: "状态", slot: "status", minWidth: 100 },
{ title: "提交人", key: "submitterName", minWidth: 100 },
{ title: "提交时间", key: "submitTime", minWidth: 170, render: fmtTime },
{ title: "办结时间", key: "finishTime", minWidth: 170, render: fmtTime },
{ title: "操作", slot: "instAction", width: 150, align: "center" },
];
/* 审批记录 Drawer(嵌入页 iframe):pageUrl 含 10 分钟短时 token,每次打开现取,
+1 -1
View File
@@ -346,7 +346,7 @@ function openPreview(item: { name?: string; filename?: string; fileid?: number;
</div>
<!-- 流程图弹窗(后端同源出图,免 token 免跨域) -->
<Modal v-model="diagramVisible" title="流程示意图" :width="860" footer-hide>
<Modal v-model="diagramVisible" title="流程示意图" :width="740" footer-hide>
<div class="diagram-wrap">
<img v-if="diagramSrc" ref="diagramEl" :src="diagramSrc" alt="流程示意图" @load="fitDiagram(diagramEl)" @error="onDiagramError" />
</div>
+3 -1
View File
@@ -189,7 +189,9 @@ const columns = [
},
{
title: "附件",
width: 70,
/* 图标外包 Tooltip 后占 32+2*2=36px,cell 左右内边距各 18px:70px 列只剩 34px 内容宽,
溢出 2px 会让 cell 的 text-overflow:ellipsis 在图标后画出「...」,故留到 80 */
width: 80,
align: "center",
render: (h: any, p: any) =>
(p.row.upFile ?? p.row.UpFile)
+1 -1
View File
@@ -552,7 +552,7 @@ const groupH = useElementHeight(groupRegionRef);
</div>
<!-- 流程图 Drawer(后端 DiagramDef 同源 PNG;竖版长图容器内纵向滚动) -->
<Drawer v-model="flowDiagramVisible" title="流程示意图" :width="860" :transfer="false"
<Drawer v-model="flowDiagramVisible" title="流程示意图" :width="740" :transfer="false"
:styles="{ body: { padding: '0' } }">
<div class="flow-diagram-frame">
<img ref="flowDiagramEl" v-if="flowDiagramSrc" :src="flowDiagramSrc" alt="流程示意图" @load="fitDiagram(flowDiagramEl)" @error="onFlowDiagramError" />