|
@@ -0,0 +1,199 @@
|
|
|
+import {
|
|
|
+ PropType,
|
|
|
+ defineComponent,
|
|
|
+ nextTick,
|
|
|
+ onMounted,
|
|
|
+ ref,
|
|
|
+ toRefs,
|
|
|
+ watch
|
|
|
+} from 'vue';
|
|
|
+import styles from '../index.module.less';
|
|
|
+import icons from '../icons.json';
|
|
|
+import { Badge, Icon, Image, Tab, Tabs } from 'vant';
|
|
|
+import * as echarts from 'echarts';
|
|
|
+import { IStudentAttendance } from '../type';
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
+import icon_4 from '../image/icon_4.png';
|
|
|
+
|
|
|
+type EChartsOption = echarts.EChartsOption;
|
|
|
+const colors = [
|
|
|
+ {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
|
+ { offset: 0, color: '#02E2DB' },
|
|
|
+ { offset: 1, color: '#01C1B5' }
|
|
|
+ ]),
|
|
|
+ name: '正常',
|
|
|
+ key: 'normalNum',
|
|
|
+ background: 'linear-gradient(180deg, #02E2DB 0%, #01C1B5 100%)'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
|
+ { offset: 0, color: '#5B8FF9' },
|
|
|
+ { offset: 1, color: '#94C2FD' }
|
|
|
+ ]),
|
|
|
+ name: '迟到',
|
|
|
+ key: 'lateNum',
|
|
|
+ background:
|
|
|
+ 'linear-gradient(180deg, rgba(148, 194, 253, 0.85) 0%, rgba(91, 143, 249, 0.85) 100%)'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
|
+ { offset: 0, color: '#FBE031' },
|
|
|
+ { offset: 1, color: '#F6BD16' }
|
|
|
+ ]),
|
|
|
+ name: '请假',
|
|
|
+ key: 'leaveNum',
|
|
|
+ background:
|
|
|
+ 'linear-gradient(180deg, rgba(251,224,49,0.85) 0%, rgba(246,189,22,0.85) 100%)'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
|
+ { offset: 0, color: '#F5A181' },
|
|
|
+ { offset: 1, color: '#E8684A' }
|
|
|
+ ]),
|
|
|
+ name: '旷课',
|
|
|
+ key: 'truantNum',
|
|
|
+ background:
|
|
|
+ 'linear-gradient(180deg, rgba(245,161,129,0.85) 0%, rgba(232,104,74,0.85) 100%)'
|
|
|
+ }
|
|
|
+];
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'Attendance',
|
|
|
+ props: {
|
|
|
+ data: {
|
|
|
+ type: Object as PropType<IStudentAttendance>,
|
|
|
+ default: () => ({})
|
|
|
+ }
|
|
|
+ },
|
|
|
+ emits: ['change'],
|
|
|
+ setup(props, { emit }) {
|
|
|
+ const firstInit = ref(false);
|
|
|
+ const router = useRouter();
|
|
|
+ const { data } = toRefs(props);
|
|
|
+ watch(
|
|
|
+ () => data.value,
|
|
|
+ () => {
|
|
|
+ firstInit.value = true;
|
|
|
+ nextTick(() => {
|
|
|
+ handleInit();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ );
|
|
|
+ let myChart: echarts.ECharts;
|
|
|
+ const handleInit = () => {
|
|
|
+ if (!data.value.attendanceRate) return
|
|
|
+ if (myChart) {
|
|
|
+ myChart.dispose();
|
|
|
+ }
|
|
|
+ const chartDom = document.getElementById('attendanceEcharts')!;
|
|
|
+ myChart = echarts.init(chartDom, {}, { renderer: 'svg' });
|
|
|
+ const option: EChartsOption = {
|
|
|
+ title: {
|
|
|
+ text: `${data.value.attendanceRate}%`,
|
|
|
+ subtext: '出勤率',
|
|
|
+ textAlign: 'center',
|
|
|
+ left: '48%',
|
|
|
+ top: '38%',
|
|
|
+ textStyle: {
|
|
|
+ fontSize: '22px',
|
|
|
+ fontWeight: 'bold',
|
|
|
+ color: '#333',
|
|
|
+ fontFamily: 'DINAlternate-Bold, DINAlternate'
|
|
|
+ },
|
|
|
+ subtextStyle: {
|
|
|
+ fontSize: '12px',
|
|
|
+ color: '#777'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'item',
|
|
|
+ confine: true
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['54%', '70%'],
|
|
|
+ itemStyle: {
|
|
|
+ borderRadius: 2,
|
|
|
+ borderColor: '#fff',
|
|
|
+ borderWidth: 1
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ labelLine: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ avoidLabelOverlap: false,
|
|
|
+ data: colors.map(item => {
|
|
|
+ return {
|
|
|
+ name: item.name,
|
|
|
+ value: data.value[item.key],
|
|
|
+ itemStyle: {
|
|
|
+ color: item.color
|
|
|
+ }
|
|
|
+ };
|
|
|
+ })
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ };
|
|
|
+
|
|
|
+ option && myChart.setOption(option);
|
|
|
+ };
|
|
|
+ return () => (
|
|
|
+ <div class={styles.item}>
|
|
|
+ <div class={styles.top}>
|
|
|
+ <Image class={styles.iconRight} src={icons.right} />
|
|
|
+ <span>学员出勤</span>
|
|
|
+ <Image class={styles.iconLeft} src={icons.left} />
|
|
|
+ </div>
|
|
|
+ <div class={styles.tabsContainer}>
|
|
|
+ <Tabs
|
|
|
+ shrink
|
|
|
+ active={"本周"}
|
|
|
+ onChange={value => {
|
|
|
+ console.log(value, 123);
|
|
|
+ emit('change', value);
|
|
|
+ }}>
|
|
|
+ <Tab name="本周" title="本周"></Tab>
|
|
|
+ <Tab name="本月" title="本月"></Tab>
|
|
|
+ <Tab name="本学期" title="本学期"></Tab>
|
|
|
+ </Tabs>
|
|
|
+ <div
|
|
|
+ class={styles.tagRight}
|
|
|
+ onClick={() => {
|
|
|
+ router.push({
|
|
|
+ path: '/student-manage'
|
|
|
+ });
|
|
|
+ }}>
|
|
|
+ 学员信息 <Icon name="arrow" color="rgba(216,216,216,1)" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ style={{ display: data.value.attendanceRate ? '' : 'none' }}
|
|
|
+ class={styles.attendanceContainer}>
|
|
|
+ <div class={styles.attendanceEcharts} id="attendanceEcharts"></div>
|
|
|
+ <div class={styles.tags}>
|
|
|
+ {colors.map((item, index) => (
|
|
|
+ <div class={styles.tag}>
|
|
|
+ <div
|
|
|
+ class={styles.rect}
|
|
|
+ style={{ background: item.background }}
|
|
|
+ />
|
|
|
+ <div class={styles.des}>{item.name}</div>
|
|
|
+ <span class={styles.tagNum}>{data.value[item.key] || 0}</span>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {!data.value.attendanceRate && (
|
|
|
+ <div class={[styles.gradeContainer, styles.itemEmtry]}>
|
|
|
+ <Image src={icon_4} />
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|