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
apaas-custom-mydemo.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"
},
"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-dcloud-page-engine": "rc",
"@x-apaas/x-dcloud-page-web": "rc",
"@x-ui/x-dcloud-ui": "^0.2.1",
"core-js": "^3.6.4",
"dayjs": "^1.8.27",
"echarts": "^5.6.0",
"element-ui": "^2.13.2",
"js-file-download": "^0.4.12",
"lodash-es": "^4.17.21",
@ -55,6 +56,7 @@
"cz-conventional-changelog": "^3.2.0",
"cz-customizable": "^6.2.0",
"eslint": "^6.7.2",
"eslint-html-reporter": "^0.7.4",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-vue": "^6.2.2",
"husky": "^4.2.5",

View File

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

View File

@ -7,7 +7,7 @@ export default {
url: '/custom/permission/updateRole?userID=',
method: 'post'
},
//获取引擎列表
// 获取引擎列表
GET_ENGINE_LIST_SELF: {
url: '/custom/dataEntryEngineModel/selectByPage',
method: 'post'
@ -16,17 +16,17 @@ export default {
url: '/custom/dataEntryEngineModel/excelExport',
method: 'get'
},
//添加引擎
// 添加引擎
ADD_ENGINE_MODEL: {
url: '/custom/dataEntryEngineModel/insert',
method: 'post'
},
//导入引擎
// 导入引擎
IMPORT_ENGINE_MODEL: {
url: '/custom/dataEntryEngineModel/import',
method: 'post'
},
//获取参数列表
// 获取参数列表
GET_PARAM_LIST: {
url: '/custom/engineParamDetailPojo/selectParamList',
method: 'get'
@ -35,7 +35,7 @@ export default {
url: '/custom/dataEntryEngineModel/excelImport',
method: 'post'
},
//获取引擎详情
// 获取引擎详情
GET_ENGINE_DETAIL: {
url: '/custom/engineParamDetailPojo/selectValueByMoreParam',
method: 'post'

View File

@ -1,31 +1,31 @@
export default {
//权限管理相关接口
//获取权限管理列表
// 权限管理相关接口
// 获取权限管理列表
GET_PERMISSION_DATA: {
url: '/custom/permission/getUserRoleAndPermission',
method: 'get'
},
//保存权限管理
// 保存权限管理
SAVE_PERMISSION_DATA: {
url: '/custom/permission/insertRole',
method: 'post'
},
//修改权限管理
// 修改权限管理
EDIT_PERMISSION_DATA: {
url: '/custom/permission/updatePermission',
method: 'post'
},
//删除权限管理
// 删除权限管理
DELETE_PERMISSION_DATA: {
url: '/custom/permission/deletePermission',
method: 'get'
},
//获取所有权限表
// 获取所有权限表
GET_ALL_PERMISSION_LIST: {
url: '/custom/permission/getAllPermission',
method: 'get'
},
DELETE_PERMISSION_DATA: {
DELETE_ROLE_DATA: {
url: '/custom/permission/deleteRole',
method: 'get'
},

View File

@ -243,6 +243,9 @@
</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 class="chart-header">
<div class="chart-title-section">
@ -299,6 +302,7 @@
<div class="config-item canshu">
<span class="config-label">Y轴(参数):</span>
<el-select
:key="`y-axis-param-${chart.id}`"
v-model="chart.yAxisParam"
filterable
multiple
@ -620,7 +624,52 @@ export default {
this.formulaFormData.operator &&
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) {
// query
@ -655,42 +704,7 @@ export default {
series.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
loadYAxisParams() {
//
@ -768,17 +782,30 @@ export default {
newSelectedModels: [] //
}
//
this.chartList.unshift(newChart)
//
const newChartList = [newChart, ...this.chartList]
this.chartList = newChartList
// DOM
this.$forceUpdate()
// 使 nextTick requestAnimationFrame DOM
this.$nextTick(() => {
this.$nextTick(() => {
// 使 requestAnimationFrame
requestAnimationFrame(() => {
requestAnimationFrame(() => {
//
setTimeout(() => {
//
this.initChart(0)
//
this.$nextTick(() => {
this.chartList.forEach((chart, idx) => {
if (!chart.chartInstance) {
if (idx !== 0 && chart && !chart.chartInstance) {
this.initChart(idx)
}
})
}, 300) // DOM
})
})
})
})
},
@ -803,24 +830,62 @@ export default {
},
handleDeleteChart(index) {
const chart = this.chartList[index]
if (chart?.chartInstance) {
if (!chart) return
//
if (chart.chartInstance) {
try {
chart.chartInstance.dispose()
} catch (e) {
console.warn('销毁图表实例时出错:', e)
}
chart.chartInstance = null
}
//
chart.selectedModels = []
chart.chartDataList = []
chart.cachedModelData = {}
chart.newSelectedModels = []
//
this.chartList.splice(index, 1)
//
//
this.$forceUpdate()
this.$nextTick(() => {
this.$forceUpdate()
//
// 使 nextTick DOM
this.$nextTick(() => {
this.chartList.forEach((c, idx) => {
if (c && !c.chartInstance) {
//
const refName = `chartContainer-${idx}`
const containerRef = this.$refs[refName]
if (containerRef) {
this.initChart(idx)
}
}
})
})
})
},
handleClearAllCharts() {
this.disposeAllCharts()
this.chartList = []
// - 使 splice
this.chartList.splice(0, this.chartList.length)
this.floatingPanelExpanded = false //
//
this.$nextTick(() => {
this.$forceUpdate()
//
this.$nextTick(() => {
this.$forceUpdate()
})
})
},
// -
filterModelNameOptions(query) {
@ -914,18 +979,19 @@ export default {
})
},
// Y
// Y
handleFilterYAxisParam(query) {
if (!query || query.trim() === '') {
// query
if (!query || typeof query !== 'string' || query.trim() === '') {
//
this.filteredYAxisParamOptions = this.yAxisParamOptions
this.filteredYAxisParamOptions = this.yAxisParamOptions || []
return
}
//
const queryLower = query.toLowerCase().trim()
this.filteredYAxisParamOptions = this.yAxisParamOptions.filter((option) => {
const options = this.yAxisParamOptions || []
this.filteredYAxisParamOptions = options.filter((option) => {
// 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) {
chart.chartHeight = 400
}
const refName = `chartContainer-${index}`
const getContainer = () => {
// 使 $refs
const containerRef = this.$refs[refName]
if (!containerRef || (Array.isArray(containerRef) && !containerRef[0])) return
const container = Array.isArray(containerRef) ? containerRef[0] : containerRef
if (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)
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() {
this.chartList.forEach((chart) => {
@ -1414,7 +1778,6 @@ export default {
//
chart.newSelectedModels = []
//
this.updateChartDataFromCache(index)
@ -2394,11 +2757,30 @@ export default {
this.resizingChartIndex = -1
},
disposeAllCharts() {
this.chartList.forEach((chart) => {
this.chartList.forEach((chart, index) => {
if (chart.chartInstance) {
chart.chartInstance.dispose()
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 {
background: white;
margin: 20px;
margin-top: 10px;
min-height: 2px;
padding: 20px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);

View File

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

View File

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

View File

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

View File

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