|
|
@@ -7514,6 +7514,7 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
sectionHeights: [],
|
|
|
sectionCollapsed: [], // 功能说明:面板折叠状态(sectionPanels 索引) by xu 20260116
|
|
|
sectionHeightsExpanded: [], // 功能说明:面板展开高度缓存(用于折叠后恢复) by xu 20260116
|
|
|
+ sectionLastItemCounts: [], // 功能说明:记录栏目数据量,供“无数据默认关闭/已选自动展开”规则复用 by xu 20260313
|
|
|
chartCollapsed: [], // 功能说明:图表面板折叠状态(chartPanels 索引) by xu 20260116
|
|
|
chartHeaderTitleDownAt: [], // 功能说明:双击检测绑定到 chart 标题区 by xu 20260116
|
|
|
reportCollapsed: [], // 功能说明:报表面板折叠状态(reportPanels 索引) by xu 20260116
|
|
|
@@ -7549,6 +7550,93 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
{ length: sectionCount },
|
|
|
(_, i) => this.sectionHeightsExpanded?.[i] ?? null
|
|
|
);
|
|
|
+ this.sectionLastItemCounts = Array.from(
|
|
|
+ { length: sectionCount },
|
|
|
+ (_, i) => Number(this.sectionLastItemCounts?.[i] ?? 0) || 0
|
|
|
+ );
|
|
|
+ },
|
|
|
+ __getPanelsForSectionState(panelsInput) {
|
|
|
+ return (panelsInput || []).length
|
|
|
+ ? panelsInput
|
|
|
+ : this.list?.length
|
|
|
+ ? [
|
|
|
+ {
|
|
|
+ type: "list",
|
|
|
+ title: "已选",
|
|
|
+ icon: "",
|
|
|
+ mode: this.listMode,
|
|
|
+ items: this.list,
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ : [];
|
|
|
+ },
|
|
|
+ __getSectionPanelsForState(panelsInput) {
|
|
|
+ return this.__getPanelsForSectionState(panelsInput)
|
|
|
+ .filter((p) => {
|
|
|
+ const k = String(p?._tabKey ?? "")
|
|
|
+ .trim()
|
|
|
+ .toLowerCase();
|
|
|
+ const t = String(p?.title ?? "").trim();
|
|
|
+ if (k === "rbarobj") return false;
|
|
|
+ if (t === "对象") return false;
|
|
|
+ return true;
|
|
|
+ })
|
|
|
+ .filter((p) => p?.type !== "chart" && p?.type !== "report-table");
|
|
|
+ },
|
|
|
+ __getSectionPanelCount(panel) {
|
|
|
+ const explicitCount = Number(panel?.count);
|
|
|
+ if (Number.isFinite(explicitCount)) return explicitCount;
|
|
|
+ return Array.isArray(panel?.items) ? panel.items.length : 0;
|
|
|
+ },
|
|
|
+ __setSectionCollapsedState(index, collapsed) {
|
|
|
+ const i = Number(index);
|
|
|
+ if (isNaN(i) || i < 0) return;
|
|
|
+ const nextCollapsed = !!collapsed;
|
|
|
+ const collapsedHeight = 37;
|
|
|
+ const cur = !!this.sectionCollapsed?.[i];
|
|
|
+ const currentHeight = Number(this.sectionHeights?.[i] ?? 190) || 190;
|
|
|
+ if (nextCollapsed === cur) {
|
|
|
+ if (nextCollapsed && currentHeight !== collapsedHeight) {
|
|
|
+ this.sectionHeights.splice(i, 1, collapsedHeight);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (nextCollapsed) {
|
|
|
+ this.sectionHeightsExpanded[i] =
|
|
|
+ currentHeight > collapsedHeight
|
|
|
+ ? currentHeight
|
|
|
+ : Number(this.sectionHeightsExpanded?.[i] ?? 190) || 190;
|
|
|
+ this.sectionHeights.splice(i, 1, collapsedHeight);
|
|
|
+ } else {
|
|
|
+ const restore =
|
|
|
+ Number(this.sectionHeightsExpanded?.[i] ?? 190) || 190;
|
|
|
+ this.sectionHeights.splice(i, 1, restore);
|
|
|
+ }
|
|
|
+ this.sectionCollapsed.splice(i, 1, nextCollapsed);
|
|
|
+ },
|
|
|
+ __syncSectionAutoCollapse(panelsInput) {
|
|
|
+ const sectionPanels = this.__getSectionPanelsForState(panelsInput);
|
|
|
+ const sectionCount = sectionPanels.length;
|
|
|
+ this.ensureSectionHeights(sectionCount);
|
|
|
+ const prevCounts = Array.isArray(this.sectionLastItemCounts)
|
|
|
+ ? this.sectionLastItemCounts.slice()
|
|
|
+ : [];
|
|
|
+ const nextCounts = Array.from({ length: sectionCount }, (_, i) =>
|
|
|
+ this.__getSectionPanelCount(sectionPanels[i])
|
|
|
+ );
|
|
|
+ this.sectionLastItemCounts = nextCounts;
|
|
|
+ sectionPanels.forEach((panel, index) => {
|
|
|
+ const count = Number(nextCounts[index] ?? 0) || 0;
|
|
|
+ const prevCount = Number(prevCounts[index] ?? 0) || 0;
|
|
|
+ const title = String(panel?.title ?? "").trim();
|
|
|
+ if (count <= 0) {
|
|
|
+ this.__setSectionCollapsedState(index, true);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (title === "已选" && count > prevCount) {
|
|
|
+ this.__setSectionCollapsedState(index, false);
|
|
|
+ }
|
|
|
+ });
|
|
|
},
|
|
|
toggleSectionCollapse(index) {
|
|
|
// 功能说明:双击 header 折叠/展开 section 面板(仅控制高度与内容渲染) by xu 20260116
|
|
|
@@ -7812,6 +7900,23 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
); // 功能说明:清理 cancel 监听,避免残留 by xu 20260122
|
|
|
},
|
|
|
},
|
|
|
+ watch: {
|
|
|
+ panels: {
|
|
|
+ handler(nextPanels) {
|
|
|
+ this.__syncSectionAutoCollapse(nextPanels);
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ immediate: true,
|
|
|
+ },
|
|
|
+ list: {
|
|
|
+ handler(nextList) {
|
|
|
+ if ((this.panels || []).length) return;
|
|
|
+ this.__syncSectionAutoCollapse(nextList);
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ immediate: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
mounted() {
|
|
|
clearTimeout(this.resizeTimer);
|
|
|
this.resizeTimer = null;
|
|
|
@@ -7916,15 +8021,14 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
// 可拖拽的业务面板容器 by xu 20260106
|
|
|
Vue.h(
|
|
|
"div",
|
|
|
- { class: "ss-sidebar-sections", style: { flex: "0 0 auto" } }, // 功能说明:禁止 flex shrink,避免面板很多时 header 被压缩成一条线 by xu 20260116
|
|
|
+ { class: "ss-sidebar-sections", style: { flex: "0 0 auto" } },
|
|
|
sectionPanels.flatMap((p, idx) => {
|
|
|
- // 功能说明:section 面板支持 list / report-table 两种渲染 by xu 20260115
|
|
|
const panelContent =
|
|
|
p?.type === "report-table"
|
|
|
? Vue.h(SsSidebarReportTableComp, {
|
|
|
key: `ss-sidebar-report-in-section-${idx}-${
|
|
|
p?.title ?? ""
|
|
|
- }`, // 功能说明:加 key 防止多面板时组件实例复用导致折叠态不更新 by xu 20260116
|
|
|
+ }`,
|
|
|
title: p?.title ?? "",
|
|
|
icon: p?.icon ?? "",
|
|
|
iconClass: p?.iconClass ?? "",
|
|
|
@@ -7932,7 +8036,7 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
onOpen: (srv, ctx) => p?.onOpen?.(srv, ctx),
|
|
|
})
|
|
|
: Vue.h(SsSidebarListComp, {
|
|
|
- key: `ss-sidebar-list-${idx}-${p?.title ?? ""}`, // 功能说明:加 key 防止多面板时组件实例复用导致折叠态不更新 by xu 20260116
|
|
|
+ key: `ss-sidebar-list-${idx}-${p?.title ?? ""}`,
|
|
|
title: p?.title ?? "",
|
|
|
icon: p?.icon ?? "",
|
|
|
count: p?.count ?? p?.items?.length ?? "",
|
|
|
@@ -7943,17 +8047,16 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
headerSearchButton: !!p?.headerSearchButton,
|
|
|
searchPlaceholder: p?.searchPlaceholder ?? "搜索",
|
|
|
itemLayout: p?.itemLayout ?? "simple",
|
|
|
- itemAction: p?.itemAction ?? true, // 功能说明:面板可配置是否显示 hover 操作按钮(之前未透传导致总显示) by xu 20260114
|
|
|
- collapsible: true, // 功能说明:双击 header 可折叠/展开 by xu 20260116
|
|
|
- collapsed: !!this.sectionCollapsed?.[idx], // 功能说明:折叠态仅展示 header by xu 20260116
|
|
|
+ itemAction: p?.itemAction ?? true,
|
|
|
+ collapsible: true,
|
|
|
+ collapsed: !!this.sectionCollapsed?.[idx],
|
|
|
onToggleCollapse: () =>
|
|
|
- this.toggleSectionCollapse?.(idx), // 功能说明:折叠事件回调 by xu 20260116
|
|
|
+ this.toggleSectionCollapse?.(idx),
|
|
|
iconClass: p?.iconClass ?? "",
|
|
|
items: p?.items || [],
|
|
|
mode: p?.mode || "search",
|
|
|
onSelect: (item) => this.$emit("select", item),
|
|
|
onRemove: (item) => this.$emit("remove", item),
|
|
|
- // closable = 清空分区数据 by xu 20260106
|
|
|
onClear: () => p?.onClear?.(),
|
|
|
onSearch: (payload) => p?.onSearch?.(payload),
|
|
|
});
|
|
|
@@ -7964,14 +8067,14 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
class: {
|
|
|
"ss-sidebar-section": true,
|
|
|
"is-collapsed": !!this.sectionCollapsed?.[idx],
|
|
|
- }, // 功能说明:折叠态加 class,配合 CSS 裁剪溢出(否则高度变了内容仍 overflow visible) by xu 20260116
|
|
|
+ },
|
|
|
key: `ss-sidebar-section-${idx}-${p?.type ?? "list"}-${
|
|
|
p?.title ?? ""
|
|
|
- }`, // 功能说明:加 key 保证 section 节点稳定更新 by xu 20260116
|
|
|
+ }`,
|
|
|
style: {
|
|
|
height: (this.sectionHeights[idx] ?? 190) + "px",
|
|
|
flex: "0 0 auto",
|
|
|
- }, // 功能说明:禁止 flex shrink,避免折叠/展开后 header 高度被挤压 by xu 20260116
|
|
|
+ },
|
|
|
},
|
|
|
[
|
|
|
Vue.h("div", { class: "ss-sidebar-section__content" }, [
|
|
|
@@ -8000,10 +8103,10 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
"ss-sidebar-panel": true,
|
|
|
"ss-sidebar-chart-panel": true,
|
|
|
"is-collapsed": !!this.chartCollapsed?.[chartIdx],
|
|
|
- }, // 功能说明:图表折叠态加 class,DOM 兜底隐藏内容 by xu 20260116
|
|
|
- style: { flex: "0 0 auto", minHeight: "37px" }, // 功能说明:禁止 flex shrink + 折叠态最小高度兜底,避免 header 被压扁 by xu 20260116
|
|
|
- "data-chart-idx": chartIdx, // 功能说明:便于 toggleChartCollapse nextTick 精确定位 DOM by xu 20260116
|
|
|
- key: `ss-sidebar-chart-${chartIdx}-${p?.title ?? ""}`, // 功能说明:加 key 防止多图表时实例复用 by xu 20260116
|
|
|
+ },
|
|
|
+ style: { flex: "0 0 auto", minHeight: "37px" },
|
|
|
+ "data-chart-idx": chartIdx,
|
|
|
+ key: `ss-sidebar-chart-${chartIdx}-${p?.title ?? ""}`,
|
|
|
},
|
|
|
[
|
|
|
p?.title
|
|
|
@@ -8011,17 +8114,15 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
"div",
|
|
|
{
|
|
|
class: "ss-sidebar-panel__header",
|
|
|
- // 功能说明:折叠触发绑定到整个 header(仅 dblclick,避免双击触发两次) by xu 20260116
|
|
|
onDblclick: (e) => {
|
|
|
e?.preventDefault?.();
|
|
|
e?.stopPropagation?.();
|
|
|
console.log("[SsSidebar] chart header dblclick", {
|
|
|
idx: chartIdx,
|
|
|
title: p?.title,
|
|
|
- }); // 功能说明:直接打印用于排查多面板不生效 by xu 20260116
|
|
|
+ });
|
|
|
this.toggleChartCollapse?.(chartIdx);
|
|
|
},
|
|
|
- // 功能说明:移除 click.detail==2 兜底,避免双击同时触发 click+dblclick 导致“折叠又立刻展开” by xu 20260116
|
|
|
},
|
|
|
[
|
|
|
Vue.h("div", { class: "ss-sidebar-panel__title" }, [
|
|
|
@@ -8043,7 +8144,6 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
]
|
|
|
)
|
|
|
: null,
|
|
|
- // hover 大图也展示与 header 一致的图标/标题 by xu 20260108
|
|
|
this.chartCollapsed?.[chartIdx]
|
|
|
? null
|
|
|
: Vue.h(Vue.resolveComponent("ss-sidebar-chart-hover"), {
|
|
|
@@ -8056,9 +8156,7 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
]
|
|
|
)
|
|
|
),
|
|
|
- // 功能说明:统计表(report-table)放在统计图下面,统一走 ss-sidebar-report-table 渲染 by xu 20260115
|
|
|
...reportPanels.map((p, reportIdx) =>
|
|
|
- // 功能说明:report-table 顶部也需要折叠态 class/定位属性,DOM 兜底隐藏内容 by xu 20260116
|
|
|
Vue.h(
|
|
|
"div",
|
|
|
{
|
|
|
@@ -8066,23 +8164,22 @@ import { EVEN_VAR } from "./EventBus.js";
|
|
|
"ss-sidebar-report-panel-wrap": true,
|
|
|
"ss-sidebar-report-panel": true,
|
|
|
"is-collapsed": !!this.reportCollapsed?.[reportIdx],
|
|
|
- }, // 功能说明:报表折叠态加 class,DOM 兜底隐藏内容 by xu 20260116
|
|
|
- style: { flex: "0 0 auto", minHeight: "37px" }, // 功能说明:禁止 flex shrink + 折叠态最小高度兜底,避免 header 被压扁 by xu 20260116
|
|
|
- "data-report-idx": reportIdx, // 功能说明:便于 toggleReportCollapse nextTick 精确定位 DOM by xu 20260116
|
|
|
- key: `ss-sidebar-report-wrap-${reportIdx}-${p?.title ?? ""}`, // 功能说明:加 key 防止多面板时实例复用导致折叠态不更新 by xu 20260116
|
|
|
+ },
|
|
|
+ style: { flex: "0 0 auto", minHeight: "37px" },
|
|
|
+ "data-report-idx": reportIdx,
|
|
|
+ key: `ss-sidebar-report-wrap-${reportIdx}-${p?.title ?? ""}`,
|
|
|
},
|
|
|
[
|
|
|
- // 功能说明:ss-sidebar-report-table 自带 ss-sidebar-panel 外壳,这里不重复包裹 by xu 20260115
|
|
|
Vue.h(SsSidebarReportTableComp, {
|
|
|
- key: `ss-sidebar-report-${reportIdx}-${p?.title ?? ""}`, // 功能说明:加 key 防止多面板时实例复用导致折叠态不更新 by xu 20260116
|
|
|
+ key: `ss-sidebar-report-${reportIdx}-${p?.title ?? ""}`,
|
|
|
title: p?.title ?? "",
|
|
|
icon: p?.icon ?? "",
|
|
|
iconClass: p?.iconClass ?? "",
|
|
|
items: p?.items || [],
|
|
|
- collapsible: true, // 功能说明:允许双击 header 折叠/展开 by xu 20260116
|
|
|
- collapsed: !!this.reportCollapsed?.[reportIdx], // 功能说明:折叠态隐藏表格 by xu 20260116
|
|
|
+ collapsible: true,
|
|
|
+ collapsed: !!this.reportCollapsed?.[reportIdx],
|
|
|
onToggleCollapse: () =>
|
|
|
- this.toggleReportCollapse?.(reportIdx), // 功能说明:报表折叠事件回调 by xu 20260116
|
|
|
+ this.toggleReportCollapse?.(reportIdx),
|
|
|
onOpen: (srv, ctx) => p?.onOpen?.(srv, ctx),
|
|
|
}),
|
|
|
]
|