diff --git a/src/views/reports/accounts/index.vue b/src/views/reports/accounts/index.vue index 52a90d101..4f2cafa8f 100644 --- a/src/views/reports/accounts/index.vue +++ b/src/views/reports/accounts/index.vue @@ -203,32 +203,36 @@ export default { if (target?.isCustom) { const rq = this.$route.query || {} const isCustomizeMode = String(Array.isArray(rq.customize) ? rq.customize[0] : rq.customize) === '1' - const targetVisibleCharts = target.query?.visible_charts || '' - const targetVisibleTables = target.query?.visible_tables || '' + const normalizeVisibleParam = (v) => { + if (v === undefined || v === null) return undefined + return String(Array.isArray(v) ? v[0] : v) || '' + } + const targetVC = normalizeVisibleParam(target.query?.visible_charts) + const targetVT = normalizeVisibleParam(target.query?.visible_tables) + const currentVC = normalizeVisibleParam(rq.visible_charts) + const currentVT = normalizeVisibleParam(rq.visible_tables) const desiredBase = { chart_key: target.query?.chart_key || target.key, - report_id: String(target.reportId || target.query?.report_id || ''), - days: normalizeReportDays(target.query?.days, '7') + report_id: String(target.reportId || target.query?.report_id || '') } const currentBase = { chart_key: normalizeRouteValue(rq.chart_key), - report_id: normalizeRouteValue(rq.report_id), - days: normalizeReportDays(normalizeRouteValue(rq.days), '7') + report_id: normalizeRouteValue(rq.report_id) } const baseNeedsCorrection = JSON.stringify(currentBase) !== JSON.stringify(desiredBase) const visibleNeedsCorrection = !isCustomizeMode && ( - (normalizeRouteValue(rq.visible_charts) || '') !== targetVisibleCharts || - (normalizeRouteValue(rq.visible_tables) || '') !== targetVisibleTables + targetVC !== currentVC || targetVT !== currentVT ) if (baseNeedsCorrection || visibleNeedsCorrection) { - const correctedQuery = { ...desiredBase } + const activeDays = normalizeReportDays(normalizeRouteValue(rq.days) || target.query?.days, '7') + const correctedQuery = { ...desiredBase, days: activeDays } if (isCustomizeMode) { - if (rq.visible_charts) correctedQuery.visible_charts = rq.visible_charts - if (rq.visible_tables) correctedQuery.visible_tables = rq.visible_tables + if (currentVC !== undefined) correctedQuery.visible_charts = currentVC + if (currentVT !== undefined) correctedQuery.visible_tables = currentVT if (rq.customize) correctedQuery.customize = rq.customize } else { - if (targetVisibleCharts) correctedQuery.visible_charts = targetVisibleCharts - if (targetVisibleTables) correctedQuery.visible_tables = targetVisibleTables + if (targetVC !== undefined) correctedQuery.visible_charts = targetVC + if (targetVT !== undefined) correctedQuery.visible_tables = targetVT } this.$router.replace({ path: this.$route.path, query: correctedQuery }) return diff --git a/src/views/reports/assets/index.vue b/src/views/reports/assets/index.vue index 37af53584..617168616 100644 --- a/src/views/reports/assets/index.vue +++ b/src/views/reports/assets/index.vue @@ -203,35 +203,37 @@ export default { if (target?.isCustom) { const rq = this.$route.query || {} const isCustomizeMode = String(Array.isArray(rq.customize) ? rq.customize[0] : rq.customize) === '1' - const targetVisibleCharts = target.query?.visible_charts || '' - const targetVisibleTables = target.query?.visible_tables || '' + const normalizeVisibleParam = (v) => { + if (v === undefined || v === null) return undefined + return String(Array.isArray(v) ? v[0] : v) || '' + } + const targetVC = normalizeVisibleParam(target.query?.visible_charts) + const targetVT = normalizeVisibleParam(target.query?.visible_tables) + const currentVC = normalizeVisibleParam(rq.visible_charts) + const currentVT = normalizeVisibleParam(rq.visible_tables) const desiredBase = { chart_key: target.query?.chart_key || target.key, - report_id: String(target.reportId || target.query?.report_id || ''), - days: normalizeReportDays(target.query?.days, '7') + report_id: String(target.reportId || target.query?.report_id || '') } const currentBase = { chart_key: normalizeRouteValue(rq.chart_key), - report_id: normalizeRouteValue(rq.report_id), - days: normalizeReportDays(normalizeRouteValue(rq.days), '7') + report_id: normalizeRouteValue(rq.report_id) } const baseNeedsCorrection = JSON.stringify(currentBase) !== JSON.stringify(desiredBase) - // 普通页面:visible_* 始终以报表保存值为准(用户无法在普通页面手动修改) const visibleNeedsCorrection = !isCustomizeMode && ( - (normalizeRouteValue(rq.visible_charts) || '') !== targetVisibleCharts || - (normalizeRouteValue(rq.visible_tables) || '') !== targetVisibleTables + targetVC !== currentVC || targetVT !== currentVT ) if (baseNeedsCorrection || visibleNeedsCorrection) { - const correctedQuery = { ...desiredBase } + // days: 优先保留用户当前选择,无则回落到报表保存值 + const activeDays = normalizeReportDays(normalizeRouteValue(rq.days) || target.query?.days, '7') + const correctedQuery = { ...desiredBase, days: activeDays } if (isCustomizeMode) { - // customize 窗口:保留用户在选项卡上的实时操作 - if (rq.visible_charts) correctedQuery.visible_charts = rq.visible_charts - if (rq.visible_tables) correctedQuery.visible_tables = rq.visible_tables + if (currentVC !== undefined) correctedQuery.visible_charts = currentVC + if (currentVT !== undefined) correctedQuery.visible_tables = currentVT if (rq.customize) correctedQuery.customize = rq.customize } else { - // 普通页面:始终使用报表保存值 - if (targetVisibleCharts) correctedQuery.visible_charts = targetVisibleCharts - if (targetVisibleTables) correctedQuery.visible_tables = targetVisibleTables + if (targetVC !== undefined) correctedQuery.visible_charts = targetVC + if (targetVT !== undefined) correctedQuery.visible_tables = targetVT } this.$router.replace({ path: this.$route.path, query: correctedQuery }) return diff --git a/src/views/reports/base/BaseReport.vue b/src/views/reports/base/BaseReport.vue index b4b98905c..c706412bf 100644 --- a/src/views/reports/base/BaseReport.vue +++ b/src/views/reports/base/BaseReport.vue @@ -222,7 +222,10 @@ export default { }, methods: { isDisplayModeEnabled(mode) { - return this.selectedDisplayModes.includes(mode) + if (!this.selectedDisplayModes.includes(mode)) return false + if (mode === 'chart' && this.chartOptions.length > 0 && this.selectedChartNames.length === 0) return false + if (mode === 'table' && this.tableOptions.length > 0 && this.selectedTableNames.length === 0) return false + return true }, normalizeOptions(items) { if (!Array.isArray(items)) return [] @@ -252,7 +255,8 @@ export default { const routeQueryValue = this.$route && this.$route.query ? this.$route.query[key] : undefined const hashQueryValue = this.getHashQueryValue(key) const queryValue = routeQueryValue !== undefined ? routeQueryValue : hashQueryValue - if (queryValue === undefined || queryValue === null || queryValue === '') return null + if (queryValue === undefined || queryValue === null) return null + if (queryValue === '') return [] const rawList = Array.isArray(queryValue) ? queryValue : String(queryValue).split(',') const selected = Array.from( new Set( @@ -352,6 +356,17 @@ export default { if (!checked && idx >= 0) nextModes.splice(idx, 1) if (!nextModes.length) return this.handleDisplayModeChange(nextModes) + // 同步 selectedNames 和 URL:关闭模式 = 清空选择,开启 = 全选 + if (mode === 'chart') { + this.selectedChartNames = checked ? this.chartOptions.map(item => item.name) : [] + this.pushVisibilityQuery() + this.$nextTick(() => this.applyItemVisibility()) + } + if (mode === 'table') { + this.selectedTableNames = checked ? this.tableOptions.map(item => item.name) : [] + this.pushVisibilityQuery() + this.$nextTick(() => this.applyItemVisibility()) + } }, handleChartSelectionChange(names) { const normalized = Array.isArray(names) @@ -377,7 +392,8 @@ export default { if (!name) return true const options = type === 'chart' ? this.chartOptions : this.tableOptions const selected = type === 'chart' ? this.selectedChartNames : this.selectedTableNames - if (!options.length || !selected.length) return true + if (!options.length) return true + if (!selected.length) return false const matchedByName = options.find(item => item.name === name) if (matchedByName) return selected.includes(matchedByName.name) const matchedByTitle = options.find(item => item.title === name) @@ -422,8 +438,8 @@ export default { const query = { customize: 1 } if (rq.report_id) query.report_id = rq.report_id if (rq.days) query.days = rq.days - if (rq.visible_charts) query.visible_charts = rq.visible_charts - if (rq.visible_tables) query.visible_tables = rq.visible_tables + if (rq.visible_charts !== undefined && rq.visible_charts !== null) query.visible_charts = rq.visible_charts + if (rq.visible_tables !== undefined && rq.visible_tables !== null) query.visible_tables = rq.visible_tables const url = appendQuery(basePath, query) this.win = window.open(url, '_blank', options) } diff --git a/src/views/reports/base/CreateReportDialog.vue b/src/views/reports/base/CreateReportDialog.vue index a127af958..5a056c856 100644 --- a/src/views/reports/base/CreateReportDialog.vue +++ b/src/views/reports/base/CreateReportDialog.vue @@ -154,6 +154,8 @@ export default { return normalizeReportDays(days, '7') }, normalizeSelection(raw, options = [], fallback = []) { + // 显式空数组 = 用户清除了所有选择(如关闭图形报表模式),直接返回空 + if (Array.isArray(raw) && raw.length === 0) return [] const safeOptions = Array.isArray(options) ? options : [] const optionNames = safeOptions .map(item => String(item && item.name ? item.name : '').trim()) diff --git a/src/views/reports/base/RightAction.vue b/src/views/reports/base/RightAction.vue index a22440a29..b2bf22334 100644 --- a/src/views/reports/base/RightAction.vue +++ b/src/views/reports/base/RightAction.vue @@ -222,10 +222,10 @@ export default { const reportDays = parseInt(normalizeReportDays(query.days || this.reportData?.days || this.getDaysParam(), '7'), 10) if (this.isCustomReport) { const savedFilters = (this.reportData && this.reportData.filters) ? { ...this.reportData.filters } : {} - if (query.visible_charts) { + if (query.visible_charts !== undefined && query.visible_charts !== null) { savedFilters.visible_charts = String(query.visible_charts).split(',').map(s => s.trim()).filter(Boolean) } - if (query.visible_tables) { + if (query.visible_tables !== undefined && query.visible_tables !== null) { savedFilters.visible_tables = String(query.visible_tables).split(',').map(s => s.trim()).filter(Boolean) } return { diff --git a/src/views/reports/base/reportPageMixin.js b/src/views/reports/base/reportPageMixin.js index 5e50da3ed..b414d6acc 100644 --- a/src/views/reports/base/reportPageMixin.js +++ b/src/views/reports/base/reportPageMixin.js @@ -428,13 +428,21 @@ export default { if (days) { query.days = normalizeReportDays(days, '7') } - const visibleCharts = normalizeVisibleFilterList(this.$route.query.visible_charts || this.reportDetail?.filters?.visible_charts) - const visibleTables = normalizeVisibleFilterList(this.$route.query.visible_tables || this.reportDetail?.filters?.visible_tables) - if (visibleCharts.length) { - query.visible_charts = visibleCharts.join(',') + const routeVC = this.$route.query.visible_charts + const routeVT = this.$route.query.visible_tables + const chartsSource = routeVC !== undefined && routeVC !== null + ? routeVC + : this.reportDetail?.filters?.visible_charts + const tablesSource = routeVT !== undefined && routeVT !== null + ? routeVT + : this.reportDetail?.filters?.visible_tables + if (chartsSource !== undefined && chartsSource !== null) { + const list = normalizeVisibleFilterList(chartsSource) + query.visible_charts = list.length ? list.join(',') : '' } - if (visibleTables.length) { - query.visible_tables = visibleTables.join(',') + if (tablesSource !== undefined && tablesSource !== null) { + const list = normalizeVisibleFilterList(tablesSource) + query.visible_tables = list.length ? list.join(',') : '' } if (this.days !== undefined && days) { this.days = normalizeReportDays(days, '7') diff --git a/src/views/reports/base/reportUtils.js b/src/views/reports/base/reportUtils.js index efc188752..a6b7e1747 100644 --- a/src/views/reports/base/reportUtils.js +++ b/src/views/reports/base/reportUtils.js @@ -34,8 +34,8 @@ export function pickReportQuery(query = {}) { export function appendQuery(url, query = {}) { const params = new URLSearchParams() Object.entries(query).forEach(([key, value]) => { - if (value !== undefined && value !== null && value !== '') { - params.set(key, value) + if (value !== undefined && value !== null) { + params.set(key, String(value)) } }) const queryString = params.toString() @@ -83,9 +83,14 @@ export function buildCustomReportRouteQuery(report = {}) { const visibleTables = normalizeVisibleFilterList(filters.visible_tables) if (visibleCharts.length) { query.visible_charts = visibleCharts.join(',') + } else if (filters.visible_charts !== undefined) { + // 显式保存为空 = 全部隐藏,用空字符串表示 + query.visible_charts = '' } if (visibleTables.length) { query.visible_tables = visibleTables.join(',') + } else if (filters.visible_tables !== undefined) { + query.visible_tables = '' } return query } diff --git a/src/views/reports/users/index.vue b/src/views/reports/users/index.vue index c103b5585..cb3a5954d 100644 --- a/src/views/reports/users/index.vue +++ b/src/views/reports/users/index.vue @@ -214,35 +214,37 @@ export default { if (target?.isCustom) { const rq = this.$route.query || {} const isCustomizeMode = String(Array.isArray(rq.customize) ? rq.customize[0] : rq.customize) === '1' - const targetVisibleCharts = target.query?.visible_charts || '' - const targetVisibleTables = target.query?.visible_tables || '' + const normalizeVisibleParam = (v) => { + if (v === undefined || v === null) return undefined + return String(Array.isArray(v) ? v[0] : v) || '' + } + const targetVC = normalizeVisibleParam(target.query?.visible_charts) + const targetVT = normalizeVisibleParam(target.query?.visible_tables) + const currentVC = normalizeVisibleParam(rq.visible_charts) + const currentVT = normalizeVisibleParam(rq.visible_tables) const desiredBase = { chart_key: target.query?.chart_key || target.key, - report_id: String(target.reportId || target.query?.report_id || ''), - days: normalizeReportDays(target.query?.days, '7') + report_id: String(target.reportId || target.query?.report_id || '') } const currentBase = { chart_key: normalizeRouteValue(rq.chart_key), - report_id: normalizeRouteValue(rq.report_id), - days: normalizeReportDays(normalizeRouteValue(rq.days), '7') + report_id: normalizeRouteValue(rq.report_id) } const baseNeedsCorrection = JSON.stringify(currentBase) !== JSON.stringify(desiredBase) - // 普通页面:visible_* 始终以报表保存值为准(用户无法在普通页面手动修改) const visibleNeedsCorrection = !isCustomizeMode && ( - (normalizeRouteValue(rq.visible_charts) || '') !== targetVisibleCharts || - (normalizeRouteValue(rq.visible_tables) || '') !== targetVisibleTables + targetVC !== currentVC || targetVT !== currentVT ) if (baseNeedsCorrection || visibleNeedsCorrection) { - const correctedQuery = { ...desiredBase } + // days: 优先保留用户当前选择,无则回落到报表保存值 + const activeDays = normalizeReportDays(normalizeRouteValue(rq.days) || target.query?.days, '7') + const correctedQuery = { ...desiredBase, days: activeDays } if (isCustomizeMode) { - // customize 窗口:保留用户在选项卡上的实时操作 - if (rq.visible_charts) correctedQuery.visible_charts = rq.visible_charts - if (rq.visible_tables) correctedQuery.visible_tables = rq.visible_tables + if (currentVC !== undefined) correctedQuery.visible_charts = currentVC + if (currentVT !== undefined) correctedQuery.visible_tables = currentVT if (rq.customize) correctedQuery.customize = rq.customize } else { - // 普通页面:始终使用报表保存值 - if (targetVisibleCharts) correctedQuery.visible_charts = targetVisibleCharts - if (targetVisibleTables) correctedQuery.visible_tables = targetVisibleTables + if (targetVC !== undefined) correctedQuery.visible_charts = targetVC + if (targetVT !== undefined) correctedQuery.visible_tables = targetVT } this.$router.replace({ path: this.$route.path, query: correctedQuery }) return