shaogen1995 2 месяцев назад
Родитель
Сommit
4fe5aef5ff

+ 186 - 0
src/pages/Aanalyse/A1resStat/data.ts

@@ -0,0 +1,186 @@
+import * as echarts from 'echarts'
+
+// 生成模拟数据 - 中图分类统计
+const generateZhongTuData = () => {
+  const categories = [
+    'A 马克思主义、列宁主义、毛泽东思想、邓小平理论',
+    'B 哲学、宗教',
+    'C 社会科学总论',
+    'D 政治、法律',
+    'E 军事',
+    'F 经济',
+    'G 文化、科学、教育、体育',
+    'H 语言、文字',
+    'I 文学',
+    'J 艺术',
+    'K 历史、地理',
+    'N 自然科学总论',
+    'O 数理科学和化学',
+    'P 天文学、地球科学',
+    'Q 生物科学',
+    'R 医药、卫生',
+    'S 农业科学',
+    'T 工业技术',
+    'U 交通运输',
+    'V 航空、航天',
+    'X 环境科学、安全科学',
+    'Z 综合性图书',
+  ]
+
+  return categories.map(name => ({
+    name,
+    value: Math.floor(Math.random() * 500) + 50
+  }))
+}
+
+// 生成模拟数据 - 四部分类统计
+const generateSiBuData = () => {
+  const categories = [
+    '经部·易类',
+    '经部·书类',
+    '经部·诗类',
+    '经部·礼类',
+    '经部·春秋类',
+    '经部·孝经类',
+    '经部·五经总义类',
+    '经部·四书类',
+    '经部·小学类',
+    '史部·正史类',
+    '史部·编年类',
+    '史部·纪事本末类',
+    '史部·别史类',
+    '史部·杂史类',
+    '史部·诏令奏议类',
+    '史部·传记类',
+    '史部·史抄类',
+    '史部·载记类',
+    '史部·时令类',
+    '史部·地理类',
+    '史部·职官类',
+    '史部·政书类',
+    '史部·目录类',
+    '史部·史评类',
+    '子部·儒家类',
+    '子部·兵家类',
+    '子部·法家类',
+    '子部·农家类',
+    '子部·医家类',
+    '子部·天文算法类',
+  ]
+
+  return categories.map(name => ({
+    name,
+    value: Math.floor(Math.random() * 400) + 30
+  }))
+}
+
+// 生成柱状图
+export const initEchZhuFu = (data: any[], dom: any, type: 'zhongTu' | 'siBu' = 'zhongTu') => {
+  if (!dom) return
+
+  // 销毁已存在的实例
+  const existingChart = echarts.getInstanceByDom(dom)
+  if (existingChart) {
+    existingChart.dispose()
+  }
+
+  const myChart = echarts.init(dom)
+
+  // 根据类型获取数据
+  const chartData = type === 'zhongTu' ? generateZhongTuData() : generateSiBuData()
+  const total = chartData.reduce((sum, item) => sum + item.value, 0)
+
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      },
+      formatter: (params: any) => {
+        const item = params[0]
+        const percent = ((item.value / total) * 100).toFixed(1)
+        return `${item.name}<br/>数量: ${item.value}<br/>占比: ${percent}%`
+      }
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '15%',
+      top: '10%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: chartData.map(item => item.name),
+      axisLabel: {
+        interval: 0,
+        rotate: 30,
+        fontSize: 11,
+        width: 100,
+        overflow: 'truncate',
+        ellipsis: '...'
+      },
+      axisTick: {
+        alignWithLabel: true
+      }
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: type === 'zhongTu' ? '中图分类' : '四部分类',
+        type: 'bar',
+        barWidth: 40,
+        data: chartData.map(item => item.value),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: type === 'zhongTu' ? '#83bff6' : '#92cc76' },
+            { offset: 0.5, color: type === 'zhongTu' ? '#188df0' : '#5cb85c' },
+            { offset: 1, color: type === 'zhongTu' ? '#188df0' : '#4cae4c' }
+          ])
+        },
+        label: {
+          show: true,
+          position: 'top',
+          formatter: (params: any) => {
+            const percent = ((params.value / total) * 100).toFixed(1)
+            return `${params.value}\n${percent}%`
+          },
+          fontSize: 10,
+          color: '#333',
+          lineHeight: 14
+        },
+        emphasis: {
+          itemStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              { offset: 0, color: type === 'zhongTu' ? '#2378f7' : '#5cb85c' },
+              { offset: 0.7, color: type === 'zhongTu' ? '#2378f7' : '#4cae4c' },
+              { offset: 1, color: type === 'zhongTu' ? '#83bff6' : '#92cc76' }
+            ])
+          }
+        }
+      }
+    ]
+  }
+
+  myChart.setOption(option)
+
+  // 点击柱子事件
+  myChart.on('click', (params: any) => {
+    console.log('点击柱子信息:', {
+      分类名称: params.name,
+      数量: params.value,
+      占比: ((params.value / total) * 100).toFixed(1) + '%',
+      系列名称: params.seriesName,
+      数据索引: params.dataIndex
+    })
+  })
+
+  // 自适应
+  window.addEventListener('resize', () => {
+    myChart.resize()
+  })
+
+  return myChart
+}

+ 103 - 0
src/pages/Aanalyse/A1resStat/index.module.scss

@@ -1,4 +1,107 @@
 .A1resStat {
+  font-size: 16px;
+  padding: 15px;
+  display: flex;
   :global {
+    .A1box {
+      background-color: #fff;
+      border-radius: 10px;
+    }
+
+    .A1tit {
+      font-weight: 700;
+      color: var(--txtColor);
+    }
+    .A1tll {
+      width: calc(100% - 490px);
+    }
+    .A1tll1 {
+      display: flex;
+      .A1row1 {
+        padding: 20px 0 0 50px;
+        width: 210px;
+        height: 100px;
+        margin-right: 20px;
+        & > p {
+          margin-top: 10px;
+          font-weight: 700;
+          font-size: 22px;
+        }
+      }
+
+      .A1row2 {
+        padding-right: 20px;
+        width: auto;
+        .A1titSon {
+          margin-top: 10px;
+          display: flex;
+          align-items: center;
+          & > span {
+            font-size: 14px;
+            color: var(--txtColor);
+          }
+          & > p {
+            margin-left: 15px;
+            margin-right: 20px;
+            font-weight: 700;
+            font-size: 22px;
+          }
+        }
+      }
+
+      .A1row3 {
+        margin-right: 0;
+        padding-right: 20px;
+        width: auto;
+        .A1row3Son {
+          display: flex;
+          align-items: center;
+          & > p {
+            font-weight: 700;
+            font-size: 22px;
+          }
+        }
+        .A1tit {
+          display: flex;
+          & > div {
+            position: relative;
+            top: -6px;
+            margin-left: 20px;
+          }
+        }
+      }
+    }
+
+    .A1tll2 {
+      margin-top: 15px;
+      height: calc(100% - 110px);
+      overflow: auto;
+      padding: 10px;
+      .A1tu {
+        .A1tit {
+          margin-bottom: 10px;
+        }
+        .echZhu {
+          height: 450px;
+          width: 100%;
+        }
+      }
+    }
+
+    .A1trr {
+      margin-left: 15px;
+      width: 475px;
+      .A1trrTop {
+        text-align: right;
+      }
+      .A1trrMain {
+        margin-top: 10px;
+        padding: 10px;
+        .echBing {
+          width: 100%;
+          height: 340px;
+        }
+      }
+    }
   }
 }

+ 88 - 2
src/pages/Aanalyse/A1resStat/index.tsx

@@ -1,9 +1,95 @@
-import React from 'react'
+import React, { useEffect, useMemo, useState } from 'react'
 import styles from './index.module.scss'
+import { Button, Select } from 'antd'
+import dayjs from 'dayjs'
+import { initEchZhuFu } from './data'
 function A1resStat() {
+  // 获取现在的年份 到 2026的数组
+  const timeArr = useMemo(() => {
+    // 待完善 去掉+1
+    const nowTime = dayjs().year() + 1
+    const num = nowTime - 2026
+    const arr: any[] = []
+    for (let index = 0; index <= num; index++) {
+      arr.push({ value: nowTime - index, label: nowTime - index + '年度' })
+    }
+    return arr
+  }, [])
+
+  const [time, setTime] = useState<number>(2026)
+
+  // 柱状图
+  useEffect(() => {
+    const data: any[] = []
+    initEchZhuFu(data, document.querySelector('#echZhu1'), 'zhongTu')
+    initEchZhuFu(data, document.querySelector('#echZhu2'), 'siBu')
+  }, [])
+
   return (
     <div className={styles.A1resStat}>
-      <h1>A1resStat</h1>
+      <div className='pageTitle'>资源统计</div>
+
+      <div className='A1tll'>
+        <div className='A1tll1'>
+          <div className='A1box A1row1'>
+            <div className='A1tit'>总资源数</div>
+            <p>3741</p>
+          </div>
+
+          <div className='A1box A1row1'>
+            <div className='A1tit'>已发布资源数</div>
+            <p>3741</p>
+          </div>
+
+          <div className='A1box A1row1 A1row2'>
+            <div className='A1tit'>各级别资源统计</div>
+            <div className='A1titSon'>
+              <span>公开级</span>
+              <p>3741</p>
+              <span>内部级</span>
+              <p>6666</p>
+            </div>
+          </div>
+
+          <div className='A1box A1row1 A1row3'>
+            <div className='A1tit'>
+              年度新增资源数量
+              <div>
+                <Select value={time} onChange={e => setTime(e)} options={timeArr} />
+              </div>
+            </div>
+            <div className='A1row3Son'>
+              <p>123</p>
+              <div className='A1tit'>(件/套)</div>
+            </div>
+          </div>
+        </div>
+
+        <div className='A1tll2 A1box'>
+          <div className='A1tu'>
+            <div className='A1tit'>中图分类统计</div>
+            <div className='echZhu' id='echZhu1'></div>
+          </div>
+          <div className='A1tu'>
+            <div className='A1tit'>四部分类统计</div>
+            <div className='echZhu' id='echZhu2'></div>
+          </div>
+        </div>
+      </div>
+      <div className='A1trr'>
+        <div className='A1trrTop'>
+          <Button type='primary'>数据导出</Button>
+        </div>
+        <div className='A1trrMain A1box'>
+          <div className='A1tit'>资源库资源数统计</div>
+          <div id='echBing1' className='echBing'></div>
+        </div>
+
+        <div className='A1trrMain A1box'>
+          <div className='A1tit'>标签统计</div>
+          <div id='echBing2' className='echBing'></div>
+        </div>
+      </div>
     </div>
   )
 }