fix:修改图表问题

This commit is contained in:
大黑 2026-01-22 15:14:55 +08:00
parent 501742b95a
commit 70d91689eb
16 changed files with 33818 additions and 4642 deletions

2
.gitignore vendored
View File

@ -27,3 +27,5 @@ yarn-error.log*
node_modules.zip node_modules.zip
apaas-custom-mydemo.zip apaas-custom-mydemo.zip
apaas-custom-mydemo-1.zip apaas-custom-mydemo-1.zip
eslint-report.html
fix-echarts-install.bat

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

28083
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,13 @@
"cm": "git-cz" "cm": "git-cz"
}, },
"dependencies": { "dependencies": {
"@x-ui/x-dcloud-ui": "^0.2.1",
"@x-apaas/x-dcloud-page-web": "rc",
"@x-apaas/x-dcloud-page-engine": "rc",
"@x-apaas/x-apaas-frontend-i18n": "rc", "@x-apaas/x-apaas-frontend-i18n": "rc",
"@x-apaas/x-dcloud-page-engine": "rc",
"@x-apaas/x-dcloud-page-web": "rc",
"@x-ui/x-dcloud-ui": "^0.2.1",
"core-js": "^3.6.4", "core-js": "^3.6.4",
"dayjs": "^1.8.27", "dayjs": "^1.8.27",
"echarts": "^5.6.0",
"element-ui": "^2.13.2", "element-ui": "^2.13.2",
"js-file-download": "^0.4.12", "js-file-download": "^0.4.12",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
@ -55,6 +56,7 @@
"cz-conventional-changelog": "^3.2.0", "cz-conventional-changelog": "^3.2.0",
"cz-customizable": "^6.2.0", "cz-customizable": "^6.2.0",
"eslint": "^6.7.2", "eslint": "^6.7.2",
"eslint-html-reporter": "^0.7.4",
"eslint-plugin-prettier": "^3.1.1", "eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"husky": "^4.2.5", "husky": "^4.2.5",

View File

@ -147,5 +147,5 @@ export default {
url: '/xdap-app/form/query/formComponent', url: '/xdap-app/form/query/formComponent',
method: 'post', method: 'post',
disableSuccessMsg: true disableSuccessMsg: true
}, }
} }

View File

@ -25,7 +25,7 @@ export default {
url: '/custom/permission/getAllPermission', url: '/custom/permission/getAllPermission',
method: 'get' method: 'get'
}, },
DELETE_PERMISSION_DATA: { DELETE_ROLE_DATA: {
url: '/custom/permission/deleteRole', url: '/custom/permission/deleteRole',
method: 'get' method: 'get'
}, },

View File

@ -243,6 +243,9 @@
</div> </div>
<!-- 图表区域列表 --> <!-- 图表区域列表 -->
<div v-if="chartList.length == 0" class="chart-area empty-chart-area">
</div>
<div v-for="(chart, index) in chartList" :key="chart.id" class="chart-area"> <div v-for="(chart, index) in chartList" :key="chart.id" class="chart-area">
<div class="chart-header"> <div class="chart-header">
<div class="chart-title-section"> <div class="chart-title-section">
@ -299,6 +302,7 @@
<div class="config-item canshu"> <div class="config-item canshu">
<span class="config-label">Y轴(参数):</span> <span class="config-label">Y轴(参数):</span>
<el-select <el-select
:key="`y-axis-param-${chart.id}`"
v-model="chart.yAxisParam" v-model="chart.yAxisParam"
filterable filterable
multiple multiple
@ -620,7 +624,52 @@ export default {
this.formulaFormData.operator && this.formulaFormData.operator &&
this.formulaFormData.param1 !== this.formulaFormData.param2 this.formulaFormData.param1 !== this.formulaFormData.param2
) )
}
}, },
watch: {
activeTab: {
immediate: true,
handler(newVal, oldVal) {
if (newVal === 'statistics') {
window.addEventListener('resize', this.handleResize)
// Y
this.loadYAxisParams()
this.$nextTick(() => {
this.$nextTick(() => {
// DOM
setTimeout(() => {
this.chartList.forEach((chart, index) => {
if (!chart.chartInstance) {
//
if (chart._pendingInit) {
delete chart._pendingInit
delete chart._pendingInitIndex
}
this.initChart(index)
} else {
chart.chartInstance.resize()
}
})
}, 100)
})
})
} else if (oldVal === 'statistics') {
window.removeEventListener('resize', this.handleResize)
this.cleanupResizeListeners()
this.disposeAllCharts()
}
}
}
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
this.cleanupResizeListeners()
this.disposeAllCharts()
},
mounted() {
// this.handleSearch()
},
methods: {
// 穿 // 穿
filterTransferMethod(query, item) { filterTransferMethod(query, item) {
// query // query
@ -655,42 +704,7 @@ export default {
series.includes(searchText) || series.includes(searchText) ||
label.includes(searchText) label.includes(searchText)
) )
}
}, },
watch: {
activeTab: {
immediate: true,
handler(newVal, oldVal) {
if (newVal === 'statistics') {
window.addEventListener('resize', this.handleResize)
// Y
this.loadYAxisParams()
this.$nextTick(() => {
this.chartList.forEach((chart, index) => {
if (!chart.chartInstance) {
this.initChart(index)
} else {
chart.chartInstance.resize()
}
})
})
} else if (oldVal === 'statistics') {
window.removeEventListener('resize', this.handleResize)
this.cleanupResizeListeners()
this.disposeAllCharts()
}
}
}
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
this.cleanupResizeListeners()
this.disposeAllCharts()
},
mounted() {
// this.handleSearch()
},
methods: {
// Y // Y
loadYAxisParams() { loadYAxisParams() {
// //
@ -768,17 +782,30 @@ export default {
newSelectedModels: [] // newSelectedModels: [] //
} }
// //
this.chartList.unshift(newChart) //
const newChartList = [newChart, ...this.chartList]
this.chartList = newChartList
// DOM
this.$forceUpdate()
// 使 nextTick requestAnimationFrame DOM
this.$nextTick(() => { this.$nextTick(() => {
this.$nextTick(() => {
// 使 requestAnimationFrame
requestAnimationFrame(() => {
requestAnimationFrame(() => {
//
setTimeout(() => {
// //
this.initChart(0) this.initChart(0)
// //
this.$nextTick(() => {
this.chartList.forEach((chart, idx) => { this.chartList.forEach((chart, idx) => {
if (!chart.chartInstance) { if (idx !== 0 && chart && !chart.chartInstance) {
this.initChart(idx) this.initChart(idx)
} }
}) })
}, 300) // DOM
})
})
}) })
}) })
}, },
@ -803,24 +830,62 @@ export default {
}, },
handleDeleteChart(index) { handleDeleteChart(index) {
const chart = this.chartList[index] const chart = this.chartList[index]
if (chart?.chartInstance) { if (!chart) return
//
if (chart.chartInstance) {
try {
chart.chartInstance.dispose() chart.chartInstance.dispose()
} catch (e) {
console.warn('销毁图表实例时出错:', e)
}
chart.chartInstance = null chart.chartInstance = null
} }
//
chart.selectedModels = []
chart.chartDataList = []
chart.cachedModelData = {}
chart.newSelectedModels = []
//
this.chartList.splice(index, 1) this.chartList.splice(index, 1)
//
//
this.$forceUpdate()
this.$nextTick(() => {
this.$forceUpdate()
// //
// 使 nextTick DOM
this.$nextTick(() => { this.$nextTick(() => {
this.chartList.forEach((c, idx) => { this.chartList.forEach((c, idx) => {
if (c && !c.chartInstance) { if (c && !c.chartInstance) {
//
const refName = `chartContainer-${idx}`
const containerRef = this.$refs[refName]
if (containerRef) {
this.initChart(idx) this.initChart(idx)
} }
}
})
}) })
}) })
}, },
handleClearAllCharts() { handleClearAllCharts() {
this.disposeAllCharts() this.disposeAllCharts()
this.chartList = [] // - 使 splice
this.chartList.splice(0, this.chartList.length)
this.floatingPanelExpanded = false // this.floatingPanelExpanded = false //
//
this.$nextTick(() => {
this.$forceUpdate()
//
this.$nextTick(() => {
this.$forceUpdate()
})
})
}, },
// - // -
filterModelNameOptions(query) { filterModelNameOptions(query) {
@ -914,18 +979,19 @@ export default {
}) })
}, },
// Y // Y
// Y
handleFilterYAxisParam(query) { handleFilterYAxisParam(query) {
if (!query || query.trim() === '') { // query
if (!query || typeof query !== 'string' || query.trim() === '') {
// //
this.filteredYAxisParamOptions = this.yAxisParamOptions this.filteredYAxisParamOptions = this.yAxisParamOptions || []
return return
} }
// //
const queryLower = query.toLowerCase().trim() const queryLower = query.toLowerCase().trim()
this.filteredYAxisParamOptions = this.yAxisParamOptions.filter((option) => { const options = this.yAxisParamOptions || []
this.filteredYAxisParamOptions = options.filter((option) => {
// label // label
return option.label && option.label.toLowerCase().includes(queryLower) return option && option.label && option.label.toLowerCase().includes(queryLower)
}) })
}, },
// //
@ -1096,12 +1162,310 @@ export default {
if (!chart.chartHeight) { if (!chart.chartHeight) {
chart.chartHeight = 400 chart.chartHeight = 400
} }
const refName = `chartContainer-${index}` const refName = `chartContainer-${index}`
const getContainer = () => {
// 使 $refs
const containerRef = this.$refs[refName] const containerRef = this.$refs[refName]
if (!containerRef || (Array.isArray(containerRef) && !containerRef[0])) return if (containerRef) {
const container = Array.isArray(containerRef) ? containerRef[0] : containerRef return Array.isArray(containerRef) ? containerRef[0] : containerRef
}
// $refs 使 querySelector
const chartAreas = document.querySelectorAll('.chart-area')
if (chartAreas && chartAreas[index]) {
const container = chartAreas[index].querySelector('.chart-container')
if (container) {
return container
}
}
return null
}
// 使
const tryInitChart = (retryCount = 0, maxRetries = 30) => {
const container = getContainer()
if (!container) {
if (retryCount >= maxRetries) {
console.warn(`初始化图表失败,已重试 ${maxRetries} 次,无法找到容器,索引: ${index}`)
return
}
//
setTimeout(() => {
tryInitChart(retryCount + 1, maxRetries)
}, 150)
return
}
//
const style = window.getComputedStyle(container)
const isVisible = style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'
// 使
const rect = container.getBoundingClientRect()
const hasSize = (container.offsetWidth > 0 && container.offsetHeight > 0) ||
(rect.width > 0 && rect.height > 0) ||
(container.clientWidth > 0 && container.clientHeight > 0)
//
if (!isVisible) {
if (retryCount >= maxRetries) {
console.warn(`容器不可见,无法初始化图表,索引: ${index}`)
return
}
setTimeout(() => {
tryInitChart(retryCount + 1, maxRetries)
}, 150)
return
}
if (!hasSize) {
//
const parent = container.parentElement
const parentHasSize = parent && (parent.offsetWidth > 0 || parent.clientWidth > 0)
//
if (parentHasSize && retryCount < maxRetries - 3) {
//
void container.offsetHeight
//
setTimeout(() => {
tryInitChart(retryCount + 1, maxRetries)
}, 150)
return
}
// 使 ResizeObserver
if (retryCount >= maxRetries - 5 && typeof ResizeObserver !== 'undefined' && !container._resizeObserver) {
container._resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const target = entry.target
const targetRect = target.getBoundingClientRect()
const targetHasSize = (target.offsetWidth > 0 && target.offsetHeight > 0) ||
(targetRect.width > 0 && targetRect.height > 0)
if (targetHasSize && !chart.chartInstance) {
//
this.initChartWithContainer(index, target)
//
if (target._resizeObserver) {
target._resizeObserver.disconnect()
delete target._resizeObserver
}
}
}
})
container._resizeObserver.observe(container)
// 3
setTimeout(() => {
if (container._resizeObserver) {
container._resizeObserver.disconnect()
delete container._resizeObserver
}
if (!chart.chartInstance) {
// 使 resize
this.initChartWithResizeObserver(index, container, chart)
}
}, 3000)
}
if (retryCount >= maxRetries) {
// 使
this.initChartWithResizeObserver(index, container, chart)
return
}
//
setTimeout(() => {
tryInitChart(retryCount + 1, maxRetries)
}, 150)
return
}
//
this.initChartWithContainer(index, container)
}
//
this.$nextTick(() => {
this.$nextTick(() => {
tryInitChart(0, 30) // 30150ms4.5
})
})
},
// 使
initChartWithContainer(index, container) {
const chart = this.chartList[index]
if (!chart || !container) return
// 使
const rect = container.getBoundingClientRect()
const hasSize = (container.offsetWidth > 0 && container.offsetHeight > 0) ||
(rect.width > 0 && rect.height > 0) ||
(container.clientWidth > 0 && container.clientHeight > 0)
//
if (!hasSize) {
// 使 ResizeObserver
this.initChartWithResizeObserver(index, container, chart)
return
}
//
if (chart.chartInstance) {
try {
chart.chartInstance.dispose()
} catch (e) {
console.warn('销毁图表实例时出错:', e)
}
chart.chartInstance = null
}
//
try {
chart.chartInstance = echarts.init(container) chart.chartInstance = echarts.init(container)
this.updateChart(index) this.updateChart(index)
} catch (e) {
console.error('初始化图表失败:', e)
// 使 ResizeObserver
if (e.message && e.message.includes('width or height')) {
this.initChartWithResizeObserver(index, container, chart)
}
}
},
// 使 ResizeObserver
initChartWithResizeObserver(index, container, chart) {
if (!container || !chart) return
// tab
const isStatisticsTab = this.activeTab === 'statistics'
if (!isStatisticsTab) {
// tabtab
chart._pendingInit = true
chart._pendingInitIndex = index
return
}
//
const style = window.getComputedStyle(container)
const isVisible = style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'
//
let parent = container.parentElement
let parentVisible = true
while (parent && parent !== document.body) {
const parentStyle = window.getComputedStyle(parent)
if (parentStyle.display === 'none' || parentStyle.visibility === 'hidden') {
parentVisible = false
break
}
parent = parent.parentElement
}
if (!isVisible || !parentVisible) {
//
chart._pendingInit = true
chart._pendingInitIndex = index
return
}
//
const rect = container.getBoundingClientRect()
const hasSize = (container.offsetWidth > 0 && container.offsetHeight > 0) ||
(rect.width > 0 && rect.height > 0)
if (hasSize) {
//
this.initChartWithContainer(index, container)
return
}
// 使 ResizeObserver
if (typeof ResizeObserver !== 'undefined') {
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
const target = entry.target
const targetRect = target.getBoundingClientRect()
const targetHasSize = (target.offsetWidth > 0 && target.offsetHeight > 0) ||
(targetRect.width > 0 && targetRect.height > 0)
if (targetHasSize && !chart.chartInstance) {
//
try {
this.initChartWithContainer(index, target)
//
if (target._chartResizeObserver) {
target._chartResizeObserver.disconnect()
delete target._chartResizeObserver
}
//
delete chart._pendingInit
delete chart._pendingInitIndex
} catch (e) {
console.error('图表初始化失败:', e)
}
} else if (targetHasSize && chart.chartInstance) {
//
chart.chartInstance.resize()
}
}
})
observer.observe(container)
// 便
container._chartResizeObserver = observer
// 30
setTimeout(() => {
if (container._chartResizeObserver === observer && !chart.chartInstance) {
container._chartResizeObserver.disconnect()
delete container._chartResizeObserver
//
const rect = container.getBoundingClientRect()
const style = window.getComputedStyle(container)
console.warn(`容器在30秒内仍没有尺寸放弃初始化图表索引: ${index}`, {
offsetWidth: container.offsetWidth,
offsetHeight: container.offsetHeight,
clientWidth: container.clientWidth,
clientHeight: container.clientHeight,
rectWidth: rect.width,
rectHeight: rect.height,
display: style.display,
visibility: style.visibility,
opacity: style.opacity,
activeTab: this.activeTab
})
}
}, 30000) // 30
} else {
// ResizeObserver使
let checkCount = 0
const maxChecks = 150 // 30秒 / 200ms = 150
const checkInterval = setInterval(() => {
checkCount++
const rect = container.getBoundingClientRect()
const hasSize = (container.offsetWidth > 0 && container.offsetHeight > 0) ||
(rect.width > 0 && rect.height > 0)
if (hasSize && !chart.chartInstance) {
clearInterval(checkInterval)
this.initChartWithContainer(index, container)
//
delete chart._pendingInit
delete chart._pendingInitIndex
} else if (checkCount >= maxChecks) {
clearInterval(checkInterval)
if (!chart.chartInstance) {
const style = window.getComputedStyle(container)
console.warn(`容器在30秒内仍没有尺寸放弃初始化图表索引: ${index}`, {
offsetWidth: container.offsetWidth,
offsetHeight: container.offsetHeight,
activeTab: this.activeTab,
display: style.display
})
}
}
}, 200)
}
}, },
handleResize() { handleResize() {
this.chartList.forEach((chart) => { this.chartList.forEach((chart) => {
@ -1414,7 +1778,6 @@ export default {
// //
chart.newSelectedModels = [] chart.newSelectedModels = []
// //
this.updateChartDataFromCache(index) this.updateChartDataFromCache(index)
@ -2394,11 +2757,30 @@ export default {
this.resizingChartIndex = -1 this.resizingChartIndex = -1
}, },
disposeAllCharts() { disposeAllCharts() {
this.chartList.forEach((chart) => { this.chartList.forEach((chart, index) => {
if (chart.chartInstance) { if (chart.chartInstance) {
chart.chartInstance.dispose() chart.chartInstance.dispose()
chart.chartInstance = null chart.chartInstance = null
} }
// resize
if (chart._resizeHandler) {
window.removeEventListener('resize', chart._resizeHandler)
delete chart._resizeHandler
}
// ResizeObserver
const refName = `chartContainer-${index}`
const containerRef = this.$refs[refName]
if (containerRef) {
const container = Array.isArray(containerRef) ? containerRef[0] : containerRef
if (container && container._chartResizeObserver) {
container._chartResizeObserver.disconnect()
delete container._chartResizeObserver
}
if (container && container._resizeObserver) {
container._resizeObserver.disconnect()
delete container._resizeObserver
}
}
}) })
} }
} }
@ -2705,11 +3087,19 @@ export default {
} }
} }
} }
.empty-chart-area {
min-height: 2px;
padding: 0 !important;
margin: 0 !important;
box-shadow: none !important;
border-radius: 0 !important;
background: transparent !important;
}
.chart-area { .chart-area {
background: white; background: white;
margin: 20px; margin: 20px;
margin-top: 10px; margin-top: 10px;
min-height: 2px;
padding: 20px; padding: 20px;
border-radius: 4px; border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);

View File

@ -1456,8 +1456,6 @@ export default {
if (matchedSubsystemName) { if (matchedSubsystemName) {
const partsNames = subsystemPartsMap.get(matchedSubsystemName) const partsNames = subsystemPartsMap.get(matchedSubsystemName)
const subsystemName = matchedSubsystemName
// partsName '/' // partsName '/'
if (partsNames.has('/')) { if (partsNames.has('/')) {
// partsName '/' // partsName '/'

View File

@ -36,7 +36,6 @@ const SearchComponentMixin = {
return this.searchValue return this.searchValue
}, },
set: function (value) { set: function (value) {
debugger
this.$emit('change', value) this.$emit('change', value)
} }
} }

View File

@ -94,4 +94,3 @@ export function clearUserRole() {
export function hasUserRole() { export function hasUserRole() {
return localStorage.getItem(USER_ROLE_STORAGE_KEY) !== null return localStorage.getItem(USER_ROLE_STORAGE_KEY) !== null
} }

View File

@ -9,7 +9,6 @@ import Vue from 'vue'
// import i18n from '@/locale' // import i18n from '@/locale'
export const GLOABL_MENU_ACTION = { export const GLOABL_MENU_ACTION = {
TO_ROUTER: (engine, event) => { TO_ROUTER: (engine, event) => {
debugger
const { menu } = event const { menu } = event
let needRefresh = true let needRefresh = true
if (engine.layoutConfig.keepAliveRouter) { if (engine.layoutConfig.keepAliveRouter) {