瀏覽代碼

Merge branch 'develop3.0' of http://106.12.23.251:10080/TEAMMODEL/TEAMModelOS into develop3.0

CrazyIter 5 年之前
父節點
當前提交
3201714ccf
共有 20 個文件被更改,包括 990 次插入633 次删除
  1. 10 9
      TEAMModelOS.Service/Models/Core/SchoolUser.cs
  2. 1 1
      TEAMModelOS/ClientApp/src/components/learnactivity/BaseHwTable.vue
  3. 5 5
      TEAMModelOS/ClientApp/src/components/learnactivity/ChooseContent.vue
  4. 18 35
      TEAMModelOS/ClientApp/src/components/student-analysis/total/BaseLine.vue
  5. 249 268
      TEAMModelOS/ClientApp/src/components/student-analysis/total/BaseRateLine.vue
  6. 3 3
      TEAMModelOS/ClientApp/src/locale/lang/en-US/teachermgmt.js
  7. 29 29
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/teachermgmt.js
  8. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/totalAnalysis.js
  9. 3 3
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachermgmt.js
  10. 169 3
      TEAMModelOS/ClientApp/src/mock/index.js
  11. 50 12
      TEAMModelOS/ClientApp/src/store/module/user.js
  12. 10 4
      TEAMModelOS/ClientApp/src/view/coursemgmt/CourseClassroom.vue
  13. 192 90
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseEditExercise.vue
  14. 9 4
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.vue
  15. 39 35
      TEAMModelOS/ClientApp/src/view/student-analysis/total-analysis/TestAnalysis/QuestionList.vue
  16. 2 2
      TEAMModelOS/ClientApp/src/view/teachcontent/index.vue
  17. 6 2
      TEAMModelOS/ClientApp/src/view/teachermgmt/Index.vue
  18. 127 67
      TEAMModelOS/ClientApp/src/view/teachermgmt/components/personnel/Index.vue
  19. 50 42
      TEAMModelOS/ClientApp/src/view/teachermgmt/components/userList/Index.vue
  20. 17 18
      TEAMModelOS/Controllers/Core/SchoolUserController.cs

+ 10 - 9
TEAMModelOS.Service/Models/Core/SchoolUser.cs

@@ -9,27 +9,28 @@ using TEAMModelOS.SDK.Module.AzureCosmosDBV3;
 
 namespace TEAMModelOS.Service.Models.Core
 {
-    [CosmosDB(RU = 400, Name = "SchoolUser")]
+    [CosmosDB(RU = 400, Name = "School")]
     public class SchoolUser:ID
     {
-        [PartitionKey]
-        public string schoolCode { get; set; }
         public string id { get; set; }
+        public string schoolCode { get; set; }
+        public string schoolName { get; set; }
         public string name { get; set; }
         public string email { get; set; }
-        public string cellphone { get; set; }
-        public string countryCode { get; set; }
-        [JsonPropertyName("TEAMModelId")]
-        [JsonProperty("TEAMModelId")]
-        public string TEAMModelId { get; set; }
+        public string mobile { get; set; }
+        public string country { get; set; }
         public string jobTitle { get; set; }
+        public string picture { get; set; }
         public List<string> role { get; set; }
         public List<string> authority { get; set; }
         public int joinStatus { get; set; } = 0;
-        public int loginCount { get; set; } = 0;
+        public bool loginFlg { get; set; }
+        public long lastLoginDate { get; set; } = 0;
         public long crtDate { get; set; } = 0;
         public long remindDate { get; set; } = 0;
         public long joinDate { get; set; } = 0;
+        [PartitionKey]
+        public string code { get; set; }
         public int? ttl { get; set ; }
     }
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/components/learnactivity/BaseHwTable.vue

@@ -370,7 +370,7 @@
              * @param val
              */
             onUsedCommentChange(val) {
-                this.currentComment = this.usedCommentList.length ? this.usedCommentList[val].comment : ''
+                this.currentComment = this.usedCommentList.length && val !== undefined  ? this.usedCommentList[val].comment : ''
             },
 
             /**

+ 5 - 5
TEAMModelOS/ClientApp/src/components/learnactivity/ChooseContent.vue

@@ -1,8 +1,8 @@
 <template>
     <div class="choose-content">
-        <Tabs type="card">
+        <Tabs type="card" name="chooseContent">
             <!-- 选择课纲内容 -->
-            <TabPane label="课纲" v-if="showSyllabus">
+            <TabPane label="课纲" v-if="showSyllabus"  tab="chooseContent">
                 <div class="tab-wrap">
                     <div class="content-filter-wrap">
                         <div class="content-filter-item">
@@ -54,7 +54,7 @@
                 </div>
             </TabPane>
             <!-- 选择资源文件 -->
-            <TabPane label="内容" v-if="showContent">
+            <TabPane label="内容" v-if="showContent" tab="chooseContent">
                 <div class="tab-wrap">
                     <div class="content-filter-wrap">
                         <div class="content-filter-item">
@@ -103,7 +103,7 @@
                 </div>
             </TabPane>
             <!-- 选择题库 -->
-            <TabPane label="题目" v-if="showQuestion">
+            <TabPane label="题目" v-if="showQuestion" tab="chooseContent">
                 <div class="tab-wrap">
                     <vuescroll>
                         <Row class="question-filter-wrap">
@@ -179,7 +179,7 @@
                 </div>
             </TabPane>
             <!-- 补充内容 -->
-            <TabPane label="补充内容" v-if="showOther">
+            <TabPane label="补充内容" v-if="showOther"  tab="chooseContent">
                 <div class="tab-wrap dark-wang-editor dark-iview-input" style="padding:10px;">
                     <p class="label-name" style="margin-top:0px;">文字描述:</p>
                     <div ref="courseNotice"></div>

+ 18 - 35
TEAMModelOS/ClientApp/src/components/student-analysis/total/BaseLine.vue

@@ -15,7 +15,19 @@
 
         },
         mounted() {
-            this.drawLine()
+            let item = this.echartsData
+            if (item) {
+                let arr = []
+                arr.push(Number(item.R1))
+                arr.push(Number(item.R2))
+                arr.push(Number(item.R3))
+                arr.push(Number(item.R4))
+                arr.push(Number(item.R5))
+                arr.push(Number(item.R6))
+                this.y = arr
+                this.drawLine()
+            }
+            
             let myLine = this.$echarts.init(document.getElementById(this.ids), 'chalk')
             this.initWidth = document.getElementById(this.ids).offsetWidth
             let resize = {
@@ -49,8 +61,8 @@
                                 backgroundColor: '#6a7985'
                             }
                         },
-                        formatter: function(v) {
-                            return v[0].name + ':' + v[0].data + '%'
+                        formatter: function (v) {
+                            return v[0].name + ' : ' + (Number(v[0].data) * 100).toFixed(2) + '%'
                         }
                     },
                     legend: {
@@ -107,19 +119,7 @@
                                 borderColor: '#efefef',
                                 borderWidth: 3
                             },
-                            // areaStyle: {
-                            //  normal: {
-                            //      color: this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-                            //          offset: 0,
-                            //          color: 'rgba(37, 129, 27, 0.3)'
-                            //      }, {
-                            //          offset: 0.8,
-                            //          color: 'rgba(137, 119, 27, 0)'
-                            //      }], false),
-                            //      shadowColor: 'rgba(255, 255, 255, 0.2)',
-                            //      shadowBlur: 10
-                            //  }
-                            // },
+                            smooth: false,
                             symbolSize: 10,
                             data: this.y
                         }
@@ -128,29 +128,12 @@
 
                 // 绘制图表
                 myLine.setOption(option)
-                window.addEventListener('resize', function() {
+                window.addEventListener('resize', function () {
                     myLine.resize()
                 })
             }
         },
-        watch: {
-
-            // 渲染最新试题统计数据
-            echartsData(val) {
-                if (!val) return
-                let echartsData = val
-                let arr = []
-                arr.push(Number(echartsData.R1))
-                arr.push(Number(echartsData.R2))
-                arr.push(Number(echartsData.R3))
-                arr.push(Number(echartsData.R4))
-                arr.push(Number(echartsData.R5))
-                arr.push(Number(echartsData.R6))
-                this.y = arr
-                this.drawLine()
-                // this.tableData = JSON.parse(JSON.stringify(val))
-            }
-        }
+        
     }
 </script>
 

+ 249 - 268
TEAMModelOS/ClientApp/src/components/student-analysis/total/BaseRateLine.vue

@@ -1,288 +1,269 @@
 <template>
-  <div :id="ids" class="myRateLine"></div>
+    <div :id="ids" class="myRateLine"></div>
 </template>
 
 <script>
-  export default {
-    name: 'hello',
-    props: ['ids', 'echartsData'],
-    data() {
-      return {
-      }
-    },
-    mounted() {
-      this.drawLine()
-      let myLine = this.$echarts.init(document.getElementById(this.ids), 'chalk')
-      this.initWidth = document.getElementById(this.ids).offsetWidth
-      let resize = {
-        width: 500,
-        height: 400
-      }
-      myLine.resize(resize)
-    },
-    methods: {
-      drawLine() {
-        // 基于准备好的dom,初始化echarts实例
-        let myLine = this.$echarts.init(document.getElementById(this.ids), 'chalk')
-
-        // 指定图表的配置项和数据
-        var option = {
-          title: {
-            text: '选项选答率分析',
-            textStyle: {
-              align: 'center',
-              color: '#333',
-              fontSize: 14
-            },
-            top: '3%',
-            left: '10%'
-          },
-          tooltip: {
-            trigger: 'axis',
-            axisPointer: {
-              label: {
-                backgroundColor: '#6a7985'
-              }
-            },
-            formatter: function(v) {
-              let str = '选项' + v[0].name + '<br>'
-              v.forEach(item => {
-                str = str + item.seriesName + ':' + item.data + '%' + '<br>'
-              })
-              return str
-            }
-          },
-          legend: {
-            textStyle: {
-              color: '#969696'
-            },
-            top: 35
-          },
-          gird: {
-            left: '3%',
-            right: '4%',
-            containLabel: true
-          },
-          xAxis: [
-            {
-              type: 'category',
-              boundaryGap: false,
-              splitLine: {
-                show: false,
-                lineStyle: {
-                  color: '#4c504a'
-                }
-              },
-              axisLine: {
-                lineStyle: {
-                  color: '#969696'
-                }
-              },
-              axisLabel: {
-                show: true, // 是否显示
-                inside: false, // 是否朝内
-                rotate: 0, // 旋转角度
-                margin: 15, // 刻度标签与轴线之间的距离
-                color: '#989898', // 默认取轴线的颜色,
-                fontSize: 14
-              },
-              data: this.echartsData.map(item => item.option)
+    export default {
+        name: 'hello',
+        props: ['ids', 'echartsData'],
+        data() {
+            return {
             }
-          ],
-          yAxis: [
-            {
-              type: 'value',
-              splitLine: {
-                show: true,
-                lineStyle: {
-                  color: '#ccc'
-                }
-              },
-              axisLine: {
-                lineStyle: {
-                  color: '#969696'
-                }
-              }
+        },
+        mounted() {
+            this.drawLine()
+            let myLine = this.$echarts.init(document.getElementById(this.ids), 'chalk')
+            this.initWidth = document.getElementById(this.ids).offsetWidth
+            let resize = {
+                width: 500,
+                height: 400
             }
-          ],
-          series: [
-            {
-              name: '选答率',
-              type: 'line',
-              data: this.echartsData.map(item => item.rate),
-              color: '#F58080',
-              lineStyle: {
-                normal: {
-                  width: 2,
-                  color: {
-                    type: 'linear',
+            myLine.resize(resize)
+        },
+        methods: {
+            drawLine() {
+                // 基于准备好的dom,初始化echarts实例
+                let myLine = this.$echarts.init(document.getElementById(this.ids), 'chalk')
 
-                    colorStops: [{
-                      offset: 0,
-                      color: '#FFCAD4' // 0% 处的颜色
-                    }, {
-                      offset: 0.4,
-                      color: '#F58080' // 100% 处的颜色
-                    }, {
-                      offset: 1,
-                      color: '#F58080' // 100% 处的颜色
-                    }],
-                    globalCoord: false // 缺省为 false
-                  },
-                  shadowColor: 'rgba(245,128,128, 0.5)',
-                  shadowBlur: 10,
-                  shadowOffsetY: 7
-                }
-              },
-        // areaStyle: {
-        //    normal: {
-        //        color: this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-        //            offset: 0,
-        //            color: 'rgba(137, 189, 27, 0.3)'
-        //        }, {
-        //            offset: 0.8,
-        //            color: 'rgba(137, 189, 27, 0)'
-        //        }], false),
-        //        shadowColor: 'rgba(0, 0, 0, 0.1)',
-        //        shadowBlur: 10
-        //    }
-        // },
-            itemStyle: {
-                normal: {
-                  color: '#F58080',
-                  borderWidth: 5,
-                  /* shadowColor: 'rgba(72,216,191, 0.3)',
-                   shadowBlur: 100, */
-                  borderColor: '#F58080'
-                }
-              },
-              smooth: false
-            },
-            {
-              name: '高分组选答率',
-              type: 'line',
-              data: this.echartsData.map(item => item.PH),
-              lineStyle: {
-                normal: {
-                  width: 2,
-                  color: {
-                    type: 'linear',
-
-                    colorStops: [{
-                      offset: 0,
-                      color: '#AAF487' // 0% 处的颜色
+                // 指定图表的配置项和数据
+                var option = {
+                    title: {
+                        text: '选项选答率分析',
+                        textStyle: {
+                            align: 'center',
+                            color: '#333',
+                            fontSize: 14
+                        },
+                        top: '3%',
+                        left: '10%'
                     },
-                    {
-                      offset: 0.4,
-                      color: '#47D8BE' // 100% 处的颜色
-                    }, {
-                      offset: 1,
-                      color: '#47D8BE' // 100% 处的颜色
-                    }
-                    ],
-                    globalCoord: false // 缺省为 false
-                  },
-                  shadowColor: 'rgba(71,216,190, 0.5)',
-                  shadowBlur: 10,
-                  shadowOffsetY: 7
-                }
-              },
-        // areaStyle: {
-        //    normal: {
-        //        color: this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-        //            offset: 0,
-        //            color: 'rgba(0, 136, 212, 0.3)'
-        //        }, {
-        //            offset: 0.8,
-        //            color: 'rgba(0, 136, 212, 0)'
-        //        }], false),
-        //        shadowColor: 'rgba(0, 0, 0, 0.1)',
-        //        shadowBlur: 10
-        //    }
-        // },
-            itemStyle: {
-                normal: {
-                  color: '#AAF487',
-                  borderWidth: 10,
-                  /* shadowColor: 'rgba(72,216,191, 0.3)',
-                   shadowBlur: 100, */
-                  borderColor: '#AAF487'
-                }
-              },
-              smooth: false
-            },
-            {
-              name: '低分组选答率',
-              type: 'line',
-              data: this.echartsData.map(item => item.PL),
-              lineStyle: {
-                normal: {
-                  width: 2,
-                  color: {
-                    type: 'linear',
-
-                    colorStops: [{
-                      offset: 0,
-                      color: '#F6D06F' // 0% 处的颜色
+                    tooltip: {
+                        trigger: 'axis',
+                        axisPointer: {
+                            label: {
+                                backgroundColor: '#6a7985'
+                            }
+                        },
+                        formatter: function (v) {
+                            let str = '选项' + v[0].name + '<br>'
+                            v.forEach(item => {
+                                str = str + item.seriesName + ':' + item.data + '%' + '<br>'
+                            })
+                            return str
+                        }
+                    },
+                    legend: {
+                        textStyle: {
+                            color: '#969696'
+                        },
+                        top: 35
+                    },
+                    gird: {
+                        left: '3%',
+                        right: '4%',
+                        containLabel: true
                     },
-                    {
-                      offset: 0.4,
-                      color: '#F9A589' // 100% 处的颜色
-                    }, {
-                      offset: 1,
-                      color: '#F9A589' // 100% 处的颜色
-                    }
+                    xAxis: [
+                        {
+                            type: 'category',
+                            boundaryGap: false,
+                            splitLine: {
+                                show: false,
+                                lineStyle: {
+                                    color: '#4c504a'
+                                }
+                            },
+                            axisLine: {
+                                lineStyle: {
+                                    color: '#969696'
+                                }
+                            },
+                            axisLabel: {
+                                show: true, // 是否显示
+                                inside: false, // 是否朝内
+                                rotate: 0, // 旋转角度
+                                margin: 15, // 刻度标签与轴线之间的距离
+                                color: '#989898', // 默认取轴线的颜色,
+                                fontSize: 14
+                            },
+                            data: this.echartsData.map(item => item.option)
+                        }
                     ],
-                    globalCoord: false // 缺省为 false
-                  },
-                  shadowColor: 'rgba(249,165,137, 0.5)',
-                  shadowBlur: 10,
-                  shadowOffsetY: 7
+                    yAxis: [
+                        {
+                            type: 'value',
+                            splitLine: {
+                                show: true,
+                                lineStyle: {
+                                    color: '#ccc'
+                                }
+                            },
+                            axisLine: {
+                                lineStyle: {
+                                    color: '#969696'
+                                }
+                            }
+                        }
+                    ],
+                    series: [
+                        {
+                            name: '选答率',
+                            type: 'line',
+                            data: this.echartsData.map(item => item.rate),
+                            color: '#F58080',
+                            lineStyle: {
+                                normal: {
+                                    width: 2,
+                                    color: {
+                                        type: 'linear',
+
+                                        colorStops: [{
+                                            offset: 0,
+                                            color: '#FFCAD4' // 0% 处的颜色
+                                        }, {
+                                            offset: 0.4,
+                                            color: '#F58080' // 100% 处的颜色
+                                        }, {
+                                            offset: 1,
+                                            color: '#F58080' // 100% 处的颜色
+                                        }],
+                                        globalCoord: false // 缺省为 false
+                                    },
+                                    shadowColor: 'rgba(245,128,128, 0.5)',
+                                    shadowBlur: 10,
+                                    shadowOffsetY: 7
+                                }
+                            },
+                            // areaStyle: {
+                            //    normal: {
+                            //        color: this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [{
+                            //            offset: 0,
+                            //            color: 'rgba(137, 189, 27, 0.3)'
+                            //        }, {
+                            //            offset: 0.8,
+                            //            color: 'rgba(137, 189, 27, 0)'
+                            //        }], false),
+                            //        shadowColor: 'rgba(0, 0, 0, 0.1)',
+                            //        shadowBlur: 10
+                            //    }
+                            // },
+                            itemStyle: {
+                                normal: {
+                                    color: '#F58080',
+                                    borderWidth: 5,
+                                    /* shadowColor: 'rgba(72,216,191, 0.3)',
+                                     shadowBlur: 100, */
+                                    borderColor: '#F58080'
+                                }
+                            },
+                            smooth: false
+                        },
+                        {
+                            name: '高分组选答率',
+                            type: 'line',
+                            data: this.echartsData.map(item => item.PH),
+                            lineStyle: {
+                                normal: {
+                                    width: 2,
+                                    color: {
+                                        type: 'linear',
+
+                                        colorStops: [{
+                                            offset: 0,
+                                            color: '#AAF487' // 0% 处的颜色
+                                        },
+                                        {
+                                            offset: 0.4,
+                                            color: '#47D8BE' // 100% 处的颜色
+                                        }, {
+                                            offset: 1,
+                                            color: '#47D8BE' // 100% 处的颜色
+                                        }
+                                        ],
+                                        globalCoord: false // 缺省为 false
+                                    },
+                                    shadowColor: 'rgba(71,216,190, 0.5)',
+                                    shadowBlur: 10,
+                                    shadowOffsetY: 7
+                                }
+                            },
+                            itemStyle: {
+                                normal: {
+                                    color: '#AAF487',
+                                    borderWidth: 10,
+                                    /* shadowColor: 'rgba(72,216,191, 0.3)',
+                                     shadowBlur: 100, */
+                                    borderColor: '#AAF487'
+                                }
+                            },
+                            smooth: false
+                        },
+                        {
+                            name: '低分组选答率',
+                            type: 'line',
+                            data: this.echartsData.map(item => item.PL),
+                            lineStyle: {
+                                normal: {
+                                    width: 2,
+                                    color: {
+                                        type: 'linear',
+
+                                        colorStops: [{
+                                            offset: 0,
+                                            color: '#F6D06F' // 0% 处的颜色
+                                        },
+                                        {
+                                            offset: 0.4,
+                                            color: '#F9A589' // 100% 处的颜色
+                                        }, {
+                                            offset: 1,
+                                            color: '#F9A589' // 100% 处的颜色
+                                        }
+                                        ],
+                                        globalCoord: false // 缺省为 false
+                                    },
+                                    shadowColor: 'rgba(249,165,137, 0.5)',
+                                    shadowBlur: 10,
+                                    shadowOffsetY: 7
+                                }
+                            },
+                            itemStyle: {
+                                normal: {
+                                    color: '#F6D06F',
+                                    borderWidth: 10,
+                                    /* shadowColor: 'rgba(72,216,191, 0.3)',
+                                     shadowBlur: 100, */
+                                    borderColor: '#F6D06F'
+                                }
+                            },
+                            smooth: false
+                        }]
                 }
-              },
-              // areaStyle: {
-              //  normal: {
-              //    color: this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [{
-              //      offset: 0,
-              //      color: 'rgba(0, 136, 212, 0.2)'
-              //    }, {
-              //      offset: 1,
-              //      color: 'rgba(0, 136, 212, 0)'
-              //    }], false),
-              //    shadowColor: 'rgba(0, 0, 0, 0.1)',
-              //    shadowBlur: 10
-              //  }
-              // },
-              itemStyle: {
-                normal: {
-                  color: '#F6D06F',
-                  borderWidth: 10,
-                  /* shadowColor: 'rgba(72,216,191, 0.3)',
-                   shadowBlur: 100, */
-                  borderColor: '#F6D06F'
+
+                // 绘制图表
+                myLine.setOption(option)
+                window.addEventListener('resize', function () {
+                    myLine.resize()
+                })
+            }
+        }, 
+        watch: {
+            echartsData: {
+                handler(n) {
+                    console.log(n)
                 }
-              },
-              smooth: false
-            }]
+            }
         }
-
-        // 绘制图表
-        myLine.setOption(option)
-        window.addEventListener('resize', function() {
-          myLine.resize()
-        })
-      }
     }
-  }
 </script>
 
 <!-- Add "scoped" attribute to limit CSS to this component only -->
 <style scoped>
 
-  .myRateLine {
-    width: 100%;
-    height: 400px;
-    margin: 20px auto;
-    display: block;
-  }
+    .myRateLine {
+        width: 100%;
+        height: 400px;
+        margin: 20px auto;
+        display: block;
+    }
 </style>

+ 3 - 3
TEAMModelOS/ClientApp/src/locale/lang/en-US/teachermgmt.js

@@ -6,14 +6,14 @@ export default {
     blurryFilter: '請輸入關鍵字或帳號資訊...',
     mulitSet: '權限管理',
     table:{
-        text1: '線',
-        text2: '',
+        text1: '當前在線',
+        text2: '最後在線',
         th1: '帳號資訊',
         th2: '用戶名稱',
         th3: '職稱',
         th4: '手機資訊',
         th5: '信箱資訊',
-        th6: '登入與在線狀況',
+        th6: '在線狀況',
     },
     authSet:{
         title:'權限設定',

+ 29 - 29
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/teachermgmt.js

@@ -1,42 +1,42 @@
 export default {
-    page:{
-        text1: '教師帳號管理',
-        text2: '添加教師帳號'
+    page: {
+        text1: '教师帐号管理',
+        text2: '添加教师帐号'
     },
-    blurryFilter: '請輸入關鍵字或帳號資訊...',
-    mulitSet: '限管理',
-    table:{
-        text1: '上線',
-        text2: '',
-        th1: '帳號資訊',
-        th2: '用戶名稱',
-        th3: '職稱',
-        th4: '手機資訊',
-        th5: '信箱資訊',
-        th6: '登入與在線狀況',
+    blurryFilter: '请输入关键字或帐号资讯...',
+    mulitSet: '限管理',
+    table: {
+        text1: '当前在线',
+        text2: '最后在线',
+        th1: '帐号资讯',
+        th2: '用户名称',
+        th3: '职称',
+        th4: '手机资讯',
+        th5: '信箱资讯',
+        th6: '在线状况',
     },
-    authSet:{
-        title:'權限設定',
-        subTitle: '變更帳號',
-        area1:{
-            title:'區、班、校管理頁面',
-            read: '允許檢視區、班、校管理頁面',
-            auth1: '允許編輯學制內容,包括年級、學期科目資訊'
+    authSet: {
+        title: '权限设定',
+        subTitle: '变更帐号',
+        area1: {
+            title: '区、班、校管理页面',
+            read: '允许检视区、班、校管理页面',
+            auth1: '允许编辑学制内容,包括年级、学期科目资讯'
         },
         reset: '重置',
         save: '保存'
     },
-    model:{
-        delTeacher:{
-            title: '刪除老師',
-            text1: '請問您確定要刪除',
+    model: {
+        delTeacher: {
+            title: '删除老师',
+            text1: '请问您确定要删除',
         },
-        warning:{
+        warning: {
             title: '提醒',
-            text1: '請先勾選左側的老師'
+            text1: '请先勾选左侧的老师'
         }
     },
-    message:{
-        info1:'刪除成功'
+    message: {
+        info1: '删除成功'
     }
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/totalAnalysis.js

@@ -224,7 +224,7 @@ export default {
     // QuestionList.vue
     ql_text1: '试卷总分',
     ql_text2: '单项选择题',
-    ql_text3: '多项选择',
+    ql_text3: '多项选择',
     ql_text4: '判断题',
     ql_text5: '填空题',
     ql_text6: '问答题',

+ 3 - 3
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachermgmt.js

@@ -6,14 +6,14 @@ export default {
     blurryFilter: '請輸入關鍵字或帳號資訊...',
     mulitSet: '權限管理',
     table:{
-        text1: '線',
-        text2: '',
+        text1: '當前在線',
+        text2: '最後在線',
         th1: '帳號資訊',
         th2: '用戶名稱',
         th3: '職稱',
         th4: '手機資訊',
         th5: '信箱資訊',
-        th6: '登入與在線狀況',
+        th6: '在線狀況',
     },
     authSet:{
         title:'權限設定',

+ 169 - 3
TEAMModelOS/ClientApp/src/mock/index.js

@@ -131,8 +131,8 @@ export default {
         } 
       }
     },
-    "personnelList|30": [{
-      "type|1": ["invite", "apply"],
+    'personnelList|30': [{
+      'type|1': ["invite", "apply"],
       'identy|+1': 123456789,
       'id': function(){ // 隨機ID
           return "TB"+this.identy
@@ -148,6 +148,172 @@ export default {
         let date = new Date(this.remindDatetime)
         return date.getTime()
       }
-    }]
+    }],
+      'userListImport': [
+          {
+              'id': 'jeffmk30033',
+              'mail': 'jeffmk3@gmail.com',
+              'mobile': '955493542'
+          },
+          {
+              'id': 'conniee01072426',
+              'mail': 'aliceluying17@gmail.com',
+              'mobile': '972118402'
+          },
+          {
+              'id': '1539305864',
+              'mail': 'k.sjjqikouk@uzkadnxnn.mo',
+              'mobile': '1336366940'
+          },
+          {
+              'id': '2255421465',
+              'mail': 'z.utbnihjy@mfvx.gy',
+              'mobile': '668633133'
+          },
+          {
+              'id': '1151879171',
+              'mail': 'e.hnksniq@kldc.pn',
+              'mobile': '5475618323'
+          },
+          {
+              'id': '153244143117',
+              'mail': 'r.uorobdz@kjwlxbd.mobi',
+              'mobile': '182103119'
+          },
+          {
+              'id': '15587110213',
+              'mail': 'd.blzdlo@pdvbleq.af',
+              'mobile': '5887232235'
+          },
+          {
+              'id': '18738179233',
+              'mail': 'w.xuommhei@yhqithcs.ko',
+              'mobile': '230235071'
+          }
+      ],
+      'userListFromCoreID|5': [
+          {
+              'id': 'jeffmk30033',
+              'mail': 'jeffmk3@gmail.com',
+              'mobile': '955493542',
+              'country': '886',
+              'name': 'jeff',
+              'picture': 'http://icons.iconarchive.com/icons/hopstarter/iron-man-avatar/128/Iron-Man-Mark-III-01-icon.png'
+          },
+          {
+              'id': 'conniee01072426',
+              'mail': 'aliceluying17@gmail.com',
+              'mobile': '972118402',
+              'country': '886',
+              'name': 'Connie Lu',
+              'picture': 'http://icons.iconarchive.com/icons/chanut/role-playing/128/Elf-icon.png'
+          },
+          {
+              'id': '1539305864',
+              'mail': 'k.sjjqikouk@uzkadnxnn.mo',
+              'mobile': '1336366940',
+              'country': '86',
+              'name': 'Steven Davis',
+              'picture|1': [
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10141-girl-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10159-woman-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10136-boy-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10142-girl-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10135-boy-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10147-adult-light-skin-tone-icon.png'
+              ]
+          },
+          {
+              'id': '2255421465',
+              'mail': 'z.utbnihjy@mfvx.gy',
+              'mobile': '668633133',
+              'country': '886',
+              'name': 'Angela Martin',
+              'picture|1': [
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10141-girl-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10159-woman-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10136-boy-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10142-girl-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10135-boy-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10147-adult-light-skin-tone-icon.png'
+              ]
+          },
+          {
+              'id': '1151879171',
+              'mail': 'e.hnksniq@kldc.pn',
+              'mobile': '5475618323',
+              'country': '886',
+              'name': 'Betty Walker',
+              'picture|1': [
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10141-girl-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10159-woman-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10136-boy-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10142-girl-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10135-boy-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10147-adult-light-skin-tone-icon.png'
+              ]
+          },
+          {
+              'id': '153244143117',
+              'mail': 'r.uorobdz@kjwlxbd.mobi',
+              'mobile': '182103119',
+              'country': '86',
+              'name': 'Dorothy Allen',
+              'picture|1': [
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10141-girl-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10159-woman-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10136-boy-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10142-girl-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10135-boy-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10147-adult-light-skin-tone-icon.png'
+              ]
+          },
+          {
+              'id': '15587110213',
+              'mail': 'd.blzdlo@pdvbleq.af',
+              'mobile': '5887232235',
+              'country': '86',
+              'name': '史秀英',
+              'picture|1': [
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10141-girl-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10159-woman-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10136-boy-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10142-girl-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10135-boy-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10147-adult-light-skin-tone-icon.png'
+              ]
+          },
+          {
+              'id': '18738179233',
+              'mail': 'w.xuommhei@yhqithcs.ko',
+              'mobile': '230235071',
+              'country': '82',
+              'name': '張東健',
+              'picture|1': [
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10141-girl-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10159-woman-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10136-boy-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10142-girl-medium-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10135-boy-light-skin-tone-icon.png',
+                  'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/64/10147-adult-light-skin-tone-icon.png'
+              ]
+          }
+      ],
+      'userFromCoreID': {
+          'idDateTime': '@datetime',
+          'id': '@id',
+          'mail': '@email',
+          'mobile': /\d{8,10}/,
+          'country|1': ['886', '86'],
+          'name': '@name',
+          'picture|1': [
+              'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/256/10141-girl-light-skin-tone-icon.png',
+              'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/256/10159-woman-light-skin-tone-icon.png',
+              'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/256/10136-boy-medium-light-skin-tone-icon.png',
+              'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/256/10142-girl-medium-light-skin-tone-icon.png',
+              'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/256/10135-boy-light-skin-tone-icon.png',
+              'http://icons.iconarchive.com/icons/google/noto-emoji-people-face/256/10147-adult-light-skin-tone-icon.png'
+          ]
+      }
   })
 }

+ 50 - 12
TEAMModelOS/ClientApp/src/store/module/user.js

@@ -42,10 +42,28 @@ export default {
                 return []
             }
         },
-        getSchoolUserByTMID: state => TMID => {
+        getSchoolUserRequestedCount: state => {
             if (state.schoolUserList !== undefined) {
                 return state.schoolUserList.filter(
-                    user => user.TEAMModelId === TMID
+                    user => user.joinStatus === 3
+                ).length
+            } else {
+                return 0
+            }
+        },
+        getSchoolUserInvitedOrRequested: state => {
+            if (state.schoolUserList !== undefined) {
+                return state.schoolUserList.filter(
+                    user => user.joinStatus === 2 || user.joinStatus === 3
+                )
+            } else {
+                return []
+            }
+        },
+        getSchoolUserByID: state => ID => {
+            if (state.schoolUserList !== undefined) {
+                return state.schoolUserList.filter(
+                    user => user.id === ID
                 )
             } else {
                 return []
@@ -76,17 +94,37 @@ export default {
     actions: {
         // 從DB取得所有該校的使用者 && commit to state.schoolUserList
         setSchoolUser(context) {
+            console.log('apiTools:');
+            console.log(apiTools);
             return new Promise(
                 (resolve, reject) => {
                     if (typeof context.state.schoolCode !== 'undefined' && context.state.schoolCode !== undefined) {
+                        var partitionKey = context.state.schoolCode + "-schooluser";
                         apiTools.schoolUser.getSchoolUser({
-                            schoolCode: context.state.schoolCode
-                        }).then(
+                            code: partitionKey
+                        }, context.state.schoolCode).then(
                             res => {
+                                console.log('user.js setSchoolUser res:')
+                                console.log(res)
                                 if (res.error == null) {
                                     if (res.result.data.length > 0) {
+                                        //時間轉換 UnixTimestamp => H:I:S
+                                        res.result.data.forEach(function (userNow, indexNow) {
+                                            if (userNow.lastLoginDate > 0) {
+                                                var d = new Date(userNow.lastLoginDate * 1000);
+                                                res.result.data[indexNow].lastLoginDateHIS = d.getFullYear() + "-" +
+                                                    ("00" + (d.getMonth() + 1)).slice(-2) + "-" +
+                                                    ("00" + d.getDate()).slice(-2) + " " +
+                                                    ("00" + d.getHours()).slice(-2) + ":" +
+                                                    ("00" + d.getMinutes()).slice(-2)
+                                            }
+                                            else {
+                                                res.result.data[indexNow].lastLoginDateHIS = ""
+                                            }
+                                        })
                                         console.log('schoolUserList:')
                                         console.log(res.result.data)
+                                        //放入storage
                                         context.commit('setSchoolUserList', res.result.data)
                                         resolve({
                                             code: 1,
@@ -119,12 +157,12 @@ export default {
             return new Promise(
                 (resolve, reject) => {
                     let schoolCode = context.state.schoolCode
-                    let TEAMModelIds = params.TEAMModelIds
+                    let ids = params.ids
                     let authList = params.authList
-                    if (typeof schoolCode !== 'undefined' && schoolCode !== undefined && typeof TEAMModelIds !== 'undefined' && TEAMModelIds !== undefined) {
+                    if (typeof schoolCode !== 'undefined' && schoolCode !== undefined && typeof ids !== 'undefined' && ids !== undefined) {
                         apiTools.schoolUser.setAuthToSchoolUser({
                             schoolCode: schoolCode,
-                            TEAMModelIds: TEAMModelIds,
+                            ids: ids,
                             authList: authList
                         }).then(
                             res => {
@@ -175,23 +213,23 @@ export default {
         },
 
         // 將使用者從學校使用者列表中移除
-        rmvFromSchoolUserByTMID(context, params) {
+        rmvFromSchoolUserByID(context, params) {
             return new Promise(
                 (resolve, reject) => {
                     let schoolCode = context.state.schoolCode
                     let schoolUserListNow = context.state.schoolUserList
-                    let rmvTMIDList = params.TEAMModelIds
-                    if (schoolUserListNow.length > 0 && rmvTMIDList.length > 0) {
+                    let rmvIdList = params.Ids
+                    if (schoolUserListNow.length > 0 && rmvIdList.length > 0) {
                         apiTools.schoolUser.rmvSchoolUser({
                             schoolCode: schoolCode,
-                            TEAMModelIds: rmvTMIDList
+                            Ids: rmvIdList
                         }).then(
                             res => {
                                 if (res.error == null) {
                                     // 更新 state.schoolUserList
                                     let i = 0
                                     while (i < schoolUserListNow.length) {
-                                        if (rmvTMIDList.indexOf(schoolUserListNow[i].TEAMModelId) > -1) {
+                                        if (rmvIdList.indexOf(schoolUserListNow[i].id) > -1) {
                                             schoolUserListNow.splice(i, 1)
                                         } else {
                                             ++i

+ 10 - 4
TEAMModelOS/ClientApp/src/view/coursemgmt/CourseClassroom.vue

@@ -89,17 +89,21 @@
                                         {{fn.getPeriod($store.state.schoolBaseInfo.schoolBaseInfo,courseClassroomList[currentClassroomIndex].periodCode).periodName }} / {{fn.getGradeName($store.state.schoolBaseInfo.schoolBaseInfo,courseClassroomList[currentClassroomIndex].gradeCode)}}
                                     </p>
                                 </div>
-                                <div class="classroom-info-item">
+                                <!--<div class="classroom-info-item">
                                     <p class="classroom-attr-label" v-show="courseClassroomList[currentClassroomIndex].scope == 'school'">{{$t('courseManage.classroom.classroomType')}}</p>
                                     <p class="classroom-attr-value">{{courseClassroomList[currentClassroomIndex].classroomType}}</p>
-                                </div>
+                                </div>-->
                                 <div class="classroom-info-item">
                                     <p class="classroom-attr-label">{{$t('courseManage.classroom.classroomTeacher')}}</p>
                                     <p class="classroom-attr-value">{{courseClassroomList[currentClassroomIndex].headMaster}}</p>
                                 </div>
-                                <div class="classroom-info-item">
+                                <div class="classroom-info-item dark-iview-select">
                                     <p class="classroom-attr-label">{{$t('courseManage.classroom.classroomTeacher1')}}</p>
-                                    <p class="classroom-attr-value">暂未设置</p>
+                                    <!--<p class="classroom-attr-value">暂未设置</p>-->
+                                    <Select v-model="model1" style="width:240px">
+                                        <Option v-for="item in teacherList" :value="item.value" :key="item.value">{{ item.label }}</Option>
+                                    </Select>
+
                                 </div>
                                 <div class="classroom-info-item">
                                     <p class="classroom-attr-label">{{$t('courseManage.classroom.classroomNotice')}}</p>
@@ -212,6 +216,7 @@
         data() {
             return {
                 fn,
+                model1:'',
                 selectedStudent:[],
                 addStudentStatus: false,
                 studentTabelLoading: false,
@@ -221,6 +226,7 @@
                     classroomName: '',
                     notice: ''
                 },
+                teacherList:[],
                 newPersonalStatus: false,
                 groupNum: 2,
                 groupType: '1',

+ 192 - 90
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseEditExercise.vue

@@ -1,100 +1,106 @@
 <template>
     <div class="ev-container component-ev-container" :id="refId">
-            <div class="display-flex">
-                <div class="exersices-attr my-radio-style">
-                    <IconText :text="'选择学段'" :color="'#00b8ff'" :icon="'md-school'"></IconText>
-                    <Select v-model="exercisePeriod" @on-change="onPeriodChange">
-                        <Option v-for="(period,index) in schoolInfo.period" :value="index" :key="index">{{ period.periodName }}</Option>
-                    </Select>
-                </div>
-                <div class="my-radio-style exersices-attr">
-                    <IconText :text="'选择年级'" :color="'#00b8ff'" :icon="'logo-buffer'"></IconText>
-                    <Select v-model="exerciseGrade" multiple>
-                        <Option v-for="(grade,index) in gradeList" :value="grade.gradeCode" :key="index">{{ grade.gradeName }}</Option>
-                    </Select>
-                </div>
-                <div class="exersices-attr my-radio-style">
-                    <IconText :text="'选择科目'" :color="'#00b8ff'" :icon="'md-bookmarks'"></IconText>
-                    <Select v-model="exerciseSubject">
-                        <Option v-for="(subject,index) in subjectList" :value="index" :key="index">{{ subject.subjectName }}</Option>
-                    </Select>
-                </div>
+        <div class="display-flex">
+            <div class="exersices-attr my-radio-style">
+                <IconText :text="'选择学段'" :color="'#00b8ff'" :icon="'md-school'"></IconText>
+                <Select v-model="exercisePeriod" @on-change="onPeriodChange">
+                    <Option v-for="(period,index) in schoolInfo.period" :value="index" :key="index">{{ period.periodName }}</Option>
+                </Select>
             </div>
-            <div class="display-flex">
-                <div class="exersices-attr my-radio-style">
-                    <IconText :text="'题目归属'" :color="'#00b8ff'" :icon="'md-cube'"></IconText>
-                    <Select v-model="exerciseScope">
-                        <Option v-for="(item,index) in scopeList" :value="index" :key="index">{{ item }}</Option>
-                    </Select>
-                </div>
-                <div class="exersices-attr my-radio-style">
-                    <IconText :text="'关联认知层次'" :color="'#00b8ff'" :icon="'md-planet'"></IconText>
-                    <Select v-model="exerciseField">
-                        <Option v-for="(item,index) in fieldList" :value="index" :key="index">{{ item }}</Option>
-                    </Select>
-                </div>
-                <div class="exersices-attr my-radio-style">
-                    <IconText :text="'关联知识点'" :color="'#00b8ff'" :icon="'md-infinite'"></IconText>
-                    <Button type="info" style="margin-top:20px" @click="selectPointsModal = true" v-if="exercisePoints.length === 0">选择知识点</Button>
-                    <div v-else style="margin-top:10px">
-                        <span v-for="(item,index) in exercisePoints" :key="index" class="exercise-item-point">
-                            {{item.name}}
-                            <span class="exercise-item-point-close"><Icon type="md-close" @click="onDeletePoint(index)" /></span>
-                        </span>
-                        <span class="exercise-item-point-modify" @click="selectPointsModal = true">修改</span>
-                    </div>
-                </div>
-
+            <div class="my-radio-style exersices-attr">
+                <IconText :text="'选择年级'" :color="'#00b8ff'" :icon="'logo-buffer'"></IconText>
+                <Select v-model="exerciseGrade" multiple>
+                    <Option v-for="(grade,index) in gradeList" :value="grade.gradeCode" :key="index">{{ grade.gradeName }}</Option>
+                </Select>
             </div>
-            <div class="exersices-attr display-flex">
-                <div class="exersices-attr-type my-radio-style" style="width:50%">
-                    <IconText :text="'选择题型'" :color="'#00b8ff'" :icon="'md-pricetags'"></IconText>
-                    <RadioGroup v-model="exersicesType" type="button" @on-change="typeChange">
-                        <Radio label="Single" :disabled="isEdit">单选</Radio>
-                        <Radio label="Multiple" :disabled="isEdit">多选</Radio>
-                        <Radio label="Judge" :disabled="isEdit">判断</Radio>
-                        <Radio label="Complete" :disabled="isEdit">填空</Radio>
-                        <Radio label="Subjective" :disabled="isEdit">问答</Radio>
-                        <Radio label="Compose" :disabled="isEdit">综合</Radio>
-                    </RadioGroup>
-                </div>
-                <div class="exersices-attr-diff edit-exersices-attr-diff my-radio-style">
-                    <IconText :text="'题目难度'" :color="'#00b8ff'" :icon="'md-pulse'"></IconText>
-                    <RadioGroup v-model="exersicesDiff" type="button" ref="diffRef">
-                        <Radio label="1" @click.native="diffChange($event,'1')">容易</Radio>
-                        <Radio label="2" @click.native="diffChange($event,'2')">较易</Radio>
-                        <Radio label="3" @click.native="diffChange($event,'3')">一般</Radio>
-                        <Radio label="4" @click.native="diffChange($event,'4')">较难</Radio>
-                        <Radio label="5" @click.native="diffChange($event,'5')">困难</Radio>
-                    </RadioGroup>
-                </div>
+            <div class="exersices-attr my-radio-style">
+                <IconText :text="'选择科目'" :color="'#00b8ff'" :icon="'md-bookmarks'"></IconText>
+                <Select v-model="exerciseSubject">
+                    <Option v-for="(subject,index) in subjectList" :value="index" :key="index">{{ subject.subjectName }}</Option>
+                </Select>
             </div>
-
-            <BaseSingle v-if="exersicesType==='Single'" ref="single" :editItem="editInfo"></BaseSingle>
-            <BaseMultiple v-else-if="exersicesType==='Multiple'" ref="multiple" :editInfo="editInfo"></BaseMultiple>
-            <BaseJudge v-else-if="exersicesType==='Judge'" ref="judge" :editInfo="editInfo"></BaseJudge>
-            <BaseCompletion v-else-if="exersicesType==='Complete'" ref="complete" :editInfo="editInfo"></BaseCompletion>
-            <BaseSubjective v-else-if="exersicesType==='Subjective'" ref="subjective" :editInfo="editInfo"></BaseSubjective>
-
-            <!-- 解析的富文本部分 -->
-            <div class="exersices-analysis">
-                <IconText :text="'解析'" :color="'#2892DD'" :icon="'md-list'" style="margin-bottom:10px;"></IconText>
-                <div>
-                    <div ref="analysisEditor" style="text-align:left"></div>
-                </div>
+        </div>
+        <div class="display-flex">
+            <div class="exersices-attr my-radio-style">
+                <IconText :text="'题目归属'" :color="'#00b8ff'" :icon="'md-cube'"></IconText>
+                <Select v-model="exerciseScope">
+                    <Option v-for="(item,index) in scopeList" :value="index" :key="index">{{ item }}</Option>
+                </Select>
             </div>
-
-            <!-- 补救的富文本部分 -->
-            <div class="exersices-analysis">
-                <IconText :text="'补救资源'" :color="'#2892DD'" :icon="'md-list'" style="margin-bottom:10px"></IconText>
-                <div>
-                    <div ref="repairEditor" style="text-align:left"></div>
+            <div class="exersices-attr my-radio-style">
+                <IconText :text="'关联认知层次'" :color="'#00b8ff'" :icon="'md-planet'"></IconText>
+                <Select v-model="exerciseField">
+                    <Option v-for="(item,index) in fieldList" :value="index" :key="index">{{ item }}</Option>
+                </Select>
+            </div>
+            <div class="exersices-attr my-radio-style">
+                <IconText :text="'关联知识点'" :color="'#00b8ff'" :icon="'md-infinite'"></IconText>
+                <Button type="info" style="margin-top:20px" @click="selectPointsModal = true" v-if="exercisePoints.length === 0">选择知识点</Button>
+                <div v-else style="margin-top:10px">
+                    <span v-for="(item,index) in exercisePoints" :key="index" class="exercise-item-point">
+                        {{item.name}}
+                        <span class="exercise-item-point-close"><Icon type="md-close" @click="onDeletePoint(index)" /></span>
+                    </span>
+                    <span class="exercise-item-point-modify" @click="selectPointsModal = true">修改</span>
                 </div>
             </div>
 
-            <div class="save-wrap display-flex">
-                <Button type="success" @click="getContent(exersicesType)">保存</Button>
+        </div>
+        <div class="exersices-attr display-flex">
+            <div class="exersices-attr-type my-radio-style" style="width:50%">
+                <IconText :text="'选择题型'" :color="'#00b8ff'" :icon="'md-pricetags'"></IconText>
+                <RadioGroup v-model="exersicesType" type="button" @on-change="typeChange">
+                    <Radio label="Single" :disabled="isEdit">单选</Radio>
+                    <Radio label="Multiple" :disabled="isEdit">多选</Radio>
+                    <Radio label="Judge" :disabled="isEdit">判断</Radio>
+                    <Radio label="Complete" :disabled="isEdit">填空</Radio>
+                    <Radio label="Subjective" :disabled="isEdit">问答</Radio>
+                    <Radio label="Compose" :disabled="isEdit">综合</Radio>
+                </RadioGroup>
+            </div>
+            <div class="exersices-attr-diff edit-exersices-attr-diff my-radio-style">
+                <IconText :text="'题目难度'" :color="'#00b8ff'" :icon="'md-pulse'"></IconText>
+                <RadioGroup v-model="exersicesDiff" type="button" ref="diffRef">
+                    <Radio label="1" @click.native="diffChange($event,'1')">容易</Radio>
+                    <Radio label="2" @click.native="diffChange($event,'2')">较易</Radio>
+                    <Radio label="3" @click.native="diffChange($event,'3')">一般</Radio>
+                    <Radio label="4" @click.native="diffChange($event,'4')">较难</Radio>
+                    <Radio label="5" @click.native="diffChange($event,'5')">困难</Radio>
+                </RadioGroup>
+            </div>
+        </div>
+
+        <BaseSingle v-if="exersicesType==='Single'" ref="single" :editItem="editInfo"></BaseSingle>
+        <BaseMultiple v-else-if="exersicesType==='Multiple'" ref="multiple" :editInfo="editInfo"></BaseMultiple>
+        <BaseJudge v-else-if="exersicesType==='Judge'" ref="judge" :editInfo="editInfo"></BaseJudge>
+        <BaseCompletion v-else-if="exersicesType==='Complete'" ref="complete" :editInfo="editInfo"></BaseCompletion>
+        <BaseSubjective v-else-if="exersicesType==='Subjective'" ref="subjective" :editInfo="editInfo"></BaseSubjective>
+
+        <!-- 解析的富文本部分 -->
+        <div class="exersices-analysis">
+            <IconText :text="'解析'" :color="'#2892DD'" :icon="'md-list'" style="margin-bottom:10px;"></IconText>
+            <div>
+                <div ref="analysisEditor" style="text-align:left"></div>
+            </div>
+        </div>
+
+        <!-- 补救的富文本部分 -->
+        <div class="exersices-analysis">
+            <IconText :text="'补救资源'" :color="'#2892DD'" :icon="'md-list'" style="margin-bottom:10px"></IconText>
+            <Button type="info" class="btn-relate-content" @click="isRelatedContent = true">关联内容</Button>
+            <div>
+                <div ref="repairEditor" style="text-align:left"></div>
             </div>
+            <!-- 显示关联的内容 -->
+            <div v-for="item in relateFileList" :key="item.id" style="margin:10px 0">
+                <span><Icon type="md-checkmark" color="#1BC6B0" size="20" /></span>
+                <span style="margin-left:10px">{{ item.fileName }}</span>
+            </div>
+        </div>
+
+        <div class="save-wrap display-flex">
+            <Button type="success" @click="getContent(exersicesType)">保存</Button>
+        </div>
 
         <Modal v-model="selectPointsModal"
                title="选择知识点"
@@ -109,6 +115,18 @@
             </div>
         </Modal>
 
+        <!-- 关联内容弹窗 -->
+        <Modal v-model="isRelatedContent" width="880" footer-hide class="relate-modal related-modal">
+            <div class="modal-header" slot="header">内容关联</div>
+            <ChooseContent :showSyllabus="isFalse"
+                           :showOther="isFalse"
+                           :showQuestion="isFalse"
+                           @on-select-file="onSelectFile"
+                           @on-cancel-file="onSelectFile"></ChooseContent>
+
+            <Button class="modal-btn" :loading="isLoading" @click="onConfirmRelate">确认</Button>
+        </Modal>
+
     </div>
 </template>
 <script>
@@ -120,15 +138,19 @@
     import BaseJudge from '@/view/evaluation/types/BaseJudge.vue'
     import BaseSubjective from '@/view/evaluation/types/BaseSubjective.vue'
     import BasePoints from '@/view/evaluation/components/BasePoints'
+    import ChooseContent from '@/components/learnactivity/ChooseContent'
     import E from 'wangeditor'
     
     export default {
         props:['exerciseItem','refId'],
         components: {
-            IconText, BaseSingle, BaseJudge, BaseMultiple, BaseCompletion, BaseSubjective, BasePoints
+            IconText, BaseSingle, BaseJudge, BaseMultiple, BaseCompletion, BaseSubjective, BasePoints, ChooseContent
         },
         data() {
             return {
+                isFalse: false,
+                isLoading:false,
+                isRelatedContent:false,
                 selectPointsModal: false,
                 isEdit: false,
                 editInfo: {},
@@ -145,6 +167,7 @@
                 periodList: [],
                 gradeList: [],
                 subjectList: [],
+                relateFileList:[],
                 exersicesDiff: 0,
                 analysisContent: '',
                 repairContent: '',
@@ -167,6 +190,15 @@
                 })
             },
 
+            onSelectFile(val) {
+                this.relateFileList = val.files
+                
+            },
+
+            onConfirmRelate() {
+                this.isRelatedContent = false
+            },
+
             getContent: function (type) {
                 let exerciseItem = this.editInfo
                 switch (type) {
@@ -210,6 +242,7 @@
                 exerciseItem.id = this.editInfo.id ? this.editInfo.id : ''
                 exerciseItem.explain = this.analysisContent
                 exerciseItem.repair = this.repairContent
+                exerciseItem.repairResource = this.relateFileList
                 exerciseItem.field = this.fieldList[this.exerciseField]
                 exerciseItem.points = this.exercisePoints.map(item => item.id)
                 exerciseItem.periodCode = this.schoolInfo.period[this.exercisePeriod].periodCode
@@ -385,7 +418,7 @@
                 this.exerciseSubject = this.subjectList.map(item => item.subjectCode).indexOf(editItem.subjectCode)
 
                 this.stemContent = editItem.question
-
+                this.relateFileList = editItem.repairResource || []
                 this.optionsContent = editItem.option
                 this.analysisContent = editItem.explain
                 this.repairContent = editItem.repair
@@ -457,4 +490,73 @@
         line-height:38px;
         height:38px;
     }
-</style>
+
+    .related-point-modal .ivu-modal-content {
+        font-family: '微軟正黑體', 'Heiti TC';
+    }
+
+    .related-point-modal .ivu-modal-header-inner {
+        font-weight: bold;
+    }
+
+
+    .exersices-attr .ivu-select-multiple .ivu-tag {
+        height: 32px;
+        line-height: 31px;
+    }
+
+        .exersices-attr .ivu-select-multiple .ivu-tag i {
+            top: 9px;
+        }
+
+    .exersices-attr .ivu-select-multiple .ivu-select-selection .ivu-select-placeholder {
+        line-height: 38px;
+    }
+
+    /* 修改iview Modal样式 */
+
+    .related-modal .ivu-modal-content {
+        background: #3c3c3c;
+        overflow: hidden;
+        color: #fff;
+        font-family: '微軟正黑體', 'Heiti TC' !important;
+    }
+
+    .related-modal .ivu-modal-body {
+        height: 400px;
+        padding: 20px;
+    }
+
+    .related-modal .ivu-modal-body {
+        height: 700px;
+    }
+
+    .related-modal .ivu-modal-header {
+        border-bottom: none;
+        font-size: 18px;
+        font-weight: bold;
+        padding: 25px;
+    }
+
+    .related-modal .modal-content {
+        padding: 0 35px 30px 35px;
+    }
+
+    .related-modal .modal-btn {
+        margin-left: 2%;
+        width: 96%;
+        height: 40px;
+        background: rgb(11, 151, 117);
+        border: none;
+        color: #fff;
+        margin-top: 30px;
+    }
+
+    .related-modal .choose-content {
+        height: 85%;
+    }
+
+    .btn-relate-content {
+        right:0;
+    }
+</style>

+ 9 - 4
TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.vue

@@ -96,13 +96,15 @@
             <Upload action="/api/file/uploadWangEditor" name="files" :show-upload-list="false" :on-success="handleRepairSuccess">
                 <Button icon="ios-cloud-upload-outline" class="btn-upload" type="info">上传文件</Button>
             </Upload>
+
+            <div>
+                <div ref="repairEditor" style="text-align:left"></div>
+            </div>
+            <!-- 显示关联的内容 -->
             <div v-for="item in relateFileList" :key="item.id" style="margin:10px 0">
                 <span><Icon type="md-checkmark" color="#1BC6B0" size="20" /></span>
                 <span style="margin-left:10px">{{ item.fileName }}</span>
             </div>
-            <div>
-                <div ref="repairEditor" style="text-align:left"></div>
-            </div>
         </div>
 
         <div class="save-wrap display-flex">
@@ -240,7 +242,8 @@
             },
 
             onConfirmRelate() {
-
+                console.log(this.relateFileList)
+                this.isRelatedContent = false
             },
 
             getContent: function(type) {
@@ -291,6 +294,7 @@
                 }
                 exerciseItem.id = this.editInfo.id ? this.editInfo.id : ''
                 exerciseItem.repair = this.repairContent
+                exerciseItem.repairResource = this.relateFileList
                 exerciseItem.field = this.fieldList[this.exerciseField]
                 exerciseItem.points = this.exercisePoints.map(item => item.id)
                 exerciseItem.periodCode = this.schoolInfo.period[this.exercisePeriod].periodCode
@@ -502,6 +506,7 @@
                 this.optionsContent = editItem.options
                 this.analysisContent = editItem.explain
                 this.repairContent = editItem.repair
+                this.relateFileList = editItem.repairResource || []
                 this.analysisEditor.txt.html(editItem.explain)
                 this.repairEditor.txt.html(editItem.repair)
             }

+ 39 - 35
TEAMModelOS/ClientApp/src/view/student-analysis/total-analysis/TestAnalysis/QuestionList.vue

@@ -72,11 +72,11 @@
                         <!-- 查看数据分析 -->
                         <span>{{$t('totalAnalysis.ql_text10')}}</span>
                         <div class="answerAndExplain" slot="content" style="margin-top:10px" v-if="collapseList.indexOf(index.toString()) > -1">
-                            <Table :columns="dataColumns" :data="tableData.filter((item,index2) => index2 === index)"></Table>
-                            <Table :columns="optionColumns" :data="optionsData" style="margin-top:20px"></Table>
+                            <Table :columns="dataColumns"  :data="tableData.filter((item,index2) => index2 === index)"></Table>
+                            <Table :columns="optionColumns" v-if="question.type === 'Single' || question.type === 'Multiple'" :data="optionsData" style="margin-top:20px"></Table>
                             <div class="analysis-charts">
                                 <BaseLine :ids="'myLine' + index" :echartsData="tableData[index]"></BaseLine>
-                                <BaseRateLine :ids="'myRateLine' + index" :echartsData="optionsData"></BaseRateLine>
+                                <BaseRateLine :ids="'myRateLine' + index" v-if="question.type === 'Single' || question.type === 'Multiple'" :echartsData="optionsData"></BaseRateLine>
                             </div>
                         </div>
                     </Panel>
@@ -88,46 +88,49 @@
         <!-- 右侧题目列表题型概览 -->
         <div class='ql-right-box' ref="rightBox">
             <div class="ql-right-score">
-                {{$t('totalAnalysis.ql_text1')}} :<span>100 {{$t('totalAnalysis.ql_text8')}}</span>
+                {{$t('totalAnalysis.ql_text1')}} :<span>{{sumArr(questionList.map(item => item.score))}} {{$t('totalAnalysis.ql_text8')}}</span>
             </div>
             <div class="ql-right-list">
                 <vuescroll>
-                    <div class="ql-right-part" v-if="SingleList.length">
-                        <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text2')}}({{sumArr(SingleList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
-                        <div class="ql-right-items">
-                            <span class="ql-right-item" v-for="(item,index) in SingleList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                    <div>
+                        <div class="ql-right-part" v-if="SingleList.length">
+                            <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text2')}}({{sumArr(SingleList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
+                            <div class="ql-right-items">
+                                <span class="ql-right-item" v-for="(item,index) in SingleList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                            </div>
                         </div>
-                    </div>
-                    <div class="ql-right-part" v-if="MultipleList.length">
-                        <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text3')}}({{sumArr(MultipleList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
-                        <div class="ql-right-items">
-                            <span class="ql-right-item" v-for="(item,index) in MultipleList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                        <div class="ql-right-part" v-if="MultipleList.length">
+                            <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text3')}}({{sumArr(MultipleList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
+                            <div class="ql-right-items">
+                                <span class="ql-right-item" v-for="(item,index) in MultipleList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                            </div>
                         </div>
-                    </div>
-                    <div class="ql-right-part" v-if="JudgeList.length">
-                        <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text4')}}({{sumArr(JudgeList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
-                        <div class="ql-right-items">
-                            <span class="ql-right-item" v-for="(item,index) in JudgeList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                        <div class="ql-right-part" v-if="JudgeList.length">
+                            <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text4')}}({{sumArr(JudgeList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
+                            <div class="ql-right-items">
+                                <span class="ql-right-item" v-for="(item,index) in JudgeList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                            </div>
                         </div>
-                    </div>
-                    <div class="ql-right-part" v-if="CompleteList.length">
-                        <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text5')}}({{sumArr(CompleteList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
-                        <div class="ql-right-items">
-                            <span class="ql-right-item" v-for="(item,index) in CompleteList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                        <div class="ql-right-part" v-if="CompleteList.length">
+                            <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text5')}}({{sumArr(CompleteList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
+                            <div class="ql-right-items">
+                                <span class="ql-right-item" v-for="(item,index) in CompleteList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                            </div>
                         </div>
-                    </div>
-                    <div class="ql-right-part" v-if="SubjectiveList.length">
-                        <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text6')}}({{sumArr(SubjectiveList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
-                        <div class="ql-right-items">
-                            <span class="ql-right-item" v-for="(item,index) in SubjectiveList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                        <div class="ql-right-part" v-if="SubjectiveList.length">
+                            <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text6')}}({{sumArr(SubjectiveList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
+                            <div class="ql-right-items">
+                                <span class="ql-right-item" v-for="(item,index) in SubjectiveList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                            </div>
                         </div>
-                    </div>
-                    <div class="ql-right-part" v-if="ComposeList.length">
-                        <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text7')}}({{sumArr(ComposeList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
-                        <div class="ql-right-items">
-                            <span class="ql-right-item" v-for="(item,index) in ComposeList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                        <div class="ql-right-part" v-if="ComposeList.length">
+                            <span class="ql-right-part-title"><span class="ql-line"></span>{{$t('totalAnalysis.ql_text7')}}({{sumArr(ComposeList.map(item => item.score))}}{{$t('totalAnalysis.ql_text8')}})</span>
+                            <div class="ql-right-items">
+                                <span class="ql-right-item" v-for="(item,index) in ComposeList" :key="index" @click="handleItemClick(item,$event)" :ref="'indexRef' + questionList.indexOf(item)">{{questionList.indexOf(item) + 1}}</span>
+                            </div>
                         </div>
-                    </div><div style="margin-top:30px">注:标红题号为班级易错题目</div>
+                    </div>
+                    <!--<div style="margin-top:30px">注:标红题号为班级易错题目</div>-->
                 </vuescroll>
             </div>
         </div>
@@ -467,7 +470,7 @@
 
             // 返回题目区域总分 字符串换算
             sumArr(arr) {
-                // return eval(arr.join('+'))
+                return arr.reduce((a,b) => a + b)
             }
         },
 
@@ -511,6 +514,7 @@
             getExerciseData(val) {
                 if (!val) return
                 this.tableData = JSON.parse(JSON.stringify(val))
+                console.log(this.tableData)
             }
         }
     }

+ 2 - 2
TEAMModelOS/ClientApp/src/view/teachcontent/index.vue

@@ -19,9 +19,9 @@
                     <span class="content-type-label">{{item.label}}</span>
                 </div>
                 <div :class="($access.can('admin.*|content-school-upd') || rangeType == 1) ? 'space-box animated fadeIn fast' : 'space-box animated fadeOut fast'">
-                    <Progress hide-info :percent="storageSpace/1024/1024/1024/2*100" :stroke-width="15" style="width:100%;" />
+                    <Progress hide-info :percent="storageSpace/1024/1024/1024*100" :stroke-width="15" style="width:100%;" />
                     <p>
-                        <span>{{$t('teachContent.space')}}{{storageSpace/1024 < 1024 ? (storageSpace/1024).toFixed(1) + 'KB' : storageSpace/1024/1024 < 1024 ?  (storageSpace/1024/1024).toFixed(1) + 'M': (storageSpace/1024/1024/1024).toFixed(1) + 'G'}}/2G</span>
+                        <span>{{$t('teachContent.space')}}{{storageSpace/1024 < 1024 ? (storageSpace/1024).toFixed(1) + 'KB' : storageSpace/1024/1024 < 1024 ?  (storageSpace/1024/1024).toFixed(1) + 'M': (storageSpace/1024/1024/1024).toFixed(1) + 'G'}}/1G</span>
                         <!--<span>扩容</span>-->
                     </p>
                 </div>

+ 6 - 2
TEAMModelOS/ClientApp/src/view/teachermgmt/Index.vue

@@ -14,7 +14,7 @@
       <div class="mgmt-top">
         <div class="tab-box">
           <span class="pane" @click="paneBtn('userList')" :class="{ 'active': compts === 'userList' }" >{{$t('teachermgmt.page.text1')}}</span>
-          <span class="pane" @click="paneBtn('personnel')" :class="{ 'active': compts === 'personnel' }">{{$t('teachermgmt.page.text2')}} <Badge :count="5" class-name="badgesty"></Badge></span>
+          <span class="pane" @click="paneBtn('personnel')" :class="{ 'active': compts === 'personnel' }">{{$t('teachermgmt.page.text2')}} <Badge :count="requestedUserCount" class-name="badgesty"></Badge></span>
         </div>
       </div>
       <div class="mgmt-main">
@@ -30,6 +30,7 @@
 <script>
 import userList from './components/userList/Index.vue'
 import personnel from './components/personnel/Index.vue'
+import { mapGetters, mapMutations } from 'vuex'
 
 export default {
   data() {
@@ -42,7 +43,10 @@ export default {
     personnel
   },
   computed: {
-    user() { return this.$access.getExtendInfo('userInfo');}
+      ...mapGetters({
+          requestedUserCount: 'user/getSchoolUserRequestedCount' //取得申請加入此學校的使用者數
+      }),
+      user() { return this.$access.getExtendInfo('userInfo'); }
   },
   methods: {
     paneBtn(pane) {

文件差異過大導致無法顯示
+ 127 - 67
TEAMModelOS/ClientApp/src/view/teachermgmt/components/personnel/Index.vue


+ 50 - 42
TEAMModelOS/ClientApp/src/view/teachermgmt/components/userList/Index.vue

@@ -123,16 +123,19 @@
             </div>
             <div class="userListContent">
                 <Table class="scrollstyle" :height="tableHeight" ref="selection" :columns="tableColumns" :data="tableData" @on-selection-change="setTeachers" @on-sort-change="changeSort">
-                    <template slot-scope="{ row }" slot="cellphone">
-                        <Icon v-if="row.cellphone" color="#1eb38d" size="30" type="md-checkmark" />
+                    <template slot="picture">
+                    </template>
+                    <!--<template slot-scope="{ row }" slot="mobile">
+                        <Icon v-if="row.mobile" color="#1eb38d" size="30" type="md-checkmark" />
                         <Icon v-else color="#c43635" size="30" type="md-close" />
                     </template>
                     <template slot-scope="{ row }" slot="email">
                         <Icon v-if="row.email" color="#1eb38d" size="30" type="md-checkmark" />
                         <Icon v-else color="#c43635" size="30" type="md-close" />
-                    </template>
-                    <template slot-scope="{ row }" slot="loginCount">
-                        {{$t('teachermgmt.table.text1')}} {{row.loginCount}} {{$t('teachermgmt.table.text2')}}
+                    </template>-->
+                    <template slot-scope="{ row }" slot="loginStatus">
+                        <span v-if="row.loginFlg">{{$t('teachermgmt.table.text1')}}</span>
+                        <span v-else>{{$t('teachermgmt.table.text2')}} {{row.lastLoginDateHIS}}</span>
                     </template>
                     <template slot-scope="{ row }" slot="action">
                         <icon icon="shield-alt" style="font-size: 14px;color: #fff;margin-right: 20px;cursor: pointer;" @click="showAuth(row)" />
@@ -151,9 +154,9 @@
                     {{$t('teachermgmt.authSet.subTitle')}}
                 </div>
                 <div class="ids scrollstyle">
-                    <span v-for="(item, key) in TEAMModelIds" :key="key">
+                    <span v-for="(item, key) in ids" :key="key">
                         {{item}}
-                        <span v-if="TEAMModelIds[key+1]">,</span>
+                        <span v-if="ids[key+1]">,</span>
                     </span>
                 </div>
             </div>
@@ -251,10 +254,31 @@ export default {
                     width: 60,
                     align: 'center'
                 },
+                {
+                    title: ' ',
+                    width: 80,
+                    key: 'picture',
+                    align: 'center',
+                    render: (h, params) => {
+                        return h('img', {
+                            attrs: {
+                                src: params.row.picture,
+                            },
+                            style: {
+                                display: 'inline-block',
+                                width: '36px',
+                                'border-radius': '50%',
+                                'align-items': 'center',
+                                'justify-content': 'center',
+                                'overflow': 'hidden'
+                            },
+                        })
+                    }
+                },
                 {
                     title: this.$t('teachermgmt.table.th1'),
                     width: 230,
-                    key: 'TEAMModelId',
+                    key: 'id',
                     sortable: true
                 },
                 {
@@ -264,32 +288,16 @@ export default {
                 },
                 {
                     title: this.$t('teachermgmt.table.th3'),
-                    width: 150,
+                    width: 200,
                     key: 'jobTitle',
                     sortable: true
                 },
-                {
-                    title: this.$t('teachermgmt.table.th4'),
-                    slot: 'cellphone',
-                    sortable: 'custom',
-                    show: true,
-                    align: 'center',
-                    width: 130
-                },
-                {
-                    title: this.$t('teachermgmt.table.th5'),
-                    slot: 'email',
-                    sortable: true,
-                    show: true,
-                    align: 'center',
-                    width: 130,
-                },
                 {
                     title: this.$t('teachermgmt.table.th6'),
-                    slot: 'loginCount',
+                    slot: 'loginStatus',
                     sortable: true,
                     show: true,
-                    width: 200,
+                    width: 260,
                 },
                 {
                     title: ' ',
@@ -303,7 +311,7 @@ export default {
             blurryFilter:'',
             tableHeight: 100,
             screenHeight: document.documentElement.clientHeight, //螢幕高度
-            TEAMModelIds:[],
+            ids:[], //操作中的ID列表
             multiSetMode: false,    // 多筆設定
             teachers:[],
             switchTrueColor: '#008f6b',
@@ -323,7 +331,7 @@ export default {
                 // 可以客制調整
                 filterData = this.data.filter(res => {
                     let a = res.name.toLowerCase();
-                    let b = res.TEAMModelId.toLowerCase();
+                    let b = res.id.toLowerCase();
                     return (a.indexOf(this.blurryFilter) >= 0) || (b.indexOf(this.blurryFilter) >= 0)
                 })
             }
@@ -352,20 +360,20 @@ export default {
         showAuth: function (val) {    // 個人設定
             console.log(val)
             this.authMulti = true
-            this.TEAMModelIds.push(val.TEAMModelId)
-            let selectUserList = this.$store.getters['user/getSchoolUserByTMID'](val.TEAMModelId)
+            this.ids.push(val.id)
+            let selectUserList = this.$store.getters['user/getSchoolUserByID'](val.id)
             if (selectUserList.length > 0) {
                 this.userSelected = selectUserList[0]
             }
-            console.log('this.userSelected') // 被選取得使用者資料 (各權限反映使用者設定 未製作)
+            console.log('this.userSelected') // 被選取得使用者資料 (各權限反映使用者設定 未製作)
             console.log(this.userSelected)
         },
-        removeUser: function(val){
+        removeUser: function(val){ //val:使用者的資料(object)
             this.$Modal.confirm({
                 title: this.$t('teachermgmt.model.delTeacher.title'),
-                content: '<p>'+this.$t('teachermgmt.model.delTeacher.text1') + ' ' + val.name + '(' + val.TEAMModelId +') ?</p>',
+                content: '<p>'+this.$t('teachermgmt.model.delTeacher.text1') + ' ' + val.name + '(' + val.id +') ?</p>',
                 onOk: () => {
-                    this.$store.dispatch('user/rmvFromSchoolUserByTMID', { TEAMModelIds: [val.TEAMModelId] }).then(
+                    this.$store.dispatch('user/rmvFromSchoolUserByID', { Ids: [val.id] }).then(
                         (res) => {
                             if (res.code == 1) {
                                 this.$Message.info(this.$t('teachermgmt.message.info1'));
@@ -389,7 +397,7 @@ export default {
                 this.authMulti = true
                 this.multiSetMode = true
                 this.teachers.forEach(res => {
-                    this.TEAMModelIds.push(res.TEAMModelId)
+                    this.ids.push(res.id)
                 })
             } else {
                 this.$Modal.warning({
@@ -404,18 +412,18 @@ export default {
         closeAuthSeting: function(){
             this.multiSetMode = false
             this.authMulti = false
-            this.TEAMModelIds = []
+            this.ids = []
             this.authSelected = []
             this.userSelected = undefined
         },
         // ASC 代表結果會以由小往大的順序列出,而 DESC 代表結果會以由大往小的順序列出。
-        changeSort({column, key, order}){
-            if(column.slot === 'cellphone' || column.slot === 'email' || column.slot === 'loginCount'){
+        changeSort({ column, key, order }) {
+            if (column.slot === 'mobile' || column.slot === 'email' || column.slot === 'loginStatus'){
                 let data = this.data
                 this.data.sort(function(a, b){
                     let nameA = a[column.slot]
                     let nameB = b[column.slot]                    
-                    if(column.slot === 'cellphone' || column.slot === 'email'){
+                    if (column.slot === 'mobile' || column.slot === 'email'){
                         nameA = a[column.slot] ? 1 : 0;
                         nameB = b[column.slot] ? 1 : 0;
                     }
@@ -433,9 +441,9 @@ export default {
         },
         //權限賦予
         setSchoolUserAuth(){
-            if(this.TEAMModelIds.length > 0)
+            if (this.ids.length > 0)
             {
-                this.$store.dispatch('user/setSchoolUserAuth', { TEAMModelIds: this.TEAMModelIds, authList: this.authSelected }).then(
+                this.$store.dispatch('user/setSchoolUserAuth', { ids: this.ids, authList: this.authSelected }).then(
                 (res) => {
                     if (res.code == 1) {
                         this.$Modal.success({

+ 17 - 18
TEAMModelOS/Controllers/Core/SchoolUserController.cs

@@ -39,7 +39,8 @@ namespace TEAMModelOS.Controllers.Core
         public async Task<BaseJosnRPCResponse> GetSchoolUser(JosnRPCRequest<Dictionary<string, object>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            List<SchoolUser> su = await _cosmosrepository.FindByDict<SchoolUser>(request.@params); 
+            request.@params.TryGetValue("code", out object partitionKey);
+            List<SchoolUser> su = await _cosmosrepository.FindByDict<SchoolUser>(request.@params, partitionKey.ToString()); 
             return builder.Data(su).build();
         }
 
@@ -52,14 +53,14 @@ namespace TEAMModelOS.Controllers.Core
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             request.@params.TryGetValue("schoolCode", out object schoolCode);
-            request.@params.TryGetValue("TEAMModelIds", out object TEAMModelIds);
+            request.@params.TryGetValue("ids", out object ids);
             request.@params.TryGetValue("authList", out object authListObj);
             List<string> authList = JsonConvert.DeserializeObject<List<string>>(authListObj.ToString());
             //取得已加入該校的使用者 (joinStatus=1: [加入狀態]  1:已加入)
             Dictionary<string, object> userDict = new Dictionary<string, object>
             {
                 { "schoolCode",  schoolCode.ToString()},
-                { "TEAMModelId",  TEAMModelIds},
+                { "id",  ids},
                 { "joinStatus",  1}
             };
             List<SchoolUser> suListResponse = new List<SchoolUser>(); //返回值
@@ -84,23 +85,21 @@ namespace TEAMModelOS.Controllers.Core
         public async Task<BaseJosnRPCResponse> RmvSchoolUser(JosnRPCRequest<Dictionary<string, object>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            if (request.@params.TryGetValue("schoolCode", out object schoolCode) && request.@params.TryGetValue("TEAMModelIds", out object TEAMModelIds)) 
+            request.@params.TryGetValue("schoolCode", out object schoolCode);
+            request.@params.TryGetValue("Ids", out object Ids);
+            //以TEAMModelId(array)取得該校的使用者
+            Dictionary<string, object> userDict = new Dictionary<string, object>
             {
-                //取得已加入該校的使用者 (joinStatus=1: [加入狀態]  1:已加入)
-                Dictionary<string, object> userDict = new Dictionary<string, object>
-                {
-                    { "schoolCode",  schoolCode.ToString()},
-                    { "TEAMModelId",  TEAMModelIds},
-                    { "joinStatus",  1}
-                };
-                List<SchoolUser> suList = await _cosmosrepository.FindByDict<SchoolUser>(userDict);
-                //移除
-                if (suList.Count > 0)
+                { "schoolCode",  schoolCode.ToString()},
+                { "id",  Ids}
+            };
+            List<SchoolUser> suList = await _cosmosrepository.FindByDict<SchoolUser>(userDict);
+            //移除
+            if (suList.Count > 0)
+            {
+                foreach (SchoolUser su in suList)
                 {
-                    foreach (SchoolUser su in suList)
-                    {
-                        await _cosmosrepository.DeleteAsync(su);
-                    }
+                    await _cosmosrepository.DeleteAsync(su);
                 }
             }
             return builder.build();