47 3 months ago
parent
commit
be6f5ded64

+ 5 - 0
src/api/system/studentAttendance/index.ts

@@ -87,4 +87,9 @@ export const StudentAttendanceApi = {
     return await request.get({ url: `/system/student-attendance/weekendAttendance` })
   },
 
+  // 日出勤统计
+  getDayAttendance: async () => {
+    return await request.get({ url: `/system/student-attendance/dayAttendanceCount` })
+  },
+
 }

+ 304 - 245
src/views/Home/Index.vue

@@ -72,10 +72,7 @@
                     <span class="text-17px c-white">{{ item.name }}</span>
                   </div>
                   <div class="mb-18px text-32px c-white ml-20px text-center">{{ t(item.message) }}</div>
-                  <!-- <div class="mt-12px flex justify-between text-12px text-gray-400">
-
-                                                                                    <span>{{ formatTime(item.time, 'yyyy-MM-dd') }}</span>
-                                                                                  </div> -->
+                  <!-- <div class="mt-12px flex justify-between text-12px text-gray-400">                                                                  </div> -->
                 </el-card>
               </el-col>
             </el-row>
@@ -91,17 +88,17 @@
               <div class="h-70px flex items-center justify-center flex-wrap mt-10px c-white">
                 <div class="px-25px text-center" style="margin: auto;">
                   <div class="mb-16px text-18px text-white ">打卡人数</div>
-                  <CountTo class="text-28px" :start-val="0" :end-val="totalSate.normal" :duration="2600" />
+                  <CountTo class="text-28px" :start-val="0" :end-val="totalSate.normalNum" :duration="2600" />
                 </div>
                 <el-divider direction="vertical" border-style="dashed" />
                 <div class="px-8px text-center" style="margin: auto;">
                   <div class="mb-16px text-18px text-white ">未打卡人数</div>
-                  <CountTo class="text-28px" :start-val="0" :end-val="totalSate.unusual" :duration="2600" />
+                  <CountTo class="text-28px" :start-val="0" :end-val="totalSate.errorNum" :duration="2600" />
                 </div>
                 <el-divider direction="vertical" border-style="dashed" />
                 <div class="px-8px text-center" style="margin: auto;">
                   <div class="mb-16px text-18px text-white ">请假人数</div>
-                  <CountTo class="text-28px" :start-val="0" :end-val="totalSate.unusual" :duration="2600" />
+                  <CountTo class="text-28px" :start-val="0" :end-val="totalSate.ExcuNum" :duration="2600" />
                 </div>
               </div>
             </el-card>
@@ -293,7 +290,6 @@ import { useUserStore } from '@/store/modules/user'
 import { useWatermark } from '@/hooks/web/useWatermark'
 import type { WorkplaceTotal, Project, Notice, Shortcut } from './types'
 import { pieOptions, barOptions } from './echarts-data'
-import { center } from "diagram-js/lib/util/PositionUtil";
 import { reactive, onMounted, watchEffect } from "vue";
 import { vue3ScrollSeamless } from "vue3-scroll-seamless";
 import * as UserApi from '@/api/system/user'
@@ -351,27 +347,87 @@ const getProject = async () => {
 }
 
 
-/**出勤统计 */
+/**实时出勤统计 */
 // 获取统计数
 let totalSate = reactive<WorkplaceTotal>({
-  project: 0,
-  access: 0,
-  todo: 0
+  normalNum: 0,
+  errorNum: 0,
+  ExcuNum: 0,
 })
 const getCount = async () => {
-  const data = {
-    project: 40,
-    access: 2340,
-    todo: 10,
-    college: 80,
-    normal: 125,
-    unusual: 5
-  }
+  const data = await StudentAttendanceApi.getDayAttendance()
+  console.log("实时出勤统计", data);
   totalSate = Object.assign(totalSate, data)
 }
 
-/**实时人数统计 */
+/**毕业达成统计 */
 let pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
+const getUserAccessSource = async () => {
+  const data = [
+    { value: 1048, name: '达成人数' },
+    { value: 735, name: '未达成人数' },
+  ];
+
+  const options = {
+    title: {
+      text: null,
+      left: 'center',
+      top: '20px'
+    },
+    tooltip: {
+      trigger: 'item',
+    },
+    legend: {
+      top: '10%',  // 顶部位置
+      left: 'left', // 左侧位置
+    },
+    series: [
+      {
+        type: 'pie',
+        radius: ['120px', '70px'], // 设定内圈和外圈半径
+        center: ['50%', '85%'], // 中心位置
+        startAngle: 180,
+        endAngle: 360,
+        data: data.map(v => ({
+          value: v.value,
+          name: t(v.name),
+          label: {
+            show: true,
+            position: 'outside',  // 拉出标注
+            formatter: '{b}: {c}', // 显示名称和数值
+            // 可以自定义引线的样式
+            emphasis: {
+              show: true,
+            },
+          },
+          // 自定义引线样式
+          labelLine: {
+            show: true,
+            length: 75, // 引线长度
+            length2: 10, // 后半段引线的长度
+            smooth: true, // 引线是否平滑
+            lineDash: [5, 5], // 引线虚线样式
+          },
+        })),
+        itemStyle: {
+          // 设置饼图的颜色
+          color: function (params) {
+            const colorList = ['#94d6da', '#00a6ac']; // 定义颜色数组
+            return colorList[params.dataIndex]; // 根据数据索引返回对应的颜色
+          }
+        }
+      },
+    ],
+  };
+
+  set(
+    pieOptionsData,
+    'legend.data',
+    data.map((v) => t(v.name))
+  );
+
+  pieOptionsData = Object.assign(pieOptionsData, options);
+};
 
 /**周出勤情况 */
 let barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption
@@ -486,254 +542,257 @@ const list1Options = reactive({
 onMounted(() => {
   getDetail()
   getWeekend()
+  getProject()
+  getCount()
+  // getNotice()
 })
 
 
 
-// 获取通知公告
-let notice = reactive<Notice[]>([])
-const getNotice = async () => {
-  const data = [
-    {
-      title: '系统支持 JDK 8/17/21,Vue 2/3',
-      type: '通知',
-      keys: ['通知', '8', '17', '21', '2', '3'],
-      date: new Date()
-    },
-    {
-      title: '后端提供 Spring Boot 2.7/3.2 + Cloud 双架构',
-      type: '公告',
-      keys: ['公告', 'Boot', 'Cloud'],
-      date: new Date()
-    },
-    {
-      title: '全部开源,个人与企业可 100% 直接使用,无需授权',
-      type: '通知',
-      keys: ['通知', '无需授权'],
-      date: new Date()
-    },
-    {
-      title: '国内使用最广泛的快速开发平台,超 300+ 人贡献',
-      type: '公告',
-      keys: ['公告', '最广泛'],
-      date: new Date()
-    }
-  ]
-  notice = Object.assign(notice, data)
-}
-
-// 获取基本信息
-let basic = reactive<Basic[]>([])
-const getBasic = async () => {
-  const data = [
-    {
-      title: '学院工作间数量',
-      type: '通知',
-      keys: ['通知', '8', '17', '21', '2', '3'],
-      date: new Date()
-    },
-    {
-      title: '硕士研究生数量',
-      type: '公告',
-      keys: ['公告', 'Boot', 'Cloud'],
-      date: new Date()
-    },
-    {
-      title: '博士研究生数量',
-      type: '通知',
-      keys: ['通知', '无需授权'],
-      date: new Date()
-    },
-    {
-      title: '硕士研究生导师数量',
-      type: '公告',
-      keys: ['公告', '最广泛'],
-      date: new Date()
-    },
-    {
-      title: '博士生导师数量',
-      type: '公告',
-      keys: ['公告', '最广泛'],
-      date: new Date()
-    }
-
-  ]
-  basic = Object.assign(basic, data)
-}
+// // 获取通知公告
+// let notice = reactive<Notice[]>([])
+// const getNotice = async () => {
+//   const data = [
+//     {
+//       title: '系统支持 JDK 8/17/21,Vue 2/3',
+//       type: '通知',
+//       keys: ['通知', '8', '17', '21', '2', '3'],
+//       date: new Date()
+//     },
+//     {
+//       title: '后端提供 Spring Boot 2.7/3.2 + Cloud 双架构',
+//       type: '公告',
+//       keys: ['公告', 'Boot', 'Cloud'],
+//       date: new Date()
+//     },
+//     {
+//       title: '全部开源,个人与企业可 100% 直接使用,无需授权',
+//       type: '通知',
+//       keys: ['通知', '无需授权'],
+//       date: new Date()
+//     },
+//     {
+//       title: '国内使用最广泛的快速开发平台,超 300+ 人贡献',
+//       type: '公告',
+//       keys: ['公告', '最广泛'],
+//       date: new Date()
+//     }
+//   ]
+//   notice = Object.assign(notice, data)
+// }
+
+// // 获取基本信息
+// let basic = reactive<Basic[]>([])
+// const getBasic = async () => {
+//   const data = [
+//     {
+//       title: '学院工作间数量',
+//       type: '通知',
+//       keys: ['通知', '8', '17', '21', '2', '3'],
+//       date: new Date()
+//     },
+//     {
+//       title: '硕士研究生数量',
+//       type: '公告',
+//       keys: ['公告', 'Boot', 'Cloud'],
+//       date: new Date()
+//     },
+//     {
+//       title: '博士研究生数量',
+//       type: '通知',
+//       keys: ['通知', '无需授权'],
+//       date: new Date()
+//     },
+//     {
+//       title: '硕士研究生导师数量',
+//       type: '公告',
+//       keys: ['公告', '最广泛'],
+//       date: new Date()
+//     },
+//     {
+//       title: '博士生导师数量',
+//       type: '公告',
+//       keys: ['公告', '最广泛'],
+//       date: new Date()
+//     }
+
+//   ]
+//   basic = Object.assign(basic, data)
+// }
 
 
 // 获取快捷入口
-let shortcut = reactive<Shortcut[]>([])
-
-const getShortcut = async () => {
-  const data = [
-    {
-      name: 'Github',
-      icon: 'akar-icons:github-fill',
-      url: 'github.io'
-    },
-    {
-      name: 'Vue',
-      icon: 'logos:vue',
-      url: 'vuejs.org'
-    },
-    {
-      name: 'Vite',
-      icon: 'vscode-icons:file-type-vite',
-      url: 'https://vitejs.dev/'
-    },
-    {
-      name: 'Angular',
-      icon: 'logos:angular-icon',
-      url: 'github.io'
-    },
-    {
-      name: 'React',
-      icon: 'logos:react',
-      url: 'github.io'
-    },
-    {
-      name: 'Webpack',
-      icon: 'logos:webpack',
-      url: 'github.io'
-    }
-  ]
-  shortcut = Object.assign(shortcut, data)
-}
+// let shortcut = reactive<Shortcut[]>([])
+
+// const getShortcut = async () => {
+//   const data = [
+//     {
+//       name: 'Github',
+//       icon: 'akar-icons:github-fill',
+//       url: 'github.io'
+//     },
+//     {
+//       name: 'Vue',
+//       icon: 'logos:vue',
+//       url: 'vuejs.org'
+//     },
+//     {
+//       name: 'Vite',
+//       icon: 'vscode-icons:file-type-vite',
+//       url: 'https://vitejs.dev/'
+//     },
+//     {
+//       name: 'Angular',
+//       icon: 'logos:angular-icon',
+//       url: 'github.io'
+//     },
+//     {
+//       name: 'React',
+//       icon: 'logos:react',
+//       url: 'github.io'
+//     },
+//     {
+//       name: 'Webpack',
+//       icon: 'logos:webpack',
+//       url: 'github.io'
+//     }
+//   ]
+//   shortcut = Object.assign(shortcut, data)
+// }
 
 // 用户来源
-const getUserAccessSource = async () => {
-  const data = [
-    { value: 1048, name: '达成人数' },
-    { value: 735, name: '未达成人数' },
-  ];
-
-  const options = {
-    title: {
-      text: null,
-      left: 'center',
-      top: '20px'
-    },
-    tooltip: {
-      trigger: 'item',
-    },
-    legend: {
-      top: '10%',  // 顶部位置
-      left: 'left', // 左侧位置
-    },
-    series: [
-      {
-        type: 'pie',
-        radius: ['120px', '70px'], // 设定内圈和外圈半径
-        center: ['50%', '85%'], // 中心位置
-        startAngle: 180,
-        endAngle: 360,
-        data: data.map(v => ({
-          value: v.value,
-          name: t(v.name),
-          label: {
-            show: true,
-            position: 'outside',  // 拉出标注
-            formatter: '{b}: {c}', // 显示名称和数值
-            // 可以自定义引线的样式
-            emphasis: {
-              show: true,
-            },
-          },
-          // 自定义引线样式
-          labelLine: {
-            show: true,
-            length: 75, // 引线长度
-            length2: 10, // 后半段引线的长度
-            smooth: true, // 引线是否平滑
-            lineDash: [5, 5], // 引线虚线样式
-          },
-        })),
-        itemStyle: {
-          // 设置饼图的颜色
-          color: function (params) {
-            const colorList = ['#94d6da', '#00a6ac']; // 定义颜色数组
-            return colorList[params.dataIndex]; // 根据数据索引返回对应的颜色
-          }
-        }
-      },
-    ],
-  };
-
-  set(
-    pieOptionsData,
-    'legend.data',
-    data.map((v) => t(v.name))
-  );
-
-  pieOptionsData = Object.assign(pieOptionsData, options);
-};
+// const getUserAccessSource = async () => {
+//   const data = [
+//     { value: 1048, name: '达成人数' },
+//     { value: 735, name: '未达成人数' },
+//   ];
+
+//   const options = {
+//     title: {
+//       text: null,
+//       left: 'center',
+//       top: '20px'
+//     },
+//     tooltip: {
+//       trigger: 'item',
+//     },
+//     legend: {
+//       top: '10%',  // 顶部位置
+//       left: 'left', // 左侧位置
+//     },
+//     series: [
+//       {
+//         type: 'pie',
+//         radius: ['120px', '70px'], // 设定内圈和外圈半径
+//         center: ['50%', '85%'], // 中心位置
+//         startAngle: 180,
+//         endAngle: 360,
+//         data: data.map(v => ({
+//           value: v.value,
+//           name: t(v.name),
+//           label: {
+//             show: true,
+//             position: 'outside',  // 拉出标注
+//             formatter: '{b}: {c}', // 显示名称和数值
+//             // 可以自定义引线的样式
+//             emphasis: {
+//               show: true,
+//             },
+//           },
+//           // 自定义引线样式
+//           labelLine: {
+//             show: true,
+//             length: 75, // 引线长度
+//             length2: 10, // 后半段引线的长度
+//             smooth: true, // 引线是否平滑
+//             lineDash: [5, 5], // 引线虚线样式
+//           },
+//         })),
+//         itemStyle: {
+//           // 设置饼图的颜色
+//           color: function (params) {
+//             const colorList = ['#94d6da', '#00a6ac']; // 定义颜色数组
+//             return colorList[params.dataIndex]; // 根据数据索引返回对应的颜色
+//           }
+//         }
+//       },
+//     ],
+//   };
+
+//   set(
+//     pieOptionsData,
+//     'legend.data',
+//     data.map((v) => t(v.name))
+//   );
+
+//   pieOptionsData = Object.assign(pieOptionsData, options);
+// };
 
 
 
 
 // 周活跃量
-const getWeeklyUserActivity = async () => {
-  const data = [
-    { value: 13253, name: '异常人数' },
-    { value: 34235, name: '正常人数' },
-  ];
-
-  const options = {
-    title: {
-      text: null,
-    },
-    tooltip: {
-      trigger: 'item',
-    },
-    grid: {
-      left: '80px',
-      top: '10px',  // 上方偏移
-    },
-    series: [
-      {
-        name: '人数',
-        type: 'bar',
-        barWidth: '40%', // 设置柱子的宽度为40%
-        data: data.map((v) => v.value), // 设置Y轴数据
-        itemStyle: {
-          // 设置每个柱状的颜色
-          color: function (params) {
-            const colorList = ['#145b7d', '#33a3dc']; // 定义颜色数组
-            return colorList[params.dataIndex]; // 根据数据索引返回对应的颜色
-          }
-        }
-      }
-    ]
-  };
-
-  set(
-    barOptionsData,
-    'xAxis.data',
-    data.map((v) => t(v.name))
-  );
-
-  barOptionsData = Object.assign(barOptionsData, options);
-};
+// const getWeeklyUserActivity = async () => {
+//   const data = [
+//     { value: 13253, name: '异常人数' },
+//     { value: 34235, name: '正常人数' },
+//   ];
+
+//   const options = {
+//     title: {
+//       text: null,
+//     },
+//     tooltip: {
+//       trigger: 'item',
+//     },
+//     grid: {
+//       left: '80px',
+//       top: '10px',  // 上方偏移
+//     },
+//     series: [
+//       {
+//         name: '人数',
+//         type: 'bar',
+//         barWidth: '40%', // 设置柱子的宽度为40%
+//         data: data.map((v) => v.value), // 设置Y轴数据
+//         itemStyle: {
+//           // 设置每个柱状的颜色
+//           color: function (params) {
+//             const colorList = ['#145b7d', '#33a3dc']; // 定义颜色数组
+//             return colorList[params.dataIndex]; // 根据数据索引返回对应的颜色
+//           }
+//         }
+//       }
+//     ]
+//   };
+
+//   set(
+//     barOptionsData,
+//     'xAxis.data',
+//     data.map((v) => t(v.name))
+//   );
+
+//   barOptionsData = Object.assign(barOptionsData, options);
+// };
 
 const getAllApi = async () => {
   await Promise.all([
     await getDetail(),
     getCount(),
     getProject(),
-    getNotice(),
-    getBasic(),
-    getShortcut(),
-    getUserAccessSource(),
-    getWeeklyUserActivity()
+    // getNotice(),
+    // getBasic(),
+    // getShortcut(),
+    // getUserAccessSource(),
+    // getWeeklyUserActivity()
   ])
   loading.value = false
 }
 
-// watchEffect(detail => {
-//   console.log('detail', detail)
-//   getBasic()
-// })
+watchEffect(detail => {
+  console.log('detail', detail)
+  // getBasic()
+})
 
 // onMounted(() => {
 

+ 8 - 6
src/views/Home/echarts-data.ts

@@ -95,8 +95,10 @@ export const pieOptions: EChartsOption = {
     {
       name: t('analysis.userAccessSource'),
       type: 'pie',
-      radius: '55%',
-      center: ['50%', '60%'],
+      radius: ['120px', '70px'],
+      center: ['50%', '85%'],
+      startAngle: 180,
+      endAngle: 360,
       data: [
         { value: 335, name: t('analysis.directAccess') },
         { value: 310, name: t('analysis.mailMarketing') },
@@ -109,10 +111,10 @@ export const pieOptions: EChartsOption = {
 }
 
 export const barOptions: EChartsOption = {
-  title: {
-    text: t('analysis.weeklyUserActivity'),
-    left: 'center'
-  },
+  // title: {
+  // text: t('analysis.weeklyUserActivity'),
+  //   left: 'center'
+  // },
   tooltip: {
     trigger: 'axis',
     axisPointer: {

+ 3 - 3
src/views/Home/types.ts

@@ -1,7 +1,7 @@
 export type WorkplaceTotal = {
-  project: number
-  access: number
-  todo: number
+  normalNum: number
+  errorNum: number
+  ExcuNum: number
 }
 
 export type Project = {

+ 14 - 1
src/views/system/workroomCollege/dept/index.vue

@@ -180,6 +180,13 @@
         </template>
       </el-table-column>
     </el-table>
+    <Pagination
+      @current-change="handleCurrentChange"
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
   </ContentWrap>
   <!-- 表单弹窗:添加/修改 -->
   <DeptForm ref="formRef" @success="handleFormSuccess" />
@@ -200,9 +207,10 @@ const { t } = useI18n() // 国际化
 
 const loading = ref(true) // 列表的加载中
 const list = ref() // 列表的数据
+const total = ref(0) // 列表的总页数
 const queryParams = reactive({
   pageNo: 1,
-  pageSize: 100,
+  pageSize: 10,
   name: undefined,
   leaderUserId: [],
   phone: undefined,
@@ -267,6 +275,11 @@ const stripHtml = (html) => {
   return html.replace(/<[^>]*>/g, ''); // 去除所有 HTML 标签
 };
 
+const handleCurrentChange = (newPage) => {
+  queryParams.pageNo = newPage;
+  getList();
+};
+
 /** 展开/折叠操作 */
 const toggleExpandAll = () => {
   refreshTable.value = false