|
@@ -1,3 +1,53 @@
|
|
|
+
|
|
|
+ <!-- <div>
|
|
|
+ <el-card shadow="never">
|
|
|
+ <el-skeleton :loading="loading" animated>
|
|
|
+ <el-row :gutter="16" justify="space-between">
|
|
|
+ <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
|
|
|
+ <div class="flex items-center">
|
|
|
+ <el-avatar :src="avatar" :size="70" class="mr-16px">
|
|
|
+ <img src="@/assets/imgs/avatar.gif" alt="" />
|
|
|
+ </el-avatar>
|
|
|
+ <div>
|
|
|
+ <div class="text-20px">
|
|
|
+ {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }}
|
|
|
+ </div>
|
|
|
+ <div class="mt-10px text-14px text-gray-500">
|
|
|
+ {{ t('workplace.toady') }},20℃ - 32℃!
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
|
|
|
+ <div class="h-70px flex items-center justify-end lt-sm:mt-10px">
|
|
|
+ <div class="px-8px text-right">
|
|
|
+ <div class="mb-16px text-14px text-gray-400">{{ t('workplace.project') }}</div>
|
|
|
+ <CountTo class="text-20px" :start-val="0" :end-val="totalSate.project" :duration="2600" />
|
|
|
+ </div>
|
|
|
+ <el-divider direction="vertical" />
|
|
|
+ <div class="px-8px text-right">
|
|
|
+ <div class="mb-16px text-14px text-gray-400">{{ t('workplace.toDo') }}</div>
|
|
|
+ <CountTo class="text-20px" :start-val="0" :end-val="totalSate.todo" :duration="2600" />
|
|
|
+ </div>
|
|
|
+ <el-divider direction="vertical" border-style="dashed" />
|
|
|
+ <div class="px-8px text-right">
|
|
|
+ <div class="mb-16px text-14px text-gray-400">{{ t('workplace.access') }}</div>
|
|
|
+ <CountTo class="text-20px" :start-val="0" :end-val="totalSate.access" :duration="2600" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-skeleton>
|
|
|
+ </el-card>
|
|
|
+ </div> -->
|
|
|
+ <!-- 日期
|
|
|
+ <div class="mt-16px text-12px text-gray-400">
|
|
|
+ {{ formatTime(item.date, 'yyyy-MM-dd') }}
|
|
|
+ </div> -->
|
|
|
+ <!-- 更多<el-link type="primary" :underline="false" href="https://github.com/yudaocode" target="_blank"> {{
|
|
|
+ t('action.more') }}
|
|
|
+ </el-link> -->
|
|
|
+
|
|
|
<template>
|
|
|
<el-skeleton :loading="loading" animated>
|
|
|
<el-row :gutter="8">
|
|
@@ -239,19 +289,15 @@
|
|
|
import { set } from 'lodash-es'
|
|
|
import { EChartsOption, List } from 'echarts'
|
|
|
import { formatTime } from '@/utils'
|
|
|
-
|
|
|
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'
|
|
|
-import { on } from 'events'
|
|
|
+import { StudentAttendanceApi } from '@/api/system/studentAttendance'
|
|
|
|
|
|
defineOptions({ name: 'Home' })
|
|
|
|
|
@@ -261,42 +307,29 @@ const { setWatermark } = useWatermark()
|
|
|
const loading = ref(true)
|
|
|
const avatar = userStore.getUser.avatar
|
|
|
const username = userStore.getUser.nickname
|
|
|
-let pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
|
|
|
-// 获取统计数
|
|
|
-let totalSate = reactive<WorkplaceTotal>({
|
|
|
- project: 0,
|
|
|
- access: 0,
|
|
|
- todo: 0
|
|
|
-})
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+/*基本信息*/
|
|
|
const detail = reactive({
|
|
|
- "deptNum": undefined,
|
|
|
- "teacherNum": undefined,
|
|
|
- "studentNum": undefined
|
|
|
+ deptNum: undefined,
|
|
|
+ teacherNum: undefined,
|
|
|
+ studentNum: undefined
|
|
|
})
|
|
|
-
|
|
|
-const getCount = async () => {
|
|
|
- const data = {
|
|
|
- project: 40,
|
|
|
- access: 2340,
|
|
|
- todo: 10,
|
|
|
- college: 80,
|
|
|
- normal: 125,
|
|
|
- unusual: 5
|
|
|
- }
|
|
|
- totalSate = Object.assign(totalSate, data)
|
|
|
+const getDetail = async () => {
|
|
|
+ const data = await UserApi.getDetail()
|
|
|
+ console.log("基本信息", data);
|
|
|
+ detail.deptNum = data.deptNum
|
|
|
+ detail.teacherNum = data.teacherNum
|
|
|
+ detail.studentNum = data.studentNum
|
|
|
}
|
|
|
-
|
|
|
// 获取项目数
|
|
|
let projects = reactive<Project[]>([])
|
|
|
const getProject = async () => {
|
|
|
- // console.log("getProject",detail.deptNum);
|
|
|
-
|
|
|
const data = [
|
|
|
{
|
|
|
name: '学院工作间数量',
|
|
|
icon: 'svg-icon:gzs',
|
|
|
-
|
|
|
message: String(detail.deptNum) + '个',
|
|
|
time: new Date()
|
|
|
},
|
|
@@ -317,6 +350,146 @@ const getProject = async () => {
|
|
|
projects = Object.assign(projects, data)
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/**出勤统计 */
|
|
|
+// 获取统计数
|
|
|
+let totalSate = reactive<WorkplaceTotal>({
|
|
|
+ project: 0,
|
|
|
+ access: 0,
|
|
|
+ todo: 0
|
|
|
+})
|
|
|
+const getCount = async () => {
|
|
|
+ const data = {
|
|
|
+ project: 40,
|
|
|
+ access: 2340,
|
|
|
+ todo: 10,
|
|
|
+ college: 80,
|
|
|
+ normal: 125,
|
|
|
+ unusual: 5
|
|
|
+ }
|
|
|
+ totalSate = Object.assign(totalSate, data)
|
|
|
+}
|
|
|
+
|
|
|
+/**实时人数统计 */
|
|
|
+let pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
|
|
|
+
|
|
|
+/**周出勤情况 */
|
|
|
+let barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption
|
|
|
+ const getWeekend = async () => {
|
|
|
+ try {
|
|
|
+ const res = await StudentAttendanceApi.getWeekendAttendance();
|
|
|
+ console.log("周出勤情况", res);
|
|
|
+ // 更新图表数据
|
|
|
+ barOptionsData.series = [
|
|
|
+ {
|
|
|
+ name: '正常出勤',
|
|
|
+ type: 'bar',
|
|
|
+ data: [res.normalNum], // 将正常出勤人数放入数据中
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '缺勤',
|
|
|
+ type: 'bar',
|
|
|
+ data: [res.errorNum], // 将缺勤人数放入数据中
|
|
|
+ }
|
|
|
+ ];
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取周出勤情况失败:", error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+/**缺勤预警 */
|
|
|
+const list2 = reactive([
|
|
|
+ { trainNumber: '张一', destination: '101', departureTime: '09:00', ID: '10' },
|
|
|
+ { trainNumber: '张二', destination: '102', departureTime: '09:15', ID: '15' },
|
|
|
+ { trainNumber: '张三', destination: '103', departureTime: '09:30', ID: '13' },
|
|
|
+ { trainNumber: '张四', destination: '104', departureTime: '09:45', ID: '18' },
|
|
|
+ { trainNumber: '张五', destination: '105', departureTime: '10:00', ID: '19' },
|
|
|
+ { trainNumber: '李一', destination: '201', departureTime: '10:15', ID: '12' },
|
|
|
+ { trainNumber: '李二', destination: '202', departureTime: '10:30', ID: '02' },
|
|
|
+ { trainNumber: '李三', destination: '203', departureTime: '10:45', ID: '09' },
|
|
|
+ { trainNumber: '李四', destination: '204', departureTime: '11:00', ID: '16' },
|
|
|
+ { trainNumber: '李五', destination: '205', departureTime: '11:15', ID: '20' },
|
|
|
+ { trainNumber: '王一', destination: '301', departureTime: '11:30', ID: '28' },
|
|
|
+ { trainNumber: '王二', destination: '302', departureTime: '11:45', ID: '36' },
|
|
|
+ { trainNumber: '王三', destination: '303', departureTime: '12:00', ID: '07' },
|
|
|
+ { trainNumber: '王四', destination: '304', departureTime: '12:15', ID: '41' },
|
|
|
+ { trainNumber: '王五', destination: '305', departureTime: '12:30', ID: '15' },
|
|
|
+ { trainNumber: '王六', destination: '306', departureTime: '12:45', ID: '22' },
|
|
|
+ { trainNumber: '王七', destination: '307', departureTime: '13:00', ID: '27' }
|
|
|
+
|
|
|
+]);
|
|
|
+const class2Options = reactive({
|
|
|
+ step: 0.5,//滚动速度值越大越快,但是值太小会卡顿
|
|
|
+ limitMoveNum: list2.length,//无缝滚动列表元素的长度,一般设置为列表的长度
|
|
|
+ direction: 1,//方向: 0 往下 1 往上 2 向左 3 向右。
|
|
|
+});
|
|
|
+
|
|
|
+/**实时打卡状态 */
|
|
|
+//打卡滚动列表
|
|
|
+const list = reactive([
|
|
|
+ { trainNumber: '张一', destination: '101', departureTime: '09:00', status: '准点' },
|
|
|
+ { trainNumber: '张二', destination: '102', departureTime: '09:15', status: '准点' },
|
|
|
+ { trainNumber: '张三', destination: '103', departureTime: '09:30', status: '晚点' },
|
|
|
+ { trainNumber: '张四', destination: '104', departureTime: '09:45', status: '准点' },
|
|
|
+ { trainNumber: '张五', destination: '105', departureTime: '10:00', status: '准点' },
|
|
|
+ { trainNumber: '李一', destination: '201', departureTime: '10:15', status: '准点' },
|
|
|
+ { trainNumber: '李二', destination: '202', departureTime: '10:30', status: '晚点' },
|
|
|
+ { trainNumber: '李三', destination: '203', departureTime: '10:45', status: '准点' },
|
|
|
+ { trainNumber: '李四', destination: '204', departureTime: '11:00', status: '晚点' },
|
|
|
+ { trainNumber: '李五', destination: '205', departureTime: '11:15', status: '准点' },
|
|
|
+ { trainNumber: '王一', destination: '301', departureTime: '11:30', status: '准点' },
|
|
|
+ { trainNumber: '王二', destination: '302', departureTime: '11:45', status: '准点' },
|
|
|
+ { trainNumber: '王三', destination: '303', departureTime: '12:00', status: '晚点' },
|
|
|
+ { trainNumber: '王四', destination: '304', departureTime: '12:15', status: '准点' },
|
|
|
+ { trainNumber: '王五', destination: '305', departureTime: '12:30', status: '准点' },
|
|
|
+ { trainNumber: '王六', destination: '306', departureTime: '12:45', status: '准点' },
|
|
|
+ { trainNumber: '王七', destination: '307', departureTime: '13:00', status: '晚点' }
|
|
|
+
|
|
|
+]);
|
|
|
+const classOptions = reactive({
|
|
|
+ step: 0.5,//滚动速度值越大越快,但是值太小会卡顿
|
|
|
+ limitMoveNum: list.length,//无缝滚动列表元素的长度,一般设置为列表的长度
|
|
|
+ direction: 1,//方向: 0 往下 1 往上 2 向左 3 向右。
|
|
|
+
|
|
|
+});
|
|
|
+
|
|
|
+/** 学生毕业条件达成率 */
|
|
|
+//在线情况滚动列表
|
|
|
+const list1 = reactive([
|
|
|
+ { destination: '101', departureNumber: '98%' },
|
|
|
+ { destination: '102', departureNumber: '94%' },
|
|
|
+ { destination: '103', departureNumber: '96%' },
|
|
|
+ { destination: '104', departureNumber: '98%' },
|
|
|
+ { destination: '105', departureNumber: '93%' },
|
|
|
+ { destination: '201', departureNumber: '97%' },
|
|
|
+ { destination: '202', departureNumber: '95%' },
|
|
|
+ { destination: '203', departureNumber: '98%' },
|
|
|
+ { destination: '204', departureNumber: '96%' },
|
|
|
+ { destination: '205', departureNumber: '94%' },
|
|
|
+ { destination: '301', departureNumber: '97%' },
|
|
|
+ { destination: '302', departureNumber: '96%' },
|
|
|
+ { destination: '303', departureNumber: '95%' },
|
|
|
+ { destination: '304', departureNumber: '97%' },
|
|
|
+ { destination: '305', departureNumber: '98%' },
|
|
|
+ { destination: '306', departureNumber: '99%' },
|
|
|
+ { destination: '307', departureNumber: '96%' }
|
|
|
+
|
|
|
+]);
|
|
|
+const list1Options = reactive({
|
|
|
+ step: 0.5,//滚动速度值越大越快,但是值太小会卡顿
|
|
|
+ limitMoveNum: list1.length,//无缝滚动列表元素的长度,一般设置为列表的长度
|
|
|
+ direction: 1,//方向: 0 往下 1 往上 2 向左 3 向右。
|
|
|
+
|
|
|
+});
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getDetail()
|
|
|
+ getWeekend()
|
|
|
+})
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
// 获取通知公告
|
|
|
let notice = reactive<Notice[]>([])
|
|
|
const getNotice = async () => {
|
|
@@ -497,7 +670,7 @@ const getUserAccessSource = async () => {
|
|
|
};
|
|
|
|
|
|
|
|
|
-let barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption
|
|
|
+
|
|
|
|
|
|
// 周活跃量
|
|
|
const getWeeklyUserActivity = async () => {
|
|
@@ -543,103 +716,6 @@ const getWeeklyUserActivity = async () => {
|
|
|
barOptionsData = Object.assign(barOptionsData, options);
|
|
|
};
|
|
|
|
|
|
-//打卡滚动列表
|
|
|
-const list = reactive([
|
|
|
- { trainNumber: '张一', destination: '101', departureTime: '09:00', status: '准点' },
|
|
|
- { trainNumber: '张二', destination: '102', departureTime: '09:15', status: '准点' },
|
|
|
- { trainNumber: '张三', destination: '103', departureTime: '09:30', status: '晚点' },
|
|
|
- { trainNumber: '张四', destination: '104', departureTime: '09:45', status: '准点' },
|
|
|
- { trainNumber: '张五', destination: '105', departureTime: '10:00', status: '准点' },
|
|
|
- { trainNumber: '李一', destination: '201', departureTime: '10:15', status: '准点' },
|
|
|
- { trainNumber: '李二', destination: '202', departureTime: '10:30', status: '晚点' },
|
|
|
- { trainNumber: '李三', destination: '203', departureTime: '10:45', status: '准点' },
|
|
|
- { trainNumber: '李四', destination: '204', departureTime: '11:00', status: '晚点' },
|
|
|
- { trainNumber: '李五', destination: '205', departureTime: '11:15', status: '准点' },
|
|
|
- { trainNumber: '王一', destination: '301', departureTime: '11:30', status: '准点' },
|
|
|
- { trainNumber: '王二', destination: '302', departureTime: '11:45', status: '准点' },
|
|
|
- { trainNumber: '王三', destination: '303', departureTime: '12:00', status: '晚点' },
|
|
|
- { trainNumber: '王四', destination: '304', departureTime: '12:15', status: '准点' },
|
|
|
- { trainNumber: '王五', destination: '305', departureTime: '12:30', status: '准点' },
|
|
|
- { trainNumber: '王六', destination: '306', departureTime: '12:45', status: '准点' },
|
|
|
- { trainNumber: '王七', destination: '307', departureTime: '13:00', status: '晚点' }
|
|
|
-
|
|
|
-]);
|
|
|
-const classOptions = reactive({
|
|
|
- step: 0.5,//滚动速度值越大越快,但是值太小会卡顿
|
|
|
- limitMoveNum: list.length,//无缝滚动列表元素的长度,一般设置为列表的长度
|
|
|
- direction: 1,//方向: 0 往下 1 往上 2 向左 3 向右。
|
|
|
-
|
|
|
-});
|
|
|
-
|
|
|
-//在线情况滚动列表
|
|
|
-const list1 = reactive([
|
|
|
- { destination: '101', departureNumber: '98%' },
|
|
|
- { destination: '102', departureNumber: '94%' },
|
|
|
- { destination: '103', departureNumber: '96%' },
|
|
|
- { destination: '104', departureNumber: '98%' },
|
|
|
- { destination: '105', departureNumber: '93%' },
|
|
|
- { destination: '201', departureNumber: '97%' },
|
|
|
- { destination: '202', departureNumber: '95%' },
|
|
|
- { destination: '203', departureNumber: '98%' },
|
|
|
- { destination: '204', departureNumber: '96%' },
|
|
|
- { destination: '205', departureNumber: '94%' },
|
|
|
- { destination: '301', departureNumber: '97%' },
|
|
|
- { destination: '302', departureNumber: '96%' },
|
|
|
- { destination: '303', departureNumber: '95%' },
|
|
|
- { destination: '304', departureNumber: '97%' },
|
|
|
- { destination: '305', departureNumber: '98%' },
|
|
|
- { destination: '306', departureNumber: '99%' },
|
|
|
- { destination: '307', departureNumber: '96%' }
|
|
|
-
|
|
|
-]);
|
|
|
-const list1Options = reactive({
|
|
|
- step: 0.5,//滚动速度值越大越快,但是值太小会卡顿
|
|
|
- limitMoveNum: list1.length,//无缝滚动列表元素的长度,一般设置为列表的长度
|
|
|
- direction: 1,//方向: 0 往下 1 往上 2 向左 3 向右。
|
|
|
-
|
|
|
-});
|
|
|
-
|
|
|
-const list2 = reactive([
|
|
|
- { trainNumber: '张一', destination: '101', departureTime: '09:00', ID: '10' },
|
|
|
- { trainNumber: '张二', destination: '102', departureTime: '09:15', ID: '15' },
|
|
|
- { trainNumber: '张三', destination: '103', departureTime: '09:30', ID: '13' },
|
|
|
- { trainNumber: '张四', destination: '104', departureTime: '09:45', ID: '18' },
|
|
|
- { trainNumber: '张五', destination: '105', departureTime: '10:00', ID: '19' },
|
|
|
- { trainNumber: '李一', destination: '201', departureTime: '10:15', ID: '12' },
|
|
|
- { trainNumber: '李二', destination: '202', departureTime: '10:30', ID: '02' },
|
|
|
- { trainNumber: '李三', destination: '203', departureTime: '10:45', ID: '09' },
|
|
|
- { trainNumber: '李四', destination: '204', departureTime: '11:00', ID: '16' },
|
|
|
- { trainNumber: '李五', destination: '205', departureTime: '11:15', ID: '20' },
|
|
|
- { trainNumber: '王一', destination: '301', departureTime: '11:30', ID: '28' },
|
|
|
- { trainNumber: '王二', destination: '302', departureTime: '11:45', ID: '36' },
|
|
|
- { trainNumber: '王三', destination: '303', departureTime: '12:00', ID: '07' },
|
|
|
- { trainNumber: '王四', destination: '304', departureTime: '12:15', ID: '41' },
|
|
|
- { trainNumber: '王五', destination: '305', departureTime: '12:30', ID: '15' },
|
|
|
- { trainNumber: '王六', destination: '306', departureTime: '12:45', ID: '22' },
|
|
|
- { trainNumber: '王七', destination: '307', departureTime: '13:00', ID: '27' }
|
|
|
-
|
|
|
-]);
|
|
|
-const class2Options = reactive({
|
|
|
- step: 0.5,//滚动速度值越大越快,但是值太小会卡顿
|
|
|
- limitMoveNum: list2.length,//无缝滚动列表元素的长度,一般设置为列表的长度
|
|
|
- direction: 1,//方向: 0 往下 1 往上 2 向左 3 向右。
|
|
|
-
|
|
|
-});
|
|
|
-
|
|
|
-const getDetail = async () => {
|
|
|
- loading.value = true
|
|
|
- try {
|
|
|
- // const D = await UserApi.getDetail();
|
|
|
- // detail.deptNum = D.deptNum
|
|
|
- // detail.studentNum = D.studentNum
|
|
|
- // detail.teacherNum = D.teacherNum
|
|
|
-
|
|
|
-
|
|
|
- } finally {
|
|
|
- loading.value = false
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
const getAllApi = async () => {
|
|
|
await Promise.all([
|
|
|
await getDetail(),
|