Browse Source

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

OnePsycho 5 years ago
parent
commit
0722e7f3d5

+ 1 - 0
TEAMModelOS.Service/Models/Core/Classroom.cs

@@ -25,6 +25,7 @@ namespace TEAMModelOS.Service.Models.Core
         public string hiteach { get; set; }
         public int studentCount { get; set; }
         public string classroomType { get; set; }
+        public int status { get; set; } = 1;
     }
 }
 public class Point

+ 36 - 0
TEAMModelOS.Service/Models/Core/LoginInfo.cs

@@ -0,0 +1,36 @@
+using Microsoft.WindowsAzure.Storage.Table;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+
+namespace TEAMModelOS.Service.Models.Core
+{
+    /// <summary>
+    /// 登录信息
+    /// </summary>
+    [TableSpace(Name = "Core")]
+    public class LoginInfo : TableEntity
+    {
+        public string TeamModelId { get; set; }
+        public string Phone { get; set; }
+        public string Ticket { get; set; }
+        public string Name { get; set; }
+        public string Token { get; set; }
+        public string CountryCode { get; set; }
+        /// <summary>
+        /// 登录时间
+        /// </summary>
+        public long LoginTime { get; set; }
+        /// <summary>
+        /// 超时时间
+        /// </summary>
+        public long Timeout { get; set; }
+        /// <summary>
+        /// 到期时间
+        /// </summary>
+        public long Expires { get; set; }
+        /// <summary>
+        /// 作用域
+        /// </summary>
+        public string Scope { get; set; }
+
+    }
+}

+ 2 - 1
TEAMModelOS.Service/Models/Core/School.cs

@@ -13,8 +13,9 @@ namespace TEAMModelOS.Service.Models.Core
         }
         [JsonProperty(PropertyName = "id")]
         public string id { get; set; }
-        [PartitionKey]
         public string schoolCode { get; set; }
+        [PartitionKey]
+        public string areaCode { get; set; }
         public string schoolName { get; set; }
         public List<Period> period { get; set; }
 

+ 43 - 0
TEAMModelOS.Service/Models/Core/Teacher.cs

@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+
+namespace TEAMModelOS.Service.Models.Core
+{
+    public class Teacher
+    {
+        public string id { get; set; }
+        /// <summary>
+        /// 0 动态id  透過第三方申請,未認證手機號,TEAMModelId暫時為virtualId但是不顯示在介面上,當使用者驗證手機號後TEAMModelId會變為手機號。
+        /// 1 动态id  透過手機號申請,TEAMModelId為手機號
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public int type { get; set; }
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string name { get; set; }
+        public string email { get; set; }
+        public string cellphone { get; set; }
+        [PartitionKey]
+        public string countryCode { get; set; }
+        public int verifyFlg { get; set; }
+        public int status { get; set; } = 0;
+        public long createDate { get; set; }
+        public Password password { get; set; }
+        public string exValue { get; set; }
+        public string product { get; set; }
+        public List<ProductToken> productToken { get; set; }
+        public string shortCode { get; set; }
+        public string profilePicture { get; set; }
+        public string profilePictureUrl { get; set; }
+        public string TEAMModelId { get; set; }
+        public string loginTime { get; set; }
+        public string virtualId { get; set; }
+        public List<Oauth> oauth { get; set; } // 0 1
+        public string haveDevice { get; set; }//2
+        public Classroom classroom { get; set; }
+        public string studentId { get; set; }
+        public int seatNo { get; set; }
+    }
+}

+ 2 - 0
TEAMModelOS/ClientApp/package.json

@@ -16,6 +16,7 @@
     "d3": "^5.9.2",
     "echarts": "^4.2.1",
     "json-markup": "^1.1.3",
+    "jsonpath": "^1.0.2",
     "jwt-decode": "^2.2.0",
     "less": "^3.9.0",
     "mockjs": "^1.0.1-beta3",
@@ -35,6 +36,7 @@
     "vue-template-compiler": "^2.6.9",
     "vue-video-player": "^5.0.2",
     "vuedraggable": "^2.23.0",
+    "vuescroll": "^4.14.4",
     "vuex": "^3.0.1",
     "vuex-oidc": "^3.3.0",
     "vuex-router-sync": "^5.0.0",

+ 2 - 2
TEAMModelOS/ClientApp/src/api/schoolSetting.js

@@ -1,13 +1,13 @@
 import { fetch, post } from '@/filters/http'
 export default {
   schoolSettingSaveOrUpdate: function (data) {
-    return post('/api/SchoolSystem/SaveOrUpdateAll',data);
+    return post('/api/School/SaveOrUpdateAll',data);
   },
   classroomSettingSaveOrUpdate: function (data) {
     return post('/api/Classroom/SaveOrUpdateAll', data);
   },
   findSchoolSystem: function (data) {
-    return post('/api/SchoolSystem/FindSchoolSystem', data);
+    return post('/api/School/FindSchool', data);
   },
   findClassInfo: function (data) {
     return post('/api/Classroom/FindClassInfo', data);

+ 6 - 6
TEAMModelOS/ClientApp/src/api/stuAccount.js

@@ -1,21 +1,21 @@
 import { fetch, post } from '@/filters/http'
 export default {
   saveStudentInfo: function (data) {
-    return post('api/StudentInfo/SaveStudentInfo', data);
+        return post('api/Student/SaveStudent', data);
   },
   findStudentInfo: function (data) {
-    return post('api/StudentInfo/FindStudentParams', data);
+      return post('api/Student/FindStudent', data);
   },
   saveAllStudentInfo: function (data) {
-    return post('api/StudentInfo/SaveAllStudentInfo', data);
+      return post('api/StudentInfo/SaveAllStudent', data);
   },
   updateAllStudentInfo: function (data) {
-    return post('api/StudentInfo/UpdateAllStudentInfo', data);
+      return post('api/StudentInfo/UpdateStudent', data);
   },
   updateStudentInfo: function (data) {
-    return post('api/StudentInfo/UpdateStudentInfo', data);
+      return post('api/StudentInfo/UpdateAllStudent', data);
   },
   deleteStudentInfo: function (data) {
-    return post('api/StudentInfo/DeleteStudentInfo', data);
+      return post('api/StudentInfo/DeleteStudent', data);
   }
 }

+ 59 - 56
TEAMModelOS/ClientApp/src/boot-app.js

@@ -10,12 +10,13 @@ import { FontAwesomeIcon } from './icons'
 //import 'iview/dist/styles/iview.css';
 import ViewUI from 'view-design';
 import 'view-design/dist/styles/iview.css';
-import commons from "@/utils/public.js";
+import tools from "@/utils/public.js";
 import apiTools from '@/api';
 import mockTools from '@/mock';
 import { fetch, post } from '@/filters/http';
 import VideoPlayer from 'vue-video-player';
 import jwtDecode from 'jwt-decode';
+import JSONPath from 'jsonpath';
 import Loading from '@/common/Loading';
 import BaseChangeLine from '@/components/student-analysis/total/BaseChangeLine.vue'
 
@@ -27,8 +28,13 @@ Vue.use(Loading);
 Vue.component('BaseChangeLine', BaseChangeLine);
 
 //新添加的
-import vuescroll from 'vue-scroll'
 import echarts from 'echarts'
+import vuescroll from 'vuescroll/dist/vuescroll-native';
+// 你可以在这里设置全局配置
+Vue.use(vuescroll, {
+    ops: tools.vueScrollOpt, // 在这里设置全局默认配置
+    name: 'vuescroll' // 在这里自定义组件名字,默认是vueScroll
+});
 
 //全局API请求
 Vue.prototype.$api = apiTools;
@@ -37,94 +43,91 @@ Vue.prototype.$get = fetch;
 
 //mock数据工具
 Vue.prototype.$Mock = mockTools;
-
 Vue.prototype.$jwtDecode = jwtDecode;
-
-Vue.use(vuescroll)
+Vue.prototype.$JSONPath = JSONPath;
 Vue.prototype.$echarts = echarts
-
 //ZXJ
-Vue.prototype.common = commons;
+Vue.prototype.$tools = tools;
 
 // Registration of global components
-Vue.component('icon', FontAwesomeIcon); 
+Vue.component('icon', FontAwesomeIcon);
 
 const _import = require('./router/_import_file.js')//获取组件的方法
 var getRouter //用来获取后台拿到的路由
 
 // 動態加路由
-//if(!getRouter){
-//  if (!getObjArr('router')) {
-//    axios.get('/api/testAPI/GetTestAuth').then(res =>{  
-//      getRouter = res.data.data;
-//      saveObjArr('router', getRouter) //存储路由到localStorage
-//      getRouter = filterAsyncRouter(getRouter) //过滤路由
-//      // 存入vuex
-//      store.state.authorization.antRouter = getRouter;
-//      router.addRoutes(getRouter) //动态添加路由
-//    });    
-//  } else {
-//    getRouter = getObjArr('router')//拿到路由
-//    getRouter = filterAsyncRouter(getRouter) //过滤路由
-//    // 存入vuex
-//    store.state.authorization.antRouter = getRouter;
-//    router.addRoutes(getRouter) //动态添加路由
-//  }
+//if (!getRouter) {
+//    if (!getObjArr('router')) {
+//        axios.get('/api/testAPI/GetTestAuth').then(res => {
+//            getRouter = res.data.data;
+//            saveObjArr('router', getRouter) //存储路由到localStorage
+//            getRouter = filterAsyncRouter(getRouter) //过滤路由
+//            // 存入vuex
+//            store.state.authorization.antRouter = getRouter;
+//            router.addRoutes(getRouter) //动态添加路由
+//        });
+//    } else {
+//        getRouter = getObjArr('router')//拿到路由
+//        getRouter = filterAsyncRouter(getRouter) //过滤路由
+//        // 存入vuex
+//        store.state.authorization.antRouter = getRouter;
+//        router.addRoutes(getRouter) //动态添加路由
+//    }
 //}
 
-router.beforeEach((to, from, next) => {  
-  document.body.scrollTop = 0;
-  next();
+router.beforeEach((to, from, next) => {
+    document.body.scrollTop = 0;
+    next();
 });
 
 function saveObjArr(name, data) { // 存储数组对象的方法
-  sessionStorage.setItem(name, JSON.stringify(data))
+    sessionStorage.setItem(name, JSON.stringify(data))
 }
 
 function getObjArr(name) { // 获取数组对象的方法
-  return JSON.parse(window.sessionStorage.getItem(name));
+    return JSON.parse(window.sessionStorage.getItem(name));
 }
 
-//function filterAsyncRouter(routers){
-//  let newRouter = [];
-//  routers.forEach(function(item){
-//    let page = {//}
-//      name: '',
-//      path: '',
-//      component: '',
-//      meta:{
-//        access:[]
-//      }
-//    };
-//    page.name = item.component;
-//    page.path = item.path;
-//    page.meta.access = item.access;
-//    page.component = _import(item.component);
-//    newRouter.push(page)
-//  }); 
-//  return newRouter;
-
+function filterAsyncRouter(routers) {
+    let newRouter = [];
+    routers.forEach(function (item) {
+        let page = {
+            name: '',
+            path: '',
+            component: '',
+            meta: {
+                access: []
+            }
+        };
+        page.name = item.component;
+        page.path = item.path;
+        page.meta.access = item.access;
+        page.component = _import(item.component);
+        newRouter.push(page)
+    });
+    return newRouter;
+}
 
 router.afterEach((to, from, next) => {
-  document.body.scrollTop = 0;
+    document.body.scrollTop = 0;
 });
 
 
 
 
 Vue.use(ViewUI, {
-  i18n: (key, value) => i18n.t(key, value)
+    i18n: (key, value) => i18n.t(key, value)
 })
 
 sync(store, router)
 
 const app = new Vue({
-  store,
-  router,
-  i18n,
-  ...App
+    store,
+    router,
+    i18n,
+    ...App
 })
 
 export {
-  app
+    app
 }

+ 9 - 5
TEAMModelOS/ClientApp/src/common/EditableLabel.vue

@@ -48,11 +48,15 @@
     display:inline-block;
     /*width:80%;*/
   }
-  #test {
-    visibility:hidden;
-    border: 1px solid black;
-    width: fit-content;
-  }
+    #test {
+        position: absolute;
+        left: 0px;
+        top: 0px;
+        font-size:18px;
+        visibility: hidden;
+        border: 1px solid black;
+        width: fit-content;
+    }
     .editable-label .ivu-input {
       background:#565656;
       border-color:transparent;

+ 46 - 48
TEAMModelOS/ClientApp/src/view/school-mgmt/ClassroomSetting/ClassroomSetting.vue

@@ -97,20 +97,20 @@
           </p>
           <div class="class-list">
             <div class="class-list-item" v-for="(item,index) in classroomListShow" @click="chooseClassroom(index)" :class="currentClassroomIndex == index ? 'active-item-bg':''">
-              <div class="class-list-item-left">
-                <p class="class-name">{{item.name}}</p>
-                <p class="class-hiteach-code second-text-color">{{item.hiTeach}}</p>
-                <p class="class-type">
-                  <Icon type="md-arrow-dropright" size="18" />{{item.classroomType}}
-                </p>
-                <p class="second-text-color">
-                  <!--<span>学生人数:</span>
-                <span class="primary-text-color">{{item.stuNum}}</span>
-                <span>|</span>-->
-                  <span>{{$t('schoolBaseInfo.headmaster')+":"}}</span>
-                  <span class="primary-text-color">{{item.headMaster}}</span>
-                </p>
-              </div>
+                <div class="class-list-item-left">
+                    <p class="class-name">{{item.classroomName}}</p>
+                    <p class="class-hiteach-code second-text-color">{{item.hiteach}}</p>
+                    <p class="class-type">
+                        <Icon type="md-arrow-dropright" size="18" />{{item.classroomType}}
+                    </p>
+                    <p class="second-text-color">
+                        <!--<span>学生人数:</span>
+                        <span class="primary-text-color">{{item.studentCount}}</span>
+                        <span>|</span>-->
+                        <span>{{$t('schoolBaseInfo.headmaster')}}</span>
+                        <span class="primary-text-color">{{item.headMaster}}</span>
+                    </p>
+                </div>
               <div class="class-list-item-tool">
                 <!--<Icon type="ios-copy" title="复制" />-->
                 <Icon type="md-trash" :title="$t('schoolBaseInfo.delete')" @click.stop="delClassroom(index)" />
@@ -127,19 +127,19 @@
             <span class="class-attr-wrap-label">{{$t('schoolBaseInfo.classroomCode')}}</span>
             <Input v-model="classroomList[currentClassroomIndex].classroomCode" clearable :placeholder="$t('schoolBaseInfo.classroomCodeHolder')" />
             <span class="class-attr-wrap-label">{{$t('schoolBaseInfo.classroomName')}}</span>
-            <Input v-model="classroomList[currentClassroomIndex].name" clearable :placeholder="$t('schoolBaseInfo.classroomNameHolder')" />
+            <Input v-model="classroomList[currentClassroomIndex].classroomName" clearable :placeholder="$t('schoolBaseInfo.classroomNameHolder')" />
             <span class="class-attr-wrap-label">{{$t('schoolBaseInfo.headmaster')}}</span>
             <Input v-model="classroomList[currentClassroomIndex].headMaster" clearable :placeholder="$t('schoolBaseInfo.headmasterHolder')" />
             <span class="class-attr-wrap-label">{{$t('schoolBaseInfo.setPeriod')}}</span>
-            <Select v-model="classroomList[currentClassroomIndex].period" clearable>
-              <Option v-for="(item,index) in periodList" :value="item.code" :key="index" @click.native="currentPIndex = index">{{ item.name }}</Option>
+            <Select v-model="classroomList[currentClassroomIndex].periodCode" clearable>
+              <Option v-for="(item,index) in periodList" :value="item.periodCode" :key="index" @click.native="currentPIndex = index">{{ item.periodName }}</Option>
             </Select>
             <span class="class-attr-wrap-label">{{$t('schoolBaseInfo.setGrade')}}</span>
-            <Select v-model="classroomList[currentClassroomIndex].grade" clearable>
-              <Option v-for="(item,index) in periodList[currentPIndex].grade" :value="item.code" :key="index">{{ item.name }}</Option>
+            <Select v-model="classroomList[currentClassroomIndex].gradeCode" clearable>
+              <Option v-for="(item,index) in periodList[currentPIndex].grades" :value="item.gradeCode" :key="index">{{ item.gradeName }}</Option>
             </Select>
             <span class="class-attr-wrap-label">{{$t('schoolBaseInfo.setHiteachCode')}}</span>
-            <Input v-model="classroomList[currentClassroomIndex].hiTeach" disabled :placeholder="$t('schoolBaseInfo.hiTeachHolder')" clearable />
+            <Input v-model="classroomList[currentClassroomIndex].hiteach" disabled :placeholder="$t('schoolBaseInfo.hiTeachHolder')" clearable />
             <Divider style="margin-top:60px;color:#424242;" />
           </div>
           <div class="hiteach-code-wrap">
@@ -296,12 +296,12 @@
           }
         ],
         classroomList: [{
-          name: '预设教室',
+          classroomName: '预设教室',
           hiTeach: '',
           headMaster: '未指定班主任',
-          period: '', 
-          grade: '',
-          stuNum: 0,
+          periodCode: '', 
+          gradeCode: '',
+          studentCount: 0,
           classroomType: 'TEAM MODEL智慧教室',
           classroomCode: '教室编码',
           point: {
@@ -312,12 +312,12 @@
         classroomListShow: [],
         periodList: [
           {
-            name: '暂无学段信息',
-            code: "",
-            grade: [
+            periodName: '暂无学段信息',
+            periodCode: "",
+            grades: [
               {
-                name: '暂无年级信息',
-                code: ""
+                gradeName: '暂无年级信息',
+                gradeCode: ""
               }
             ]
           }
@@ -450,7 +450,7 @@
         if (this.serchClassname == '') {
           this.classroomListShow = [...this.classroomList];
         } else {
-          this.classroomListShow = this.classroomList.filter(item => item.name.indexOf(_this.serchClassName) != -1);
+          this.classroomListShow = this.classroomList.filter(item => item.classroomName.indexOf(_this.serchClassName) != -1);
         }
       },
       drawText(text, x, y) {
@@ -526,7 +526,7 @@
           let index = this.checkActivieIcon(this.point);
           if (index != -1) {
             if (this.textStatus == true) {
-              this.drawText(this.classroomList[index].name, (this.classroomList[index].point.x + 25)* this.scaleDefault, (this.classroomList[index].point.y + 20) * this.scaleDefault);
+              this.drawText(this.classroomList[index].classroomName, (this.classroomList[index].point.x + 25)* this.scaleDefault, (this.classroomList[index].point.y + 20) * this.scaleDefault);
               this.textStatus = false;
             }
           } else {
@@ -625,7 +625,7 @@
       },
       getClassroom() {
         this.$api.schoolSetting.findClassInfo({
-          SchoolCode: this.demoLoginInfo.schoolCode
+          schoolCode: this.demoLoginInfo.schoolCode
         }).then(res => {
           if (res.error == null) {
             if (res.result.data.length > 0) {
@@ -662,8 +662,6 @@
           }
       },
       chooseHiTeach(index) {
-        
-        
         let i = this.hiTeachs.indexOf(this.hiTeachsShow[index]);
         //if (this.hiTeachsShow[index].single == 0) {
         //  this.hiTeachsShow[index].using = 1;
@@ -676,16 +674,16 @@
           if (this.hiTeachs[i].using > 0) {
             this.$Message.warning(this.$t('schoolBaseInfo.csTips6'));
           } else {
-            if (!this.isEmpty(this.classroomList[this.currentClassroomIndex].hiTeach)) {
+            if (!this.isEmpty(this.classroomList[this.currentClassroomIndex].hiteach)) {
               let showIndex = -1;
               let allIndex = -1;
               this.hiTeachsShow.forEach((v, i) => {
-                if (v.code == this.classroomList[this.currentClassroomIndex].hiTeach) {
+                if (v.code == this.classroomList[this.currentClassroomIndex].hiteach) {
                   showIndex = i;
                 }
               });
               this.hiTeachs.forEach((v, i) => {
-                if (v.code == this.classroomList[this.currentClassroomIndex].hiTeach) {
+                if (v.code == this.classroomList[this.currentClassroomIndex].hiteach) {
                   allIndex = i;
                 }
               });
@@ -695,19 +693,19 @@
               }
             }
             this.hiTeachs[i].using = 1;
-            this.classroomList[this.currentClassroomIndex].hiTeach = this.hiTeachsShow[index].code;
+            this.classroomList[this.currentClassroomIndex].hiteach = this.hiTeachsShow[index].code;
           }
         } else {
-          if (!this.isEmpty(this.classroomList[this.currentClassroomIndex].hiTeach)) {
+          if (!this.isEmpty(this.classroomList[this.currentClassroomIndex].hiteach)) {
             let showIndex = -1;
             let allIndex = -1;
             this.hiTeachsShow.forEach((v, i) => {
-              if (v.code == this.classroomList[this.currentClassroomIndex].hiTeach) {
+              if (v.code == this.classroomList[this.currentClassroomIndex].hiteach) {
                 showIndex = i;
               }
             });
             this.hiTeachs.forEach((v, i) => {
-              if (v.code == this.classroomList[this.currentClassroomIndex].hiTeach) {
+              if (v.code == this.classroomList[this.currentClassroomIndex].hiteach) {
                 allIndex = i;
               }
             });
@@ -717,7 +715,7 @@
             }
           }
           this.hiTeachs[i].using++;
-          this.classroomList[this.currentClassroomIndex].hiTeach = this.hiTeachsShow[index].code;
+          this.classroomList[this.currentClassroomIndex].hiteach = this.hiTeachsShow[index].code;
         }
         this.filterCode();
       },
@@ -748,7 +746,7 @@
           _this.greenImageData = green;
         }
         this.$api.schoolSetting.findSchoolSystem({
-          Code: this.demoLoginInfo.schoolCode
+          schoolCode: this.demoLoginInfo.schoolCode
         }).then(res => {
           if (res.error == null) {
             if (res.result.data.length > 0) {
@@ -760,12 +758,12 @@
       addClassroom() {
         this.serchClassName = '';
         this.classroomList.push({
-          name: this.$t('schoolBaseInfo.presetClassroomName') + (this.classroomList.length + 1),
-          hiTeach: '',
+          classroomName: this.$t('schoolBaseInfo.presetClassroomName') + (this.classroomList.length + 1),
+          hiteach: '',
           headMaster: this.$t('schoolBaseInfo.presetHeadmaster'),
-          period: '小学',
-          grade: '一年级',
-          stuNum: 0,
+          periodCode: '小学',
+          gradeCode: '一年级',
+          studentCount: 0,
           classroomType: '一般教室',
           classroomCode: '教室编码',
           point: {

File diff suppressed because it is too large
+ 550 - 543
TEAMModelOS/ClientApp/src/view/school-mgmt/SystemSetting/SystemSetting.vue


+ 4 - 4
TEAMModelOS/ClientApp/src/view/student-account/Index.vue

@@ -259,7 +259,7 @@
                 (res) => {
                   if (res.error == null) {
                     this.tableData.splice(originIndex, 1);
-                    this.tablePageData.splice(index, 1);
+                    this.tablePageData.splice(index, 1);  
                     this.tableShowData.splice(showIndex, 1);
                   }
                 },
@@ -286,7 +286,7 @@
       },
       getSchoolData() {
         this.$api.schoolSetting.findSchoolSystem({
-          Code: this.demoLoginInfo.schoolCode
+          schoolCode: this.demoLoginInfo.schoolCode
         }).then(res => {
           if (res.error == null) {
             if (res.result.data.length > 0) {
@@ -300,7 +300,7 @@
       },
       getClassroom() {
         this.$api.schoolSetting.findClassInfo({
-          SchoolCode: this.demoLoginInfo.schoolCode
+          schoolCode: this.demoLoginInfo.schoolCode
         }).then(res => {
           if (res.error == null) {
             if (res.result.data.length > 0) {
@@ -371,7 +371,7 @@
       findStudentInfo() {
         this.tableLoading = true;
         let params = {
-          SchoolCode: this.demoLoginInfo.schoolCode
+          schoolCode: this.demoLoginInfo.schoolCode
         }
         this.$api.stuAccount.findStudentInfo(params).then(
           (res) => {

+ 2 - 2
TEAMModelOS/Controllers/Core/ClassRoomController.cs

@@ -19,8 +19,8 @@ namespace TEAMModelOS.Controllers.Syllabus
         public ClassroomController(IAzureCosmosDBRepository _cosmosrepository) {
             cosmosrepository = _cosmosrepository;
         }
-        [HttpPost("SaveOrUpdateAll")]
-        public async Task<BaseJosnRPCResponse> SaveOrUpdateAll(JosnRPCRequest<Classroom> request)
+        [HttpPost("SaveOrUpdate")]
+        public async Task<BaseJosnRPCResponse> SaveOrUpdate(JosnRPCRequest<Classroom> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             

+ 233 - 0
TEAMModelOS/Controllers/Core/LoginController.cs

@@ -0,0 +1,233 @@
+using IdentityModel;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.Context.Constant.Common;
+using TEAMModelOS.SDK.Context.Exception;
+using TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest;
+using TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse;
+using TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper;
+using TEAMModelOS.SDK.Extension.JwtAuth.Models;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
+using TEAMModelOS.SDK.Helper.Common.ValidateHelper;
+using TEAMModelOS.SDK.Module.AzureCosmosDB.Interfaces;
+using TEAMModelOS.SDK.Module.AzureTable.Interfaces;
+using TEAMModelOS.Service.Models.Core;
+
+namespace TEAMModelOS.Controllers.Core
+{
+    public class LoginController
+    {
+        private readonly IAzureTableDBRepository azureTableDBRepository;
+        private readonly IAzureCosmosDBRepository azureCosmosDBRepository;
+        private readonly IOptions<JwtSetting> options;
+        public LoginController(IAzureTableDBRepository _azureTableDBRepository, IAzureCosmosDBRepository _azureCosmosDBRepository, IOptions<JwtSetting> _options)
+        {
+            azureTableDBRepository = _azureTableDBRepository;
+            azureCosmosDBRepository = _azureCosmosDBRepository;
+            options = _options;
+        }
+        /// <summary>
+        /// 登录验证
+        /// </summary>
+        /// <param name="test"></param>
+        /// <returns></returns>
+        [HttpPost("CheckLogin")]
+        [AllowAnonymous]
+        public async Task<BaseJosnRPCResponse> CheckLogin(JosnRPCRequest<TicketInfo> request)
+        {
+            JsonRPCResponseBuilder responseBuilder = JsonRPCResponseBuilder.custom();
+
+            if (ValidateHelper.IsValid(request.@params))
+            {
+                LoginResult result = await CheckLoginAsync(request.@params);
+                if (result.CheckTicket)
+                {
+                    responseBuilder.Data(result);
+                }
+                else
+                {
+                    responseBuilder.Error(false, ResponseCode.FAILED, "ticket error!");
+                }
+            }
+            else
+            {
+                responseBuilder.Error(false, ResponseCode.FAILED, "ticket error!");
+            }
+            return responseBuilder.build();
+        }
+
+        public async Task<LoginResult> CheckLoginAsync(TicketInfo ticketInfo)
+        {
+
+            // string jtoken = HttpContextHelper.GetValueInHttp(_httpContextAccessor.HttpContext.Request, Constants.AUTHORIZATION);
+            if (string.IsNullOrEmpty(ticketInfo.Token))
+            {
+                LoginResult result = new LoginResult();
+                if (string.IsNullOrEmpty(ticketInfo.Ticket))
+                {
+                    result.CheckTicket = false;
+                    return result;
+                }
+
+                LoginInfo login = azureTableDBRepository.FindOneByKey<LoginInfo>("Ticket", ticketInfo.Ticket).Result;
+                if (login != null && !string.IsNullOrEmpty(login.Token))
+                {
+                    result.CheckTicket = true;
+                    JwtResponse token = await CreateJwtToken(login);
+                    result.JwtToken = token;
+                    login.Token = token.Access_token;
+                    result.JwtToken.Scope = login.Scope;
+                    await azureTableDBRepository.Update<LoginInfo>(login);
+                    return result;
+                }
+
+                ///不验证TmdID
+                #region
+                result.CheckTicket = true;
+                LoginInfo loginInfo = new LoginInfo
+                {
+                    PartitionKey = "15283771540",
+                    Phone = "15283771540",
+                    RowKey = Guid.NewGuid().ToString(),
+                    TeamModelId = ticketInfo.TEAMModelId,
+                    Name = ticketInfo.Name,
+                    Ticket = ticketInfo.Ticket,
+                    CountryCode = "86"
+                };
+                List<Teacher> users = await azureCosmosDBRepository.FindByDict<Teacher>(new Dictionary<string, object>() { { "TEAMModelId", ticketInfo.TEAMModelId } }, true);
+                Teacher user;
+                if (users.IsEmpty())
+                {
+                    user = new Teacher { id = ticketInfo.TEAMModelId.Replace("#", ""), countryCode = loginInfo.CountryCode, createDate = DateTimeOffset.UtcNow.Ticks };
+                }
+                else
+                {
+                    user = users[0];
+                }
+                user.cellphone = "15283771540";
+                user.name = ticketInfo.Name;
+                user.TEAMModelId = ticketInfo.TEAMModelId;
+                user.countryCode = "86";
+                JwtResponse jwtToken = await CreateJwtToken(loginInfo);
+                loginInfo.Token = jwtToken.Access_token;
+                loginInfo.Scope = jwtToken.Scope;
+                result.JwtToken = jwtToken;
+                await azureTableDBRepository.Save<LoginInfo>(loginInfo);
+                await azureCosmosDBRepository.SaveAll<Teacher>(new List<Teacher>() { user });
+                //  JosnRPCResponse<TeamModelIdInfo> response = MessagePackHelper.JsonToObject<JosnRPCResponse<TeamModelIdInfo>>(jsonStr);
+                return result;
+                #endregion
+                /*
+                JosnRPCRequest<Dictionary<string, object>> request = new JosnRPCRequest<Dictionary<string, object>>
+                {
+                    method = "UserInfo"
+                };
+               
+                    Dictionary<string, object> ticket = new Dictionary<string, object>
+                {
+                    { "ticket", ticketInfo.Ticket }
+                };
+                request.@params = ticket;
+                string data = MessagePackHelper.ObjectToJson(request);
+                string jsonStr = _httpClientService.HttpPost(BaseConfigModel.Configuration["HaBookAuth:AccountUrl"], data,  Constants.CONTENT_TYPE_JSON, Encoding.UTF8);
+                if (!string.IsNullOrEmpty(jsonStr))
+                {
+                    JosnRPCResponse<TeamModelIdInfo> response = MessagePackHelper.JsonToObject<JosnRPCResponse<TeamModelIdInfo>>(jsonStr);
+                    if (response.error == null && response != null)
+                    {
+                        result.CheckTicket = true;
+                        LoginInfo loginInfo = new LoginInfo
+                        {
+                            PartitionKey = response.result.cellphone,
+                            Phone = response.result.cellphone,
+                            RowKey = Guid.NewGuid().ToString(),
+                            TeamModelId = response.result.id,
+                            Name = response.result.name,
+                            Ticket = ticketInfo.Ticket,
+                            CountryCode = response.result.countryCode
+                        };
+                        TeamModelUser user= await FindOneByKey<TeamModelUser>("TeamModelId", response.result.id);
+                        if (user == null || string.IsNullOrEmpty(user.RowKey))
+                        {
+                            user = new TeamModelUser { RowKey = Guid.NewGuid().ToString(), PartitionKey = loginInfo.CountryCode ,RegisterTime=DateTimeHelper.ConvertToTimeStamp13(DateTime.Now) };
+                        }
+                        user.Cellphone = response.result.cellphone;
+                        user.NickName = response.result.name;
+                        if (string.IsNullOrEmpty(user.FullName)) {
+                            user.FullName = response.result.name;
+                        }
+                        user.TeamModelId = response.result.id;
+                        user.CountryCode = response.result.countryCode;
+                        JwtResponse jwtToken = await CreateJwtToken(loginInfo);
+                        loginInfo.Token = jwtToken.Access_token;
+                        loginInfo.Scope = jwtToken.Scope;
+                        result.JwtToken = jwtToken;
+                        await Save<LoginInfo>(loginInfo);
+                        await SaveOrUpdate<TeamModelUser>(user);
+                        return result;
+                    }
+                    else
+                    {
+                        result.CheckTicket = false;
+                        return result;
+                    }
+                }
+                else
+                {
+                    result.CheckTicket = false;
+                    return result;
+                }
+                */
+            }
+            else
+            {
+                ClaimModel claimModel = JwtHelper.SerializeJWT(ticketInfo.Token);
+
+                var dateTime = DateTimeHelper.ConvertToTimeStamp10(DateTime.Now);
+                var expExt = claimModel.Claim.TryGetValue("exp", out var exp);
+                if (expExt == false || dateTime > long.Parse(exp.ToString()))
+                {
+                    throw new BizException(401, "Unauthorized");
+                }
+
+                Dictionary<string, object> msp = new Dictionary<string, object>
+                {
+                    { "Token", ticketInfo.Token }
+                };
+                LoginInfo loginInfo = azureTableDBRepository.FindOneByDict<LoginInfo>(msp).Result;
+                if (loginInfo != null && !string.IsNullOrEmpty(loginInfo.Token))
+                {
+                    return new LoginResult { JwtToken = new JwtResponse { Access_token = loginInfo.Token, Scope = loginInfo.Scope }, CheckTicket = true };
+                }
+                else
+                {
+                    throw new BizException(401, "Unauthorized");
+                }
+            }
+        }
+        public async Task<JwtResponse> CreateJwtToken(LoginInfo loginInfo)
+        {
+            string role = "Teacher";
+            ClaimModel model = new ClaimModel
+            {
+                Scope = "WebApp"
+            };
+            model.Claims.Add(new Claim(JwtClaimTypes.Name, loginInfo.Name));
+            model.Claims.Add(new Claim(JwtClaimTypes.Id, loginInfo.TeamModelId));
+            ////保护隐私
+            //model.Claims.Add(new Claim(JwtClaimTypes.PhoneNumber, loginInfo.Phone));
+            model.Claims.AddRange(role.Split(',').Select(s => new Claim(JwtClaimTypes.Role, s)));
+            model.Roles.Add(role);
+            JwtResponse jwtResponse = JwtHelper.IssueJWT(model, options.Value);
+            return jwtResponse;
+        }
+    }
+}

+ 6 - 6
TEAMModelOS/Controllers/Core/StudentController.cs

@@ -57,11 +57,11 @@ namespace TEAMModelOS.Controllers.Syllabus
             }
         }
         [HttpPost("SaveAllStudent")]
-        public async Task<BaseJosnRPCResponse> SaveAllStudentInfo(JosnRPCRequest<List<StudentDto>> request)
+        public async Task<BaseJosnRPCResponse> SaveAllStudentInfo(JosnRPCRequest<List<Student>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            Dictionary<string, List<StudentDto>> dictInfo = new Dictionary<string, List<StudentDto>>();
-            foreach (IGrouping<string, StudentDto> group in request.@params.GroupBy(c => c.classroomCode))
+            Dictionary<string, List<Student>> dictInfo = new Dictionary<string, List<Student>>();
+            foreach (IGrouping<string, Student> group in request.@params.GroupBy(c => c.classroom.classroomCode))
             {
                 dictInfo.Add(group.Key, group.ToList());
             }
@@ -72,7 +72,7 @@ namespace TEAMModelOS.Controllers.Syllabus
                 if (classrooms.IsNotEmpty())
                 {
                     long createDate = DateTimeOffset.UtcNow.Ticks;
-                    dictInfo.TryGetValue(key, out List<StudentDto> sts);
+                    dictInfo.TryGetValue(key, out List<Student> sts);
                     List<long>  ids= IdWorker.getIdsByCount(sts.Count);
                     sts.ForEach(x => {
                         Student student = new Student
@@ -90,7 +90,7 @@ namespace TEAMModelOS.Controllers.Syllabus
                         }
                         Classroom classroom = new Classroom
                         {
-                            classroomCode = x.classroomCode,
+                            classroomCode = x.classroom.classroomCode,
                             gradeCode = classrooms[0].gradeCode,
                             periodCode = classrooms[0].periodCode,
                             schoolCode = classrooms[0].schoolCode,
@@ -105,7 +105,7 @@ namespace TEAMModelOS.Controllers.Syllabus
         }
 
         [HttpPost("UpdateStudent")]
-        public async Task<BaseJosnRPCResponse> UpdateStudent(JosnRPCRequest<StudentDto> request)
+        public async Task<BaseJosnRPCResponse> UpdateStudent(JosnRPCRequest<Student> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
             //设置密码 isSet 是否加密 如果加密则不会再次加密

+ 14 - 0
TEAMModelOS/Models/LoginResult.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Extension.JwtAuth.Models;
+
+namespace TEAMModelOS.Models
+{
+    public class LoginResult
+    {
+        public JwtResponse JwtToken { get; set; }
+        public bool CheckTicket { get; set; } = false;
+    }
+}

+ 0 - 17
TEAMModelOS/Models/StudentDto.cs

@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using TEAMModelOS.Service.Models.Core;
-
-namespace TEAMModelOS.Models
-{
-    /// <summary>
-    /// 用于批量导入使用
-    /// </summary>
-    public class StudentDto :Student
-    {
-        public string classroomCode { get; set; }
-        
-    }
-}

+ 23 - 0
TEAMModelOS/Models/TicketInfo.cs

@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.Models
+{
+    /// <summary>
+    /// 前端返回获取的醍摩豆ID登录基本信息及ticket
+    /// </summary>
+    public class TicketInfo
+    {
+        //[Required(ErrorMessage = "{0} 必须填写")]
+        public string Ticket { get; set; }
+        //[Required(ErrorMessage = "{0} 必须填写")]
+        public string Name { get; set; }
+        //[Required(ErrorMessage = "{0} 必须填写")]
+        public string Sign { get; set; }
+        // [Required(ErrorMessage = "{0} 必须填写")]
+        public string TEAMModelId { get; set; }
+        public string Token { get; set; }
+    }
+}

+ 2 - 2
TEAMModelOS/appsettings.Development.json

@@ -18,8 +18,8 @@
       "AzureTableDialect": ""
     },
     "CosmosDB": {
-      "ConnectionString": "https://192.168.8.192:8081",
-      "ConnectionKey": "GCe8wmHSRl/3hKUNXW6TfLiNTs3Vw8aBC9LKuma1Q4aUfukYqWb7lO0UCnWAJTeWmbMqU8JsufmIZQ3lk0VIbA==",
+      "ConnectionString": "https://localhost:8081",
+      "ConnectionKey": "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
       "Database": "TEAMModelOS",
       "AzureTableDialect": "",
       "CollectionThroughput": 400