|
|
@@ -0,0 +1,1237 @@
|
|
|
+import * as echarts from 'echarts'
|
|
|
+import { getAuditTaskList } from '@/api/auditInitiation.js'
|
|
|
+import { getAllUnitList } from '@/api/auditEntityManage.js'
|
|
|
+import { analyzeStatistics } from '@/api/comprehensive'
|
|
|
+// 综合分析页面的通用mixin
|
|
|
+export const comprehensiveMixin = {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ // 通用加载状态
|
|
|
+ loading: false,
|
|
|
+ projectOptions: [],
|
|
|
+ auditedUnitOptions: [],
|
|
|
+ // 指标树基础配置
|
|
|
+ treeProps: {
|
|
|
+ children: 'children',
|
|
|
+ label: 'label',
|
|
|
+ },
|
|
|
+ // 图表实例集合
|
|
|
+ chartInstances: {},
|
|
|
+ // 组件是否已销毁标志
|
|
|
+ isDestroyed: false,
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.getOptions()
|
|
|
+ // 监听窗口大小变化
|
|
|
+ window.addEventListener('resize', this.handleResize)
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ // 标记组件已销毁
|
|
|
+ this.isDestroyed = true
|
|
|
+ // 销毁所有图表实例
|
|
|
+ this.destroyCharts()
|
|
|
+ // 移除窗口大小变化监听
|
|
|
+ window.removeEventListener('resize', this.handleResize)
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 根据索引获取颜色
|
|
|
+ getColorByIndex(index) {
|
|
|
+ const colors = [
|
|
|
+ '#5470C6', // 蓝色
|
|
|
+ '#91CC75', // 绿色
|
|
|
+ '#FAC858', // 黄色
|
|
|
+ '#EE6666', // 红色
|
|
|
+ '#73C0DE', // 浅蓝色
|
|
|
+ '#3BA272', // 深绿色
|
|
|
+ '#FC8452', // 橙色
|
|
|
+ '#9A60B4', // 紫色
|
|
|
+ ]
|
|
|
+ return colors[index % colors.length]
|
|
|
+ },
|
|
|
+
|
|
|
+ // 将 costSurveysList 组装为树结构(用于左侧勾选)
|
|
|
+ buildIndicatorTree(costSurveysList = []) {
|
|
|
+ const processNode = (item) => {
|
|
|
+ const node = {
|
|
|
+ ...item,
|
|
|
+ label: this.buildIndicatorLabel(item),
|
|
|
+ children: [],
|
|
|
+ }
|
|
|
+ // 如果有子项,递归处理
|
|
|
+ if (Array.isArray(item.costSurveysVos) && item.costSurveysVos.length) {
|
|
|
+ node.children = item.costSurveysVos.map(processNode)
|
|
|
+ }
|
|
|
+ return node
|
|
|
+ }
|
|
|
+
|
|
|
+ return costSurveysList.map(processNode)
|
|
|
+ },
|
|
|
+
|
|
|
+ // label 规则:parentId 为 -1 时,用 “number、name”,否则 “number.name”
|
|
|
+ buildIndicatorLabel(item) {
|
|
|
+ const num = item.number || ''
|
|
|
+ const nm = item.name || ''
|
|
|
+ if (!num) return nm
|
|
|
+ const isRoot = !item.parentId || item.parentId === '-1'
|
|
|
+ return isRoot ? `${num}、${nm}` : `${num}.${nm}`
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取树的叶子 id 列表
|
|
|
+ getLeafIds(tree = []) {
|
|
|
+ const ids = []
|
|
|
+ const dfs = (node) => {
|
|
|
+ if (!node.children || node.children.length === 0) {
|
|
|
+ ids.push(node.id)
|
|
|
+ } else {
|
|
|
+ node.children.forEach(dfs)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tree.forEach(dfs)
|
|
|
+ return ids
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取树的父级(拥有子节点)id 列表和节点列表
|
|
|
+ getParentIds(tree = []) {
|
|
|
+ const ids = []
|
|
|
+ const items = []
|
|
|
+ const dfs = (node) => {
|
|
|
+ if (node.parentId == '-1') {
|
|
|
+ ids.push(node.id)
|
|
|
+ items.push(node)
|
|
|
+ node.children.forEach(dfs)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tree.forEach(dfs)
|
|
|
+ return { ids, items }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 去重成本列表:同级内去重,优先按 id,其次 rowId/rowid,再按 parentId+number+name
|
|
|
+ dedupeCostSurveysList(list = []) {
|
|
|
+ const dedupeLevel = (arr = []) => {
|
|
|
+ const seenIds = new Set()
|
|
|
+ const seenRowIds = new Set()
|
|
|
+ const seenCombo = new Set()
|
|
|
+ const result = []
|
|
|
+ for (const node of arr || []) {
|
|
|
+ if (!node) continue
|
|
|
+ const normId =
|
|
|
+ node.id !== undefined && node.id !== null
|
|
|
+ ? String(node.id).trim()
|
|
|
+ : ''
|
|
|
+ const normRowId =
|
|
|
+ node.rowId !== undefined && node.rowId !== null
|
|
|
+ ? String(node.rowId).trim()
|
|
|
+ : node.rowid !== undefined && node.rowid !== null
|
|
|
+ ? String(node.rowid).trim()
|
|
|
+ : ''
|
|
|
+ const normParent =
|
|
|
+ node.parentId !== undefined && node.parentId !== null
|
|
|
+ ? String(node.parentId).trim()
|
|
|
+ : ''
|
|
|
+ const normNumber =
|
|
|
+ node.number !== undefined && node.number !== null
|
|
|
+ ? String(node.number).trim()
|
|
|
+ : ''
|
|
|
+ const normName =
|
|
|
+ node.name !== undefined && node.name !== null
|
|
|
+ ? String(node.name).trim()
|
|
|
+ : ''
|
|
|
+ const comboKey = `p:${normParent}|num:${normNumber}|name:${normName}`
|
|
|
+
|
|
|
+ // 先用 id 去重
|
|
|
+ if (normId && seenIds.has(normId)) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 其次用 rowId/rowid 去重
|
|
|
+ if (!normId && normRowId && seenRowIds.has(normRowId)) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 再用组合字段去重(处理不同 id 但显示相同的重复)
|
|
|
+ if (!normId && !normRowId && seenCombo.has(comboKey)) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if (normId) {
|
|
|
+ seenIds.add(normId)
|
|
|
+ } else if (normRowId) {
|
|
|
+ seenRowIds.add(normRowId)
|
|
|
+ } else {
|
|
|
+ seenCombo.add(comboKey)
|
|
|
+ }
|
|
|
+
|
|
|
+ const next = {
|
|
|
+ ...node,
|
|
|
+ id: normId || node.id,
|
|
|
+ rowId: normRowId || node.rowId || node.rowid,
|
|
|
+ parentId: normParent || node.parentId,
|
|
|
+ number: normNumber || node.number,
|
|
|
+ name: normName || node.name,
|
|
|
+ }
|
|
|
+ if (
|
|
|
+ Array.isArray(node.costSurveysVos) &&
|
|
|
+ node.costSurveysVos.length > 0
|
|
|
+ ) {
|
|
|
+ next.costSurveysVos = dedupeLevel(node.costSurveysVos)
|
|
|
+ }
|
|
|
+ result.push(next)
|
|
|
+ }
|
|
|
+ return result
|
|
|
+ }
|
|
|
+ return dedupeLevel(list)
|
|
|
+ },
|
|
|
+
|
|
|
+ // 统一请求统计数据(接口失败或无数据时使用mock)
|
|
|
+ async requestStatistics(params = {}) {
|
|
|
+ // 如果组件已销毁,直接返回 mock 数据
|
|
|
+ if (this.isDestroyed) {
|
|
|
+ return mockStatisticsData
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ const res = await analyzeStatistics(params)
|
|
|
+ // 再次检查组件是否已销毁
|
|
|
+ if (this.isDestroyed) {
|
|
|
+ return mockStatisticsData
|
|
|
+ }
|
|
|
+ if (res && res.value) return res.value
|
|
|
+ } catch (e) {
|
|
|
+ // 如果是请求中止错误,静默处理
|
|
|
+ if (e && e.message && e.message.includes('aborted')) {
|
|
|
+ return mockStatisticsData
|
|
|
+ }
|
|
|
+ // 其他错误才打印警告
|
|
|
+ if (!this.isDestroyed) {
|
|
|
+ console.warn('analyzeStatistics 调用失败,使用 mock 数据', e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return mockStatisticsData
|
|
|
+ },
|
|
|
+
|
|
|
+ getOptions() {
|
|
|
+ // 获取监审任务列表
|
|
|
+ getAuditTaskList()
|
|
|
+ .then((res) => {
|
|
|
+ if (!this.isDestroyed && res && res.value) {
|
|
|
+ this.projectOptions = res.value
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch((e) => {
|
|
|
+ // 如果是请求中止错误,静默处理
|
|
|
+ if (e && e.message && !e.message.includes('aborted')) {
|
|
|
+ console.warn('获取项目列表失败', e)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ getAllUnitList()
|
|
|
+ .then((res) => {
|
|
|
+ if (!this.isDestroyed && res && res.value) {
|
|
|
+ this.auditedUnitOptions = res.value
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch((e) => {
|
|
|
+ // 如果是请求中止错误,静默处理
|
|
|
+ if (e && e.message && !e.message.includes('aborted')) {
|
|
|
+ console.warn('获取单位列表失败', e)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 根据选中的指标 ID 过滤 costSurveysList
|
|
|
+ filterCostSurveysListBySelectedIds(costSurveysList = [], selectedIds = []) {
|
|
|
+ if (!selectedIds || selectedIds.length === 0) {
|
|
|
+ return []
|
|
|
+ }
|
|
|
+ const selectedIdSet = new Set(selectedIds)
|
|
|
+
|
|
|
+ // 递归过滤节点
|
|
|
+ const filterNode = (node) => {
|
|
|
+ if (!node) return null
|
|
|
+
|
|
|
+ // 如果当前节点被选中,保留它及其所有子节点
|
|
|
+ if (selectedIdSet.has(node.id)) {
|
|
|
+ const filteredNode = { ...node }
|
|
|
+ if (
|
|
|
+ Array.isArray(node.costSurveysVos) &&
|
|
|
+ node.costSurveysVos.length
|
|
|
+ ) {
|
|
|
+ // 如果父节点被选中,保留所有子节点
|
|
|
+ filteredNode.costSurveysVos = node.costSurveysVos.map((child) => ({
|
|
|
+ ...child,
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ return filteredNode
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果当前节点未被选中,检查是否有子节点被选中
|
|
|
+ if (Array.isArray(node.costSurveysVos) && node.costSurveysVos.length) {
|
|
|
+ const filteredChildren = node.costSurveysVos
|
|
|
+ .map(filterNode)
|
|
|
+ .filter(Boolean)
|
|
|
+ if (filteredChildren.length > 0) {
|
|
|
+ // 如果有子节点被选中,保留父节点和选中的子节点
|
|
|
+ return {
|
|
|
+ ...node,
|
|
|
+ costSurveysVos: filteredChildren,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return null
|
|
|
+ }
|
|
|
+
|
|
|
+ return costSurveysList.map(filterNode).filter(Boolean)
|
|
|
+ },
|
|
|
+
|
|
|
+ // 将 costSurveysList 展平为趋势数据 [{indicatorName, year, value}]
|
|
|
+ // 规则:只展示选中节点对应的年度数据(surveysVos),不追加“合计年”;若无则递归子节点
|
|
|
+ transformTrendFromCostList(costSurveysList = []) {
|
|
|
+ const trendArr = []
|
|
|
+ const dfs = (node) => {
|
|
|
+ if (!node) return
|
|
|
+
|
|
|
+ if (Array.isArray(node.surveysVos) && node.surveysVos.length) {
|
|
|
+ node.surveysVos.forEach((sv) => {
|
|
|
+ const yearKey = String(sv.name || sv.year || '').trim()
|
|
|
+ if (!yearKey) return
|
|
|
+ trendArr.push({
|
|
|
+ indicatorName: node.name,
|
|
|
+ year: yearKey,
|
|
|
+ value: Number(sv.value) || 0,
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Array.isArray(node.costSurveysVos) && node.costSurveysVos.length) {
|
|
|
+ node.costSurveysVos.forEach(dfs)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ costSurveysList.forEach(dfs)
|
|
|
+ return trendArr
|
|
|
+ },
|
|
|
+
|
|
|
+ // 将 costSurveysList 汇总为构成数据 [{name, value}](叶子求和)
|
|
|
+ transformCompositionFromCostList(costSurveysList = []) {
|
|
|
+ const result = []
|
|
|
+ const dfs = (node) => {
|
|
|
+ if (!node) return
|
|
|
+ if (Array.isArray(node.costSurveysVos) && node.costSurveysVos.length) {
|
|
|
+ node.costSurveysVos.forEach(dfs)
|
|
|
+ } else {
|
|
|
+ const total = Array.isArray(node.surveysVos)
|
|
|
+ ? node.surveysVos.reduce(
|
|
|
+ (sum, sv) => sum + (Number(sv.value) || 0),
|
|
|
+ 0
|
|
|
+ )
|
|
|
+ : 0
|
|
|
+ result.push({
|
|
|
+ name: node.name,
|
|
|
+ value: total,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ costSurveysList.forEach(dfs)
|
|
|
+ return result
|
|
|
+ },
|
|
|
+
|
|
|
+ // 构建趋势图数据结构(xAxis + series)
|
|
|
+ buildTrendSeries(trendArr = []) {
|
|
|
+ const years = [
|
|
|
+ ...new Set(
|
|
|
+ trendArr
|
|
|
+ .map((item) =>
|
|
|
+ String(item.year || item.name || '').replace('年', '')
|
|
|
+ )
|
|
|
+ .filter(Boolean)
|
|
|
+ ),
|
|
|
+ ]
|
|
|
+ .sort()
|
|
|
+ .map((y) => `${y}年`)
|
|
|
+
|
|
|
+ const indicatorMap = {}
|
|
|
+ trendArr.forEach((item) => {
|
|
|
+ const yearKey = String(item.year || item.name || '').replace('年', '')
|
|
|
+ if (!yearKey) return
|
|
|
+ if (!indicatorMap[item.indicatorName]) {
|
|
|
+ indicatorMap[item.indicatorName] = {
|
|
|
+ name: item.indicatorName,
|
|
|
+ data: {},
|
|
|
+ color: this.getColorByIndex(Object.keys(indicatorMap).length),
|
|
|
+ }
|
|
|
+ }
|
|
|
+ indicatorMap[item.indicatorName].data[yearKey] = Number(item.value) || 0
|
|
|
+ })
|
|
|
+
|
|
|
+ const series = Object.values(indicatorMap).map((indicator) => ({
|
|
|
+ name: indicator.name,
|
|
|
+ data: years.map((y) => {
|
|
|
+ const key = y.replace('年', '')
|
|
|
+ return indicator.data[key] || 0
|
|
|
+ }),
|
|
|
+ color: indicator.color,
|
|
|
+ }))
|
|
|
+
|
|
|
+ return { xAxis: years, series }
|
|
|
+ },
|
|
|
+ // 初始化图表
|
|
|
+ initChart(chartId, containerId) {
|
|
|
+ const chartDom = document.getElementById(containerId)
|
|
|
+ if (chartDom) {
|
|
|
+ this.chartInstances[chartId] = echarts.init(chartDom)
|
|
|
+ return this.chartInstances[chartId]
|
|
|
+ }
|
|
|
+ return null
|
|
|
+ },
|
|
|
+
|
|
|
+ // 销毁指定图表实例
|
|
|
+ destroyChart(chartId) {
|
|
|
+ if (this.chartInstances[chartId]) {
|
|
|
+ this.chartInstances[chartId].dispose()
|
|
|
+ delete this.chartInstances[chartId]
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 销毁所有图表实例
|
|
|
+ destroyCharts() {
|
|
|
+ Object.keys(this.chartInstances).forEach((chartId) => {
|
|
|
+ this.destroyChart(chartId)
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理窗口大小变化
|
|
|
+ handleResize() {
|
|
|
+ // 调整所有图表大小
|
|
|
+ Object.values(this.chartInstances).forEach((chart) => {
|
|
|
+ if (chart) {
|
|
|
+ chart.resize()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 更新图表数据
|
|
|
+ updateChart(chartId, option) {
|
|
|
+ if (this.chartInstances[chartId]) {
|
|
|
+ this.chartInstances[chartId].setOption(option)
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.chartInstances[chartId].resize()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取趋势图表基础配置
|
|
|
+ getBaseTrendChartOption(
|
|
|
+ seriesData = [],
|
|
|
+ xAxisData = ['2022年', '2023年', '2024年']
|
|
|
+ ) {
|
|
|
+ return {
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ axisPointer: {
|
|
|
+ type: 'cross',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ show: true,
|
|
|
+ data: seriesData.map((item) => item.name),
|
|
|
+ bottom: 0,
|
|
|
+ left: 'center',
|
|
|
+ itemGap: 20,
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 12,
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ bottom: '15%',
|
|
|
+ top: '10%',
|
|
|
+ containLabel: true,
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ boundaryGap: false,
|
|
|
+ data: xAxisData,
|
|
|
+ show: true,
|
|
|
+ axisLine: {
|
|
|
+ show: true,
|
|
|
+ lineStyle: {
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: true,
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ show: true,
|
|
|
+ fontSize: 12,
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ show: true,
|
|
|
+ axisLine: {
|
|
|
+ show: true,
|
|
|
+ lineStyle: {
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ axisTick: {
|
|
|
+ show: false,
|
|
|
+ },
|
|
|
+ axisLabel: {
|
|
|
+ show: true,
|
|
|
+ fontSize: 12,
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ show: true,
|
|
|
+ lineStyle: {
|
|
|
+ type: 'dashed',
|
|
|
+ color: '#e0e0e0',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ series: seriesData.map((item) => ({
|
|
|
+ name: item.name,
|
|
|
+ type: 'line',
|
|
|
+ data: item.data,
|
|
|
+ symbol: 'circle',
|
|
|
+ symbolSize: 8,
|
|
|
+ smooth: false,
|
|
|
+ lineStyle: {
|
|
|
+ width: 2,
|
|
|
+ color: item.color || '#37A2DA',
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ color: item.color || '#37A2DA',
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ focus: 'series',
|
|
|
+ },
|
|
|
+ })),
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取构成图表基础配置(historyAnalysis.vue 使用)
|
|
|
+ getBaseCompositionChartOption(data = []) {
|
|
|
+ return {
|
|
|
+ tooltip: {
|
|
|
+ show: true,
|
|
|
+ trigger: 'item',
|
|
|
+ formatter: (p) => `${p.name}: ${p.value} (${p.percent}%)`,
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ show: true,
|
|
|
+ orient: 'vertical',
|
|
|
+ right: 10,
|
|
|
+ top: 'center',
|
|
|
+ data: data.map((item) => item.name),
|
|
|
+ formatter: function (name) {
|
|
|
+ return name
|
|
|
+ },
|
|
|
+ itemGap: 10,
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 12,
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ itemWidth: 14,
|
|
|
+ itemHeight: 14,
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '成本构成',
|
|
|
+ type: 'pie',
|
|
|
+ radius: '60%',
|
|
|
+ center: ['35%', '50%'],
|
|
|
+ avoidLabelOverlap: true,
|
|
|
+ itemStyle: {
|
|
|
+ borderRadius: 0,
|
|
|
+ borderColor: '#fff',
|
|
|
+ borderWidth: 1,
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ position: 'outside',
|
|
|
+ formatter: '{b}',
|
|
|
+ fontSize: 12,
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ labelLine: {
|
|
|
+ show: true,
|
|
|
+ length: 10,
|
|
|
+ length2: 5,
|
|
|
+ lineStyle: {
|
|
|
+ width: 1,
|
|
|
+ color: '#999',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ fontSize: 12,
|
|
|
+ fontWeight: 'normal',
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ shadowBlur: 0,
|
|
|
+ shadowOffsetX: 0,
|
|
|
+ shadowColor: 'transparent',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data: data,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取构成图表基础配置(industryAnalysis.vue 使用)
|
|
|
+ getIndustryCompositionChartOption(data = []) {
|
|
|
+ const colorPalette = [
|
|
|
+ '#5470C6', // 蓝色 - 基本工资
|
|
|
+ '#73C0DE', // 青色/蓝绿色 - 津贴
|
|
|
+ '#91CC75', // 绿色 - 奖金
|
|
|
+ '#FAC858', // 黄色 - 福利费
|
|
|
+ '#FF85C0', // 粉色 - 其他人员支出
|
|
|
+ '#EE6666', // 红色
|
|
|
+ '#3BA272', // 深绿色
|
|
|
+ '#FC8452', // 橙色
|
|
|
+ '#9A60B4', // 紫色
|
|
|
+ '#E71D36', // 深红
|
|
|
+ ]
|
|
|
+ return {
|
|
|
+ color: colorPalette,
|
|
|
+ tooltip: {
|
|
|
+ show: true,
|
|
|
+ trigger: 'item',
|
|
|
+ formatter: (p) => `${p.name}: ${p.value} (${p.percent}%)`,
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ show: true,
|
|
|
+ orient: 'horizontal',
|
|
|
+ bottom: 10,
|
|
|
+ left: 'center',
|
|
|
+ data: data.map((item) => item.name),
|
|
|
+ icon: 'circle',
|
|
|
+ itemGap: 20,
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 12,
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ itemWidth: 10,
|
|
|
+ itemHeight: 10,
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '成本构成',
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['40%', '60%'], // 环形图
|
|
|
+ center: ['50%', '45%'],
|
|
|
+ avoidLabelOverlap: true,
|
|
|
+ silent: false,
|
|
|
+ itemStyle: {
|
|
|
+ borderRadius: 0,
|
|
|
+ borderColor: '#fff',
|
|
|
+ borderWidth: 1,
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ position: 'outside',
|
|
|
+ formatter: '{b}: {d}%', // 名称: 百分比
|
|
|
+ fontSize: 12,
|
|
|
+ color: '#333',
|
|
|
+ },
|
|
|
+ labelLine: {
|
|
|
+ show: true,
|
|
|
+ length: 10,
|
|
|
+ length2: 5,
|
|
|
+ lineStyle: {
|
|
|
+ width: 1,
|
|
|
+ color: '#999',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ fontSize: 12,
|
|
|
+ fontWeight: 'normal',
|
|
|
+ },
|
|
|
+ itemStyle: {
|
|
|
+ shadowBlur: 0,
|
|
|
+ shadowOffsetX: 0,
|
|
|
+ shadowColor: 'transparent',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data: data,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 轮播功能基础配置(仅historyAnalysis.vue使用)
|
|
|
+ initCarousel(chartId, totalPages = 1, onPageChange) {
|
|
|
+ // 若已有轮播,先清理旧定时器,避免重复计时导致数据持续跳动
|
|
|
+ if (this.carouselConfigs && this.carouselConfigs[chartId]) {
|
|
|
+ this.pauseCarousel(chartId)
|
|
|
+ }
|
|
|
+ const carouselConfig = {
|
|
|
+ totalPages,
|
|
|
+ currentPage: 0,
|
|
|
+ timer: null,
|
|
|
+ interval: 5000,
|
|
|
+ onPageChange,
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存轮播配置
|
|
|
+ this.carouselConfigs = this.carouselConfigs || {}
|
|
|
+ this.carouselConfigs[chartId] = carouselConfig
|
|
|
+
|
|
|
+ // 启动轮播
|
|
|
+ if (totalPages > 1) {
|
|
|
+ this.startCarousel(chartId)
|
|
|
+ } else {
|
|
|
+ // 单页不需要轮播,但仍确保跳转到第一页
|
|
|
+ this.goToCarouselPage(chartId, 0)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 启动轮播
|
|
|
+ startCarousel(chartId) {
|
|
|
+ const config = this.carouselConfigs?.[chartId]
|
|
|
+ if (!config) return
|
|
|
+
|
|
|
+ // 清除现有定时器
|
|
|
+ this.pauseCarousel(chartId)
|
|
|
+
|
|
|
+ // 设置新定时器
|
|
|
+ config.timer = setInterval(() => {
|
|
|
+ config.currentPage = (config.currentPage + 1) % config.totalPages
|
|
|
+ this.goToCarouselPage(chartId, config.currentPage)
|
|
|
+ }, config.interval)
|
|
|
+ },
|
|
|
+
|
|
|
+ // 暂停轮播
|
|
|
+ pauseCarousel(chartId) {
|
|
|
+ const config = this.carouselConfigs?.[chartId]
|
|
|
+ if (config?.timer) {
|
|
|
+ clearInterval(config.timer)
|
|
|
+ config.timer = null
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 恢复轮播
|
|
|
+ resumeCarousel(chartId) {
|
|
|
+ this.startCarousel(chartId)
|
|
|
+ },
|
|
|
+
|
|
|
+ // 跳转到指定轮播页
|
|
|
+ goToCarouselPage(chartId, pageIndex) {
|
|
|
+ const config = this.carouselConfigs?.[chartId]
|
|
|
+ if (!config) return
|
|
|
+
|
|
|
+ config.currentPage = pageIndex
|
|
|
+ if (typeof config.onPageChange === 'function') {
|
|
|
+ config.onPageChange(pageIndex)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+}
|
|
|
+
|
|
|
+// mock 数据
|
|
|
+export const mockStatisticsData = {
|
|
|
+ costSurveysList: [
|
|
|
+ {
|
|
|
+ id: '1997964654884069376',
|
|
|
+ name: '人数',
|
|
|
+ orderNum: '1',
|
|
|
+ rowid: 'ce2c23fd-0a60-4d98-a27e-d5344c7f2f7b',
|
|
|
+ number: '一',
|
|
|
+ rvalue: '2',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '-1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2024', value: '30' },
|
|
|
+ { name: '2025', value: '35' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: [
|
|
|
+ {
|
|
|
+ id: '1997964655014092800',
|
|
|
+ name: '1班',
|
|
|
+ orderNum: '2',
|
|
|
+ rowid: '0a075d08-1805-4ce0-a5e1-c4f264db76bd',
|
|
|
+ number: '1',
|
|
|
+ rvalue: '4',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'ce2c23fd-0a60-4d98-a27e-d5344c7f2f7b',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2024', value: '12' },
|
|
|
+ { name: '2025', value: '15' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964655131533312',
|
|
|
+ name: '2班',
|
|
|
+ orderNum: '3',
|
|
|
+ rowid: 'ab3efd32-9a10-4355-8d6e-19d99ebdbe4a',
|
|
|
+ number: '2',
|
|
|
+ rvalue: '7',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'ce2c23fd-0a60-4d98-a27e-d5344c7f2f7b',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2024', value: '18' },
|
|
|
+ { name: '2025', value: '20' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964655244779520',
|
|
|
+ name: '1班费用',
|
|
|
+ orderNum: '4',
|
|
|
+ rowid: '6a81c1d3-ea8b-48d5-bd11-27e5b150cea1',
|
|
|
+ number: '二',
|
|
|
+ rvalue: '53',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '-1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2024', value: '120' },
|
|
|
+ { name: '2025', value: '140' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: [
|
|
|
+ {
|
|
|
+ id: '1997964655387385856',
|
|
|
+ name: '押金',
|
|
|
+ orderNum: '5',
|
|
|
+ rowid: 'bf17169e-9d03-49f0-b7c7-7502879a935b',
|
|
|
+ number: '1',
|
|
|
+ rvalue: '124',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '6a81c1d3-ea8b-48d5-bd11-27e5b150cea1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2024', value: '50' },
|
|
|
+ { name: '2025', value: '60' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964655559352320',
|
|
|
+ name: '缴纳',
|
|
|
+ orderNum: '6',
|
|
|
+ rowid: 'e130564b-dc73-4fa9-a004-01c3af418021',
|
|
|
+ number: '2',
|
|
|
+ rvalue: '146',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '6a81c1d3-ea8b-48d5-bd11-27e5b150cea1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2024', value: '70' },
|
|
|
+ { name: '2025', value: '80' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964655680987136',
|
|
|
+ name: '班级乘法',
|
|
|
+ orderNum: '7',
|
|
|
+ rowid: 'aec785e0-86fa-436e-be7b-bb9d2d9eaf32',
|
|
|
+ number: '三',
|
|
|
+ rvalue: '246',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '-1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2024', value: '300' },
|
|
|
+ { name: '2025', value: '320' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: [],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964655794233344',
|
|
|
+ name: '人均费用',
|
|
|
+ orderNum: '8',
|
|
|
+ rowid: '857ba697-aaf0-4e26-97a6-4bd97d8ff6f7',
|
|
|
+ number: '四',
|
|
|
+ rvalue: '246',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '-1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2024', value: '15' },
|
|
|
+ { name: '2025', value: '16' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: [],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964655903279104',
|
|
|
+ name: '材料成本',
|
|
|
+ orderNum: '9',
|
|
|
+ rowid: 'f3a8b2c1-5d6e-4f7a-8b9c-0d1e2f3a4b5c',
|
|
|
+ number: '五',
|
|
|
+ rvalue: '580',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '-1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '450' },
|
|
|
+ { name: '2023', value: '520' },
|
|
|
+ { name: '2024', value: '580' },
|
|
|
+ { name: '2025', value: '620' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: [
|
|
|
+ {
|
|
|
+ id: '1997964656012324864',
|
|
|
+ name: '原材料',
|
|
|
+ orderNum: '10',
|
|
|
+ rowid: 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d',
|
|
|
+ number: '1',
|
|
|
+ rvalue: '320',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'f3a8b2c1-5d6e-4f7a-8b9c-0d1e2f3a4b5c',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '250' },
|
|
|
+ { name: '2023', value: '290' },
|
|
|
+ { name: '2024', value: '320' },
|
|
|
+ { name: '2025', value: '350' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964656121370624',
|
|
|
+ name: '辅助材料',
|
|
|
+ orderNum: '11',
|
|
|
+ rowid: 'b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e',
|
|
|
+ number: '2',
|
|
|
+ rvalue: '180',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'f3a8b2c1-5d6e-4f7a-8b9c-0d1e2f3a4b5c',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '140' },
|
|
|
+ { name: '2023', value: '160' },
|
|
|
+ { name: '2024', value: '180' },
|
|
|
+ { name: '2025', value: '200' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964656230416384',
|
|
|
+ name: '包装材料',
|
|
|
+ orderNum: '12',
|
|
|
+ rowid: 'c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f',
|
|
|
+ number: '3',
|
|
|
+ rvalue: '80',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'f3a8b2c1-5d6e-4f7a-8b9c-0d1e2f3a4b5c',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '60' },
|
|
|
+ { name: '2023', value: '70' },
|
|
|
+ { name: '2024', value: '80' },
|
|
|
+ { name: '2025', value: '70' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964656339462144',
|
|
|
+ name: '人工成本',
|
|
|
+ orderNum: '13',
|
|
|
+ rowid: 'd4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a',
|
|
|
+ number: '六',
|
|
|
+ rvalue: '850',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '-1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '680' },
|
|
|
+ { name: '2023', value: '750' },
|
|
|
+ { name: '2024', value: '850' },
|
|
|
+ { name: '2025', value: '920' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: [
|
|
|
+ {
|
|
|
+ id: '1997964656448507904',
|
|
|
+ name: '基本工资',
|
|
|
+ orderNum: '14',
|
|
|
+ rowid: 'e5f6a7b8-c9d0-4e1f-2a3b-4c5d6e7f8a9b',
|
|
|
+ number: '1',
|
|
|
+ rvalue: '520',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'd4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '420' },
|
|
|
+ { name: '2023', value: '460' },
|
|
|
+ { name: '2024', value: '520' },
|
|
|
+ { name: '2025', value: '580' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964656557553664',
|
|
|
+ name: '绩效奖金',
|
|
|
+ orderNum: '15',
|
|
|
+ rowid: 'f6a7b8c9-d0e1-4f2a-3b4c-5d6e7f8a9b0c',
|
|
|
+ number: '2',
|
|
|
+ rvalue: '200',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'd4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '150' },
|
|
|
+ { name: '2023', value: '180' },
|
|
|
+ { name: '2024', value: '200' },
|
|
|
+ { name: '2025', value: '220' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964656666599424',
|
|
|
+ name: '社保公积金',
|
|
|
+ orderNum: '16',
|
|
|
+ rowid: 'a7b8c9d0-e1f2-4a3b-4c5d-6e7f8a9b0c1d',
|
|
|
+ number: '3',
|
|
|
+ rvalue: '130',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'd4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '110' },
|
|
|
+ { name: '2023', value: '120' },
|
|
|
+ { name: '2024', value: '130' },
|
|
|
+ { name: '2025', value: '120' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964656775645184',
|
|
|
+ name: '设备成本',
|
|
|
+ orderNum: '17',
|
|
|
+ rowid: 'b8c9d0e1-f2a3-4b4c-5d6e-7f8a9b0c1d2e',
|
|
|
+ number: '七',
|
|
|
+ rvalue: '420',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '-1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '380' },
|
|
|
+ { name: '2023', value: '400' },
|
|
|
+ { name: '2024', value: '420' },
|
|
|
+ { name: '2025', value: '450' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: [
|
|
|
+ {
|
|
|
+ id: '1997964656884690944',
|
|
|
+ name: '设备折旧',
|
|
|
+ orderNum: '18',
|
|
|
+ rowid: 'c9d0e1f2-a3b4-4c5d-6e7f-8a9b0c1d2e3f',
|
|
|
+ number: '1',
|
|
|
+ rvalue: '280',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'b8c9d0e1-f2a3-4b4c-5d6e-7f8a9b0c1d2e',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '260' },
|
|
|
+ { name: '2023', value: '270' },
|
|
|
+ { name: '2024', value: '280' },
|
|
|
+ { name: '2025', value: '300' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964656993736704',
|
|
|
+ name: '设备维护',
|
|
|
+ orderNum: '19',
|
|
|
+ rowid: 'd0e1f2a3-b4c5-4d6e-7f8a-9b0c1d2e3f4a',
|
|
|
+ number: '2',
|
|
|
+ rvalue: '90',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'b8c9d0e1-f2a3-4b4c-5d6e-7f8a9b0c1d2e',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '80' },
|
|
|
+ { name: '2023', value: '85' },
|
|
|
+ { name: '2024', value: '90' },
|
|
|
+ { name: '2025', value: '100' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964657102782464',
|
|
|
+ name: '设备租赁',
|
|
|
+ orderNum: '20',
|
|
|
+ rowid: 'e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b',
|
|
|
+ number: '3',
|
|
|
+ rvalue: '50',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'b8c9d0e1-f2a3-4b4c-5d6e-7f8a9b0c1d2e',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '40' },
|
|
|
+ { name: '2023', value: '45' },
|
|
|
+ { name: '2024', value: '50' },
|
|
|
+ { name: '2025', value: '50' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964657211828224',
|
|
|
+ name: '管理费用',
|
|
|
+ orderNum: '21',
|
|
|
+ rowid: 'f2a3b4c5-d6e7-4f8a-9b0c-1d2e3f4a5b6c',
|
|
|
+ number: '八',
|
|
|
+ rvalue: '360',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '-1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '320' },
|
|
|
+ { name: '2023', value: '340' },
|
|
|
+ { name: '2024', value: '360' },
|
|
|
+ { name: '2025', value: '380' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: [
|
|
|
+ {
|
|
|
+ id: '1997964657320873984',
|
|
|
+ name: '办公费用',
|
|
|
+ orderNum: '22',
|
|
|
+ rowid: 'a3b4c5d6-e7f8-4a9b-0c1d-2e3f4a5b6c7d',
|
|
|
+ number: '1',
|
|
|
+ rvalue: '150',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'f2a3b4c5-d6e7-4f8a-9b0c-1d2e3f4a5b6c',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '130' },
|
|
|
+ { name: '2023', value: '140' },
|
|
|
+ { name: '2024', value: '150' },
|
|
|
+ { name: '2025', value: '160' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964657429919744',
|
|
|
+ name: '差旅费用',
|
|
|
+ orderNum: '23',
|
|
|
+ rowid: 'b4c5d6e7-f8a9-4b0c-1d2e-3f4a5b6c7d8e',
|
|
|
+ number: '2',
|
|
|
+ rvalue: '120',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'f2a3b4c5-d6e7-4f8a-9b0c-1d2e3f4a5b6c',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '110' },
|
|
|
+ { name: '2023', value: '115' },
|
|
|
+ { name: '2024', value: '120' },
|
|
|
+ { name: '2025', value: '130' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964657538965504',
|
|
|
+ name: '培训费用',
|
|
|
+ orderNum: '24',
|
|
|
+ rowid: 'c5d6e7f8-a9b0-4c1d-2e3f-4a5b6c7d8e9f',
|
|
|
+ number: '3',
|
|
|
+ rvalue: '90',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'f2a3b4c5-d6e7-4f8a-9b0c-1d2e3f4a5b6c',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '80' },
|
|
|
+ { name: '2023', value: '85' },
|
|
|
+ { name: '2024', value: '90' },
|
|
|
+ { name: '2025', value: '90' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964657648011264',
|
|
|
+ name: '能源成本',
|
|
|
+ orderNum: '25',
|
|
|
+ rowid: 'd6e7f8a9-b0c1-4d2e-3f4a-5b6c7d8e9f0a',
|
|
|
+ number: '九',
|
|
|
+ rvalue: '280',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: '-1',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '250' },
|
|
|
+ { name: '2023', value: '270' },
|
|
|
+ { name: '2024', value: '280' },
|
|
|
+ { name: '2025', value: '290' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: [
|
|
|
+ {
|
|
|
+ id: '1997964657757057024',
|
|
|
+ name: '电费',
|
|
|
+ orderNum: '26',
|
|
|
+ rowid: 'e7f8a9b0-c1d2-4e3f-4a5b-6c7d8e9f0a1b',
|
|
|
+ number: '1',
|
|
|
+ rvalue: '180',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'd6e7f8a9-b0c1-4d2e-3f4a-5b6c7d8e9f0a',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '160' },
|
|
|
+ { name: '2023', value: '170' },
|
|
|
+ { name: '2024', value: '180' },
|
|
|
+ { name: '2025', value: '190' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964657866102784',
|
|
|
+ name: '水费',
|
|
|
+ orderNum: '27',
|
|
|
+ rowid: 'f8a9b0c1-d2e3-4f4a-5b6c-7d8e9f0a1b2c',
|
|
|
+ number: '2',
|
|
|
+ rvalue: '60',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'd6e7f8a9-b0c1-4d2e-3f4a-5b6c7d8e9f0a',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '55' },
|
|
|
+ { name: '2023', value: '58' },
|
|
|
+ { name: '2024', value: '60' },
|
|
|
+ { name: '2025', value: '62' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '1997964657975148544',
|
|
|
+ name: '燃气费',
|
|
|
+ orderNum: '28',
|
|
|
+ rowid: 'a9b0c1d2-e3f4-4a5b-6c7d-8e9f0a1b2c3d',
|
|
|
+ number: '3',
|
|
|
+ rvalue: '40',
|
|
|
+ taskId: '1995015537499938816',
|
|
|
+ nianfen: null,
|
|
|
+ parentId: 'd6e7f8a9-b0c1-4d2e-3f4a-5b6c7d8e9f0a',
|
|
|
+ surveysVos: [
|
|
|
+ { name: '2022', value: '35' },
|
|
|
+ { name: '2023', value: '38' },
|
|
|
+ { name: '2024', value: '40' },
|
|
|
+ { name: '2025', value: '38' },
|
|
|
+ ],
|
|
|
+ costSurveysVos: null,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+}
|