diff --git a/pages/views/renliziyuan/renyuanxinxi/qttongji - 副本 (2).vue b/pages/views/renliziyuan/renyuanxinxi/qttongji - 副本 (2).vue deleted file mode 100644 index bff7dc5..0000000 --- a/pages/views/renliziyuan/renyuanxinxi/qttongji - 副本 (2).vue +++ /dev/null @@ -1,352 +0,0 @@ - - - - - diff --git a/pages/views/renliziyuan/renyuanxinxi/qttongji - 副本.vue b/pages/views/renliziyuan/renyuanxinxi/qttongji - 副本.vue deleted file mode 100644 index 625676a..0000000 --- a/pages/views/renliziyuan/renyuanxinxi/qttongji - 副本.vue +++ /dev/null @@ -1,730 +0,0 @@ - - - - - diff --git a/pages/views/renliziyuan/renyuanxinxi/qttongji.vue b/pages/views/renliziyuan/renyuanxinxi/qttongji.vue index 9a265bf..0948c74 100644 --- a/pages/views/renliziyuan/renyuanxinxi/qttongji.vue +++ b/pages/views/renliziyuan/renyuanxinxi/qttongji.vue @@ -2,19 +2,17 @@ - - - - + + + - - - 选择字段: {{ selectedFieldLabel }} - + + + @@ -87,15 +85,15 @@ const bottomHeight = ref(0); const chart = ref(null); const fieldList = ref([ { - label: '性别', + text: '性别', value: 'xb' }, { - label: '年龄', + text: '年龄', value: 'nl' }, { - label: '学历', + text: '学历', value: 'rylb1' } ]); // 字段列表 @@ -103,10 +101,10 @@ const selectedOrgCode = ref(''); // 当前选择的单位 orgCode const selectedOrgCodeLabel = ref('请选择单位'); // 当前选择的单位名称 const selectedField = ref(''); // 当前选择的字段 const selectedFieldLabel = ref('请选择字段'); // 当前选择的字段名称 -const orgCodeGroupData = ref([]); //按照orgcode进行分组的数据 +const orgCodeGroupData = ref([]); //按照orgcode进行分组的数据 含劳动合同号 const chartData = ref({}); // 图表数据 const personnelList = ref([]); // 人员列表 initChart - +const fieldValues = ref([]); const chartOption = ref({}); function detail(record) { @@ -153,91 +151,209 @@ const initChart = () => { }; // 更新图表 -const updateChart = () => { +const updateChart = (tempchartData) => { // 初始化图表 setTimeout(async () => { if (!chart.value) return; const myChart = await chart.value.init(echarts); - chartOption.value = transformDataForEcharts(chartData.value, selectedOrgCode.value); + console.log(tempchartData); + let temp = JSON.parse(JSON.stringify(tempchartData[0].children)); + let xData = []; + let seriesData = []; + console.log(1, temp); + //当前机构下的数据 transformDataForEcharts + + temp.forEach((item) => { + xData.push(item.name); + }); + + for (let i = 0; i < fieldValues.value.length; i++) { + let tempData = []; + temp.forEach((item) => { + if (item.data[i]) { + tempData.push(item.data[i]); + } else { + tempData.push(0); + } + }); + seriesData.push({ name: fieldValues.value[i], type: 'bar', data: tempData }); + } + + console.log(xData, seriesData, fieldValues.value); myChart.setOption({ xAxis: { type: 'category', - data: chartOption.value.categories.map((code) => `${code}${chartOption.value.children ? ' ▶' : ''}`) + data: xData }, yAxis: { type: 'value' }, - series: chartOption.value.series, + series: seriesData, tooltip: { trigger: 'axis' }, - legend: { data: chartOption.value.series.map((s) => s.name) } + legend: { data: fieldValues.value } }); + // 点击钻取事件 myChart.on('click', (params) => { - const clickedCode = params.name.split(' ')[0]; - const nextData = transformDataForEcharts(originalData, clickedCode); - - if (nextData.categories.length > 0) { - historyStack.push(currentLevel); - currentLevel = clickedCode; - renderChart(nextData); - } else if (nextData.children) { - historyStack.push(currentLevel); - currentLevel = clickedCode; - chartData = transformDataForEcharts(originalData, currentLevel); - renderChart(chartData); - } else { - console.log('已是最末级节点'); - } + // console.log(params.name, params.seriesIndex, params.dataIndex); + console.log(orgCodeGroupData.value); + let updateData = findNodeByOrgCode(orgCodeGroupData.value, params.name); + console.log(updateData); + // updateChart(updateData); }); }, 300); }; +//根据一个键值查找数据 +/** + * 从树状数据中根据 orgCode 获取节点及其子节点数据 + * @param {Array} treeData 树状数据 + * @param {string} targetOrgCode 目标 orgCode + * @returns {Object|null} 匹配的节点及其子节点数据,未找到返回 null + */ +function findNodeByOrgCode(treeData, targetOrgCode) { + // console.log(treeData, targetOrgCode); + for (const node of treeData) { + // 如果当前节点匹配,直接返回该节点及其子节点 + if (node.name === targetOrgCode) { + return node; + } + // 递归检查子节点 + if (node.children && node.children.length > 0) { + const found = findNodeByOrgCode(node.children, targetOrgCode); + if (found) return found; + } + } + return null; +} + +//获取所有的fieldValue +function collectUniqueKeyValues(tree, key) { + const uniqueValues = new Set(); // 使用Set来自动处理唯一性 + + function traverse(node) { + if (node[key] !== undefined) { + uniqueValues.add(node[key]); + } + if (node.children && Array.isArray(node.children)) { + node.children.forEach((child) => traverse(child)); + } + } + + tree.forEach((node) => traverse(node)); // 假设tree是一个数组 + + return Array.from(uniqueValues); // 将Set转换为数组 +} + +// 示例用法 +// const result = findNodeByOrgCode(echartData, "A01A01A01A01"); +// console.log(result); /** * 转换数据为支持钻取的ECharts格式 * @param {Array} data 原始数据 - * @param {string} currentOrgCode 当前组织编码 - * @returns {Object} 包含当前层级数据和子节点信息的对象 + * @param {string} selectOrgCode 当前选择的组织编码 + * @returns {Object} 包含当前层级数据和子节点信息的对象 符合echart的格式 */ -function transformDataForEcharts(data, currentOrgCode = '') { - // 计算当前层级的长度(每级+3) - const currentLevel = currentOrgCode.length; - const nextLevel = currentLevel + 3; - console.log(currentLevel, nextLevel, currentOrgCode, data); - // 过滤当前层级数据 - const currentLevelData = data.filter((item) => item.orgCode.length === currentLevel && (currentLevel === 0 || item.orgCode === currentOrgCode)); - console.log(1); - console.log(currentLevelData); - // 过滤直接子节点(严格前缀匹配) - const children = data - .filter( - (item) => item.orgCode.startsWith(currentOrgCode) && item.orgCode.length === nextLevel && (currentLevel === 0 || item.orgCode.slice(0, currentLevel) === currentOrgCode) - ) - .map((item) => ({ - orgCode: item.orgCode, - hasChildren: data.some((d) => d.orgCode.startsWith(item.orgCode) && d.orgCode.length === nextLevel + 3) - })); - console.log(2, children); - // 按fieldValue分组统计 - const fieldGroups = currentLevelData.reduce((acc, curr) => { - const key = curr.fieldValue; - if (!acc[key]) { - acc[key] = { - name: key, - data: [] - }; +//----------------------------------------------------------------------------------------- +function transformData(selectOrgCode, data) { + const nodes = new Map(); + //获取所有的fieldValue 用于图例和钻取和data[]中的数据顺序保持一致 动态建立fieldValue的数据 + fieldValues.value = collectUniqueKeyValues(data, 'fieldValue'); + // 获取orgCode的所有层级 + function getHierarchy(orgCode) { + const hierarchy = []; + for (let i = selectOrgCode.length; i <= orgCode.length; i += 3) { + hierarchy.push(orgCode.substring(0, i)); } - acc[key].data.push(curr.number); - return acc; - }, {}); + // console.log('hierarchy', hierarchy); + return hierarchy; + } + // 获取父级orgCode + function getParentCode(code) { + if (code.length <= 3) return null; + return code.substring(0, code.length - 3); + } + // 动态赋值series的数据长度 + let tempArrayValue = new Array(fieldValues.value.length).fill(0); + // 创建所有节点并建立父子关系 + data.forEach((entry) => { + const hierarchy = getHierarchy(entry.orgCode); + hierarchy.forEach((code) => { + if (!nodes.has(code)) { + nodes.set(code, { + orgCode: code, + type: 'bar', + data: JSON.parse(JSON.stringify(tempArrayValue)), // 初始化data为[0, 0] 动态 + children: [] + }); + } + }); - return { - categories: currentLevelData.map((d) => d.orgCode), - series: Object.values(fieldGroups), - children: children.length > 0 ? children : null - }; + // console.log('fieldValues', fieldValues.value, fieldValues.value.length, hierarchy); + + // 更新当前节点的data + const node = nodes.get(entry.orgCode); + const fieldValue = parseInt(entry.fieldValue, 10); + + for (let i = 0; i < fieldValues.value.length; i++) { + if (fieldValue === parseInt(fieldValues.value[i], 10)) { + // console.log(555, i, fieldValue, fieldValues.value[i], entry.number); + node.data[i] += entry.number; + } + } + + // console.log(11, node); + + // 建立父子关系 + for (let i = 0; i < hierarchy.length - 1; i++) { + const parentCode = hierarchy[i]; + const childCode = hierarchy[i + 1]; + const parentNode = nodes.get(parentCode); + const childNode = nodes.get(childCode); + if (!parentNode.children.some((c) => c.orgCode === childCode)) { + parentNode.children.push(childNode); + } + } + }); + + // 计算非叶子节点的data(子节点之和) + function computeData(node) { + if (node.children.length === 0) return; + node.data = JSON.parse(JSON.stringify(tempArrayValue)); + node.children.forEach((child) => { + computeData(child); + for (let i = 0; i < fieldValues.value.length; i++) { + // console.log(666, i, node.data[i], child.data[i]); + node.data[i] += child.data[i]; + } + }); + } + + // 获取所有根节点(没有父节点或父节点不存在) + const rootNodes = []; + nodes.forEach((node, code) => { + const parentCode = getParentCode(code); + // console.log(parentCode); + if (!parentCode || !nodes.has(parentCode)) { + rootNodes.push(node); + } + }); + + // 递归计算每个根节点的data + rootNodes.forEach((root) => computeData(root)); + // console.log('rootNodes', rootNodes); + // 转换为目标格式 + function formatTree(node) { + return { + name: node.orgCode, + type: 'bar', + data: node.data, + children: node.children.map((child) => formatTree(child)) + }; + } + + return rootNodes.map((root) => formatTree(root)); } -// 使用示例 -// let currentLevel = 'A01A01'; // 初始层级 -// let chartData = transformDataForEcharts(originalData, currentLevel); +//----------------------------------------------------------------------------------------- //根据 orgCode 的分级格式,递归地汇总本级及其所有下级的数据,并将下级数据放在本级的 children 属性中。 deepseek @@ -253,12 +369,14 @@ const groupByOrgCode = (orgCode, data) => { // 按照 fieldValue 分组 const groupedByFieldValue = {}; filteredData.forEach((item) => { + // console.log(item.orgCode, 11, groupedByFieldValue[item.fieldValue]); if (!groupedByFieldValue[item.fieldValue]) { groupedByFieldValue[item.fieldValue] = { number: 0, ldhth: [] }; } + // console.log(item.orgCode, 22, groupedByFieldValue[item.fieldValue]); groupedByFieldValue[item.fieldValue].number += item.number; groupedByFieldValue[item.fieldValue].ldhth.push(...item.ldhth.split(',')); }); @@ -274,6 +392,8 @@ const groupByOrgCode = (orgCode, data) => { children: [] }; + console.log('本级', result); + // 获取所有下一级的 orgCode const nextLevelOrgCodes = new Set(); filteredData.forEach((item) => { @@ -291,11 +411,10 @@ const groupByOrgCode = (orgCode, data) => { } }); + console.log('全部', result); + return result; }; - -//----------------------------------------------------------------------------------------- - // 获取统计数据 then const fetchStatisticsData = async () => { if (!selectedOrgCode.value || !selectedField.value) return; @@ -304,11 +423,11 @@ const fetchStatisticsData = async () => { orgCode: selectedOrgCode.value, field: selectedField.value }); - // console.log(res); //deepseek + // console.log(res); //deepseek orgCodeGroupData.value = groupByOrgCode(selectedOrgCode.value, res); - console.log(orgCodeGroupData.value); - chartData.value = orgCodeGroupData.value.children; - updateChart(); + chartData.value = transformData(selectedOrgCode.value, res); + // console.log(chartData.value); + updateChart(chartData.value); } catch (error) { console.error('获取统计数据失败:', error); } @@ -336,10 +455,21 @@ const onOrgCodeChange = (e, data) => { }; const onFieldChange = (e) => { - const index = e.detail.value; - selectedField.value = fieldList.value[index].value; - selectedFieldLabel.value = fieldList.value[index].label; - fetchStatisticsData(); + console.log(e); + try { + selectedField.value = e; + for (var index = 0; index < fieldList.length; index++) { + var element = array[index]; + if (element.value === e) { + selectedFieldLabel.value = element.text; + } + } + console.log(selectedFieldLabel); + fetchStatisticsData(); + } catch (error) { + //TODO handle the exception + console.log(error); + } }; const onChartClick = (e) => { @@ -349,90 +479,154 @@ const onChartClick = (e) => { } }; -