|
@@ -6,11 +6,86 @@ import Panel2 from './components/Panel2'
|
|
|
import ModelPanel from './components/ModelPanel'
|
|
import ModelPanel from './components/ModelPanel'
|
|
|
import { echPageBackFu } from '@/components/MenuSider/data'
|
|
import { echPageBackFu } from '@/components/MenuSider/data'
|
|
|
import Zback from '@/components/Zback'
|
|
import Zback from '@/components/Zback'
|
|
|
-import ChartInput from './components/ChartInput'
|
|
|
|
|
|
|
+import http from '@/utils/axios'
|
|
|
|
|
+
|
|
|
|
|
+import level1 from './images/level_01-min.png'
|
|
|
|
|
+import level2 from './images/level_02-min.png'
|
|
|
|
|
+import level3 from './images/level_03-min.png'
|
|
|
|
|
+import level4 from './images/level_04-min.png'
|
|
|
|
|
+import level5 from './images/level_05-min.png'
|
|
|
|
|
+import level6 from './images/level_06-min.png'
|
|
|
|
|
+import { baseUrl } from '@/utils/http'
|
|
|
|
|
+import { DotLoading } from 'antd-mobile'
|
|
|
|
|
+
|
|
|
|
|
+const levelImages = [level1, level1, level1, level2, level3, level4, level5, level6]
|
|
|
|
|
+const getLevelImage = (depth: number) => levelImages[Math.min(depth, 5)]
|
|
|
|
|
+const getLevelSize = (depth: number) => (depth <= 2 ? 60 : 40)
|
|
|
|
|
+
|
|
|
|
|
+const transformData = (data: any[]): any[] => {
|
|
|
|
|
+ return data.map(item => ({
|
|
|
|
|
+ ...item,
|
|
|
|
|
+ label: item.name,
|
|
|
|
|
+ children: item.children ? transformData(item.children) : undefined
|
|
|
|
|
+ }))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const loadImage = (src: string): Promise<HTMLImageElement> => {
|
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
|
+ const img = new Image()
|
|
|
|
|
+ img.crossOrigin = 'anonymous'
|
|
|
|
|
+ img.onload = () => resolve(img)
|
|
|
|
|
+ img.onerror = () => reject(new Error(`Failed to load: ${src}`))
|
|
|
|
|
+ img.src = src
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const createCombinedSymbol = async (
|
|
|
|
|
+ levelImageSrc: string,
|
|
|
|
|
+ thumbSrc: string,
|
|
|
|
|
+ symbolSize: number
|
|
|
|
|
+): Promise<string> => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const canvas = document.createElement('canvas')
|
|
|
|
|
+ canvas.width = symbolSize
|
|
|
|
|
+ canvas.height = symbolSize
|
|
|
|
|
+ const ctx = canvas.getContext('2d')!
|
|
|
|
|
+
|
|
|
|
|
+ const levelImg = await loadImage(levelImageSrc)
|
|
|
|
|
+ ctx.drawImage(levelImg, 0, 0, symbolSize, symbolSize)
|
|
|
|
|
+
|
|
|
|
|
+ const thumbImg = await loadImage(thumbSrc)
|
|
|
|
|
+ const thumbSize = symbolSize === 40 ? 30 : 48
|
|
|
|
|
+ const centerX = symbolSize / 2 - (symbolSize === 60 ? 1 : 0)
|
|
|
|
|
+ const centerY = symbolSize / 2 - (symbolSize === 60 ? 1 : 0)
|
|
|
|
|
+ const imgW = thumbImg.width
|
|
|
|
|
+ const imgH = thumbImg.height
|
|
|
|
|
+ const scale = Math.max(thumbSize / imgW, thumbSize / imgH)
|
|
|
|
|
+ const drawW = imgW * scale
|
|
|
|
|
+ const drawH = imgH * scale
|
|
|
|
|
+ const drawX = centerX - drawW / 2
|
|
|
|
|
+ const drawY = centerY - drawH / 2
|
|
|
|
|
+
|
|
|
|
|
+ ctx.save()
|
|
|
|
|
+ ctx.beginPath()
|
|
|
|
|
+ ctx.arc(centerX, centerY, thumbSize / 2, 0, Math.PI * 2)
|
|
|
|
|
+ ctx.clip()
|
|
|
|
|
+ ctx.drawImage(thumbImg, drawX, drawY, drawW, drawH)
|
|
|
|
|
+ ctx.restore()
|
|
|
|
|
+
|
|
|
|
|
+ return `image://${canvas.toDataURL()}`
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ return `image://${levelImageSrc}`
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
function A9knowlege() {
|
|
function A9knowlege() {
|
|
|
// 是否显示返回按钮
|
|
// 是否显示返回按钮
|
|
|
const [backShow, setBackShow] = useState(false)
|
|
const [backShow, setBackShow] = useState(false)
|
|
|
|
|
+ // 控制 sidebar 显示
|
|
|
|
|
+ const [sidebarVisible, setSidebarVisible] = useState(true)
|
|
|
|
|
+ const [knowlegeData, setKnowlegeData] = useState<any[]>([])
|
|
|
|
|
+ const [dataLoading, setDataLoading] = useState(true)
|
|
|
|
|
+ const currentId = useRef<string | null>(null)
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
if (!window.location.href.includes('?l=look')) {
|
|
if (!window.location.href.includes('?l=look')) {
|
|
@@ -21,8 +96,30 @@ function A9knowlege() {
|
|
|
const echartRef = useRef<HTMLDivElement | null>(null)
|
|
const echartRef = useRef<HTMLDivElement | null>(null)
|
|
|
const chartInstance = useRef<any>(null)
|
|
const chartInstance = useRef<any>(null)
|
|
|
const [detail, setDetail] = useState<any>(null)
|
|
const [detail, setDetail] = useState<any>(null)
|
|
|
|
|
+ const [detailLoading, setDetailLoading] = useState(false)
|
|
|
|
|
|
|
|
- const buildGraphFromKnowlege = (data: any[]) => {
|
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ const fetchKnowlegeData = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ setDataLoading(true)
|
|
|
|
|
+ const response = await http.get('/show/dict/getTree')
|
|
|
|
|
+ if (response.code === 0 && response.data) {
|
|
|
|
|
+ const transformedData = transformData(Array.isArray(response.data) ? response.data : [])
|
|
|
|
|
+ setKnowlegeData(transformedData)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ setKnowlegeData([])
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('获取知识图谱数据失败:', error)
|
|
|
|
|
+ setKnowlegeData([])
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ setDataLoading(false)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ fetchKnowlegeData()
|
|
|
|
|
+ }, [])
|
|
|
|
|
+
|
|
|
|
|
+ const buildGraphFromKnowlege = async (data: any[]) => {
|
|
|
const nodes: any[] = []
|
|
const nodes: any[] = []
|
|
|
const links: any[] = []
|
|
const links: any[] = []
|
|
|
let idCounter = 0
|
|
let idCounter = 0
|
|
@@ -32,14 +129,35 @@ function A9knowlege() {
|
|
|
const traverse = (item: any, parentId: string | null, depth: number) => {
|
|
const traverse = (item: any, parentId: string | null, depth: number) => {
|
|
|
const id = genId(item.label)
|
|
const id = genId(item.label)
|
|
|
const category = `level${depth}`
|
|
const category = `level${depth}`
|
|
|
- const symbolSize = depth === 0 ? 60 : depth === 1 ? 40 : 20
|
|
|
|
|
- nodes.push({ id, name: item.label, category, symbolSize, raw: item })
|
|
|
|
|
- if (parentId) links.push({ source: parentId, target: id })
|
|
|
|
|
|
|
+ const symbolSize = getLevelSize(depth)
|
|
|
|
|
+ const symbol = `image://${getLevelImage(depth)}`
|
|
|
|
|
+ // 保存 thumb 信息用于后续处理
|
|
|
|
|
+ nodes.push({
|
|
|
|
|
+ id,
|
|
|
|
|
+ name: item.label,
|
|
|
|
|
+ category,
|
|
|
|
|
+ symbolSize,
|
|
|
|
|
+ symbol,
|
|
|
|
|
+ raw: item,
|
|
|
|
|
+ depth,
|
|
|
|
|
+ thumb: item.thumb ? baseUrl + item.thumb : null
|
|
|
|
|
+ })
|
|
|
|
|
+ if (parentId) links.push({ source: parentId, target: id, targetDepth: depth })
|
|
|
if (Array.isArray(item.children))
|
|
if (Array.isArray(item.children))
|
|
|
item.children.forEach((child: any) => traverse(child, id, depth + 1))
|
|
item.children.forEach((child: any) => traverse(child, id, depth + 1))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
data.forEach((root: any) => traverse(root, null, 0))
|
|
data.forEach((root: any) => traverse(root, null, 0))
|
|
|
|
|
+
|
|
|
|
|
+ // 对于有 thumb 的节点,异步生成合成 symbol
|
|
|
|
|
+ const thumbPromises = nodes
|
|
|
|
|
+ .filter(n => n.thumb)
|
|
|
|
|
+ .map(async n => {
|
|
|
|
|
+ const levelImageSrc = getLevelImage(n.depth)
|
|
|
|
|
+ n.symbol = await createCombinedSymbol(levelImageSrc, n.thumb, n.symbolSize)
|
|
|
|
|
+ })
|
|
|
|
|
+ await Promise.all(thumbPromises)
|
|
|
|
|
+
|
|
|
const maxDepth = nodes.reduce((m, n) => {
|
|
const maxDepth = nodes.reduce((m, n) => {
|
|
|
const match = (n.category || '').match(/level(\d+)/)
|
|
const match = (n.category || '').match(/level(\d+)/)
|
|
|
const d = match ? Number(match[1]) : 0
|
|
const d = match ? Number(match[1]) : 0
|
|
@@ -50,12 +168,11 @@ function A9knowlege() {
|
|
|
return { nodes, links, categories }
|
|
return { nodes, links, categories }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const initChart = useCallback(() => {
|
|
|
|
|
|
|
+ const initChart = useCallback(async () => {
|
|
|
// @ts-ignore
|
|
// @ts-ignore
|
|
|
const echarts = (window as any).echarts
|
|
const echarts = (window as any).echarts
|
|
|
- // @ts-ignore
|
|
|
|
|
const data = knowlegeData || []
|
|
const data = knowlegeData || []
|
|
|
- if (!echarts || !echartRef.current) return
|
|
|
|
|
|
|
+ if (!echarts || !echartRef.current || dataLoading || data.length === 0) return
|
|
|
|
|
|
|
|
if (chartInstance.current) {
|
|
if (chartInstance.current) {
|
|
|
try {
|
|
try {
|
|
@@ -70,7 +187,7 @@ function A9knowlege() {
|
|
|
})
|
|
})
|
|
|
chartInstance.current = myChart
|
|
chartInstance.current = myChart
|
|
|
|
|
|
|
|
- const graph = buildGraphFromKnowlege(data)
|
|
|
|
|
|
|
+ const graph = await buildGraphFromKnowlege(data)
|
|
|
|
|
|
|
|
const option = {
|
|
const option = {
|
|
|
tooltip: { show: false },
|
|
tooltip: { show: false },
|
|
@@ -79,18 +196,66 @@ function A9knowlege() {
|
|
|
name: 'KnowledgeGraph',
|
|
name: 'KnowledgeGraph',
|
|
|
type: 'graph',
|
|
type: 'graph',
|
|
|
layout: 'force',
|
|
layout: 'force',
|
|
|
- data: graph.nodes.map((n: any) => ({
|
|
|
|
|
- ...n,
|
|
|
|
|
- label: { show: true, formatter: n.name, fontSize: 12 }
|
|
|
|
|
- })),
|
|
|
|
|
- links: graph.links,
|
|
|
|
|
|
|
+ data: graph.nodes.map((n: any) => {
|
|
|
|
|
+ const match = (n.category || '').match(/level(\d+)/)
|
|
|
|
|
+ const depth = match ? Number(match[1]) : 0
|
|
|
|
|
+ let fontColor = '#FFE9B6'
|
|
|
|
|
+ let fontSize = 16
|
|
|
|
|
+ let fontWeight: 'bold' | 'normal' = 'bold'
|
|
|
|
|
+ if (depth === 3) {
|
|
|
|
|
+ fontColor = '#FF9807'
|
|
|
|
|
+ fontWeight = 'normal'
|
|
|
|
|
+ } else if (depth >= 4) {
|
|
|
|
|
+ fontColor = '#D1C9B2'
|
|
|
|
|
+ fontSize = 14
|
|
|
|
|
+ fontWeight = 'normal'
|
|
|
|
|
+ }
|
|
|
|
|
+ return {
|
|
|
|
|
+ ...n,
|
|
|
|
|
+ symbol: n.symbol,
|
|
|
|
|
+ symbolSize: n.symbolSize,
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: fontColor
|
|
|
|
|
+ },
|
|
|
|
|
+ label: {
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ formatter: n.name,
|
|
|
|
|
+ fontSize,
|
|
|
|
|
+ fontWeight,
|
|
|
|
|
+ color: fontColor,
|
|
|
|
|
+ position: 'bottom',
|
|
|
|
|
+ distance: 6,
|
|
|
|
|
+ align: 'center',
|
|
|
|
|
+ textShadowColor: 'rgba(0, 0, 0, 0.5)',
|
|
|
|
|
+ textShadowBlur: 4,
|
|
|
|
|
+ textShadowOffsetX: 0,
|
|
|
|
|
+ textShadowOffsetY: 0
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }),
|
|
|
|
|
+ links: graph.links.map((link: any) => {
|
|
|
|
|
+ const depth = link.targetDepth
|
|
|
|
|
+ let lineColor = '#FFE9B6'
|
|
|
|
|
+ if (depth === 3) {
|
|
|
|
|
+ lineColor = '#FF9807'
|
|
|
|
|
+ } else if (depth >= 4) {
|
|
|
|
|
+ lineColor = '#D1C9B2'
|
|
|
|
|
+ }
|
|
|
|
|
+ return {
|
|
|
|
|
+ ...link,
|
|
|
|
|
+ lineStyle: {
|
|
|
|
|
+ color: lineColor
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }),
|
|
|
categories: graph.categories,
|
|
categories: graph.categories,
|
|
|
roam: true,
|
|
roam: true,
|
|
|
|
|
+ zoom: 0.5,
|
|
|
scaleLimit: {
|
|
scaleLimit: {
|
|
|
- min: 0.5,
|
|
|
|
|
- max: 3
|
|
|
|
|
|
|
+ min: 0.2,
|
|
|
|
|
+ max: 1.2
|
|
|
},
|
|
},
|
|
|
- label: { position: 'right' },
|
|
|
|
|
|
|
+ label: { position: 'bottom', distance: 6, align: 'center' },
|
|
|
focusNodeAdjacency: true,
|
|
focusNodeAdjacency: true,
|
|
|
emphasis: {
|
|
emphasis: {
|
|
|
focus: 'adjacency',
|
|
focus: 'adjacency',
|
|
@@ -99,8 +264,15 @@ function A9knowlege() {
|
|
|
opacity: 1
|
|
opacity: 1
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- force: { repulsion: 200, edgeLength: [50, 120] },
|
|
|
|
|
- lineStyle: { color: 'source', curveness: 0.2 },
|
|
|
|
|
|
|
+ // force 布局参数:调大 repulsion 让斥力更明显
|
|
|
|
|
+ // 降低 gravity 避免被拉回中心过紧
|
|
|
|
|
+ force: {
|
|
|
|
|
+ repulsion: 900,
|
|
|
|
|
+ edgeLength: [80, 80],
|
|
|
|
|
+ gravity: 0.05
|
|
|
|
|
+ },
|
|
|
|
|
+ // 连线为直线:curveness 设为 0
|
|
|
|
|
+ lineStyle: { curveness: 0 },
|
|
|
edgeLabel: { show: false },
|
|
edgeLabel: { show: false },
|
|
|
edgeSymbol: ['none', 'none']
|
|
edgeSymbol: ['none', 'none']
|
|
|
}
|
|
}
|
|
@@ -122,6 +294,7 @@ function A9knowlege() {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
if (params.dataType === 'edge') {
|
|
if (params.dataType === 'edge') {
|
|
|
|
|
+ // 关系线
|
|
|
const edge = params.data
|
|
const edge = params.data
|
|
|
const sourceIndex = graph.nodes.findIndex((n: any) => n.id === edge.source)
|
|
const sourceIndex = graph.nodes.findIndex((n: any) => n.id === edge.source)
|
|
|
const targetIndex = graph.nodes.findIndex((n: any) => n.id === edge.target)
|
|
const targetIndex = graph.nodes.findIndex((n: any) => n.id === edge.target)
|
|
@@ -141,25 +314,83 @@ function A9knowlege() {
|
|
|
}, 10)
|
|
}, 10)
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- // 点击的是节点
|
|
|
|
|
|
|
+ // 节点
|
|
|
myChart.dispatchAction({
|
|
myChart.dispatchAction({
|
|
|
type: 'highlight',
|
|
type: 'highlight',
|
|
|
dataIndex: params.dataIndex
|
|
dataIndex: params.dataIndex
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
const node = params.data
|
|
const node = params.data
|
|
|
- if (node && node.raw && node.raw.type) {
|
|
|
|
|
- setDetail(node.raw)
|
|
|
|
|
|
|
+ if (node && node.raw && node.raw.id) {
|
|
|
|
|
+ if (currentId.current === node.raw.id) return
|
|
|
|
|
+
|
|
|
|
|
+ const fetchDetail = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ currentId.current = node.raw.id
|
|
|
|
|
+ setDetailLoading(true)
|
|
|
|
|
+ const response = await http.get(`/show/dict/detail/${node.raw.id}`)
|
|
|
|
|
+ if (response.code === 0 && response.data) {
|
|
|
|
|
+ const { label, name, rtf } = response.data
|
|
|
|
|
+ let detailData: any = { name }
|
|
|
|
|
+
|
|
|
|
|
+ // 存在 label 显示 Panel
|
|
|
|
|
+ if (label) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const parsedLabel = JSON.parse(label.replace(/\\\\"/g, '\\"'))
|
|
|
|
|
+ detailData = {
|
|
|
|
|
+ ...detailData,
|
|
|
|
|
+ label: name,
|
|
|
|
|
+ content: Array.isArray(parsedLabel) ? parsedLabel : [],
|
|
|
|
|
+ type: 'label'
|
|
|
|
|
+ }
|
|
|
|
|
+ setDetail(detailData)
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('解析 label 失败:', e)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 存在 rtf 显示 Panel2
|
|
|
|
|
+ else if (rtf) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const parsedRtf = JSON.parse(rtf)
|
|
|
|
|
+ const content = parsedRtf?.txtArr?.[0]?.txt || ''
|
|
|
|
|
+ detailData = {
|
|
|
|
|
+ ...detailData,
|
|
|
|
|
+ label: name,
|
|
|
|
|
+ content: content,
|
|
|
|
|
+ type: 'rtf'
|
|
|
|
|
+ }
|
|
|
|
|
+ setDetail(detailData)
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('解析 rtf 失败:', e)
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ setDetail(null)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ setDetail(null)
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ setDetailLoading(false)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ fetchDetail()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
const resizeHandler = () => myChart.resize()
|
|
const resizeHandler = () => myChart.resize()
|
|
|
window.addEventListener('resize', resizeHandler)
|
|
window.addEventListener('resize', resizeHandler)
|
|
|
;(chartInstance.current as any)._resizeHandler = resizeHandler
|
|
;(chartInstance.current as any)._resizeHandler = resizeHandler
|
|
|
- }, [])
|
|
|
|
|
|
|
+ }, [knowlegeData, dataLoading])
|
|
|
|
|
+
|
|
|
|
|
+ const handleClosePanel = () => {
|
|
|
|
|
+ setDetail(null)
|
|
|
|
|
+ currentId.current = null
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
- initChart()
|
|
|
|
|
|
|
+ if (!dataLoading && knowlegeData.length > 0) {
|
|
|
|
|
+ initChart()
|
|
|
|
|
+ }
|
|
|
return () => {
|
|
return () => {
|
|
|
if (chartInstance.current) {
|
|
if (chartInstance.current) {
|
|
|
try {
|
|
try {
|
|
@@ -171,7 +402,16 @@ function A9knowlege() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
- }, [])
|
|
|
|
|
|
|
+ }, [knowlegeData, dataLoading, initChart])
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ const timer = setTimeout(() => {
|
|
|
|
|
+ if (chartInstance.current) {
|
|
|
|
|
+ chartInstance.current.resize()
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 300)
|
|
|
|
|
+ return () => clearTimeout(timer)
|
|
|
|
|
+ }, [sidebarVisible])
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<div className={styles.A9knowlege}>
|
|
<div className={styles.A9knowlege}>
|
|
@@ -181,16 +421,27 @@ function A9knowlege() {
|
|
|
<div id='echart-container' ref={echartRef} />
|
|
<div id='echart-container' ref={echartRef} />
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <div className={styles.sidebar}>
|
|
|
|
|
- {!detail ? (
|
|
|
|
|
|
|
+ <div className={`${styles.sidebar} ${!sidebarVisible ? styles.sidebarHidden : ''}`}>
|
|
|
|
|
+ {detailLoading ? (
|
|
|
|
|
+ <div className={styles.loading}>
|
|
|
|
|
+ <DotLoading color='#7c4b36' />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ ) : !detail ? (
|
|
|
<Chart />
|
|
<Chart />
|
|
|
- ) : detail.type === 1 ? (
|
|
|
|
|
- <Panel detail={detail} onClose={() => setDetail(null)} />
|
|
|
|
|
|
|
+ ) : detail.type === 'label' ? (
|
|
|
|
|
+ <Panel detail={detail} onClose={handleClosePanel} />
|
|
|
|
|
+ ) : detail.type === 'rtf' ? (
|
|
|
|
|
+ <Panel2 detail={detail} onClose={handleClosePanel} />
|
|
|
) : detail.type === 5 ? (
|
|
) : detail.type === 5 ? (
|
|
|
- <ModelPanel detail={detail} onClose={() => setDetail(null)} />
|
|
|
|
|
|
|
+ <ModelPanel detail={detail} onClose={handleClosePanel} />
|
|
|
) : (
|
|
) : (
|
|
|
- <Panel2 detail={detail} onClose={() => setDetail(null)} />
|
|
|
|
|
|
|
+ <Panel2 detail={detail} onClose={handleClosePanel} />
|
|
|
)}
|
|
)}
|
|
|
|
|
+
|
|
|
|
|
+ <div
|
|
|
|
|
+ className={`${styles.sidebarHideBtn} ${!sidebarVisible ? styles.hide : ''}`}
|
|
|
|
|
+ onClick={() => setSidebarVisible(!sidebarVisible)}
|
|
|
|
|
+ ></div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
)
|
|
)
|