Przeglądaj źródła

Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd

CrazyIter_Bin 3 lat temu
rodzic
commit
c8af526491

+ 11 - 21
TEAMModelOS/ClientApp/src/router/routes.js

@@ -1151,14 +1151,24 @@ export const routes = [{
 				},
 				children: []
 			},
+			// 区级数据
 			{
 				path: 'areaMgmt',
 				name: 'areaMgmt',
-				component: resolve => require(['@/view/areaMgmt/Index.vue'], resolve),
+				component: resolve => require(['@/view/areaMgmt/AreaData.vue'], resolve),
 				meta: {
 					activeName: 'areaMgmt'
 				}
 			},
+			// 学校总览
+			{
+				path: 'schoolMgmt',
+				name: 'schoolMgmt',
+				component: resolve => require(['@/view/areaMgmt/SchoolIndex.vue'], resolve),
+				meta: {
+					activeName: 'schoolMgmt'
+				}
+			},
 			{
 				path: 'spotCheck',
 				name: 'spotCheck',
@@ -1234,26 +1244,6 @@ export const routes = [{
 				},
 				children: []
 			},
-			// // 政策文件管理
-			// {
-			// 	path: 'policyMgt',
-			// 	name: 'policyMgt',
-			// 	component: resolve => require(['@/view/areaMgmt/PolicyMgt.vue'], resolve),
-			// 	meta: {
-			// 		activeName: 'policyMgt'
-			// 	},
-			// 	children: []
-			// },
-			// // 资源内容管理
-			// {
-			// 	path: 'resourceMgt',
-			// 	name: 'resourceMgt',
-			// 	component: resolve => require(['@/view/areaMgmt/ResourceMgt.vue'], resolve),
-			// 	meta: {
-			// 		activeName: 'resourceMgt'
-			// 	},
-			// 	children: []
-			// },
 			// 资源中心
 			{
 				path: 'resource',

+ 582 - 0
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaData.vue

@@ -0,0 +1,582 @@
+<template>
+    <div class="area-data-container">
+        <Loading v-show="isLoading"></Loading>
+        <vuescroll>
+            <!-- 头部统计 -->
+            <div class="top-block-wrap">
+                <div class="content-con-item border-style" v-for="(item,index) in topData" :key="index">
+                    <div class="left-area" :style="{background: item.color, width: '36%'}">
+                        <Icon :type="item.icon" class="icon" style="font-size: 40px; color: rgb(255, 255, 255);"></Icon>
+                    </div>
+                    <div class="right-area" style="width: 64%;">
+                        <div>
+                            <div class="count-to-wrapper">
+                                <p class="content-outer">
+                                    <CountTo class="count-to-count-text count-style" :endVal="item.number" :duration="600"></CountTo>
+                                    <span style="font-size: 28px;" v-if="item.type === 'rate'">%</span>
+                                </p>
+                            </div>
+                            <p>{{item.text}}</p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <!-- 网络研修数据统计 -->
+            <div class="online-train-wrap">
+                <h4 class="block-title">网络研修统计</h4>
+                <div class="online-data-wrap">
+                    <div class="percent-wrap border-style">
+                        <Percent :count="dimension"></Percent>
+                    </div>
+                    <div class="point-wrap border-style">
+                        <AbilityPoint :count="abilityPoint"></AbilityPoint>
+                    </div>
+                </div>
+            </div>
+            <!-- 校本研修数据统计 -->
+            <div class="online-train-wrap">
+                <h4 class="block-title">校本研修统计</h4>
+                <div class="offline-data-wrap">
+                    <div class="offline-data-item border-style" v-for="(item,index) in trainType" :key="index">
+                        <img class="offline-img" :src="trainImgs[index]">
+                        <div style="margin-left:20px;height:fit-content;">
+                            <p class="offline-label" :title="item.label">{{item.label}}</p>
+                            <p class="offline-value"><b>{{item.count || 0}}</b></p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <!-- 学时数据统计 -->
+            <div class="online-train-wrap" style="margin-bottom:40px">
+
+                <h4 class="block-title">学时统计</h4>
+                <div class="hour-data-wrap">
+                    <div class="hour-data-item border-style" v-for="(item,index) in hourData" :key="index">
+                        <p class="hour-data-title">
+                            {{item.name}}
+                            <span class="hour-value">({{item.total}}学时)</span>
+                        </p>
+                        <div class="hour-chart">
+                            <HourProg :count="[item.complete,item.going,item.uncomplete]"></HourProg>
+                            <p class="legend-item">
+                                <span>
+                                    未开始:{{item.uncomplete}}人
+                                </span>
+                            </p>
+                            <p class="legend-item">
+                                <span>
+                                    进行中:{{item.going}}人
+                                </span>
+                            </p>
+                            <p class="legend-item">
+                                <span>
+                                    已完成:{{item.complete}}人
+                                </span>
+                            </p>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <!-- 学校概览 -->
+            <div class="online-train-wrap" style="margin-bottom:40px">
+                <div>
+                    <h4 class="block-title">学校总览</h4>
+                    <Button class="export-data-wrap" type="primary" icon="md-cloud-download">
+                        导出数据
+                    </Button>
+                    <Input search placeholder="搜索学校" class="school-search" />
+                </div>
+
+                <div class="school-data-wrap">
+                    <div class="school-data-item border-style" v-for="(item,index) in schoolList" :key="index">
+                        <img class="school-img" :src="item.picture">
+                        <div style="margin-left:20px;height:fit-content;">
+                            <p class="school-name" :title="item.label">{{item.name}}</p>
+                            <p class="school-value">
+                                <span>参训人数:</span>
+                                <span>68人</span>
+                            </p>
+                            <p class="school-value">
+                                <span>完成人数:</span>
+                                <span>48人</span>
+                            </p>
+                        </div>
+                        <span class="to-school-detail">
+                            更多>>>
+                        </span>
+                    </div>
+                </div>
+            </div>
+        </vuescroll>
+    </div>
+</template>
+<script>
+import Percent from '@/view/statistics/Percent.vue'
+import AbilityPoint from '@/view/statistics/AbilityPoint.vue'
+import HourProg from './HourProg.vue'
+import CountTo from 'vue-count-to'
+export default {
+    components: {
+        Percent, AbilityPoint, HourProg, CountTo
+    },
+    data() {
+        return {
+            schoolList: [],
+            topData: [
+                {
+                    icon: 'ios-people',
+                    color: '#2d8cf0',
+                    number: 281,
+                    text: '学校数量',
+                    type: 'num'
+                },
+                {
+                    icon: 'md-cube',
+                    color: '#2db7f5',
+                    number: 3021,
+                    text: '教师人数',
+                    type: 'num'
+                },
+                {
+                    icon: 'md-bookmark',
+                    color: '#5cadff',
+                    number: 2890,
+                    text: '参训人数',
+                    type: 'num'
+                },
+                {
+                    icon: 'md-thumbs-up',
+                    color: '#ff9900',
+                    number: 83,
+                    text: '参训率',
+                    type: 'rate'
+                },
+                {
+                    icon: 'md-checkmark-circle',
+                    color: '#19be6b',
+                    number: 13,
+                    text: '完成率',
+                    type: 'rate'
+                }
+
+            ],
+            schoolInfo: undefined,
+            isLoading: false,
+            dimension: [],
+            abilityPoint: [],
+            offlineData: [
+                {
+                    label: '教研组',
+                    value: 0
+                }
+            ],
+            trainType: [],
+            trainImgs: [
+                'https://teammodelstorage.blob.core.chinacloudapi.cn/0-public/image/%E4%BF%A1%E6%81%AF%E5%8C%96%E6%95%99%E5%AD%A6%E6%A1%88%E4%BE%8B.png',
+                'https://teammodelstorage.blob.core.chinacloudapi.cn/0-public/image/%E4%B8%93%E5%AE%B6%E4%B8%93%E9%A2%98%E5%9F%B9%E8%AE%AD.png',
+                'https://teammodelstorage.blob.core.chinacloudapi.cn/0-public/image/%E5%90%8C%E8%AF%BE%E5%BC%82%E6%9E%84.png',
+                'https://teammodelstorage.blob.core.chinacloudapi.cn/0-public/image/%E5%90%8C%E8%AF%BE%E5%90%8C%E6%9E%84.png',
+                'https://teammodelstorage.blob.core.chinacloudapi.cn/0-public/image/%E6%A0%A1%E6%9C%AC2.0%E5%9F%B9%E8%AE%AD.png'
+            ],
+            hourData: [
+                {
+                    name: '线上研修',
+                    total: 20,
+                    complete: 0,
+                    going: 0,
+                    uncomplete: 0
+                },
+                {
+                    name: '校本研修',
+                    total: 10,
+                    complete: 0,
+                    going: 0,
+                    uncomplete: 0
+                },
+                {
+                    name: '应用考核',
+                    total: 15,
+                    complete: 0,
+                    going: 0,
+                    uncomplete: 0
+                },
+                {
+                    name: '课堂实录',
+                    total: 5,
+                    complete: 0,
+                    going: 0,
+                    uncomplete: 0
+                }
+            ]
+        }
+    },
+    methods: {
+        returnList() {
+            this.$router.push({
+                name: 'areaMgmt'
+            })
+        },
+        findTotalData() {
+            this.isLoading = true
+            let params = {
+                school: this.schoolInfo.id
+            }
+            this.$api.ability.FindTotalData(params).then(
+                res => {
+                    if (!res.error) {
+                        let deData = this.$GLOBAL.DIMENSIONS()
+                        // 能力点统计
+                        res.abilityCount.forEach(item => {
+                            item.percent = (item.count * 100 / res.subCount).toFixed(1) + '%'
+                            let d = deData.find(i => {
+                                return i.code == item.dimension
+                            })
+                            if (d) {
+                                item.dimensionName = d.val
+                            }
+                        })
+                        this.abilityPoint = res.abilityCount
+
+                        // 能力维度统计
+                        res.dimensionCount.forEach(item => {
+                            let d = deData.find(i => {
+                                return i.code == item.dimension
+                            })
+                            if (d) {
+                                item.name = d.val
+                            }
+                        })
+                        this.dimension = res.dimensionCount
+
+                        //学时数据统计
+                        res.groupMembers.forEach(item => {
+                            // 线上研修
+                            if (item.onlineTime == 0) {
+                                this.hourData[0].uncomplete++
+                            } else if (item.onlineTime >= 20) {
+                                this.hourData[0].complete++
+                            } else {
+                                this.hourData[0].going++
+                            }
+                            // 校本研修
+                            if (item.offlinelTime == 0) {
+                                this.hourData[1].uncomplete++
+                            } else if (item.onlineTime >= 10) {
+                                this.hourData[1].complete++
+                            } else {
+                                this.hourData[1].going++
+                            }
+                            // 应用考核
+                            if (item.schoolScoreTime == 0) {
+                                this.hourData[2].uncomplete++
+                            } else if (item.onlineTime >= 15) {
+                                this.hourData[2].complete++
+                            } else {
+                                this.hourData[2].going++
+                            }
+                            // 课堂实录
+                            if (item.classVideoTime == 0) {
+                                this.hourData[3].uncomplete++
+                            } else if (item.onlineTime >= 5) {
+                                this.hourData[3].complete++
+                            } else {
+                                this.hourData[3].going++
+                            }
+                        })
+                    }
+                },
+                err => {
+
+                }
+            ).finally(() => {
+                this.isLoading = false
+            })
+        },
+        findTrainList() {
+            let params = {
+                code: this.schoolInfo.id
+            }
+            this.$api.train.findTrainList(params).then(
+                res => {
+                    console.log(res)
+                    this.trainType = this.$GLOBAL.TRAIN_TYPE()
+                    res.studies.forEach(item => {
+                        this.trainType[item.type - 1].count = this.trainType[item.type - 1].count || 0
+                        this.trainType[item.type - 1].count++
+                    })
+                    this.trainType.splice(this.trainType.length - 1, 1)
+                },
+                err => {
+                }
+            )
+        }
+    },
+    created() {
+        this.schoolInfo = {}
+        this.schoolInfo.id = 'hbcn'
+        this.findTotalData()
+        this.findTrainList()
+        this.schoolList = this.$store.state.user.userProfile.schools
+    },
+    watch: {
+
+    }
+}
+</script>
+<style lang="less" scoped>
+.export-data-wrap {
+    float: right;
+    // margin-top: 8px;
+    cursor: pointer;
+}
+.school-search {
+    float: right;
+    width: 240px;
+    border-radius: 20px;
+    margin-right: 20px;
+}
+.border-style {
+    box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
+    border-radius: 4px;
+}
+.hour-chart {
+    // height: 200px;
+    text-align: center;
+    .legend-item {
+        font-size: 12px;
+        margin-top: 5px;
+        &::before {
+            content: " ";
+            display: inline-block;
+            width: 15px;
+            height: 8px;
+            // background: red;
+            border-radius: 2px;
+            margin-right: 10px;
+            margin-left: 15px;
+        }
+        &:nth-child(2)::before {
+            background: #ed4014;
+        }
+        &:nth-child(3)::before {
+            background: #ff9900;
+        }
+        &:nth-child(4)::before {
+            background: #19be6b;
+        }
+    }
+}
+.hour-data-item {
+    width: 23%;
+    background: white;
+    padding-bottom: 20px;
+}
+.hour-data-wrap {
+    display: flex;
+    justify-content: space-between;
+    margin-top: 20px;
+    font-size: 16px;
+    .hour-value {
+        font-weight: bold;
+        color: #1e1f24;
+        font-size: 16px;
+    }
+    .hour-data-title {
+        text-align: center;
+        // background: #f9f9f9;
+        padding: 10px 0px;
+    }
+}
+.offline-data-wrap {
+    margin-bottom: 20px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-top: 20px;
+}
+.offline-data-item {
+    // margin: 10px;
+    display: flex;
+    align-items: center;
+    background: white;
+    padding: 15px 30px;
+    border-radius: 5px;
+    .offline-label {
+        width: 120px;
+        text-overflow: ellipsis;
+        overflow: hidden;
+        white-space: nowrap;
+        color: #1e1f24;
+        cursor: pointer;
+    }
+    .offline-value {
+        margin-top: 5px;
+        font-size: 30px;
+        font-weight: bold;
+        color: #1e1f24;
+    }
+}
+.school-data-wrap {
+    margin-bottom: 20px;
+    display: flex;
+    // justify-content: space-between;
+    align-items: center;
+    margin-top: 20px;
+}
+.school-data-item {
+    position: relative;
+    display: flex;
+    align-items: center;
+    background: white;
+    padding: 20px 40px 20px 30px;
+    margin-right: 30px;
+    border-radius: 5px;
+    transition: all 0.2s ease 0s;
+    &:hover {
+        box-shadow: 0 26px 40px -24px #aaa;
+        transform: translateY(-4px);
+    }
+    .school-name {
+        width: 120px;
+        text-overflow: ellipsis;
+        overflow: hidden;
+        white-space: nowrap;
+        color: #17233d;
+        cursor: pointer;
+        font-weight: 600;
+        font-size: 15px;
+    }
+    .school-value {
+        margin-top: 5px;
+        font-size: 12px;
+        font-weight: bold;
+        color: #808695;
+    }
+    .to-school-detail {
+        position: absolute;
+        right: 5px;
+        bottom: 5px;
+        color: #2d8cf0;
+        font-size: 12px;
+        cursor: pointer;
+    }
+}
+.offline-img {
+    width: 80px;
+    height: 80px;
+    border-radius: 10px;
+}
+.school-img {
+    width: 80px;
+    height: 80px;
+    border-radius: 10px;
+}
+.area-data-container {
+    width: 100%;
+    height: 100%;
+    padding: 15px;
+    background: #f7f7f7;
+}
+.school-base-info {
+    border-radius: 5px;
+    width: 100%;
+    background: white;
+    padding: 25px 15px;
+    // box-shadow: 0px 4px 4px 1px #f0f0f0;
+    display: flex;
+    position: relative;
+    align-items: center;
+}
+.return-list {
+    position: absolute;
+    right: 80px;
+    top: 35px;
+    color: #1cc0f3;
+    font-weight: bold;
+    cursor: pointer;
+}
+.school-info-item {
+    margin-top: 10px;
+    .info-label {
+        color: #a0a0a0;
+    }
+    .info-value {
+        color: #5cadff;
+        font-weight: 600;
+    }
+}
+.online-train-wrap {
+    border-radius: 5px;
+    width: 100%;
+    // background: white;
+    padding: 0px 20px;
+    // box-shadow: 0px 4px 4px 1px #f0f0f0;
+    margin-top: 50px;
+}
+.block-title {
+    border-left: 6px solid #1cc0f3;
+    padding-left: 15px;
+    font-size: 18px;
+    line-height: 16px;
+    color: #414749;
+    margin-bottom: 0px;
+}
+.online-data-wrap {
+    display: flex;
+    margin-top: 15px;
+}
+.percent-wrap {
+    width: fit-content;
+    padding: 30px 0px;
+    background: white;
+    // margin-left: 30px;
+}
+.point-wrap {
+    width: fit-content;
+    padding: 30px 0px;
+    background: white;
+    margin-left: 20px;
+    flex: 1;
+}
+.top-block-wrap {
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+    margin-top: 10px;
+    padding: 0px 20px 0px 20px;
+    // background: white;
+    // border-radius: 5px;
+}
+.content-con-item {
+    width: 18%;
+    height: 110px;
+    position: relative;
+    border-radius: 2px;
+    overflow: hidden;
+    .left-area {
+        float: left;
+        height: 100%;
+        display: table;
+        text-align: center;
+        .icon {
+            display: table-cell;
+            vertical-align: middle;
+        }
+    }
+    .right-area {
+        background: white;
+        float: left;
+        height: 100%;
+        display: table;
+        text-align: center;
+        .count-style {
+            font-size: 50px;
+        }
+    }
+}
+</style>
+<style lang="less">
+.school-search .ivu-input {
+    // border-radius: 20px;
+}
+</style>

+ 10 - 0
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaLayout.vue

@@ -120,6 +120,16 @@ export default {
                     menuName: 'areaMgmt',
                     child: []
                 },
+                // {
+                //     icon: 'iconfont icon-shujufenxi',
+                //     name: '学校总览',
+                //     router: '/area/schoolMgmt',
+                //     tag: '',
+                //     role: '',
+                //     permission: '',
+                //     menuName: 'schoolMgmt',
+                //     child: []
+                // },
                 {
                     icon: 'iconfont icon-basic-setting',
                     name: '研修总览',

TEAMModelOS/ClientApp/src/view/areaMgmt/Index.less → TEAMModelOS/ClientApp/src/view/areaMgmt/SchoolIndex.less


+ 1 - 1
TEAMModelOS/ClientApp/src/view/areaMgmt/Index.vue

@@ -65,4 +65,4 @@ export default {
 }
 </script>
 
-<style lang="less" src="./Index.less" scoped></style>
+<style lang="less" src="./SchoolIndex.less" scoped></style>