Quellcode durchsuchen

新增首页、课程详情页及功能

zengyicheng vor 2 Jahren
Ursprung
Commit
5a8ad4ddce

+ 9 - 0
src/api/courseDetail.js

@@ -1,2 +1,11 @@
 // axios
 import request from '@/utils/request'
+// 获取课程信息
+export function getCourseDetail(params) {
+    return request({
+        url: '/selectCourseDetail2',
+        method: 'get',
+        params,
+        hideloading: false
+    })
+}

+ 19 - 0
src/api/home.js

@@ -1,2 +1,21 @@
 // axios
 import request from '@/utils/request'
+// 获取所有分类
+export function selectAllType(params) {
+    return request({
+        url: '/selectAllType',
+        method: 'get',
+        params,
+        hideloading: false
+    })
+}
+
+//查询课程
+export function selectTypeCourse2(params) {
+    return request({
+        url: '/selectTypeCourse2',
+        method: 'get',
+        params,
+        hideloading: false
+    })
+}

BIN
src/assets/images/home/analysisIcon.png


BIN
src/assets/images/home/checkIcon.png


BIN
src/assets/images/home/courseEvaIcon.png


BIN
src/assets/images/home/evaIcon.png


BIN
src/assets/images/home/jd.png


BIN
src/assets/images/home/people.png


BIN
src/assets/images/home/search.png


BIN
src/assets/images/home/wheel.png


+ 111 - 0
src/views/courseDetail/components/courseChap.vue

@@ -0,0 +1,111 @@
+<template>
+  <div class="chapBox">
+    <div class="chapTop">
+      <div :class="{ isStepCss: isStep == 0 }" @click="isStep = 0">项目详情</div>
+      <div :class="{ isStepCss: isStep == 1 }" @click="isStep = 1">任务阶段</div>
+    </div>
+    <div v-if="isStep == 0" class="briefCss">
+      {{ brief ? brief : '暂无详情' }}
+    </div>
+    <div v-if="isStep == 1" class="courseJdBox">
+      <div class="blue_box_one" v-for="(item, index) in chInfo" :key="index" @click="goCourse">
+        <div>第{{ index + 1 }}阶段</div>
+        <div :title="item.dyName">{{ item.dyName }}</div>
+        <div>{{ item.chapterInfo[0].taskJson.length }}个任务</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    chInfo: {
+      type: Array,
+      default: []
+    },
+    brief: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      isStep: 0
+    }
+  },
+  methods: {
+    goCourse() {
+      this.$emit('goCourse')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.chapBox {
+  margin-top: 15px;
+  background: #fff;
+  .chapTop {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: nowrap;
+    align-items: center;
+    font-size: 16px;
+    padding: 10px 0 10px 15px;
+    > div {
+      color: #afafaf;
+      padding: 0 0 5px 0;
+      margin-right: 30px;
+    }
+    .isStepCss {
+      color: #000;
+      font-weight: bold;
+      border-bottom: 3px solid #4f86d6;
+    }
+  }
+  .briefCss {
+    width: 90%;
+    text-indent: 30px;
+    font-size: 15px;
+    margin: 10px auto;
+    height: 300px;
+    overflow: auto;
+  }
+  .courseJdBox {
+    width: 100%;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    align-items: flex-start;
+    justify-content: flex-start;
+    padding: 0 0 0 30px;
+    height: 300px;
+    overflow: auto;
+    .blue_box_one {
+      width: 150px;
+      height: 150px;
+      background-image: linear-gradient(90deg, #477cd7, #65b9fc);
+      display: flex;
+      flex-direction: column;
+      flex-wrap: nowrap;
+      align-items: center;
+      justify-content: center;
+      color: #fff;
+      border-radius: 12px;
+      margin: 0 15px 10px 0;
+      > div:nth-child(1) {
+        font-size: 16px;
+        font-weight: bold;
+      }
+      > div:nth-child(2) {
+        max-width: 100px;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        word-break: break-word;
+      }
+    }
+  }
+}
+</style>

+ 167 - 0
src/views/courseDetail/components/courseMessage.vue

@@ -0,0 +1,167 @@
+<template>
+  <div class="courseBox">
+    <div class="courseTop">
+      <div class="courseImg">
+        <img
+          :src="
+            cDetail.cover != null && cDetail.cover != ''
+              ? JSON.parse(cDetail.cover).length > 0
+                ? JSON.parse(cDetail.cover)[0].url
+                : mr
+              : mr
+          "
+          alt=""
+        />
+      </div>
+      <div class="courseMes">
+        <div class="cFirst">
+          <div class="cTitle">{{ cDetail.title }}</div>
+          <div class="jd">{{ cInfo.length }}阶段</div>
+          <div class="jd">{{ rwLength }}任务</div>
+        </div>
+        <div class="cSecond">
+          <div class="cType" v-if="cType.length">
+            <div v-for="(item, index) in cType" :key="index">
+              <span>{{ item + ':' }}</span>
+              <span v-for="(item2, index2) in cJson[item]" :key="index2">{{ item2 }}</span>
+            </div>
+          </div>
+          <div>
+            创建者:<span>{{ cDetail.username }}</span>
+          </div>
+        </div>
+        <div class="Tname" v-if="tName.length > 0" @click="TnameCheck = !TnameCheck">
+          协同人员:<span v-for="(tname, tIndex) in TnameCheck ? tName : tName.slice(0, 6)" :key="tIndex">{{
+            tname
+          }}</span
+          ><span v-if="!TnameCheck && tName.length > 6">更多....</span>
+        </div>
+        <div class="people">
+          <div class="man">
+            <img src="../../../assets/images/home/people.png" alt />
+          </div>
+          <div class="person">{{ cDetail.vcount != null ? cDetail.vcount : 0 }}人</div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    cDetail: {
+      type: Object,
+      default: {}
+    },
+    cInfo: {
+      type: Array,
+      default: []
+    },
+    rwLength: {
+      type: Number,
+      default: 0
+    },
+    cType: {
+      type: Array,
+      default: []
+    },
+    cJson: {
+      type: Object,
+      default: {}
+    },
+    tName: {
+      type: Array,
+      default: []
+    }
+  },
+  data() {
+    return {
+      TnameCheck: false,
+      mr: 'https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/noBanner1656409780264.jpg'
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@mixin display() {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+}
+$pad: 0 0 10px 0;
+.courseBox {
+  margin-top: 50px;
+  height: 100%;
+  .courseTop {
+    .courseImg {
+      width: 100%;
+      height: 200px;
+      > img {
+        width: 100%;
+        height: 100%;
+        object-fit: cover;
+      }
+    }
+    .courseMes {
+      background: #fff;
+      padding: 10px 0 0 15px;
+      .cFirst {
+        @include display();
+        padding: $pad;
+        .cTitle {
+          font-size: 18px;
+          font-weight: bold;
+          max-width: 200px;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          word-break: break-word;
+          margin-right: 10px;
+        }
+        .jd {
+          background: #4a9eed;
+          color: #fff;
+          height: 20px;
+          line-height: 20px;
+          text-align: center;
+          border-radius: 10px;
+          padding: 0 10px;
+          margin: 0 10px 0 0;
+        }
+      }
+      .cSecond {
+        @include display();
+        padding: $pad;
+        .cType {
+          margin-right: 10px;
+        }
+      }
+      .Tname {
+        padding: $pad;
+        > span {
+          margin: 0px 5px;
+        }
+      }
+      .people {
+        padding: $pad;
+        @include display();
+        .man {
+          width: 15px;
+          height: 15px;
+          > img {
+            width: 100%;
+            height: 100%;
+          }
+        }
+        .person {
+          font-size: 14px;
+          margin-left: 10px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 94 - 8
src/views/courseDetail/index.vue

@@ -1,30 +1,116 @@
 <template>
   <div>
     <head-bar @back="back">
-      <template #title>
-        <div>
-          课程名字
-        </div>
-      </template>
+      <template #title> </template>
     </head-bar>
+    <div class="courseBoxMes">
+      <course-message
+        :cDetail="courseDetail"
+        :cInfo="chapInfo"
+        :rwLength="rw"
+        :cType="courseType"
+        :cJson="courseTypeJson"
+        :tName="Tname"
+      ></course-message>
+      <course-chap :chInfo="chapInfo" :brief="courseDetail.brief" @goCourse="goToStudy"></course-chap>
+    </div>
+    <div class="studyCss">
+      <div style="stuButton" @click="goToStudy">点击学习</div>
+    </div>
   </div>
 </template>
 
 <script>
+import { getCourseDetail } from '@/api/courseDetail'
 import headBar from '@/components/headBar.vue'
+import courseMessage from './components/courseMessage.vue'
+import courseChap from './components/courseChap.vue'
 export default {
   components: {
-    headBar
+    headBar,
+    courseMessage,
+    courseChap
   },
   data() {
-    return {}
+    return {
+      courseid: this.$route.query.courseid,
+      courseDetail: {},
+      courseTypeJson: {},
+      chapInfo: [],
+      courseType: [],
+      Tname: [],
+      rw: 0
+    }
   },
   methods: {
     back() {
       this.$router.push({ path: '/home' })
+    },
+    goToStudy() {
+      this.$router.push({ path: '/course', query: { courseid: this.courseid } })
+    },
+    getCourse() {
+      const params = {
+        courseId: this.courseid
+      }
+      getCourseDetail(params)
+        .then(res => {
+          this.courseDetail = res[0][0]
+          var a = res[0]
+          var b = res[1]
+          var c = res[2]
+          for (var i = 0; i < b.length; i++) {
+            for (var j = 0; j < a.length; j++) {
+              if (b[i].id == a[j].pid) {
+                if (!this.courseTypeJson[b[i].name]) {
+                  this.courseType.push(b[i].name)
+                  this.courseTypeJson[b[i].name] = []
+                }
+                this.courseTypeJson[b[i].name].push(a[j].name)
+              }
+            }
+          }
+          this.Tname = []
+          for (var k = 0; k < c.length; k++) {
+            this.Tname.push(c[k].name)
+          }
+          this.chapInfo = JSON.parse(this.courseDetail.chapters)
+          for (var z = 0; z < this.chapInfo.length; z++) {
+            this.rw += this.chapInfo[z].chapterInfo[0].taskJson.length
+          }
+        })
+        .catch(err => {
+          console.error(err)
+        })
     }
+  },
+  mounted() {
+    this.getCourse()
   }
 }
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.courseBoxMes {
+  background: #e8ebf2;
+  height: 100%;
+}
+.studyCss {
+  height: 60px;
+  border-top: 1px solid #dddddd;
+  position: fixed;
+  width: 100%;
+  bottom: 0;
+  background: #fff;
+  > div {
+    width: 90%;
+    height: 40px;
+    margin: 10px auto;
+    text-align: center;
+    color: #fff;
+    background-image: linear-gradient(90deg, #477cd7, #65b9fc);
+    line-height: 40px;
+    border-radius: 10px;
+  }
+}
+</style>

+ 203 - 0
src/views/home/components/classFilter.vue

@@ -0,0 +1,203 @@
+<template>
+  <div class="classBox">
+    <div class="allType">
+      <div :class="{ isClickCss: isClick == 0 }" @click="cleanAllType">全部</div>
+      <div v-for="(item, index) in CourseType[0]" :key="index" class="tNameBox">
+        <div :class="{ isClickCss: isClick == index + 1 }" @click="typeClick(item.id)">{{ item.name }}</div>
+      </div>
+    </div>
+    <div v-if="isClick != 0 && isOpen == true">
+      <div class="childTypeBox">
+        <div
+          v-for="(item1, index1) in CourseTypeJson[cTypeId]"
+          :key="index1"
+          :class="{ iscTypeClickCss: CourseChildType[cTypeId] == item1.id }"
+        >
+          <div @click="chooseChildType(item1.id)">
+            {{ item1.name }}
+          </div>
+          <div v-if="CourseChildType[cTypeId] == item1.id" class="checkIcon">
+            <img src="../../../assets/images/home/checkIcon.png" alt="" />
+          </div>
+        </div>
+      </div>
+    </div>
+    <div v-if="isOpen == true" @click="isOpen = false"></div>
+  </div>
+</template>
+
+<script>
+import { selectAllType } from '@/api/home'
+import { mapGetters } from 'vuex'
+export default {
+  data() {
+    return {
+      isClick: 0,
+      CourseType: [],
+      CourseTypeJson: {},
+      cTypeId: '',
+      CourseChildType: {},
+      zoneClass: [],
+      isOpen: false
+    }
+  },
+  computed: {
+    ...mapGetters(['userinfo'])
+  },
+  methods: {
+    typeClick(id) {
+      for (var i = 0; i < this.CourseType[0].length; i++) {
+        if (id == this.CourseType[0][i].id) {
+          this.isOpen = true
+          this.isClick = i + 1
+        }
+      }
+      this.cTypeId = id
+    },
+    chooseChildType(id) {
+      if (this.CourseChildType[this.cTypeId] == id) {
+        this.CourseChildType[this.cTypeId] = ''
+      } else {
+        this.CourseChildType[this.cTypeId] = id
+      }
+      this.$forceUpdate()
+      this.getAll()
+    },
+    cleanAllType() {
+      this.isClick = 0
+      this.CourseChildType = {}
+      this.getAll()
+    },
+    getAll() {
+      this.$emit('getAll', this.CourseChildType)
+    },
+    getType() {
+      const params = {
+        org: this.userinfo.org && this.userinfo.org != '' ? this.userinfo.org : '',
+        oid: this.userinfo.organizeid && this.userinfo.organizeid != '' ? this.userinfo.organizeid : ''
+      }
+      selectAllType(params)
+        .then(res => {
+          this.CourseType = res
+          for (var i = 0; i < res[0].length; i++) {
+            if (!this.CourseTypeJson[res[0][i].id]) {
+              this.CourseTypeJson[res[0][i].id] = []
+            }
+            if (this.userinfo.organizeid == '69893dca-1d47-11ed-8c78-005056b86db5') {
+              if (res[0][i].name == '栏目') {
+                this.CourseType[0][i].name = '主题'
+              }
+            }
+
+            if (res[2].length == 0 && res[3].length == 0) {
+              for (var j = 0; j < res[1].length; j++) {
+                if (res[0][i].id == res[1][j].pid) {
+                  if (!this.CourseTypeJson[res[0][i].id]) {
+                    this.CourseTypeJson[res[0][i].id] = []
+                  }
+                  this.CourseTypeJson[res[0][i].id].push(res[1][j]) // 去除公共分类
+                }
+              }
+            } else {
+              if (res[2].length > 0) {
+                for (var j = 0; j < res[2].length; j++) {
+                  if (res[0][i].id == res[2][j].pid) {
+                    this.CourseTypeJson[res[0][i].id].push(res[2][j]) // 去除公共分类
+                  }
+                }
+              }
+              if (res[3].length > 0) {
+                for (var j = 0; j < res[3].length; j++) {
+                  if (res[0][i].id == res[3][j].pid) {
+                    this.CourseTypeJson[res[0][i].id].push(res[3][j]) // 去除公共分类
+                  }
+                }
+              }
+            }
+          }
+        })
+        .catch(err => {
+          console.log(err)
+        })
+    }
+  },
+  mounted() {
+    this.getType()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.classBox {
+  padding-bottom: 10px;
+  position: relative;
+  > div:nth-child(2) {
+    position: absolute;
+    width: 100%;
+    background: #fff;
+    z-index: 9;
+  }
+  > div:nth-child(3) {
+    z-index: 5;
+    height: 100%;
+    width: 100%;
+    position: absolute;
+    min-height: 700px;
+  }
+  .allType {
+    margin-top: 60px;
+    display: flex;
+    width: 100%;
+    flex-direction: row;
+    flex-wrap: nowrap;
+    align-items: center;
+    justify-content: flex-start;
+    padding-top: 5px;
+    > div:nth-child(1) {
+      font-weight: bold;
+    }
+    > div:nth-child(1),
+    .tNameBox > div {
+      padding: 0 8px 3px 8px;
+      margin: 0 10px;
+      font-size: 14px;
+    }
+    .tNameBox > div {
+      color: #8c8c8c;
+    }
+    .isClickCss {
+      border-bottom: 3px solid #5089d6;
+    }
+  }
+  .childTypeBox {
+    width: 97%;
+    height: 250px;
+    margin: 0 auto;
+    box-shadow: 0 2px 10px 0px #ccc;
+    overflow: auto;
+    > div {
+      font-size: 15px;
+      padding: 10px;
+      border-bottom: 1px solid #ededed;
+      position: relative;
+    }
+    > div:last-child {
+      border: none;
+    }
+    .iscTypeClickCss {
+      background: #e7f3ff;
+    }
+    > div > .checkIcon {
+      width: 20px;
+      height: 20px;
+      position: absolute;
+      top: 10px;
+      right: 20px;
+    }
+    > div > .checkIcon > img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+}
+</style>

+ 140 - 0
src/views/home/components/courseAll.vue

@@ -0,0 +1,140 @@
+<template>
+  <div class="courseBox" v-if="courseList.length > 0">
+    <div v-for="(c, cIndex) in courseList" :key="cIndex" class="courseItem" @click="goTo(c.courseId)">
+      <div class="cDetail">
+        <div class="courseImg">
+          <img :src="c.cover ? JSON.parse(c.cover)[0].url : require('../../../assets/images/home/wheel.png')" alt="" />
+        </div>
+        <div class="cRight">
+          <div>{{ c.title }}</div>
+          <div>创建者:{{ c.uname }}</div>
+          <div class="jdBox">
+            <div class="jdImg"><img src="../../../assets/images/home/jd.png" alt="" /></div>
+            <div>{{ JSON.parse(c.chapters).length }}阶段</div>
+          </div>
+          <div>{{ c.typename ? c.typename : '暂无分类' }}</div>
+        </div>
+      </div>
+      <div class="cButtonBox" v-show="false">
+        <div class="cButton">
+          <div class="bImg"><img src="../../../assets/images/home/courseEvaIcon.png" alt="" /></div>
+          <div>评课</div>
+        </div>
+        <div class="cButton">
+          <div class="bImg"><img src="../../../assets/images/home/evaIcon.png" alt="" /></div>
+          <div>评价</div>
+        </div>
+        <div class="cButton">
+          <div class="bImg"><img src="../../../assets/images/home/analysisIcon.png" alt="" /></div>
+          <div>分析</div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    courseList: {
+      type: Array,
+      default: []
+    }
+  },
+  methods: {
+    goTo(cid) {
+      this.$router.push({ path: '/courseDetail', query: { courseid: cid } })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.courseBox {
+  background: #e8ebf2;
+  padding: 15px 0;
+  .courseItem {
+    background: #fff;
+    width: 90%;
+    margin: 0 auto 15px;
+    border-radius: 10px;
+    box-shadow: 0 0 10px 1px #dcdfe6;
+    padding: 10px;
+    .cDetail {
+      display: flex;
+      flex-direction: row;
+      flex-wrap: nowrap;
+      align-items: flex-start;
+      .courseImg {
+        width: 110px;
+        height: 80px;
+        > img {
+          width: 100%;
+          height: 100%;
+          border-radius: 5px;
+        }
+      }
+      .cRight {
+        margin-left: 20px;
+        > div {
+          margin: 2px 0;
+        }
+        > div:nth-child(1) {
+          font-size: 18px;
+          font-weight: bold;
+          max-width: 225px;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          word-break: break-word;
+        }
+        .jdBox {
+          display: flex;
+          flex-direction: row;
+          flex-wrap: nowrap;
+          align-items: center;
+          justify-content: flex-start;
+          .jdImg {
+            width: 15px;
+            margin-top: 1px;
+            height: 15px;
+            > img {
+              width: 100%;
+              height: 100%;
+            }
+          }
+        }
+      }
+    }
+    .cButtonBox {
+      width: 100%;
+      display: flex;
+      flex-direction: row;
+      flex-wrap: nowrap;
+      align-items: center;
+      padding: 10px 0 0 0;
+      .cButton {
+        width: 100px;
+        height: 30px;
+        margin: 0 10px 0 0;
+        display: flex;
+        flex-direction: row;
+        flex-wrap: nowrap;
+        align-items: center;
+        border: 1px solid #587ff3;
+        color: #587ff3;
+        border-radius: 5px;
+        justify-content: center;
+        .bImg {
+          width: 20px;
+          height: 20px;
+          > img {
+            width: 100%;
+            height: 100%;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 92 - 4
src/views/home/index.vue

@@ -2,21 +2,109 @@
   <div>
     <head-bar :isBack="false">
       <template #title>
-        <div>
-          搜索框样式
+        <div style="width: 100%">
+          <div class="rightSearch">
+            <div class="searchImg" @click="selectAll1">
+              <img src="../../assets/images/home/search.png" alt="" />
+            </div>
+            <el-input v-model="courseName" auto-complete="off" placeholder="搜索课程..."></el-input>
+          </div>
         </div>
       </template>
     </head-bar>
+    <class-filter @getAll="selectAll"> </class-filter>
+    <course-all :courseList="zoneClass"></course-all>
   </div>
 </template>
 
 <script>
+import { selectTypeCourse2 } from '@/api/home'
+import { mapGetters } from 'vuex'
 import headBar from '@/components/headBar.vue'
+import classFilter from './components/classFilter.vue'
+import courseAll from './components/courseAll.vue'
 export default {
   components: {
-    headBar
+    headBar,
+    classFilter,
+    courseAll
+  },
+  data() {
+    return {
+      courseName: '',
+      zoneClass: []
+    }
+  },
+  computed: {
+    ...mapGetters(['userinfo'])
+  },
+  methods: {
+    selectAll1(){
+      this.selectAll({})
+    },
+    selectAll(tList) {
+      var a = '',b = '',c = ''
+      if (tList != undefined) {
+        var typeList = Object.values(tList);
+        a = typeList[0]
+        b = typeList[2]
+        c = typeList[1]
+      }
+      const params = {
+        uid: this.userinfo.userid,
+        oid: this.userinfo.organizeid,
+        typea: a != undefined ? a : '',
+        typeb: b != undefined ? a : '',
+        typec: '',
+        typed: c != undefined ? a : '',
+        typeE: '',
+        cu: '',
+        cn: this.courseName,
+        classid: this.userinfo.classid,
+        org: this.userinfo.org,
+        page: 1,
+        pageSize: 10
+      }
+      selectTypeCourse2(params)
+        .then(res => {
+          this.zoneClass = res[0]
+        })
+        .catch(err => {
+          console.log(err)
+        })
+    }
+  },
+  mounted() {
+    this.selectAll()
   }
 }
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+/deep/.rightSearch {
+  display: flex;
+  flex-direction: row;
+  width: 100%;
+  height: 30px;
+  position: relative;
+
+  .searchImg {
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    z-index: 9;
+    top: 5px;
+    left: 5px;
+    > img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  .el-input__inner {
+    width: 100%;
+    height: 30px;
+    text-indent: 15px;
+    line-height: 30px;
+  }
+}
+</style>

+ 9 - 0
src/views/layouts/index.vue

@@ -46,3 +46,12 @@ export default {
   }
 }
 </script>
+<style lang="scss" scoped>
+.app-container {
+  height: 100%;
+  .layout-content {
+  }
+  .layout-footer {
+  }
+}
+</style>