shaogen1995 1 年之前
父節點
當前提交
73887d9117
共有 6 個文件被更改,包括 414 次插入14 次删除
  1. 59 0
      package-lock.json
  2. 1 0
      package.json
  3. 78 3
      src/pages/A6hot/index.module.scss
  4. 255 5
      src/pages/A6hot/index.tsx
  5. 15 0
      src/store/action/A6hot.ts
  6. 6 6
      src/utils/http.ts

+ 59 - 0
package-lock.json

@@ -20,6 +20,7 @@
         "antd-mobile": "^5.30.0",
         "axios": "^1.1.3",
         "dayjs": "^1.11.7",
+        "echarts": "^5.4.0",
         "js-base64": "^3.7.3",
         "js-export-excel": "^1.1.4",
         "react": "^18.2.0",
@@ -6746,6 +6747,20 @@
       "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz",
       "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="
     },
+    "node_modules/echarts": {
+      "version": "5.4.3",
+      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.4.3.tgz",
+      "integrity": "sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==",
+      "dependencies": {
+        "tslib": "2.3.0",
+        "zrender": "5.4.4"
+      }
+    },
+    "node_modules/echarts/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+    },
     "node_modules/ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
@@ -17381,6 +17396,19 @@
       "engines": {
         "node": ">=10"
       }
+    },
+    "node_modules/zrender": {
+      "version": "5.4.4",
+      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.4.4.tgz",
+      "integrity": "sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==",
+      "dependencies": {
+        "tslib": "2.3.0"
+      }
+    },
+    "node_modules/zrender/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
     }
   },
   "dependencies": {
@@ -22464,6 +22492,22 @@
       "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz",
       "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="
     },
+    "echarts": {
+      "version": "5.4.3",
+      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.4.3.tgz",
+      "integrity": "sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==",
+      "requires": {
+        "tslib": "2.3.0",
+        "zrender": "5.4.4"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+          "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+        }
+      }
+    },
     "ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
@@ -30582,6 +30626,21 @@
       "version": "0.1.0",
       "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",
       "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
+    },
+    "zrender": {
+      "version": "5.4.4",
+      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.4.4.tgz",
+      "integrity": "sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==",
+      "requires": {
+        "tslib": "2.3.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+          "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+        }
+      }
     }
   }
 }

+ 1 - 0
package.json

@@ -15,6 +15,7 @@
     "antd-mobile": "^5.30.0",
     "axios": "^1.1.3",
     "dayjs": "^1.11.7",
+    "echarts": "^5.4.0",
     "js-base64": "^3.7.3",
     "js-export-excel": "^1.1.4",
     "react": "^18.2.0",

+ 78 - 3
src/pages/A6hot/index.module.scss

@@ -1,5 +1,80 @@
-.A6hot{
-  :global{
-    
+.A6hot {
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 30px 20px 0px;
+  display: flex;
+  justify-content: space-between;
+  position: relative;
+
+  :global {
+
+    .A6tit {
+      font-size: 16px;
+    }
+
+    .A6box1 {
+      width: 58%;
+
+      .A6box1_1 {
+        height: calc(50% - 30px);
+        margin-bottom: 30px;
+
+        .echBox {
+          margin-top: 10px;
+          height: calc(100% - 32px);
+        }
+      }
+    }
+
+    .A6box2 {
+      width: 40%;
+
+      .A6box2_1 {
+        height: calc(50% - 30px);
+        margin-bottom: 30px;
+
+        .A6RowBox {
+          margin-top: 10px;
+          height: calc(100% - 32px);
+
+          .A6RowBox1 {
+            height: 16.67%;
+            width: 100%;
+            border-bottom: 1px solid #ccc;
+            display: flex;
+            align-items: center;
+
+            &:nth-of-type(1) {
+              border-top: 1px solid #ccc;
+              background-color: #eaeaea;
+              font-weight: 700;
+            }
+
+            &>div {
+              text-align: center;
+
+              &:nth-of-type(1) {
+                width: calc(100% - 90px);
+                padding: 0 20px;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+              }
+
+              &:nth-of-type(2) {
+                width: 90px;
+              }
+            }
+          }
+        }
+      }
+    }
+
+    .A6DeriveBox {
+      position: absolute;
+      z-index: 10;
+      top: 10px;
+      right: 20px;
+    }
   }
 }

+ 255 - 5
src/pages/A6hot/index.tsx

@@ -1,12 +1,262 @@
-import React from "react";
+import React, { useCallback, useEffect, useRef, useState } from "react";
 import styles from "./index.module.scss";
- function A6hot() {
-  
+import * as echarts from "echarts/core";
+import { GridComponent } from "echarts/components";
+import { LineChart } from "echarts/charts";
+import { UniversalTransition } from "echarts/features";
+import { CanvasRenderer } from "echarts/renderers";
+import { TooltipComponent, LegendComponent } from "echarts/components";
+
+import { PieChart } from "echarts/charts";
+import { LabelLayout } from "echarts/features";
+
+import { A6_APIgetLikeList, A6_APIgetNumList } from "@/store/action/A6hot";
+import { Button, Empty } from "antd";
+import dayjs from "dayjs";
+import ExportJsonExcel from "js-export-excel";
+
+echarts.use([
+  GridComponent,
+  LineChart,
+  CanvasRenderer,
+  UniversalTransition,
+  TooltipComponent,
+  LegendComponent,
+  PieChart,
+  LabelLayout,
+]);
+
+type dataType = { name: string; value: string | number }[];
+
+function A6hot() {
+  const echartsRef1 = useRef(null);
+  const echartsRef2 = useRef(null);
+
+  // 折线图
+  const echartsFu1 = useCallback((dom: HTMLDivElement, data: dataType) => {
+    const myChart1 = echarts.getInstanceByDom(dom) || echarts.init(dom);
+    const option1 = {
+      grid: {
+        left: "-40", //距左边边框的距离
+        right: "0%", //距右边边框的距离
+        bottom: "10", //距下面边框的距离
+        top: "15", //距上面边框的距离
+        containLabel: true,
+      },
+
+      xAxis: {
+        type: "category",
+        data: data.map((v) => v.name),
+        axisLine: {
+          show: false, //隐藏X轴
+        },
+        axisTick: {
+          show: false, //隐藏刻度线
+        },
+        axisLabel: {
+          show: false, //隐藏X轴文字
+        },
+      },
+      yAxis: {
+        type: "value",
+      },
+      series: [
+        {
+          data: data.map((v) => v.value),
+          type: "line",
+          // 平滑曲线
+          // smooth: true
+        },
+      ],
+      tooltip: {
+        trigger: "axis",
+        axisPointer: {
+          type: "cross",
+          label: {
+            backgroundColor: "#6a7985",
+          },
+        },
+        // formatter: "{a} <br/>{b} : {c}"
+      },
+    };
+    option1 && myChart1.setOption(option1);
+  }, []);
+
+  const deriveDataRef1 = useRef<any>([]);
+
+  // 获取左边数据
+  const getListFu1 = useCallback(async () => {
+    const res1 = await A6_APIgetLikeList("exhibition");
+    const obj1 = {};
+    if (res1.code === 0) {
+      const data1: dataType = [];
+      res1.data.forEach((v: any) => {
+        Reflect.set(obj1, v.groupKey, v.pcsStar);
+
+        data1.push({
+          name: v.groupKey,
+          value: v.pcsStar,
+        });
+      });
+      echartsFu1(echartsRef1.current!, data1);
+    }
+
+    const res2 = await A6_APIgetLikeList("goods");
+    const obj2 = {};
+    if (res2.code === 0) {
+      const data2: dataType = [];
+      res2.data.forEach((v: any) => {
+        Reflect.set(obj2, v.groupKey, v.pcsStar);
+
+        data2.push({
+          name: v.groupKey,
+          value: v.pcsStar,
+        });
+      });
+      echartsFu1(echartsRef2.current!, data2);
+    }
+
+    const tempArr: any = [];
+
+    const objMax =
+      Object.keys(obj1).length >= Object.keys(obj2).length ? obj1 : obj2;
+
+    for (const k in objMax) {
+      tempArr.push({
+        name: k,
+        num1: Reflect.get(obj1, k) || "",
+        num2: Reflect.get(obj2, k) || "",
+      });
+    }
+    tempArr.push({ name: "", num1: "", num2: "" });
+    tempArr.push({ name: "云展名称", num1: "点赞数", num2: "" });
+
+    deriveDataRef1.current = tempArr;
+    console.log("-----------", deriveDataRef1.current);
+  }, [echartsFu1]);
+
+  const [rightData1, setRightData1] = useState<{ pcs: number; name: string }[]>(
+    []
+  );
+
+  const [rightData2, setRightData2] = useState<{ pcs: number; name: string }[]>(
+    []
+  );
+
+  const [isOk, setIsOk] = useState(false);
+
+  // 获取右边数据
+  const getListFu2 = useCallback(async () => {
+    const res1 = await A6_APIgetNumList("goods");
+    if (res1.code === 0) {
+      setRightData1(res1.data);
+
+      const res2 = await A6_APIgetNumList("exhibition");
+      if (res2.code === 0) {
+        setRightData2(res2.data);
+
+        setIsOk(true);
+      }
+    }
+  }, []);
+
+  useEffect(() => {
+    getListFu1();
+    getListFu2();
+  }, [getListFu1, getListFu2]);
+
+  // 点击导出
+  const deriveFu = useCallback(async () => {
+    const name = "热度统计" + dayjs(new Date()).format("YYYY-MM-DD HH:mm");
+
+    const option = {
+      fileName: name,
+      datas: [
+        {
+          sheetData: [
+            ...deriveDataRef1.current,
+            ...rightData1.map((v) => ({ name: v.name, num1: v.pcs, num2: "" })),
+            { name: "", num1: "", num2: "" },
+            { name: "馆藏名称", num1: "点赞数", num2: "" },
+            ...rightData2.map((v) => ({ name: v.name, num1: v.pcs, num2: "" })),
+          ],
+          sheetName: name,
+          sheetFilter: ["name", "num1", "num2"],
+          sheetHeader: ["日期", "云展点赞数", "馆藏点赞数"],
+          columnWidths: [10, 10, 10],
+        },
+      ],
+    };
+
+    const toExcel = new ExportJsonExcel(option); //new
+    toExcel.saveExcel(); //保存
+  }, [rightData1, rightData2]);
+
   return (
     <div className={styles.A6hot}>
-      <h1>A6hot</h1>
+      <div className="pageTitle">热度统计</div>
+      <div className="A6box1">
+        <div className="A6box1_1">
+          <div className="A6tit">云展点赞趋势</div>
+          <div className="echBox" ref={echartsRef1}></div>
+        </div>
+        <div className="A6box1_1">
+          <div className="A6tit">馆藏点赞趋势</div>
+          <div className="echBox" ref={echartsRef2}></div>
+        </div>
+      </div>
+      <div className="A6box2">
+        <div className="A6box2_1">
+          <div className="A6tit">云展点赞排行</div>
+          <div className="A6RowBox">
+            <div className="A6RowBox1">
+              <div>名称</div>
+              <div>点赞</div>
+            </div>
+            {rightData1.length <= 0 && isOk ? (
+              <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+            ) : (
+              <>
+                {rightData1.map((v) => (
+                  <div className="A6RowBox1" key={v.name + v.pcs}>
+                    <div title={v.name}>{v.name}</div>
+                    <div>{v.pcs}</div>
+                  </div>
+                ))}
+              </>
+            )}
+          </div>
+        </div>
+        <div className="A6box2_1">
+          <div className="A6tit">馆藏点赞排行</div>
+          <div className="A6RowBox">
+            <div className="A6RowBox1">
+              <div>名称</div>
+              <div>点赞</div>
+            </div>
+            {rightData2.length <= 0 && isOk ? (
+              <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+            ) : (
+              <>
+                {rightData2.map((v) => (
+                  <div className="A6RowBox1" key={v.name + v.pcs}>
+                    <div title={v.name}>{v.name}</div>
+                    <div>{v.pcs}</div>
+                  </div>
+                ))}
+              </>
+            )}
+          </div>
+        </div>
+      </div>
+
+      <div className="A6DeriveBox">
+        <Button type="primary" onClick={deriveFu}>
+          导出
+        </Button>
+      </div>
     </div>
-  )
+  );
 }
 
 const MemoA6hot = React.memo(A6hot);

+ 15 - 0
src/store/action/A6hot.ts

@@ -0,0 +1,15 @@
+import http from "@/utils/http";
+
+/**
+ * 获取点赞趋势
+ */
+export const A6_APIgetLikeList = (type: "goods" | "exhibition") => {
+  return http.get(`cms/report/trend/${type}?dayScope=14`);
+};
+
+/**
+ * 获取排行榜
+ */
+export const A6_APIgetNumList = (type: "goods" | "exhibition") => {
+  return http.get(`cms/report/ranking/${type}?limit=5`);
+};

+ 6 - 6
src/utils/http.ts

@@ -7,10 +7,10 @@ import { domShowFu } from "./domShow";
 // 请求基地址
 export const baseURL =
   // 线下的图片地址需要加上/api/
-  process.env.NODE_ENV === "development"
-    ? "http://192.168.20.61:8064/api/"
-    : "";
-  // process.env.NODE_ENV === "development" ? "https://sit-chaozhoubwg.4dage.com" : ""; //测试环境
+  // process.env.NODE_ENV === "development"
+  //   ? "http://192.168.20.61:8064/api/"
+  //   : "";
+  process.env.NODE_ENV === "development" ? "https://sit-chaozhoubwg.4dage.com" : ""; //测试环境
 
 // 处理  类型“AxiosResponse<any, any>”上不存在属性“code”
 declare module "axios" {
@@ -24,10 +24,10 @@ declare module "axios" {
 // 创建 axios 实例
 const http = axios.create({
   // --------线下的地址不用加/api/
-  baseURL: baseURL,
+  // baseURL: baseURL,
 
   // --------打包或线上环境接口需要加上api/
-  // baseURL: baseURL + "/api/",
+  baseURL: baseURL + "/api/",
   timeout: 5000,
 });