lianghongjie 1 gadu atpakaļ
vecāks
revīzija
da4e5f0250

+ 98 - 0
src/modules/stat/components/ChinaMap.tsx

@@ -0,0 +1,98 @@
+import * as echarts from "echarts";
+import { defineComponent, onMounted, ref, watch } from "vue";
+import { array } from "vue-types";
+
+export default defineComponent({
+  props: {
+    data: array().isRequired,
+  },
+  setup(props) {
+    const echartRef = ref();
+    let chartInstance: any;
+    let mapLoaded = false;
+
+    const option = {
+      tooltip: {
+        trigger: "item",
+        showDelay: 0,
+        transitionDuration: 0.2,
+      },
+      visualMap: {
+        show: false,
+        inRange: {
+          color: [
+            "#313695",
+            "#4575b4",
+            "#74add1",
+            "#abd9e9",
+            "#e0f3f8",
+            "#ffffbf",
+            "#fee090",
+            "#fdae61",
+            "#f46d43",
+            "#d73027",
+            "#a50026",
+          ],
+        },
+      },
+      series: [
+        {
+          name: "统计分析",
+          type: "map",
+          roam: true,
+          map: "china",
+          boundingCoords: [
+            // 定位左上角经纬度
+            [68.99814, 50.74432],
+            // 定位右下角经纬度
+            [139.93812, 25.23403],
+          ],
+          emphasis: {
+            label: {
+              show: true,
+            },
+          },
+          data: [] as any[],
+        },
+      ],
+    };
+
+    onMounted(() => {
+      initEchart(echartRef.value);
+    });
+
+    watch(
+      () => props.data,
+      () => {
+        if (mapLoaded) {
+          updateEchart();
+        }
+      }
+    );
+
+    function updateEchart() {
+      option.series[0].data = props.data;
+      chartInstance.setOption(option);
+    }
+
+    function initEchart(el: HTMLElement) {
+      chartInstance = echarts.init(el);
+      chartInstance.showLoading();
+
+      fetch(
+        "https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json"
+      ).then(async (res) => {
+        const json = await res.json();
+        chartInstance.hideLoading();
+
+        echarts.registerMap("china", json);
+        updateEchart();
+        mapLoaded = true;
+      });
+    }
+
+    return () => {
+      return <div class="h-300px" ref={echartRef}></div>;
+    };
+  },
+});

+ 5 - 0
src/modules/stat/components/index.ts

@@ -0,0 +1,5 @@
+import ChinaMap from "./ChinaMap";
+
+export const components = {
+  ChinaMap,
+};

+ 5 - 0
src/modules/stat/index.ts

@@ -0,0 +1,5 @@
+import { ModuleRoot } from "queenjs";
+
+export class StatModule extends ModuleRoot {
+  
+}

+ 5 - 4
src/pages/h5/statistics/Stat/EchartMap.tsx

@@ -7,11 +7,9 @@ export default defineComponent({
     data: array().isRequired,
   },
   setup(props) {
-    const params = new URLSearchParams(location.href.split("?")[1]);
-    const id = params.get("id");
     const echartRef = ref();
-
     let chartInstance: any;
+    let mapLoaded = false;
 
     const option = {
       tooltip: {
@@ -66,7 +64,9 @@ export default defineComponent({
     watch(
       () => props.data,
       () => {
-        updateEchart();
+        if (mapLoaded) {
+          updateEchart();
+        }
       }
     );
 
@@ -87,6 +87,7 @@ export default defineComponent({
 
         echarts.registerMap("china", json);
         updateEchart();
+        mapLoaded = true;
       });
     }
 

+ 83 - 7
src/pages/h5/statistics/Stat/index.tsx

@@ -1,28 +1,55 @@
-import { defineComponent, onMounted, reactive, ref } from "vue";
 import { Dict_Apis } from "@/dict";
-import EchartMap from "./EchartMap";
 import { css } from "@linaria/core";
+import { defineComponent, reactive } from "vue";
+import EchartMap from "./EchartMap";
 
 export default defineComponent(() => {
   const params = new URLSearchParams(location.href.split("?")[1]);
   const id = params.get("id");
-  const mapData = ref();
   const state = reactive({
     total: {
       uv: 0,
       pv: 0,
       ip: 0,
-    },
+    } as Record<string, number>,
     currType: "pv",
-    currMapData: [],
+    currMapData: [] as any[],
   });
+  const result = { areas: [] as any[] };
 
   fetch(`${Dict_Apis.promotion}/count/${id}`).then((res) => {
     res.json().then((ret) => {
-      console.log(ret);
+      if (ret.errorNo === 200) {
+        result.areas = ret.result.areas || [];
+        const total = { uv: 0, pv: 0, ip: 0 };
+        result.areas.forEach((item) => {
+          total.pv += item.PV;
+          total.uv += item.UV.length;
+          total.ip += item.IP.length;
+        });
+        state.total = total;
+        state.currMapData = createMapData();
+      }
     });
   });
 
+  function createMapData() {
+    const data: any[] = [];
+    result.areas.forEach((item) => {
+      const itemNum: any = {
+        pv: item.PV,
+        uv: item.UV.length,
+        ip: item.IP.length,
+      };
+
+      data.push({
+        name: item.Province,
+        value: itemNum[state.currType] || 0,
+      });
+    });
+    return data;
+  }
+
   const tabs = [
     {
       label: "浏览量(PV)",
@@ -40,6 +67,7 @@ export default defineComponent(() => {
 
   function switchStatType(type: string) {
     state.currType = type;
+    state.currMapData = createMapData();
   }
 
   return () => (
@@ -56,7 +84,7 @@ export default defineComponent(() => {
           );
         })}
       </div>
-      <div class="bg-white rounded text-center font-500">
+      <div class="bg-white rounded text-center font-500 flow-root">
         <div class="grid grid-cols-3 leading-48px text-14px">
           {tabs.map((d) => {
             return (
@@ -70,6 +98,34 @@ export default defineComponent(() => {
           })}
         </div>
         <EchartMap data={state.currMapData} />
+        <div class="m-15px">
+          <table class={tableCls}>
+            <thead>
+              <th>序列</th>
+              <th>省份</th>
+              <th>{tabs.find((d) => d.value == state.currType)?.label.split("(")[0]}</th>
+              <th>占比</th>
+            </thead>
+            <tbody>
+              {state.currMapData.map((d, i) => {
+                return (
+                  <tr key={i}>
+                    <td>{i + 1}</td>
+                    <td>{d.name}</td>
+                    <td>{d.value}</td>
+                    <td>
+                      {parseFloat(
+                        ((d.value / state.total[state.currType]) * 100).toFixed(
+                          2
+                        )
+                      ) + "%"}
+                    </td>
+                  </tr>
+                );
+              })}
+            </tbody>
+          </table>
+        </div>
       </div>
     </div>
   );
@@ -87,3 +143,23 @@ const mapTabCls = css`
     background-color: #fff;
   }
 `;
+
+const tableCls = css`
+  width: 100%;
+  border: 1px solid #f5f6f7;
+  font-size: 12px;
+  thead {
+    height: 48px;
+    background-color: #f5f6f7;
+    th {
+      font-weight: 400;
+      color: #666;
+      width: 25%;
+    }
+  }
+  tr {
+    height: 42px;
+    border-bottom: 1px solid #f5f6f7;
+    color: #333;
+  }
+`;

+ 7 - 0
src/pages/stat/Count/index.tsx

@@ -0,0 +1,7 @@
+import { defineComponent } from "vue";
+
+export default defineComponent({
+  setup() {
+    return <div></div>;
+  },
+});

+ 7 - 0
src/pages/stat/components/Layout.tsx

@@ -0,0 +1,7 @@
+import { defineComponent } from "vue";
+
+export default defineComponent({
+  setup() {
+    return () => <div></div>;
+  },
+});

+ 12 - 0
src/pages/stat/index.ts

@@ -0,0 +1,12 @@
+import { startApp } from "@/App";
+import { initAuthDef } from "@/hooks/initAuthDef";
+import { initLauncher } from "@/modules/launcher";
+import { initResource } from "@/modules/resource";
+import CKEditor from "@ckeditor/ckeditor5-vue";
+import router from "./router";
+
+document.title = "推广编辑器";
+
+startApp(router, [initAuthDef, initResource, initLauncher], (app) => {
+  app.use(CKEditor);
+});

+ 24 - 0
src/pages/stat/router.ts

@@ -0,0 +1,24 @@
+import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
+import Layout from "./components/Layout"
+
+const routes: Array<RouteRecordRaw> = [
+  {
+    path: "/",
+    name: "backend",
+    component: Layout,
+    children: [
+      {
+        path: "/count",
+        name: "count",
+        component: () => import("./Count")
+      }
+    ]
+  },
+];
+
+const router = createRouter({
+  history: createWebHashHistory(),
+  routes,
+});
+
+export default router;