فهرست منبع

build: "区域级看板接口调试"

chaooo 2 سال پیش
والد
کامیت
8f8c1e926f
6فایلهای تغییر یافته به همراه764 افزوده شده و 466 حذف شده
  1. 71 0
      src/api/areaboard/index.ts
  2. 32 0
      src/api/areaboard/types.ts
  3. 0 5
      src/api/dashboard/types.ts
  4. 2 2
      src/store/modules/user.ts
  5. 534 339
      src/views/areaboard/index.vue
  6. 125 120
      src/views/charts-components/LineChart.vue

+ 71 - 0
src/api/areaboard/index.ts

@@ -0,0 +1,71 @@
+import request from "@/utils/request";
+import { AxiosPromise } from "axios";
+import {
+  AddressId,
+  Area,
+  AreaCard,
+  AreaLineData,
+  AreaParams,
+} from "@/api/areaboard/types";
+import { DashboardData } from "@/api/dashboard/types";
+
+/**
+ * 获取区域
+ */
+export function getAreaAddress(id: number): AxiosPromise<Area> {
+  return request({
+    url: "/board/v1/area",
+    method: "get",
+    params: { parent_id: id },
+  });
+}
+
+/**
+ * 获取学校
+ * /board/v1/get-school?province_id=&city_id=
+ */
+export function getAreaSchool(params: AddressId): AxiosPromise<Area> {
+  return request({
+    url: "/board/v1/get-school",
+    method: "get",
+    params: params,
+  });
+}
+
+/**
+ * 获取区域级数据卡片
+ * /board/v1/record-top?start_time=1672502400&end_time=1688349643&school_id=95&grade_id=35
+ */
+export function getAreaCard(id: number): AxiosPromise<AreaCard> {
+  return request({
+    url: "/board/v1/record-top",
+    method: "get",
+    params: { school_id: id },
+  });
+}
+/**
+ * 获取区域级饼图
+ * /board/v1/record?start_time=1672502400&end_time=1688349643&school_id=95&grade_id=35
+ */
+export function getAreaBoardPies(
+  params: AreaParams
+): AxiosPromise<DashboardData> {
+  return request({
+    url: "/board/v1/record",
+    method: "get",
+    params: params,
+  });
+}
+/**
+ * 获取区域级折线图
+ * /board/v1/record-bottom?start_time=1672502400&end_time=1688349643&school_id=95&grade_id=35
+ */
+export function getAreaBoardLines(
+  params: AreaParams
+): AxiosPromise<AreaLineData> {
+  return request({
+    url: "/board/v1/record-bottom",
+    method: "get",
+    params: params,
+  });
+}

+ 32 - 0
src/api/areaboard/types.ts

@@ -0,0 +1,32 @@
+export interface Area {
+  area_id: number;
+  area_name: string;
+}
+export interface AddressId {
+  province_id: number;
+  city_id: number;
+}
+export interface AreaParams {
+  school_id: number;
+  grade_id: number;
+  start_time: number;
+  end_time: number;
+}
+/**
+ * 区域顶部数据
+ */
+export interface AreaCard {
+  student: number;
+  game: number;
+  school: number;
+}
+/**
+ * 区域折线数据
+ */
+export interface AreaLineData {
+  frontHeight: number; //训练前期全体学员高专注占比平均值
+  frontNum: number[]; //训练前区间人数
+  afterHeight: number; //训练后期全体学员高专注占比平均值
+  afterNum: number[]; // 训练后区间人数
+  curve: number[]; //整体变化曲线
+}

+ 0 - 5
src/api/dashboard/types.ts

@@ -8,11 +8,6 @@ export interface DashboardCard {
   equipment: number;
   game: number;
 }
-export interface AreaCard {
-	student: number;
-	game: number;
-	school: number;
-}
 /**
  * 初期分期占比分析
  */

+ 2 - 2
src/store/modules/user.ts

@@ -53,8 +53,8 @@ export const useUserStore = defineStore("user", () => {
     nickname.value = data.name;
     phone.value = data.phone;
     schoolNum.value = data.num;
-    role.value = data.role;
-    //role.value = "ADMIN";
+    //role.value = data.role;
+    role.value = "ADMIN";
     perms.value = data.perms;
     return role.value;
   }

+ 534 - 339
src/views/areaboard/index.vue

@@ -1,412 +1,607 @@
 <script setup lang="ts">
-import {watch} from "vue";
-import {useUserStore} from "@/store/modules/user";
-import {AreaCard, DashboardData} from "@/api/dashboard/types";
+import { DashboardData } from "@/api/dashboard/types";
+import {
+  AddressId,
+  Area,
+  AreaCard,
+  AreaLineData,
+  AreaParams,
+} from "@/api/areaboard/types";
 import AreaDataCard from "@/views/areaboard/components/AreaDataCard.vue";
 import LiquidChart from "@/views/charts-components/LiquidChart.vue";
 import PercentBarChart from "@/views/charts-components/PercentBarChart.vue";
 import CircleChart from "@/views/charts-components/CircleChart.vue";
-import {getDashboardData} from "@/api/dashboard";
 import LineChart from "@/views/charts-components/LineChart.vue";
 import AverageBarChart from "@/views/charts-components/AverageBarChart.vue";
+import { GradeList } from "@/api/grade/types";
+import { getGradeSelect } from "@/api/grade";
+import {
+  getAreaAddress,
+  getAreaBoardLines,
+  getAreaBoardPies,
+  getAreaCard,
+  getAreaSchool,
+} from "@/api/areaboard";
+import { SchoolList } from "@/api/school/types";
 
 defineOptions({
   name: "DashboardArea",
   inheritAttrs: false,
 });
-const userStore = useUserStore();
-watch(
-  () => userStore.schoolId,
-  (newValue, oldValue) => {
-    console.log(newValue, oldValue);
-  }
-);
-
-const date = ref("");
 /**
- * 数据卡片
+ * 筛选条件
  */
-let cards: AreaCard = reactive({
-	student: 0, // 样本人数
-	game: 0, // 累计训练次数
-	school: 10, // 全部班级
+const address: AddressId = reactive({
+  province_id: 0,
+  city_id: 0,
+});
+const dataParams: AreaParams = reactive({
+  school_id: 0,
+  grade_id: 0,
+  start_time: Math.ceil(Date.parse("2023/1/1 00:00") / 1000),
+  end_time: Math.ceil(Date.now() / 1000),
 });
+const datePicker = ref<number[]>([Date.parse("2023/1/1 00:00"), Date.now()]);
+const provinceData = ref<Area[]>();
+const cityData = ref<Area[]>();
+async function getAddressData(id: number) {
+  getAreaAddress(id)
+    .then(({ data }) => {
+      if (id == 0) {
+        provinceData.value = data;
+        provinceData.value.unshift({ area_id: 0, area_name: "全部省" });
+      } else {
+        cityData.value = data;
+        cityData.value.unshift({ area_id: 0, area_name: "全部市" });
+      }
+      // 重新获取学校
+      getSchoolData(address);
+    })
+    .catch((error) => {
+      console.log(error);
+      if (id == 0) {
+        provinceData.value = [{ area_id: 0, area_name: "全部省" }];
+      } else {
+        cityData.value = [{ area_id: 0, area_name: "全部市" }];
+      }
+    });
+}
+//getAreaSchool
 /**
- * 图表数据
+ * 获取学校
  */
-const chartStatus = ref(false);
-let chartData: DashboardData = reactive({
-	frontAverage: 0, // 初期专注力估值
-	afterAverage: 0, // 近期专注力估值
-	front: 0, // 初期50分以上的占比
-	after: 0, // 近期50分以上的占比
-	frontProportion: { num: [], percentage: [] }, // 初期分期占比分析
-	afterProportion: { num: [], percentage: [] }, // 近期分期占比分析
-});
-async function getChartData(gradeId: number) {
-	getDashboardData(gradeId)
-		.then(({ data }) => {
-			chartData = <DashboardData>{ ...data };
-			if (chartData.frontAverage > 0) {
-				chartStatus.value = true;
-				dataStatus.value = 1;
-			} else {
-				dataStatus.value = 2;
-			}
-		})
-		.catch((error) => {
-			console.log(error.toString());
-			dataStatus.value = 2;
-		});
+const schoolData = ref<SchoolList[]>();
+async function getSchoolData(address: AddressId) {
+  getAreaSchool(address)
+    .then(({ data }) => {
+      schoolData.value = data;
+      schoolData.value?.unshift({ num: "", school_id: 0, name: "全部学校" });
+    })
+    .catch((error) => {
+      schoolData.value = [];
+      schoolData.value?.unshift({ num: "", school_id: 0, name: "全部学校" });
+      console.log(error);
+    });
+}
+/**
+ * 班级数据
+ */
+const gradeData = ref<GradeList[]>();
+async function getGradeData(schoolId: number) {
+  getGradeSelect(schoolId)
+    .then(({ data }) => {
+      gradeData.value = data;
+      gradeData.value?.unshift({ id: 0, name: "全部班级" });
+    })
+    .catch((error) => {
+      gradeData.value = [];
+      gradeData.value?.unshift({ id: 0, name: "全部班级" });
+      console.log(error);
+    });
+}
+// 改变时间
+function changeDate() {
+  dataParams.start_time = Math.ceil(datePicker.value[0] / 1000);
+  dataParams.end_time = Math.ceil(datePicker.value[1] / 1000);
+}
+/**
+ * 数据卡片
+ */
+const cardStatus = ref(false);
+const cards = ref<AreaCard>();
+async function getDataCard(schoolId: number) {
+  getAreaCard(schoolId)
+    .then(({ data }) => {
+      cards.value = data;
+      cardStatus.value = true;
+    })
+    .catch((error) => {
+      console.log(error);
+    });
+}
+/**
+ * 饼图数据
+ */
+const pieStatus = ref(false);
+const pieMessage = ref("加载中...");
+const pieChartData = ref<DashboardData>();
+async function getPieChartData(params: AreaParams) {
+  pieStatus.value = false;
+  getAreaBoardPies(params)
+    .then(({ data }) => {
+      pieChartData.value = data;
+      pieStatus.value = true;
+    })
+    .catch((error) => {
+      pieStatus.value = false;
+      pieMessage.value = error.message;
+      console.log(error.message);
+    });
+}
+/**
+ * 折线图数据
+ */
+const lineStatus = ref(false);
+const lineMessage = ref("加载中...");
+const lineChartData = ref<AreaLineData>();
+const averageData = ref<number[][]>();
+async function getLineChartData(params: AreaParams) {
+  lineStatus.value = false;
+  getAreaBoardLines(params)
+    .then(({ data }) => {
+      lineChartData.value = data;
+      // 柱状图
+      averageData.value = [];
+      averageData.value.push(lineChartData.value?.frontNum);
+      averageData.value.push(lineChartData.value?.afterNum);
+      lineStatus.value = true;
+    })
+    .catch((error) => {
+      lineStatus.value = false;
+      lineMessage.value = error.message;
+      console.log(error.message);
+    });
+}
+/**
+ * 获取页面数据
+ */
+function getPageData() {
+  // 数据卡片
+  getDataCard(dataParams.school_id);
+  // 饼图数据
+  getPieChartData(dataParams);
+  // 折线图数据
+  getLineChartData(dataParams);
 }
-// 数据状态:1正常,2训练次数小于3,3过期,4缺省
-const dataStatus = ref(5);
 onMounted(() => {
-	// 图表数据
-	getChartData(0);
+  // 获取省份
+  getAddressData(0);
+  cityData.value = [{ area_id: 0, area_name: "全部市" }];
+  // 获取学校
+  getSchoolData(address);
+  gradeData.value = [{ id: 0, name: "全部班级" }];
+  // 获取页面数据
+  getPageData();
 });
-const averageData = ref([
-	[5, 6, 5, 4, 3],
-	[9, 10, 15, 12, 8],
-]);
 </script>
 
 <template>
   <div class="area-container">
     <div class="area-top">
-			<div class="search-box">
-				<el-select placeholder="全部省" size="large">
-					<el-option key="0" label="全部省" :value="Number(0)" />
-					<el-option key="1" label="省1" :value="Number(1)" />
-					<el-option key="1" label="省2" :value="Number(2)" />
-				</el-select>
-				<el-select placeholder="全部市" size="large">
-					<el-option key="0" label="全部市" :value="Number(0)" />
-					<el-option key="1" label="市1" :value="Number(1)" />
-					<el-option key="1" label="市2" :value="Number(2)" />
-				</el-select>
-				<el-select placeholder="全龄" size="large">
-					<el-option key="0" label="全龄" :value="Number(0)" />
-					<el-option key="1" label="1岁" :value="Number(1)" />
-					<el-option key="1" label="2岁" :value="Number(2)" />
-				</el-select>
-				<div>
-					<el-date-picker
-							v-model="date"
-							type="daterange"
-							size="large"
-							start-placeholder="开始日期"
-							end-placeholder="结束日期"
-							:default-value="[new Date(2023, 6, 1), new Date(2030, 10, 1)]"
-					/>
-				</div>
-				<el-button size="large" type="primary">查找</el-button>
-			</div>
-			<div class="card-box">
-				<AreaDataCard :schools="cards.school" :games="cards.game" :students="cards.student"/>
-			</div>
+      <div class="search-box">
+        <el-select
+          v-model="address.province_id"
+          placeholder="全部省"
+          size="large"
+          @change="getAddressData(address.province_id)"
+        >
+          <el-option
+            v-for="item in provinceData"
+            :key="item.area_id"
+            :label="item.area_name"
+            :value="item.area_id"
+          />
+        </el-select>
+        <el-select
+          v-model="address.city_id"
+          placeholder="全部市"
+          size="large"
+          @change="getSchoolData(address)"
+        >
+          <el-option
+            v-for="item in cityData"
+            :key="item.area_id"
+            :label="item.area_name"
+            :value="item.area_id"
+          />
+        </el-select>
+        <div>
+          <el-date-picker
+            v-model="datePicker"
+            type="daterange"
+            size="large"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            format="YYYY-MM-DD"
+            value-format="x"
+            @change="changeDate()"
+          />
+        </div>
+        <el-button size="large" color="#4284f2" @click="getPageData()"
+          >查找</el-button
+        >
+      </div>
+      <div class="card-box">
+        <!-- 数据卡片 -->
+        <template v-if="cardStatus">
+          <AreaDataCard
+            :key="cards.toString()"
+            :schools="cards.school"
+            :games="cards.game"
+            :students="cards.student"
+          />
+        </template>
+      </div>
+    </div>
+    <div class="search-box s2">
+      <el-select
+        v-model="dataParams.school_id"
+        placeholder="全部学校"
+        size="large"
+        @change="getGradeData(dataParams.school_id)"
+      >
+        <el-option
+          v-for="item in schoolData"
+          :key="item.school_id"
+          :label="item.name"
+          :value="item.school_id"
+        />
+      </el-select>
+      <el-select
+        v-model="dataParams.grade_id"
+        placeholder="全部班级"
+        size="large"
+      >
+        <el-option
+          v-for="item in gradeData"
+          :key="item.id"
+          :label="item.name"
+          :value="item.id"
+        />
+      </el-select>
+      <el-button size="large" color="#4284f2" @click="getPageData()"
+        >查找</el-button
+      >
+    </div>
+    <!-- Echarts 图表 -->
+    <div class="charts-container">
+      <el-row :gutter="20">
+        <el-col :md="24" :lg="12" :xl="8">
+          <div class="charts-item">
+            <p class="title">学员专注力平均值整体对比分析</p>
+            <el-row justify="space-between">
+              <el-col :xs="24" :sm="12">
+                <div v-if="pieStatus" class="item">
+                  <LiquidChart
+                    id="liquidChart1"
+                    :key="pieChartData.frontAverage"
+                    :data="
+                      pieChartData.frontAverage ? pieChartData.frontAverage : 0
+                    "
+                    height="200px"
+                    width="200px"
+                    color="#3a7fc2"
+                    bg-color="#accded"
+                    class="chart"
+                  />
+                  <p>全体学员初期</p>
+                  <p>专注力评估均值</p>
+                </div>
+              </el-col>
+              <el-col :xs="24" :sm="12">
+                <div v-if="pieStatus" class="item">
+                  <LiquidChart
+                    id="liquidChart2"
+                    :key="pieChartData.afterAverage"
+                    :data="
+                      pieChartData.afterAverage ? pieChartData.afterAverage : 0
+                    "
+                    height="200px"
+                    width="200px"
+                    color="#5563ac"
+                    bg-color="#cacce6"
+                    class="chart"
+                  />
+                  <p>全体学员训练近期</p>
+                  <p>专注力评估均值</p>
+                </div>
+              </el-col>
+            </el-row>
+            <el-row justify="space-between">
+              <el-col :xs="24" :sm="12">
+                <div v-if="pieStatus" class="item">
+                  <CircleChart
+                    id="circleChart1"
+                    :key="pieChartData.front"
+                    :data="pieChartData.front ? pieChartData.front : 0"
+                    height="200px"
+                    width="200px"
+                    color="#3a7fc2"
+                    bg-color="#e4e7f4"
+                    font-color="#3a7fc2"
+                    font-size="30px"
+                    :round-cap="Boolean(true)"
+                  />
+                  <p>初期训练</p>
+                  <p>专注力50以上人数比例</p>
+                </div>
+              </el-col>
+              <el-col :xs="24" :sm="12">
+                <div v-if="pieStatus" class="item">
+                  <CircleChart
+                    id="circleChart2"
+                    :key="pieChartData.after.toString()"
+                    :data="pieChartData.after ? pieChartData.after : 0"
+                    height="200px"
+                    width="200px"
+                    color="#5563ac"
+                    bg-color="#e4e7f4"
+                    font-color="#5563ac"
+                    font-size="30px"
+                    :round-cap="Boolean(true)"
+                  />
+                  <p>近期训练</p>
+                  <p>专注力50以上人数比例</p>
+                </div>
+              </el-col>
+            </el-row>
+          </div>
+        </el-col>
+        <!-- 学员专注力评分分级占比分析 -->
+        <el-col :md="24" :lg="12" :xl="16">
+          <div class="charts-item">
+            <p class="title">样本每次训练专注力评分均值整体变化曲线</p>
+            <template v-if="lineStatus">
+              <line-chart
+                id="lineChart1"
+                :data="lineChartData?.curve"
+                width="1000px"
+                height="558px"
+              />
+            </template>
+          </div>
+        </el-col>
+      </el-row>
+    </div>
+    <div class="charts-container">
+      <el-row :gutter="20">
+        <el-col :md="24" :lg="12" :xl="8">
+          <div class="charts-item">
+            <p class="title pos">学员专注力训练高专注占比分析</p>
+            <template v-if="lineStatus">
+              <AverageBarChart
+                id="averageBarChart1"
+                :key="averageData.toString()"
+                :data-sets="averageData"
+                width="520px"
+                height="520px"
+                class="chart"
+              />
+            </template>
+            <el-row :gutter="15" class="bottom">
+              <el-col :span="12">
+                <p class="l">
+                  <span>训练前期全体学员</span>
+                  <span>高专注占比平均值</span>
+                  <b>{{ lineChartData?.frontHeight }}</b>
+                </p>
+              </el-col>
+              <el-col :span="12">
+                <p class="r">
+                  <span>训练后期全体学员</span>
+                  <span>高专注占比平均值</span>
+                  <b>{{ lineChartData?.afterHeight }}</b>
+                </p>
+              </el-col>
+            </el-row>
+          </div>
+        </el-col>
+        <!-- 学员专注力评分分级占比分析 -->
+        <el-col :md="24" :lg="12" :xl="16">
+          <div class="charts-item">
+            <p class="title">学员专注力评分分级占比分析</p>
+            <el-row justify="space-between">
+              <el-col :xs="24" :sm="24" :md="12" :lg="24" :xl="12">
+                <div v-if="pieStatus" class="bar">
+                  <PercentBarChart
+                    id="barChart1"
+                    :key="pieChartData.frontProportion.toString()"
+                    width="400px"
+                    height="500px"
+                    title="全体学员初期训练专注力评分占比"
+                    :percent="pieChartData.frontProportion.percentage"
+                    :data="pieChartData.frontProportion.num"
+                    class="chart"
+                  />
+                </div>
+              </el-col>
+              <el-col :xs="24" :sm="24" :md="12" :lg="24" :xl="12">
+                <div v-if="pieStatus" class="bar">
+                  <PercentBarChart
+                    id="barChart2"
+                    :key="pieChartData.afterProportion.toString()"
+                    width="400px"
+                    height="500px"
+                    title="全体学员训练近期专注力评分平均占比"
+                    :percent="pieChartData.afterProportion.percentage"
+                    :data="pieChartData.afterProportion.num"
+                    class="chart"
+                  />
+                </div>
+              </el-col>
+            </el-row>
+          </div>
+        </el-col>
+      </el-row>
     </div>
-		<div class="search-box s2">
-			<el-select placeholder="全部省" size="large">
-				<el-option key="0" label="全部省" :value="Number(0)" />
-				<el-option key="1" label="省1" :value="Number(1)" />
-				<el-option key="1" label="省2" :value="Number(2)" />
-			</el-select>
-			<el-select placeholder="全部市" size="large">
-				<el-option key="0" label="全部市" :value="Number(0)" />
-				<el-option key="1" label="市1" :value="Number(1)" />
-				<el-option key="1" label="市2" :value="Number(2)" />
-			</el-select>
-			<el-select placeholder="全龄" size="large">
-				<el-option key="0" label="全龄" :value="Number(0)" />
-				<el-option key="1" label="1岁" :value="Number(1)" />
-				<el-option key="1" label="2岁" :value="Number(2)" />
-			</el-select>
-			<el-button size="large" type="primary">查找</el-button>
-		</div>
-		<!-- Echarts 图表 -->
-		<div class="charts-container">
-			<el-row :gutter="20">
-				<el-col :md="24" :lg="12" :xl="8">
-					<div class="charts-item">
-						<p class="title">学员专注力平均值整体对比分析</p>
-						<el-row justify="space-between">
-							<el-col :xs="24" :sm="12">
-								<div v-if="chartStatus" class="item">
-									<LiquidChart
-											id="liquidChart1"
-											:key="chartData.frontAverage"
-											:data="chartData.frontAverage ? chartData.frontAverage : 0"
-											height="200px"
-											width="200px"
-											color="#3a7fc2"
-											bg-color="#accded"
-											class="chart"
-									/>
-									<p>全体学员初期</p>
-									<p>专注力评估均值</p>
-								</div>
-							</el-col>
-							<el-col :xs="24" :sm="12">
-								<div v-if="chartStatus" class="item">
-									<LiquidChart
-											id="liquidChart2"
-											:key="chartData.afterAverage"
-											:data="chartData.afterAverage ? chartData.afterAverage : 0"
-											height="200px"
-											width="200px"
-											color="#5563ac"
-											bg-color="#cacce6"
-											class="chart"
-									/>
-									<p>全体学员训练近期</p>
-									<p>专注力评估均值</p>
-								</div>
-							</el-col>
-						</el-row>
-						<el-row justify="space-between">
-							<el-col :xs="24" :sm="12">
-								<div v-if="chartStatus" class="item">
-									<CircleChart
-											id="circleChart1"
-											:key="chartData.front"
-											:data="chartData.front ? chartData.front : 0"
-											height="200px"
-											width="200px"
-											color="#3a7fc2"
-											bg-color="#e4e7f4"
-											font-color="#3a7fc2"
-											font-size="30px"
-											:round-cap="Boolean(true)"
-									/>
-									<p>初期训练</p>
-									<p>专注力50以上人数比例</p>
-								</div>
-							</el-col>
-							<el-col :xs="24" :sm="12">
-								<div v-if="chartStatus" class="item">
-									<CircleChart
-											id="circleChart2"
-											:key="chartData.after.toString()"
-											:data="chartData.after ? chartData.after : 0"
-											height="200px"
-											width="200px"
-											color="#5563ac"
-											bg-color="#e4e7f4"
-											font-color="#5563ac"
-											font-size="30px"
-											:round-cap="Boolean(true)"
-									/>
-									<p>近期训练</p>
-									<p>专注力50以上人数比例</p>
-								</div>
-							</el-col>
-						</el-row>
-					</div>
-				</el-col>
-				<!-- 学员专注力评分分级占比分析 -->
-				<el-col :md="24" :lg="12" :xl="16">
-					<div class="charts-item">
-						<p class="title">样本每次训练专注力评分均值整体变化曲线</p>
-						<line-chart id="lineChart1" width="1000px" height="558px"/>
-					</div>
-				</el-col>
-			</el-row>
-		</div>
-		<div class="charts-container">
-			<el-row :gutter="20">
-				<el-col :md="24" :lg="12" :xl="8">
-					<div class="charts-item">
-						<p class="title pos">学员专注力训练高专注占比分析</p>
-						<AverageBarChart
-								id="averageBarChart1"
-								:data-sets="averageData"
-								width="520px"
-								height="520px"
-								class="chart"
-						/>
-						<el-row :gutter="15" class="bottom">
-							<el-col :span="12">
-								<p class="l">
-									<span>训练前期全体学员</span>
-									<span>高专注占比平均值</span>
-									<b>13.5</b>
-								</p>
-							</el-col>
-							<el-col :span="12">
-								<p class="r">
-									<span>训练后期全体学员</span>
-									<span>高专注占比平均值</span>
-									<b>33.7</b>
-								</p>
-							</el-col>
-						</el-row>
-					</div>
-				</el-col>
-				<!-- 学员专注力评分分级占比分析 -->
-				<el-col :md="24" :lg="12" :xl="16">
-					<div class="charts-item">
-						<p class="title">学员专注力评分分级占比分析</p>
-						<el-row justify="space-between">
-							<el-col :xs="24" :sm="24" :md="12" :lg="24" :xl="12">
-								<div v-if="chartStatus" class="bar">
-									<PercentBarChart
-											id="barChart1"
-											:key="chartData.frontProportion.toString()"
-											width="400px"
-											height="500px"
-											title="全体学员初期训练专注力评分占比"
-											:percent="chartData.frontProportion.percentage"
-											:data="chartData.frontProportion.num"
-											class="chart"
-									/>
-								</div>
-							</el-col>
-							<el-col :xs="24" :sm="24" :md="12" :lg="24" :xl="12">
-								<div v-if="chartStatus" class="bar">
-									<PercentBarChart
-											id="barChart2"
-											:key="chartData.afterProportion.toString()"
-											width="400px"
-											height="500px"
-											title="全体学员训练近期专注力评分平均占比"
-											:percent="chartData.afterProportion.percentage"
-											:data="chartData.afterProportion.num"
-											class="chart"
-									/>
-								</div>
-							</el-col>
-						</el-row>
-					</div>
-				</el-col>
-			</el-row>
-		</div>
   </div>
 </template>
 
 <style lang="scss" scoped>
 .area-top {
-  background: #ffffff;
+  background: #fff;
 }
-.card-box{
-  padding:0 30px 20px 30px;
+
+.card-box {
+  padding: 0 30px 20px;
 }
+
 .search-box {
-	display: flex;
-	line-height: 40px;
-	padding: 20px 55px 20px 55px;
-  .el-select{
-		width: 140px;
-		margin-right: 10px;
-	}
-	.el-date-editor{
-		width:300px !important;
-		margin: 0;
-	}
+  display: flex;
+  padding: 20px 55px;
+  line-height: 40px;
+
+  .el-select {
+    width: 140px;
+    margin-right: 10px;
+  }
+
+  .el-date-editor {
+    width: 300px !important;
+    margin: 0;
+  }
+
   .el-button {
-		font-size: 16px;
-		padding: 0 26px;
-		margin: 0 20px;
-		border-radius: 10px;
+    padding: 0 26px;
+    margin: 0 20px;
+    font-size: 16px;
+    border-radius: 10px;
   }
 }
-:deep(.el-select),:deep(.el-date-editor) {
+
+:deep(.el-select),
+:deep(.el-date-editor) {
   --el-select-input-focus-border-color: none !important;
-  border: 1px solid #dddddd;
-  border-radius: 10px;
+
   overflow: hidden;
+  border: 1px solid #ddd;
+  border-radius: 10px;
 }
-:deep(.search-box.s2 .el-select){
-	border: none;
+
+:deep(.search-box.s2 .el-select) {
+  border: none;
 }
+
 :deep(.el-date-editor) {
   --el-select-input-focus-border-color: none !important;
 }
+
 :deep(.el-input__wrapper) {
   box-shadow: none !important;
 }
+
 :deep(.el-input__wrapper.is-focus) {
   box-shadow: none !important;
 }
+
 :deep(.el-select:hover:not(.el-select--disabled) .el-input__wrapper) {
   box-shadow: none !important;
 }
-.charts-container{
+
+.charts-container {
   position: relative;
-  padding:0 30px 20px 30px;
+  padding: 0 30px 20px;
 }
+
 .charts-item {
-  background: #ffffff;
+  position: relative;
+  text-align: center;
+  background: #fff;
   border: 1px solid #e8eaec;
   border-radius: 24px;
-  text-align: center;
-  position: relative;
+
   .title {
-		margin: 0;
-		height: 78px;
-		line-height: 78px;
-		text-align: left;
-		text-indent: 2em;
-		font-size: 18px;
-		&.pos{
-	  	margin-bottom: -50px;
-		}
+    height: 78px;
+    margin: 0;
+    font-size: 18px;
+    line-height: 78px;
+    text-align: left;
+    text-indent: 2em;
+
+    &.pos {
+      margin-bottom: -50px;
+    }
   }
+
   .item {
-	padding-bottom: 30px;
+    padding-bottom: 30px;
   }
+
   .chart {
-	margin: 0 auto;
+    margin: 0 auto;
   }
+
   p {
-	margin: 0;
-	line-height: 24px;
-	font-size: 16px;
+    margin: 0;
+    font-size: 16px;
+    line-height: 24px;
   }
+
   .bar {
-	margin-top: 60px;
+    margin-top: 60px;
   }
-  .bottom{
-		padding:0 20px 20px 20px;
-		.el-col p{
-			position: relative;
-			box-sizing: border-box;
-			white-space: nowrap;
-			border-radius: 10px;
-			padding:10px 20px;
-			text-align: left;
-			color: #ffffff;
-			&.l{
-				background: #f8b865;
-			}
-			&.r{
-				background: #8877ef;
-			}
-			span{display: block}
-			b{
-				position: absolute;
-				right:20px;
-				top:22px;
-				font-size: 26px;
-				font-style: normal;
-			}
-		}
+
+  .bottom {
+    padding: 0 20px 20px;
+
+    .el-col p {
+      position: relative;
+      box-sizing: border-box;
+      padding: 10px 20px;
+      color: #fff;
+      text-align: left;
+      white-space: nowrap;
+      border-radius: 10px;
+
+      &.l {
+        background: #f8b865;
+      }
+
+      &.r {
+        background: #8877ef;
+      }
+
+      span {
+        display: block;
+      }
+
+      b {
+        position: absolute;
+        top: 22px;
+        right: 20px;
+        font-size: 26px;
+        font-style: normal;
+      }
+    }
   }
+
   .empty {
-	box-sizing: border-box;
-	height: 400px;
-	padding-top: 200px;
-	text-align: center;
-	background-image: url("../../assets/empty.png");
-	background-repeat: no-repeat;
-	background-position: center 30%;
-		p {
-			font-size: 14px;
-			color: #a1a1a1;
-			&.red {
-			color: #e04962;
-			}
-		}
+    box-sizing: border-box;
+    height: 400px;
+    padding-top: 200px;
+    text-align: center;
+    background-image: url("../../assets/empty.png");
+    background-repeat: no-repeat;
+    background-position: center 30%;
+
+    p {
+      font-size: 14px;
+      color: #a1a1a1;
+
+      &.red {
+        color: #e04962;
+      }
+    }
   }
 }
 </style>

+ 125 - 120
src/views/charts-components/LineChart.vue

@@ -1,138 +1,143 @@
 <!-- 圆饼图 -->
 <template>
-	<div :id="id" :class="className" :style="{ height, width }" />
+  <div :id="id" :class="className" :style="{ height, width }" />
 </template>
 
 <script setup lang="ts">
 import * as echarts from "echarts";
 
 const props = defineProps({
-	id: {
-		type: String,
-		default: "lineChart",
-		required: true,
-	},
-	className: {
-		type: String,
-		default: "chart",
-	},
-	width: {
-		type: String,
-		default: "400px",
-	},
-	height: {
-		type: String,
-		default: "300px",
-	},
-	title: {
-		type: String,
-		default: "",
-	},
-	data: {
-		type: Array,
-		default: [] as Array<number>,
-	},
+  id: {
+    type: String,
+    default: "lineChart",
+    required: true,
+  },
+  className: {
+    type: String,
+    default: "chart",
+  },
+  width: {
+    type: String,
+    default: "400px",
+  },
+  height: {
+    type: String,
+    default: "300px",
+  },
+  title: {
+    type: String,
+    default: "",
+  },
+  //[20, 30, 50, 78, 53, 47, 60,30, 50, 78, 53, 47, 60,30, 50, 78, 53, 47, 60]
+  data: {
+    type: Array,
+    default: [] as Array<number>,
+  },
 });
 /**
  * 配置项
  */
 const options = {
-	grid: {
-		x: "5%",
-		y: "5%",
-		x2: "8%",
-		y2: "10%",
-	},
-	xAxis: {
-		type: "category",
-		data: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
-		boundaryGap: true,
-		axisLabel: {
-			color: "#09132e",
-			interval: (value, index) => { return (index%4)==0;}
-		},
-		axisLine:{
-			show:true,
-			lineStyle: {
-				color: "#aaaaaa",
-			},
-		},
-		axisTick: {
-			show: true,
-			alignWithLabel: true,
-		}
-	},
-	yAxis: {
-		type: "value",
-		max: 100,
-		interval: 10,
-		axisLabel: {
-			color: "#09132e",
-		},
-		axisLine:{
-			show:true,
-			lineStyle: {
-				color: "#aaaaaa",
-			},
-		},
-		splitNumber: 10,
-		axisTick: {
-			show: true,
-			alignWithLabel: true,
-		}
-	},
-	series: [
-		{
-			data: [20, 30, 50, 78, 53, 47, 60,30, 50, 78, 53, 47, 60,30, 50, 78, 53, 47, 60],
-			type: "line",
-			symbol: "circle",
-			symbolSize: 10,
-			lineStyle:{
-				normal:{
-					color:{
-						type: "linear",
-						x:0,
-						y:0,
-						x2:0,
-						y2:1,
-						colorStops:[
-							{
-								offset:0,
-								color:"#ffd223",
-							},
-							{
-								offset:1,
-								color:"#9685fb",
-							},
-						]
-					}
-				}
-			}
-		}
-	],
-	visualMap: {
-		type: "continuous",
-		min: 0,
-		max: 100,
-		text: ["HIGH", "LOW"],
-		realtime: false,
-		calculable: false,
-		color: ["#ffd223", "#9685fb"],
-		itemWidth: 30,
-		right: "2%",
-		bottom: "5%",
-	},
+  grid: {
+    x: "5%",
+    y: "5%",
+    x2: "8%",
+    y2: "10%",
+  },
+  xAxis: {
+    type: "category",
+    data: [
+      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+    ],
+    boundaryGap: true,
+    axisLabel: {
+      color: "#09132e",
+      interval: (value, index) => {
+        return index % 4 == 0;
+      },
+    },
+    axisLine: {
+      show: true,
+      lineStyle: {
+        color: "#aaaaaa",
+      },
+    },
+    axisTick: {
+      show: true,
+      alignWithLabel: true,
+    },
+  },
+  yAxis: {
+    type: "value",
+    max: 100,
+    interval: 10,
+    axisLabel: {
+      color: "#09132e",
+    },
+    axisLine: {
+      show: true,
+      lineStyle: {
+        color: "#aaaaaa",
+      },
+    },
+    splitNumber: 10,
+    axisTick: {
+      show: true,
+      alignWithLabel: true,
+    },
+  },
+  series: [
+    {
+      data: props.data,
+      type: "line",
+      symbol: "circle",
+      symbolSize: 10,
+      lineStyle: {
+        normal: {
+          color: {
+            type: "linear",
+            x: 0,
+            y: 0,
+            x2: 0,
+            y2: 1,
+            colorStops: [
+              {
+                offset: 0,
+                color: "#ffd223",
+              },
+              {
+                offset: 1,
+                color: "#9685fb",
+              },
+            ],
+          },
+        },
+      },
+    },
+  ],
+  visualMap: {
+    type: "continuous",
+    min: 0,
+    max: 100,
+    text: ["HIGH", "LOW"],
+    realtime: false,
+    calculable: false,
+    color: ["#ffd223", "#9685fb"],
+    itemWidth: 30,
+    right: "2%",
+    bottom: "5%",
+  },
 };
 
 onMounted(() => {
-	// 图表初始化
-	const chart = echarts.init(
-		document.getElementById(<string>props.id) as HTMLDivElement
-	);
-	chart.setOption(options);
-	// 大小自适应
-	window.addEventListener("resize", () => {
-		chart.resize();
-	});
+  // 图表初始化
+  const chart = echarts.init(
+    document.getElementById(<string>props.id) as HTMLDivElement
+  );
+  chart.setOption(options);
+  // 大小自适应
+  window.addEventListener("resize", () => {
+    chart.resize();
+  });
 });
 </script>