diff --git a/.collaboration b/.collaboration index e374be97..2b18b8f5 100644 --- a/.collaboration +++ b/.collaboration @@ -2270,19 +2270,7 @@ }, { "ModuleName": "PCPage/工作台首页", - "State": 1, - "LockedBy": { - "UserName": "cuckooent", - "Email": "phoben@qq.com" - }, - "LockDateTime": "2024-11-05T17:36:48.7042561+08:00", - "ModuleType": 1, - "ToRemoveFiles": [ - "Pages\\工作台\\工作台首页.json", - "Pages\\工作台\\工作台首页.rd", - "Pages\\3868fc7f40b841649f14b5adba61954.json", - "Pages\\3868fc7f40b841649f14b5adba61954.rd" - ] + "ModuleType": 1 }, { "ModuleName": "PCPage/项目负荷 (2)", @@ -2530,16 +2518,7 @@ }, { "ModuleName": "TableView/项目反馈数量统计视图", - "State": 1, - "LockedBy": { - "UserName": "cuckooent", - "Email": "phoben@qq.com" - }, - "LockDateTime": "2024-11-05T17:50:33.1606037+08:00", - "ModuleType": 23, - "ToRemoveFiles": [ - "Tables\\需求反馈\\项目反馈数量统计视图.json" - ] + "ModuleType": 23 }, { "ModuleName": "RdlReport/客户部门工时报表", diff --git a/Pages/工作台/工作台首页.json b/Pages/工作台/工作台首页.json index fac21cc2..2a470155 100644 --- a/Pages/工作台/工作台首页.json +++ b/Pages/工作台/工作台首页.json @@ -649,6 +649,24 @@ }, "ColumnName": "类型" }, + { + "GUID": "91c7c1db-40ed-457b-9f7e-c2b410873c02", + "BindingInfo": { + "TableName": "项目反馈数量统计视图", + "ColumnName": "项目ID", + "GUID": "cfa41e1a-2896-4a3c-a568-2f7b989da45a" + }, + "ColumnName": "项目ID" + }, + { + "GUID": "1da4d2ca-b7f5-4067-870c-50e8958c9c01", + "BindingInfo": { + "TableName": "项目反馈数量统计视图", + "ColumnName": "任务ID", + "GUID": "d7cb473d-7134-4378-bcc2-a32ee2a7fcce" + }, + "ColumnName": "任务ID" + }, { "GUID": "7c1248ae-7392-43a9-b0b9-f8f2b7d1e20e", "BindingInfo": { @@ -684,7 +702,7 @@ ], "JSONDataSources": [], "ImageDataSource": [], - "Config": "{\"option\":\"console.log(Context[\\\"recommands\\\"]);\\n\\n// 处理数据,生成节点和链接 \\nconst processData = (data) => {\\n // 生成颜色函数 - 使用HSL颜色空间 \\n const getColorByDepthAndIndex = (depth, index, totalInDepth) => {\\n const goldenRatio = 0.618033988749895;\\n const hue = ((index * goldenRatio) % 1) * 360;\\n return `hsl(${hue}, 60%, 55%)`;\\n };\\n\\n // 收集所有唯一的节点 \\n const typeSet = new Set(data.map(item => item.类型 || \\\"其他\\\"));\\n const projectSet = new Set(data.map(item => item.项目 || \\\"未知项目\\\"));\\n const taskSet = new Set(data.map(item => item.任务 || \\\"未知任务\\\"));\\n\\n // 转换为数组以便计算总数和索引 \\n const typeArray = Array.from(typeSet);\\n const projectArray = Array.from(projectSet);\\n const taskArray = Array.from(taskSet);\\n\\n // 给每个类型分配固定颜色 \\n const typeColors = {};\\n typeArray.forEach((type, index) => {\\n const hue = ((index * 0.618033988749895) % 1) * 360;\\n typeColors[type] = `hsl(${hue}, 60%, 55%)`;\\n });\\n\\n // 创建项目到类型的映射和任务到类型的映射\\n const projectToTypeMap = {};\\n const taskToTypeMap = {};\\n data.forEach(item => {\\n projectToTypeMap[item.项目] = item.类型;\\n taskToTypeMap[item.任务] = item.类型;\\n });\\n\\n // 预计算每个节点的总值 \\n const nodeValues = {};\\n data.forEach(item => {\\n nodeValues[item.类型] = (nodeValues[item.类型] || 0) + item.数量;\\n nodeValues[item.项目] = (nodeValues[item.项目] || 0) + item.数量;\\n nodeValues[item.任务] = (nodeValues[item.任务] || 0) + item.数量;\\n });\\n\\n // 创建节点类型的映射\\n const nodeTypeMap = new Map();\\n data.forEach(item => {\\n nodeTypeMap.set(item.类型, '类型');\\n nodeTypeMap.set(item.项目, '项目');\\n nodeTypeMap.set(item.任务, '任务');\\n });\\n\\n // 生成节点数组\\n const nodes = [\\n ...typeArray.map((name, index) => ({\\n name: name,\\n depth: 0,\\n value: nodeValues[name],\\n itemStyle: {\\n color: typeColors[name],\\n borderColor: typeColors[name]\\n },\\n category: '类型'\\n })),\\n ...projectArray.map((name, index) => ({\\n name: name,\\n depth: 1,\\n value: nodeValues[name],\\n itemStyle: {\\n color: typeColors[projectToTypeMap[name]],\\n borderColor: typeColors[projectToTypeMap[name]]\\n },\\n category: '项目',\\n sourceType: projectToTypeMap[name]\\n })),\\n ...taskArray.map((name, index) => ({\\n name: name,\\n depth: 2,\\n value: nodeValues[name],\\n itemStyle: {\\n color: typeColors[taskToTypeMap[name]],\\n borderColor: typeColors[taskToTypeMap[name]]\\n },\\n category: '任务',\\n sourceType: taskToTypeMap[name]\\n }))\\n ];\\n\\n // 生成链接数组 \\n const links = [];\\n\\n // 处理类型到项目的链接\\n data.forEach(item => {\\n const existingLink = links.find(\\n link => link.source === item.类型 && link.target === item.项目\\n );\\n if (existingLink) {\\n existingLink.value += item.数量;\\n } else {\\n links.push({\\n source: item.类型,\\n target: item.项目,\\n value: item.数量,\\n sourceType: item.类型,\\n lineStyle: {\\n color: typeColors[item.类型],\\n opacity: 0.7\\n }\\n });\\n }\\n });\\n\\n // 处理项目到任务的链接\\n data.forEach(item => {\\n const existingLink = links.find(\\n link => link.source === item.项目 && link.target === item.任务\\n );\\n if (existingLink) {\\n existingLink.value += item.数量;\\n } else {\\n const sourceType = projectToTypeMap[item.项目];\\n links.push({\\n source: item.项目,\\n target: item.任务,\\n value: item.数量,\\n sourceType: sourceType,\\n lineStyle: {\\n color: typeColors[sourceType] || '#999',\\n opacity: 0.7\\n }\\n });\\n }\\n });\\n\\n return { nodes, links };\\n};\\n\\n// 获取提示文字\\nconst gettooltip = (params) => {\\n if (params.dataType === 'node') {\\n const sourceType = params.data.sourceType ? `\\\\n来源类型: ${params.data.sourceType}` : '';\\n return `${params.name}\\\\n类别: ${params.data.category}\\\\n数量: ${params.value}${sourceType}`;\\n }\\n return `${params.data.source} → ${params.data.target}\\\\n数量: ${params.value}\\\\n类型: ${params.data.sourceType}`;\\n}\\n\\n// 处理数据 \\nconst { nodes, links } = processData(Context[\\\"recommands\\\"]);\\n\\n// Echarts配置 \\noption = {\\n backgroundColor: \\\"rgba(0, 0, 0, 0)\\\",\\n title: {\\n text: \\\"项目反馈桑基图\\\",\\n subtext: \\\"展示各个项目任务的不同反馈分类占比\\\",\\n left: \\\"center\\\",\\n top: 24,\\n textStyle: {\\n fontSize: 16,\\n fontWeight: \\\"bold\\\",\\n },\\n },\\n tooltip: {\\n trigger: 'item',\\n triggerOn: 'mousemove',\\n formatter: gettooltip\\n },\\n series: [{\\n type: \\\"sankey\\\",\\n animation: true,\\n animationDuration: 300,\\n animationEasingUpdate: 'quinticInOut',\\n left: '5%',\\n top: '12%',\\n right: '20%',\\n bottom: '12%',\\n nodeAlign: 'left',\\n orient: 'horizontal',\\n data: nodes,\\n links: links,\\n nodeGap: 15,\\n nodeWidth: 25,\\n draggable: true,\\n lineStyle: {\\n curveness: 0.5,\\n opacity: 0.7,\\n width: function (params) {\\n return Math.max(10, params.value);\\n },\\n shadowBlur: 3,\\n shadowColor: 'rgba(0,0,0,0.2)'\\n },\\n emphasis: {\\n focus: 'adjacency',\\n lineStyle: {\\n opacity: 0.9,\\n shadowBlur: 10,\\n shadowColor: 'rgba(0,0,0,0.5)'\\n }\\n },\\n label: {\\n position: 'right',\\n fontSize: 12,\\n lineHeight: 16,\\n color: '#000000',\\n distance: 10,\\n formatter: function (params) {\\n var name = params.name;\\n if (name.length > 10) {\\n name = name.substring(0, 10) + '...';\\n }\\n if (params.value && params.value > 0) {\\n return `${name}(${params.value}个)`;\\n }\\n return \\\"\\\";\\n },\\n show: true,\\n align: 'left',\\n verticalAlign: 'middle',\\n backgroundColor: '#ffffffa1',\\n overflow: 'break',\\n padding: [4, 8],\\n borderRadius: 4\\n }\\n }]\\n};\",\"graphTheme\":null,\"displayMode\":\"canvas\",\"jsCode\":\"\\n async ({Context,JSONContext,ImageContext,echarts,myChart,dat,Forguncy,d3,setInterval,setTimeout,ForguncyEchartsHelper,PublicResource})=>{\\n var datGUI=undefined;\\n var option={};\\n console.log(Context[\\\"recommands\\\"]);\\n// 处理数据,生成节点和链接 \\nconst processData = (data) => {\\n // 生成颜色函数 - 使用HSL颜色空间 \\n const getColorByDepthAndIndex = (depth, index, totalInDepth) => {\\n const goldenRatio = 0.618033988749895;\\n const hue = ((index * goldenRatio) % 1) * 360;\\n return `hsl(${hue}, 60%, 55%)`;\\n };\\n // 收集所有唯一的节点 \\n const typeSet = new Set(data.map(item => item.类型 || \\\"其他\\\"));\\n const projectSet = new Set(data.map(item => item.项目 || \\\"未知项目\\\"));\\n const taskSet = new Set(data.map(item => item.任务 || \\\"未知任务\\\"));\\n // 转换为数组以便计算总数和索引 \\n const typeArray = Array.from(typeSet);\\n const projectArray = Array.from(projectSet);\\n const taskArray = Array.from(taskSet);\\n // 给每个类型分配固定颜色 \\n const typeColors = {};\\n typeArray.forEach((type, index) => {\\n const hue = ((index * 0.618033988749895) % 1) * 360;\\n typeColors[type] = `hsl(${hue}, 60%, 55%)`;\\n });\\n // 创建项目到类型的映射和任务到类型的映射\\n const projectToTypeMap = {};\\n const taskToTypeMap = {};\\n data.forEach(item => {\\n projectToTypeMap[item.项目] = item.类型;\\n taskToTypeMap[item.任务] = item.类型;\\n });\\n // 预计算每个节点的总值 \\n const nodeValues = {};\\n data.forEach(item => {\\n nodeValues[item.类型] = (nodeValues[item.类型] || 0) + item.数量;\\n nodeValues[item.项目] = (nodeValues[item.项目] || 0) + item.数量;\\n nodeValues[item.任务] = (nodeValues[item.任务] || 0) + item.数量;\\n });\\n // 创建节点类型的映射\\n const nodeTypeMap = new Map();\\n data.forEach(item => {\\n nodeTypeMap.set(item.类型, '类型');\\n nodeTypeMap.set(item.项目, '项目');\\n nodeTypeMap.set(item.任务, '任务');\\n });\\n // 生成节点数组\\n const nodes = [\\n ...typeArray.map((name, index) => ({\\n name: name,\\n depth: 0,\\n value: nodeValues[name],\\n itemStyle: {\\n color: typeColors[name],\\n borderColor: typeColors[name]\\n },\\n category: '类型'\\n })),\\n ...projectArray.map((name, index) => ({\\n name: name,\\n depth: 1,\\n value: nodeValues[name],\\n itemStyle: {\\n color: typeColors[projectToTypeMap[name]],\\n borderColor: typeColors[projectToTypeMap[name]]\\n },\\n category: '项目',\\n sourceType: projectToTypeMap[name]\\n })),\\n ...taskArray.map((name, index) => ({\\n name: name,\\n depth: 2,\\n value: nodeValues[name],\\n itemStyle: {\\n color: typeColors[taskToTypeMap[name]],\\n borderColor: typeColors[taskToTypeMap[name]]\\n },\\n category: '任务',\\n sourceType: taskToTypeMap[name]\\n }))\\n ];\\n // 生成链接数组 \\n const links = [];\\n // 处理类型到项目的链接\\n data.forEach(item => {\\n const existingLink = links.find(link => link.source === item.类型 && link.target === item.项目);\\n if (existingLink) {\\n existingLink.value += item.数量;\\n }\\n else {\\n links.push({\\n source: item.类型,\\n target: item.项目,\\n value: item.数量,\\n sourceType: item.类型,\\n lineStyle: {\\n color: typeColors[item.类型],\\n opacity: 0.7\\n }\\n });\\n }\\n });\\n // 处理项目到任务的链接\\n data.forEach(item => {\\n const existingLink = links.find(link => link.source === item.项目 && link.target === item.任务);\\n if (existingLink) {\\n existingLink.value += item.数量;\\n }\\n else {\\n const sourceType = projectToTypeMap[item.项目];\\n links.push({\\n source: item.项目,\\n target: item.任务,\\n value: item.数量,\\n sourceType: sourceType,\\n lineStyle: {\\n color: typeColors[sourceType] || '#999',\\n opacity: 0.7\\n }\\n });\\n }\\n });\\n return { nodes, links };\\n};\\n// 获取提示文字\\nconst gettooltip = (params) => {\\n if (params.dataType === 'node') {\\n const sourceType = params.data.sourceType ? `\\\\n来源类型: ${params.data.sourceType}` : '';\\n return `${params.name}\\\\n类别: ${params.data.category}\\\\n数量: ${params.value}${sourceType}`;\\n }\\n return `${params.data.source} → ${params.data.target}\\\\n数量: ${params.value}\\\\n类型: ${params.data.sourceType}`;\\n};\\n// 处理数据 \\nconst { nodes, links } = processData(Context[\\\"recommands\\\"]);\\n// Echarts配置 \\noption = {\\n backgroundColor: \\\"rgba(0, 0, 0, 0)\\\",\\n title: {\\n text: \\\"项目反馈桑基图\\\",\\n subtext: \\\"展示各个项目任务的不同反馈分类占比\\\",\\n left: \\\"center\\\",\\n top: 24,\\n textStyle: {\\n fontSize: 16,\\n fontWeight: \\\"bold\\\",\\n },\\n },\\n tooltip: {\\n trigger: 'item',\\n triggerOn: 'mousemove',\\n formatter: gettooltip\\n },\\n series: [{\\n type: \\\"sankey\\\",\\n animation: true,\\n animationDuration: 300,\\n animationEasingUpdate: 'quinticInOut',\\n left: '5%',\\n top: '12%',\\n right: '20%',\\n bottom: '12%',\\n nodeAlign: 'left',\\n orient: 'horizontal',\\n data: nodes,\\n links: links,\\n nodeGap: 15,\\n nodeWidth: 25,\\n draggable: true,\\n lineStyle: {\\n curveness: 0.5,\\n opacity: 0.7,\\n width: function (params) {\\n return Math.max(10, params.value);\\n },\\n shadowBlur: 3,\\n shadowColor: 'rgba(0,0,0,0.2)'\\n },\\n emphasis: {\\n focus: 'adjacency',\\n lineStyle: {\\n opacity: 0.9,\\n shadowBlur: 10,\\n shadowColor: 'rgba(0,0,0,0.5)'\\n }\\n },\\n label: {\\n position: 'right',\\n fontSize: 12,\\n lineHeight: 16,\\n color: '#000000',\\n distance: 10,\\n formatter: function (params) {\\n var name = params.name;\\n if (name.length > 10) {\\n name = name.substring(0, 10) + '...';\\n }\\n if (params.value && params.value > 0) {\\n return `${name}(${params.value}个)`;\\n }\\n return \\\"\\\";\\n },\\n show: true,\\n align: 'left',\\n verticalAlign: 'middle',\\n backgroundColor: '#ffffffa1',\\n overflow: 'break',\\n padding: [4, 8],\\n borderRadius: 4\\n }\\n }]\\n};\\n\\n return {\\n option,\\n datGUI,\\n };\\n }\\n \"}" + "Config": "{\"option\":\"console.log(JSON.stringify(Context[\\\"recommands\\\"]));\\n\\n// 处理数据,生成节点和链接 \\nconst processData = (data) => {\\n // 生成颜色函数 - 使用HSL颜色空间 \\n const getColorByType = (type, index, totalTypes) => {\\n const hue = ((index / totalTypes) * 360) % 360;\\n return `hsl(${hue}, 70%, 50%)`;\\n };\\n\\n // 收集所有唯一的节点 \\n const typeSet = new Set(data.map(item => item.类型));\\n const projectSet = new Set();\\n const taskSet = new Set();\\n\\n // 创建项目和任务的映射关系 \\n const projectTypeMap = new Map();\\n const taskTypeMap = new Map();\\n\\n data.forEach(item => {\\n const projectKey = `[${item.项目ID}]${item.项目}`;\\n const taskKey = `[${item.任务ID}]${item.任务}`;\\n\\n projectSet.add(projectKey);\\n taskSet.add(taskKey);\\n\\n // 记录项目和任务与类型的关系 \\n if (!projectTypeMap.has(projectKey)) {\\n projectTypeMap.set(projectKey, new Set());\\n }\\n if (!taskTypeMap.has(taskKey)) {\\n taskTypeMap.set(taskKey, new Set());\\n }\\n\\n projectTypeMap.get(projectKey).add(item.类型);\\n taskTypeMap.get(taskKey).add(item.类型);\\n });\\n\\n // 转换为数组 \\n const typeArray = Array.from(typeSet);\\n const projectArray = Array.from(projectSet);\\n const taskArray = Array.from(taskSet);\\n\\n // 创建类型颜色映射 \\n const typeColors = {};\\n typeArray.forEach((type, index) => {\\n typeColors[type] = getColorByType(type, index, typeArray.length);\\n });\\n\\n // 计算节点值 \\n const nodeValues = {};\\n data.forEach(item => {\\n const projectKey = `[${item.项目ID}]${item.项目}`;\\n const taskKey = `[${item.任务ID}]${item.任务}`;\\n\\n nodeValues[item.类型] = (nodeValues[item.类型] || 0) + item.数量;\\n nodeValues[projectKey] = (nodeValues[projectKey] || 0) + item.数量;\\n nodeValues[taskKey] = (nodeValues[taskKey] || 0) + item.数量;\\n });\\n\\n // 生成节点 \\n const nodes = [\\n // 类型节点 \\n ...typeArray.map((type, index) => ({\\n name: type,\\n value: nodeValues[type],\\n itemStyle: {\\n color: typeColors[type],\\n borderColor: typeColors[type]\\n },\\n category: '类型',\\n depth: 0\\n })),\\n\\n // 项目节点 \\n ...projectArray.map(project => ({\\n name: project,\\n value: nodeValues[project],\\n itemStyle: {\\n color: typeColors[Array.from(projectTypeMap.get(project))[0]],\\n opacity: 0.8\\n },\\n category: '项目',\\n depth: 1\\n })),\\n\\n // 任务节点 \\n ...taskArray.map(task => ({\\n name: task,\\n value: nodeValues[task],\\n itemStyle: {\\n color: typeColors[Array.from(taskTypeMap.get(task))[0]],\\n opacity: 0.8\\n },\\n category: '任务',\\n depth: 2\\n }))\\n ];\\n\\n // 生成连接 \\n const links = [];\\n\\n // 处理类型到项目的连接 \\n data.forEach(item => {\\n const projectKey = `[${item.项目ID}]${item.项目}`;\\n const source = item.类型;\\n const target = projectKey;\\n\\n const existingLink = links.find(link =>\\n link.source === source && link.target === target\\n );\\n\\n if (existingLink) {\\n existingLink.value += item.数量;\\n } else {\\n links.push({\\n source: source,\\n target: target,\\n value: item.数量,\\n sourceType: item.类型,\\n lineStyle: {\\n color: typeColors[item.类型],\\n opacity: 0.7\\n }\\n });\\n }\\n });\\n\\n // 处理项目到任务的连接 \\n data.forEach(item => {\\n const projectKey = `[${item.项目ID}]${item.项目}`;\\n const taskKey = `[${item.任务ID}]${item.任务}`;\\n\\n const existingLink = links.find(link =>\\n link.source === projectKey && link.target === taskKey\\n );\\n\\n if (existingLink) {\\n existingLink.value += item.数量;\\n } else {\\n links.push({\\n source: projectKey,\\n target: taskKey,\\n value: item.数量,\\n sourceType: item.类型,\\n lineStyle: {\\n color: typeColors[item.类型],\\n opacity: 0.7\\n }\\n });\\n }\\n });\\n\\n return { nodes, links };\\n};\\n\\n// 修改提示文字获取函数 \\nconst gettooltip = (params) => {\\n if (params.dataType === 'node') {\\n return `${params.name}
数量: ${params.value}`;\\n }\\n\\n // 获取源节点和目标节点的深度 \\n const sourceNode = params.data.source;\\n const targetNode = params.data.target;\\n const isProjectToTask = sourceNode.includes(']') && targetNode.includes(']');\\n\\n if (isProjectToTask) {\\n // 项目到任务的连接 \\n return `\\n ${params.data.sourceType}
\\n 项目:${params.data.source}
\\n 任务:${params.data.target}
数量: ${params.value}`;\\n } else {\\n return `\\n ${params.data.sourceType}
\\n 项目:${params.data.target}
\\n 数量: ${params.value}`;\\n }\\n};\\n\\n// 处理数据 \\nconst { nodes, links } = processData(Context[\\\"recommands\\\"]);\\n\\n// Echarts配置 \\noption = {\\n backgroundColor: \\\"rgba(0, 0, 0, 0)\\\",\\n title: {\\n text: \\\"项目反馈桑基图\\\",\\n subtext: \\\"展示各个项目任务的不同反馈分类占比\\\",\\n left: \\\"center\\\",\\n top: 24,\\n textStyle: {\\n fontSize: 16,\\n fontWeight: \\\"bold\\\",\\n },\\n },\\n tooltip: {\\n trigger: 'item',\\n triggerOn: 'mousemove',\\n formatter: gettooltip\\n },\\n series: [{\\n type: \\\"sankey\\\",\\n animation: true,\\n animationDuration: 300,\\n animationEasingUpdate: 'quinticInOut',\\n left: '5%',\\n top: '12%',\\n right: '20%',\\n bottom: '12%',\\n nodeAlign: 'justify',\\n orient: 'horizontal',\\n emphasis: {\\n focus: 'adjacency'\\n },\\n data: nodes,\\n links: links,\\n nodeGap: 12,\\n nodeWidth: 24,\\n draggable: true,\\n levels: [{\\n depth: 0,\\n itemStyle: {\\n borderWidth: 2\\n },\\n lineStyle: {\\n curveness: 0.5,\\n opacity: 0.7\\n }\\n }, {\\n depth: 1,\\n itemStyle: {\\n borderWidth: 1\\n },\\n lineStyle: {\\n curveness: 0.5,\\n opacity: 0.7\\n }\\n }, {\\n depth: 2,\\n itemStyle: {\\n borderWidth: 1\\n },\\n lineStyle: {\\n curveness: 0.5,\\n opacity: 0.7\\n }\\n }],\\n label: {\\n position: 'right',\\n fontSize: 12,\\n lineHeight: 16,\\n color: '#000000',\\n distance: 10,\\n formatter: function (params) {\\n var name = params.name;\\n if (name.length > 15) {\\n name = name.substring(0, 15) + '...';\\n }\\n return `${name}(${params.value})`;\\n },\\n show: true,\\n align: 'left',\\n verticalAlign: 'middle',\\n backgroundColor: '#ffffffcc',\\n padding: [4, 8],\\n borderRadius: 4\\n }\\n }]\\n};\",\"graphTheme\":null,\"displayMode\":\"canvas\",\"jsCode\":\"\\n async ({Context,JSONContext,ImageContext,echarts,myChart,dat,Forguncy,d3,setInterval,setTimeout,ForguncyEchartsHelper,PublicResource})=>{\\n var datGUI=undefined;\\n var option={};\\n console.log(JSON.stringify(Context[\\\"recommands\\\"]));\\n// 处理数据,生成节点和链接 \\nconst processData = (data) => {\\n // 生成颜色函数 - 使用HSL颜色空间 \\n const getColorByType = (type, index, totalTypes) => {\\n const hue = ((index / totalTypes) * 360) % 360;\\n return `hsl(${hue}, 70%, 50%)`;\\n };\\n // 收集所有唯一的节点 \\n const typeSet = new Set(data.map(item => item.类型));\\n const projectSet = new Set();\\n const taskSet = new Set();\\n // 创建项目和任务的映射关系 \\n const projectTypeMap = new Map();\\n const taskTypeMap = new Map();\\n data.forEach(item => {\\n const projectKey = `[${item.项目ID}]${item.项目}`;\\n const taskKey = `[${item.任务ID}]${item.任务}`;\\n projectSet.add(projectKey);\\n taskSet.add(taskKey);\\n // 记录项目和任务与类型的关系 \\n if (!projectTypeMap.has(projectKey)) {\\n projectTypeMap.set(projectKey, new Set());\\n }\\n if (!taskTypeMap.has(taskKey)) {\\n taskTypeMap.set(taskKey, new Set());\\n }\\n projectTypeMap.get(projectKey).add(item.类型);\\n taskTypeMap.get(taskKey).add(item.类型);\\n });\\n // 转换为数组 \\n const typeArray = Array.from(typeSet);\\n const projectArray = Array.from(projectSet);\\n const taskArray = Array.from(taskSet);\\n // 创建类型颜色映射 \\n const typeColors = {};\\n typeArray.forEach((type, index) => {\\n typeColors[type] = getColorByType(type, index, typeArray.length);\\n });\\n // 计算节点值 \\n const nodeValues = {};\\n data.forEach(item => {\\n const projectKey = `[${item.项目ID}]${item.项目}`;\\n const taskKey = `[${item.任务ID}]${item.任务}`;\\n nodeValues[item.类型] = (nodeValues[item.类型] || 0) + item.数量;\\n nodeValues[projectKey] = (nodeValues[projectKey] || 0) + item.数量;\\n nodeValues[taskKey] = (nodeValues[taskKey] || 0) + item.数量;\\n });\\n // 生成节点 \\n const nodes = [\\n // 类型节点 \\n ...typeArray.map((type, index) => ({\\n name: type,\\n value: nodeValues[type],\\n itemStyle: {\\n color: typeColors[type],\\n borderColor: typeColors[type]\\n },\\n category: '类型',\\n depth: 0\\n })),\\n // 项目节点 \\n ...projectArray.map(project => ({\\n name: project,\\n value: nodeValues[project],\\n itemStyle: {\\n color: typeColors[Array.from(projectTypeMap.get(project))[0]],\\n opacity: 0.8\\n },\\n category: '项目',\\n depth: 1\\n })),\\n // 任务节点 \\n ...taskArray.map(task => ({\\n name: task,\\n value: nodeValues[task],\\n itemStyle: {\\n color: typeColors[Array.from(taskTypeMap.get(task))[0]],\\n opacity: 0.8\\n },\\n category: '任务',\\n depth: 2\\n }))\\n ];\\n // 生成连接 \\n const links = [];\\n // 处理类型到项目的连接 \\n data.forEach(item => {\\n const projectKey = `[${item.项目ID}]${item.项目}`;\\n const source = item.类型;\\n const target = projectKey;\\n const existingLink = links.find(link => link.source === source && link.target === target);\\n if (existingLink) {\\n existingLink.value += item.数量;\\n }\\n else {\\n links.push({\\n source: source,\\n target: target,\\n value: item.数量,\\n sourceType: item.类型,\\n lineStyle: {\\n color: typeColors[item.类型],\\n opacity: 0.7\\n }\\n });\\n }\\n });\\n // 处理项目到任务的连接 \\n data.forEach(item => {\\n const projectKey = `[${item.项目ID}]${item.项目}`;\\n const taskKey = `[${item.任务ID}]${item.任务}`;\\n const existingLink = links.find(link => link.source === projectKey && link.target === taskKey);\\n if (existingLink) {\\n existingLink.value += item.数量;\\n }\\n else {\\n links.push({\\n source: projectKey,\\n target: taskKey,\\n value: item.数量,\\n sourceType: item.类型,\\n lineStyle: {\\n color: typeColors[item.类型],\\n opacity: 0.7\\n }\\n });\\n }\\n });\\n return { nodes, links };\\n};\\n// 修改提示文字获取函数 \\nconst gettooltip = (params) => {\\n if (params.dataType === 'node') {\\n return `${params.name}
数量: ${params.value}`;\\n }\\n // 获取源节点和目标节点的深度 \\n const sourceNode = params.data.source;\\n const targetNode = params.data.target;\\n const isProjectToTask = sourceNode.includes(']') && targetNode.includes(']');\\n if (isProjectToTask) {\\n // 项目到任务的连接 \\n return `\\n ${params.data.sourceType}
\\n 项目:${params.data.source}
\\n 任务:${params.data.target}
数量: ${params.value}`;\\n }\\n else {\\n return `\\n ${params.data.sourceType}
\\n 项目:${params.data.target}
\\n 数量: ${params.value}`;\\n }\\n};\\n// 处理数据 \\nconst { nodes, links } = processData(Context[\\\"recommands\\\"]);\\n// Echarts配置 \\noption = {\\n backgroundColor: \\\"rgba(0, 0, 0, 0)\\\",\\n title: {\\n text: \\\"项目反馈桑基图\\\",\\n subtext: \\\"展示各个项目任务的不同反馈分类占比\\\",\\n left: \\\"center\\\",\\n top: 24,\\n textStyle: {\\n fontSize: 16,\\n fontWeight: \\\"bold\\\",\\n },\\n },\\n tooltip: {\\n trigger: 'item',\\n triggerOn: 'mousemove',\\n formatter: gettooltip\\n },\\n series: [{\\n type: \\\"sankey\\\",\\n animation: true,\\n animationDuration: 300,\\n animationEasingUpdate: 'quinticInOut',\\n left: '5%',\\n top: '12%',\\n right: '20%',\\n bottom: '12%',\\n nodeAlign: 'justify',\\n orient: 'horizontal',\\n emphasis: {\\n focus: 'adjacency'\\n },\\n data: nodes,\\n links: links,\\n nodeGap: 12,\\n nodeWidth: 24,\\n draggable: true,\\n levels: [{\\n depth: 0,\\n itemStyle: {\\n borderWidth: 2\\n },\\n lineStyle: {\\n curveness: 0.5,\\n opacity: 0.7\\n }\\n }, {\\n depth: 1,\\n itemStyle: {\\n borderWidth: 1\\n },\\n lineStyle: {\\n curveness: 0.5,\\n opacity: 0.7\\n }\\n }, {\\n depth: 2,\\n itemStyle: {\\n borderWidth: 1\\n },\\n lineStyle: {\\n curveness: 0.5,\\n opacity: 0.7\\n }\\n }],\\n label: {\\n position: 'right',\\n fontSize: 12,\\n lineHeight: 16,\\n color: '#000000',\\n distance: 10,\\n formatter: function (params) {\\n var name = params.name;\\n if (name.length > 15) {\\n name = name.substring(0, 15) + '...';\\n }\\n return `${name}(${params.value})`;\\n },\\n show: true,\\n align: 'left',\\n verticalAlign: 'middle',\\n backgroundColor: '#ffffffcc',\\n padding: [4, 8],\\n borderRadius: 4\\n }\\n }]\\n};\\n\\n return {\\n option,\\n datGUI,\\n };\\n }\\n \"}" } }, "16,1": { @@ -1041,4 +1059,4 @@ "Size": "1473,1000" } ] -}//d/OdtusR5qSuWOcQTG6eLY4yFPWc6mSJlu1/Q2uba0vqTBM81YLRwZIxgiNHKwjJRKoKSeetAVPlq25GPy322tT32YMuvpkcl5Y9a+1BG3N6K4oE7RKCz2I3zQn9b0JVjiH1WAgaWhvXldWwoNw+U3Z1Mkexz37FJy3M/LAISHRWK5vr4KD58/9ktkT14XLA6Ccm2RY4LBxF2uF2Wdu9TvZOuY6yqfJOsvRw5M3X93nFAbsPkG/ArgeJqEORfp6+xRWE9gJHb5LPXAtvrTQRSNG6VP1AScLiIwJQHDuH2tvyD2EHlfl8blexp/EyoUX/ijCa1eiI3hTSmu0jDOP6MFdAdzdNyTsU6eO3pl2rRDM6zY1G5YFf7f38UM2o1cP7ACdOhfgS2jMo8t4rD8/ghOeFUmKNGCNFHYlcYaqjGJEHz4xrUcfOL+sxb8T4HW5TeQ2qpjuCcQU6b6alO15BjBbgh1rZBcBm/IhdKlBSDBn2CdDB/E8grmdZfWTq26qq3hewjgwCQXgnbYeI9Q0RNAWYL9jxCK2kstDy6KIZqY6H1JFrWsEpQ2e7w+4orItYF/YoPjv8wsTaTPbwVG3ueGapBvJVIP0uvvmmLeSI7bQxSDye5A+KsULFLGP6EBosjkicNoGJAWq8WeiD7n3yXglQGn8t+hnXJo+NpRMln0+fWTkoglpmqNSw/9ddYy7AinINvIclC0Sh2monz4XjsAtW/6VjH8A6+Jr38gq6ADJmrm/Pb7pFY2dEoRc+94WRETeBzTDtYT6Ru5P1PpeHflEhWJDROrDGUZjopD3AfIz+rx8tzQ5OdkTqSCdbCShzSNJKpqmFkwXRLbzRz9e4xF2SNrZrjHRzGNoG289D2MvSHhxN5zOrjUz+0gk8v5vykN1Y11mnuMmgLQiGOFBBpw==|920 \ No newline at end of file +}//shXdgHaVBhtjzqdCqqH2bKdKpfV0eCm/YuIBP1C2iFJYHqW5mc2/hGyPZ65PBrzK9G70kSznKBYPQgG4FCKiH/ck70Ntb33bN7nrE80TADpq/Jl060riCjTz13fUyUhWWCe+B+E+76pCaBvYK5PfXNsh21SSYFks04867JGTJEviyqKicbDTcFozU9ZzlQ+iY+8/h1qtFwLAr5coWp+qKeNwCcjlFKx8gwSTk6OFxtrPkQRh79/HbOZfWSbl+kLjrLo4VE9s3JE6pOXG1umNkXDpdcNpUj9QJdNsWQcUFG2AIY3cr+tDo0bBA8/Fu+DawASOaUGZBT98pbQTMe1cKb5qHW9fbWaNWP+DExIL94Lrpx7+w89E6hpTpNb2yGfeMo+1pEJaXtI+6y1BJ99o4BYa2moIy9xY3YSQ6e5M3DDF9wKlkFmleLhl04pzKDGyDUQkGCwn9o6ue6FHHHTxOOCXSqXadIpZmLRVSB0pK/HDDToLKcfC8nrV91bounHJtWzQCiWjxZJfvYs97A03B0IQ/NxGdM+Tp1gTOq+TUBBKLKaZES4vt7MWhvzkXONtdk0c5/2vkTA34j6ucL6tXUO6HQtDmmFk+seymPqm3PSzwhsJ4AiWIfy1PQI9EY4DmgHCV3jRfEaCr0A5v+ThZUlAghjxnL16XK0JXBa0+C6Cuakv4K4JKqvTNIGR0KpL7PuMykmWwpByv0t5LmqYedTp5Uhag9YxVGRS7TGkpcrdzUpQZCNmZ7NaBKdUsf7RxO+Q52EfsjE2Rw+/jSO5jVQab9CeRahFeZm0hRTdg7mv5RmFBxka9U+d2TPopti6xHTYyit5f0INZB7m0tHkNQuLOQKUqLY4cBPefDWPs+HuQqt3JvcdGZwOOl4GLKRcT/P7u3c28jhcL+dD6B8JYQ==|920 \ No newline at end of file diff --git a/Tables/需求反馈/项目反馈数量统计视图.json b/Tables/需求反馈/项目反馈数量统计视图.json index 18342ae5..ae884fcf 100644 --- a/Tables/需求反馈/项目反馈数量统计视图.json +++ b/Tables/需求反馈/项目反馈数量统计视图.json @@ -8,6 +8,20 @@ "Name": "类型", "ColumnType": "System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" }, + { + "$type": "Forguncy.SaveLoad.BindingColumnSaveData, ServerDesignerCommon", + "DatabaseColumnType": "bigint", + "MaxLength": -1, + "Name": "项目ID", + "ColumnType": "System.Int64, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" + }, + { + "$type": "Forguncy.SaveLoad.BindingColumnSaveData, ServerDesignerCommon", + "DatabaseColumnType": "bigint", + "MaxLength": -1, + "Name": "任务ID", + "ColumnType": "System.Int64, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" + }, { "$type": "Forguncy.SaveLoad.BindingColumnSaveData, ServerDesignerCommon", "DatabaseColumnType": "nvarchar", @@ -17,11 +31,19 @@ }, { "$type": "Forguncy.SaveLoad.BindingColumnSaveData, ServerDesignerCommon", + "Required": true, "DatabaseColumnType": "nvarchar", "MaxLength": -1, "Name": "任务", "ColumnType": "System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" }, + { + "$type": "Forguncy.SaveLoad.BindingColumnSaveData, ServerDesignerCommon", + "DatabaseColumnType": "nvarchar", + "MaxLength": -1, + "Name": "处理人", + "ColumnType": "System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" + }, { "$type": "Forguncy.SaveLoad.BindingColumnSaveData, ServerDesignerCommon", "DatabaseColumnType": "int", @@ -35,7 +57,7 @@ "ConnectionId": "业务表", "SourceTableName": "项目反馈数量统计视图", "SourceTableSchema": "dbo", - "CreateViewSql": "SELECT\r\nlx.[反馈类型] AS 类型,\r\nxm.[项目名称] AS 项目,\r\nrw.[任务名称] AS 任务,\r\ncount(main.ID) AS 数量\r\nFROM [需求反馈登记表] main\r\nLEFT JOIN [反馈类型表] lx ON main.[反馈类型] = lx.[ID]\r\nLEFT JOIN [项目表] xm ON main.[项目ID] = xm.[ID]\r\nLEFT JOIN [任务表] rw ON main.[关联任务] = rw.[ID]\r\nWHERE xm.[项目名称] is not null\r\nGROUP BY\r\nlx.[反馈类型],xm.[项目名称],rw.[任务名称]", + "CreateViewSql": "SELECT\r\nlx.[反馈类型] AS 类型,\r\nxm.[ID] AS [项目ID],\r\nrw.[ID] AS [任务ID],\r\nxm.[项目名称] AS 项目,\r\nISNULL(rw.[任务名称], '未指定任务') AS 任务,\r\nmain.[处理人],\r\ncount(main.ID) AS 数量\r\nFROM [需求反馈登记表] main\r\nLEFT JOIN [反馈类型表] lx ON main.[反馈类型] = lx.[ID]\r\nLEFT JOIN [项目表] xm ON main.[项目ID] = xm.[ID]\r\nLEFT JOIN [任务表] rw ON main.[关联任务] = rw.[ID]\r\nWHERE xm.[项目名称] is not null\r\nGROUP BY\r\nlx.[反馈类型],xm.[ID],rw.[ID],xm.[项目名称],rw.[任务名称],main.[处理人]", "ViewInfo": { "ViewName": "项目反馈数量统计视图", "IsUpdatable": true,