Browse Source

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

zhousheng 4 years ago
parent
commit
1760b973b8
63 changed files with 1537 additions and 1060 deletions
  1. 3 3
      TEAMModelFunction/MonitorCosmosDB.cs
  2. 3 3
      TEAMModelFunction/model/ExamResult.cs
  3. 2 2
      TEAMModelOS/ClientApp/src/api/http.js
  4. 4 4
      TEAMModelOS/ClientApp/src/api/stuAccount.js
  5. BIN
      TEAMModelOS/ClientApp/src/assets/loading/water-loading.gif
  6. 2 0
      TEAMModelOS/ClientApp/src/boot-app.js
  7. 1 1
      TEAMModelOS/ClientApp/src/common/BaseLayout.less
  8. 12 14
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  9. 22 19
      TEAMModelOS/ClientApp/src/common/BaseSelectSchool.vue
  10. 23 34
      TEAMModelOS/ClientApp/src/common/BaseUserPoptip.vue
  11. 1 1
      TEAMModelOS/ClientApp/src/components/coursemgt/StudentList.vue
  12. 17 4
      TEAMModelOS/ClientApp/src/components/public/personalPhoto/Index.vue
  13. 5 4
      TEAMModelOS/ClientApp/src/components/selflearn/NewChooseContent.vue
  14. 2 2
      TEAMModelOS/ClientApp/src/components/vote/BaseVoteForm.vue
  15. 1 1
      TEAMModelOS/ClientApp/src/css/common-style.less
  16. 1 0
      TEAMModelOS/ClientApp/src/css/dark-wang-editor.less
  17. 2 0
      TEAMModelOS/ClientApp/src/css/disabled-iview-form.less
  18. 10 1
      TEAMModelOS/ClientApp/src/css/site.css
  19. 29 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/teachermgmt.js
  20. 29 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/teachermgmt.js
  21. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachContent.js
  22. 29 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachermgmt.js
  23. 4 0
      TEAMModelOS/ClientApp/src/router/routes.js
  24. 1 1
      TEAMModelOS/ClientApp/src/service/User.js
  25. 26 12
      TEAMModelOS/ClientApp/src/store/module/user.js
  26. 224 0
      TEAMModelOS/ClientApp/src/utils/editorTools.js
  27. 9 1
      TEAMModelOS/ClientApp/src/utils/public.js
  28. 1 0
      TEAMModelOS/ClientApp/src/view/Home.vue
  29. 2 2
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue
  30. 28 22
      TEAMModelOS/ClientApp/src/view/evaluation/bank/ExerciseList.vue
  31. 351 347
      TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.vue
  32. 1 2
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseCreateChild.vue
  33. 15 16
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseEditExercise.vue
  34. 15 10
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseFilter.vue
  35. 29 22
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseImport.vue
  36. 2 8
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.less
  37. 7 4
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.vue
  38. 15 9
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreatePaper.vue
  39. 0 1
      TEAMModelOS/ClientApp/src/view/evaluation/index/PickExercise.css
  40. 1 10
      TEAMModelOS/ClientApp/src/view/evaluation/index/index.vue
  41. 324 221
      TEAMModelOS/ClientApp/src/view/evaluation/types/BaseMultiple.vue
  42. 2 2
      TEAMModelOS/ClientApp/src/view/evaluation/types/BaseSingle.vue
  43. 56 101
      TEAMModelOS/ClientApp/src/view/evaluation/types/BaseMultipleNew.vue
  44. 20 0
      TEAMModelOS/ClientApp/src/view/joinclass/JoinClass.vue
  45. 0 7
      TEAMModelOS/ClientApp/src/view/knowledge-point/index/Index.vue
  46. 33 24
      TEAMModelOS/ClientApp/src/view/newcourse/ManageCourse.vue
  47. 8 6
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue
  48. 8 8
      TEAMModelOS/ClientApp/src/view/newcourse/NewCoursePlan.vue
  49. 9 6
      TEAMModelOS/ClientApp/src/view/questionnaire/ManageQuestionnaire.vue
  50. 1 0
      TEAMModelOS/ClientApp/src/view/schoolList/Index.vue
  51. 57 45
      TEAMModelOS/ClientApp/src/view/schoolmgmt/ClassroomSetting/ClassroomSetting.vue
  52. 14 15
      TEAMModelOS/ClientApp/src/view/schoolmgmt/SystemSetting/SystemSetting.vue
  53. 2 1
      TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.less
  54. 30 25
      TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.vue
  55. 5 3
      TEAMModelOS/ClientApp/src/view/student-account/Index.vue
  56. 1 0
      TEAMModelOS/ClientApp/src/view/student-web/App.vue
  57. 12 12
      TEAMModelOS/ClientApp/src/view/teachcontent/index.vue
  58. 1 0
      TEAMModelOS/ClientApp/src/view/teachermgmt/components/userList/Index.vue
  59. 6 3
      TEAMModelOS/ClientApp/src/view/vote/ManageVote.vue
  60. 1 1
      TEAMModelOS/Controllers/School/ClassRoomController.cs
  61. 15 15
      TEAMModelOS/Controllers/School/CourseController.cs
  62. 1 1
      TEAMModelOS/Controllers/Teacher/InitController.cs
  63. 1 0
      TEAMModelOS/Models/SchoolInfo/Classroom.cs

+ 3 - 3
TEAMModelFunction/MonitorCosmosDB.cs

@@ -97,7 +97,7 @@ namespace TEAMModelFunction
                                         }
                                         break;
                                     case "going":
-                                        if (examClassResults.Count < 0)
+                                        if (examClassResults.Count == 0)
                                         {
                                             for (int j = 0; j < info.subjects.Count; j++)
                                             {
@@ -219,10 +219,10 @@ namespace TEAMModelFunction
                                                 result.subjectId = info.subjects[j].id;
                                                 result.year = info.year;
                                                 result.paper = info.papers[j];
-                                                result.point = info.papers[j].point;
+                                                //result.point = info.papers[j].point;
                                                 result.scope = info.scope;
                                                 result.name = info.name;
-                                                //result.time                                    
+                                                result.time = info.startTime;                                 
                                                 await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(result, new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}"));
                                             }
                                         }

+ 3 - 3
TEAMModelFunction/model/ExamResult.cs

@@ -23,16 +23,16 @@ namespace TEAMModelFunction
             classes = new List<ClassRange>();
             studentScores = new List<List<double>>();
             studentIds = new List<string>();
-            point = new List<double>();
+            //point = new List<double>();
         }
         public string id { get; set; }
         public string name { get; set; }
-        public string time { get; set; }
+        public long time { get; set; }
         public string subjectId { get; set; }
         public List<ClassRange> classes { get; set; }
         public List<List<double>> studentScores { get; set; }
         public List<string> studentIds { get; set; }
-        public List<double> point { get; set; }
+        //public List<double> point { get; set; }
      
         public string schoolId { get; set; }
         public PaperSimple paper { get; set; }

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

@@ -21,11 +21,11 @@ axios.interceptors.request.use(
         if(isProduction && access_token && webEndTime){
             let time_now = new Date().getTime()
             if(time_now > webEndTime){
-                let login_schooCode = localStorage.getItem('login_schooCode')
+                let login_schoolCode = localStorage.getItem('login_schoolCode')
                 let srvAdr = localStorage.getItem('srvAdr')
                 localStorage.clear()
                 localStorage.setItem('srvAdr', srvAdr)
-                localStorage.setItem('login_schooCode', login_schooCode)
+                localStorage.setItem('login_schoolCode', login_schoolCode)
                 window.location.href = window.location.origin + '/login'
             }
         } 

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

@@ -4,7 +4,7 @@ export default {
     saveStudent: function(schoolId, data) {
         let format = {
             "grant_type": "create",
-            "schoolId": schoolId.toLowerCase(),
+            "schoolId": schoolId,
             "students": []
         }
         format.students.push(...data)
@@ -14,14 +14,14 @@ export default {
     findStudent: function(schoolId) {
         let format = {
             "grant_type": "read",
-            "schoolId": schoolId.toLowerCase()
+            "schoolId": schoolId
         }
         return post('/student/student-manage', format)
     },
     saveAllStudent: function(schoolId, data) {
         let format = {
             "grant_type": "update",
-            "schoolId": schoolId.toLowerCase(),
+            "schoolId": schoolId,
             "students": []
         }
         format.students.push(...data)
@@ -34,7 +34,7 @@ export default {
     deleteStudent: function(schoolId, data) {
         let format = {
             "grant_type": "delete",
-            "schoolId": schoolId.toLowerCase(),
+            "schoolId": schoolId,
             "students": []
         }
         format.students.push(...data)

BIN
TEAMModelOS/ClientApp/src/assets/loading/water-loading.gif


+ 2 - 0
TEAMModelOS/ClientApp/src/boot-app.js

@@ -10,6 +10,7 @@ import ViewUI from 'view-design'
 import 'view-design/dist/styles/iview.css'
 import tools from '@/utils/public.js'
 import evTools from '@/utils/evTools.js'
+import editorTools from '@/utils/editorTools.js'
 import jsFn from '@/utils/js-fn.js'
 import apiTools from '@/api'
 import mockTools from '@/mock'
@@ -101,6 +102,7 @@ Vue.prototype.$JSONPath = JSONPath
 Vue.prototype.$echarts = echarts
 Vue.prototype.$tools = tools
 Vue.prototype.$evTools = evTools
+Vue.prototype.$editorTools = editorTools
 Vue.prototype.$jsFn = jsFn //常用工具方法
 Vue.prototype.$azblob = window.azblob //azblob API
 Vue.prototype._ = _

+ 1 - 1
TEAMModelOS/ClientApp/src/common/BaseLayout.less

@@ -37,7 +37,7 @@
         top: 70px;
         bottom: 0px;
         width: 100%;
-        padding-left: 248px;
+        padding-left: 225px;
         overflow-y: auto;
         background: var(--body-bg);
         transition: padding-left 0.4s;

+ 12 - 14
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -16,7 +16,7 @@
                ref="side1"
                hide-trigger
                collapsible
-               width="248"
+               width="225"
                :collapsed-width="78"
                v-model="isCollapsed">
             <div class="collapse-icon-box" @click="changeMenuStatus">
@@ -101,7 +101,7 @@
                                 router: '/home/teachermgmt',
                                 tag: '',
                                 role: 'admin',
-                                permission: ''
+                                permission: 'teacher-read|teacher-upd'
                             },
                             {
                                 icon: 'iconfont icon-student-mgt',
@@ -119,15 +119,13 @@
                                 role: 'admin',
                                 permission: 'classroom-upd|classroom-read'
                             },
-                            
-                            
                             {
                                 icon: 'iconfont icon-kecheng',
                                 name: '课程设置',
                                 router: '/home/ManageCourse',
                                 tag: '',
                                 role: 'admin',
-                                permission: '',
+                                permission: 'course-read|course-upd',
                             },
                             //{
                             //    icon: 'iconfont icon-time',
@@ -143,7 +141,7 @@
                                 router: '/home/NewCoursePlan',
                                 tag: '',
                                 role: 'admin',
-                                permission: '',
+                                permission: 'coursePlan-read|coursePlan-upd',
                             },
                             {
                                 icon: 'iconfont icon-auth',
@@ -151,7 +149,7 @@
                                 router: '/home/serviceDriveAuth',
                                 tag: '(预览)',
                                 role: 'admin',
-                                permission: ''
+                                permission: 'auth-read|auth-upd'
                             },
                             {
                                 icon: 'iconfont icon-syllabus',
@@ -192,7 +190,7 @@
                         name: '统计分析',
                         router: '',
                         role: 'admin',
-                        permission: 'analysis',
+                        permission: 'analysis-read|scboard-read',
                         child: [
                             {
                                 icon: 'iconfont icon-xueqing',
@@ -200,7 +198,7 @@
                                 router: '/totalIndex',
                                 tag: '*',
                                 role: 'admin',
-                                permission: 'analysis'
+                                permission: 'analysis-read'
                             },
                             {
                                 icon: 'iconfont icon-school-analysis',
@@ -208,7 +206,7 @@
                                 router: '/home/scboard',
                                 tag: '(预览)',
                                 role: 'admin',
-                                permission: 'analysis'
+                                permission: 'scboard-read'
                             }
                         ]
                     },
@@ -217,7 +215,7 @@
                         name: '校园活动',
                         router: '',
                         role: 'admin',
-                        permission: 'analysis',
+                        permission: 'schoolAc-read|schoolAc-upd',
                         child: [
                             {
                                 icon: 'iconfont icon-test',
@@ -225,7 +223,7 @@
                                 router: '/home/schoolEvaluation',
                                 tag: '*',
                                 role: 'admin',
-                                permission: 'analysis'
+                                permission: 'schoolAc-read|schoolAc-upd'
                             },
                             {
                                 icon: 'iconfont icon-vote',
@@ -233,7 +231,7 @@
                                 router: '/home/manageVote',
                                 tag: '*',
                                 role: 'admin',
-                                permission: 'analysis'
+                                permission: 'schoolAc-read|schoolAc-upd'
                             },
                             {
                                 icon: 'iconfont icon-questionnaire',
@@ -241,7 +239,7 @@
                                 router: '/home/manageQuestionnaire',
                                 tag: '*',
                                 role: 'admin',
-                                permission: 'analysis'
+                                permission: 'schoolAc-read|schoolAc-upd'
                             },
                         ]
                     },

+ 22 - 19
TEAMModelOS/ClientApp/src/common/BaseSelectSchool.vue

@@ -1,14 +1,14 @@
 <template>
 	<div class="base-school-select">
-		<div v-if="!user.schools">暂未加入学校</div>
+		<div v-if="!joinSchools.length">暂未加入学校</div>
 		<Dropdown @on-click="onSchoolSelect" v-else>
 			<img class="school-logo" :src="curSchool.logo || defaultLogo" />
-			<a href="javascript:void(0)" :class="['base-user-post', user.schools.length === 1 ? 'single-school' : '']">
+			<a href="javascript:void(0)" :class="['base-user-post', joinSchools.length === 1 ? 'single-school' : '']">
 				{{ curSchool.name }}
 				<Icon type="ios-arrow-down"></Icon>
 			</a>
 			<DropdownMenu slot="list">
-				<div v-for="(item,index) in user.schools" :key="index">
+				<div v-for="(item,index) in joinSchools" :key="index">
 					<DropdownItem :name="index">
 						<div class="school-item">
 							<img :src="item.logo || defaultLogo" alt="">
@@ -34,36 +34,40 @@
 				defaultLogo: '',
 				user: {
 					schools: []
-				}
+				},
+				joinSchools:[]
 			}
 		},
 		created() {
 			this.defaultLogo = require('@/assets/icon/default_school.png')
 			// 获取本地存储中的 用户信息
 			let user = JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"));
+			console.log(user)
 			let schoolProfile = localStorage.school_profile ? JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")) :undefined;
-
-			let schools = user.schools && user.schools.length ?  user.schools.filter(i => i.status === 'join') : null
-			this.user.schools = schools
+			this.user.schools = user.schools
+			let joinSchools = user.schools && user.schools.length ?  user.schools.filter(i => i.status === 'join') : null
+			this.joinSchools = joinSchools
 			// 如果本地存储已经有保存学校信息 则刷新后会直接读取之前的学校信息
-			if (schoolProfile && schools) {
-				this.curSchool = schools.filter(i => i.schoolId === schoolProfile.school_base.id)[0]
+			if (schoolProfile && joinSchools.length) {
+				this.curSchool = joinSchools.filter(i => i.schoolId === schoolProfile.school_base.id)[0]
 				this.$store.commit('setSchoolCode', this.curSchool.schoolId)
-			} else if (user.schools) {
+			} else if (joinSchools.length) {
 				// 拿到用户管理的schools 必须是已加入的学校
-				if (schools.length) {
-					this.curSchool = user.defaultschool ? schools.filter(i => i.schoolId === user.defaultschool)[0] : schools[0]
-					this.$store.commit('setSchoolCode', this.curSchool.schoolId)
-				}
+				this.curSchool = user.defaultschool ? joinSchools.filter(i => i.schoolId === user.defaultschool)[0] : joinSchools[0]
+				this.$store.commit('setSchoolCode', this.curSchool.schoolId)
 			} else {
 				this.$Message.warning('用户暂无学校列表数据')
 			}
 		},
 		methods: {
 			async onSchoolSelect(val) {
+				console.log(val)
+				console.log(this.user.schools)
+				console.log(this.joinSchools)
+				this.joinSchools = this.user.schools.filter(i => i.status === 'join')
 				this.$EventBus.$emit('onGlobalLoading', true)
-				this.curSchool = this.user.schools[val]
-				let schoolCode = this.user.schools[val].schoolId
+				this.curSchool = this.joinSchools[val]
+				let schoolCode = this.joinSchools[val].schoolId
 				// 更新当前school_code
 				this.$store.dispatch('user/setSchoolCode', schoolCode)
 				// 更新当前school_profile以及access
@@ -108,9 +112,8 @@
 					console.log('检测到切换学校')
 					console.log(params)
 					this.user = params.user
-					// this.curSchool = params.user.defaultschool ? params.user.schools.filter(i => i.schoolId === params.user.defaultschool)[
-					// 	0] : params.user.schools[0]
-					this.onSchoolSelect(params.user.schools.map(i => i.schoolId).indexOf(params.schoolCode))
+					let joinSchools = params.user.schools.filter(i => i.status === 'join')
+					this.onSchoolSelect(params.isFirst ? 0 : joinSchools.map(j => j.schoolId).indexOf(params.schoolCode))
 				}
 			})
 		},

+ 23 - 34
TEAMModelOS/ClientApp/src/common/BaseUserPoptip.vue

@@ -15,18 +15,18 @@
 					</DropdownMenu>
 				</Dropdown>
 			</div>
-			<Poptip class="dark-iview-poptip" @on-popper-show="getSize()">
+			<Poptip class="dark-iview-poptip" @on-popper-show="doRefresh()">
 				<!-- <img :src="user.picture" /> -->
 				<PersonalPhoto style="cursor: pointer;" :name="userInfo.username" :picture="user.picture" :color="userInfo.nameColor"/>
 
 				<div slot="content" class="user-center">
 					<div class="user-info">
 						<!-- <img :src="user.picture" />     border: 2px solid #fff;-->
-						<PersonalPhoto :width="'70px'" :height="'70px'" :fontSize="'2.50rem'" :name="userInfo.username" :picture="user.picture" :color="userInfo.nameColor"/>
+						<PersonalPhoto :width="'70px'" :height="'70px'" :fontSize="'1.50rem'" :name="userInfo.username" :picture="user.picture" :color="userInfo.nameColor"/>
 
 						<span class="user-info-username">{{ userInfo.username }}</span>
 						<span class="user-info-account">{{ user.id }}</span>
-						<span class="user-info-account">{{ userInfo.role }}</span>
+						<span class="user-info-account">{{ curRole }}</span>
 						<span class="user-info-btn">账号管理</span>
 					</div>
 					<div class="user-nums">
@@ -84,12 +84,12 @@
 			return {
 				curRole: '',
 				userInfo: {
-					username: 'Hao James Ker',
-					account: '15895626464',
-					role: 'admin',
-					courseNum: 7,
-					activityNum: 16,
-					classNum: 21,
+					username: '',
+					account: '',
+					role: '',
+					courseNum: 0,
+					activityNum: 0,
+					classNum: 0,
 					nameColor: '',
 				},
 				user: {},
@@ -106,30 +106,19 @@
 			}
 		},
 		created() {
-			this.user = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"));
-            let user_profile = JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"));
-   //         if (user_profile.schools.length) {
-			//	this.$store.commit('setUserInfo', {
-			//		TEAMModelId: this.user.id,
-			//		name: this.user.name,
-			//		schoolCode: user_profile.defaultschool || user_profile.schools[0].schoolId
-			//	})
-			//} else {
-			//	this.$store.commit('setUserInfo', {
-			//		TEAMModelId: this.user.id,
-			//		name: this.user.name,
-			//		schoolCode: 'SYSTEM_NO_SCHOOL'
-			//	})
-			//}
-			
-			if(this.user.roles.length){
-				this.curRole = this.user.roles[0]
-			}
-			this.userInfo.username = this.user.name
-			this.userInfo.nameColor = this.randomColor()
-            this.getSize()
+            this.doRefresh()
 		},
 		methods: {
+			doRefresh(){
+				this.user = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"));
+				let user_profile = JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"));
+				if(this.user.roles.length){
+					this.curRole = this.user.roles[0]
+				}
+				this.userInfo.username = this.user.name
+				this.userInfo.nameColor = this.randomColor()
+				this.getSize()
+			},
 			//获取Blob空间信息
 			async getSize() {
 				let sasRes = await this.$tools.getPrivateSas()
@@ -420,10 +409,10 @@
 			.btn-logout {
 				.fl-col-center;
 				background: #1CC0F3;
-				padding: 10px 60px;
+				padding: 6px 0;
 				color: #fff;
-				width: 70%;
-				margin-left: 15%;
+				width: 60%;
+				margin-left: 20%;
 				margin-top: 40px;
 				border-radius: 5px;
 				font-size: 16px;

+ 1 - 1
TEAMModelOS/ClientApp/src/components/coursemgt/StudentList.vue

@@ -2,7 +2,7 @@
     <div class="dark-iview-table student-list">
         <div class="student-filter-wrap dark-iview-select dark-iview-input">
             <!-- 學制Select -->
-            <Select v-model="searchPeriod" style="width:120px;" :placeholder="$t('stuAccount.periodHolder')" clearable @on-change="filterData">
+            <Select v-model="searchPeriod" style="width:120px;" :placeholder="$t('stuAccount.periodHolder')" clearable @on-change="filterData" not-found-text="暂未归属学校">
                 <Option v-for="(item,index) in periods" :value="item.id" :key="index">{{ item.name }}</Option>
             </Select>
             <!-- 學級Select -->

+ 17 - 4
TEAMModelOS/ClientApp/src/components/public/personalPhoto/Index.vue

@@ -11,7 +11,7 @@
         <div class="fakeAvatar" 
         :style="{backgroundColor: randomColor, width: width, height: height, fontSize: fontSize}"
         >
-            {{ name.substr(0, 1)}}
+            {{  getChinese(name) }}
         </div>
     </div>
   </div>
@@ -26,15 +26,15 @@ export default {
       color: String,
       fontSize: {
         type: String,
-        default: '1.25rem'
+        default: '1rem'
       },
       width: {
         type: String,
-        default: '36px'
+        default: '40px'
       },
       height: {
         type: String,
-        default: '36px'
+        default: '40px'
       }
     },
   data(){      
@@ -42,6 +42,8 @@ export default {
       
     }
   },
+  created() {
+  },
   computed:{
     randomColor: function(){
       if(!this.color){
@@ -55,6 +57,17 @@ export default {
     }
   },
   methods: {
+	  getChinese(strValue) {  
+	      var reg = /[\u4e00-\u9fa5]/g;
+	      var names = strValue.match(reg);
+		  if(names){
+			  return names.join("").substring(names.length - 2)
+		  }else{
+			  return strValue.substr(0,2)
+		  }
+	  } 
+  },
+  mounted(){
   }
 }
 </script>

+ 5 - 4
TEAMModelOS/ClientApp/src/components/selflearn/NewChooseContent.vue

@@ -338,11 +338,12 @@
             initData() {
                 this.questionFilter.code = this.$store.state.userInfo.TEAMModelId
                 this.$store.dispatch('user/getSchoolProfile').then(res => {
-                    this.questionFilter.periodId = this.$store.state.user.schoolProfile.school_base.period[0].id
-                    this.questionFilter.subjectId = this.$store.state.user.schoolProfile.school_base.period[0].subjects[0].id
-                    this.questionFilter.gradeIds = [this.$store.state.user.schoolProfile.school_base.period[0].grades[0].id]
+                    if (res.school_base) {
+                        this.questionFilter.periodId = res.school_base.period[0].id
+                        this.questionFilter.subjectId = res.school_base.period[0].subjects[0].id
+                        this.questionFilter.gradeIds = [res.school_base.period[0].grades[0].id]
+                    }
                 })
-                
             },
             /**
              * 选择全部逻辑

+ 2 - 2
TEAMModelOS/ClientApp/src/components/vote/BaseVoteForm.vue

@@ -8,14 +8,14 @@
 				<div v-if="!voteFormEdit && curVoteItem" class="vote-class">
 					<span v-for="item in curVoteItem.targetClassIds" class="vote-class-item">{{ getTargetName(item) }}</span>
 				</div>
-				<Select multiple v-model="voteForm.targetClassIds" :class="!voteFormEdit ? 'vote-form-disabled':''" placeholder="请选择投票发布对象" v-else>
+				<Select multiple v-model="voteForm.targetClassIds" :class="!voteFormEdit ? 'vote-form-disabled':''" placeholder="请选择投票发布对象" not-found-text="暂未创建班级" v-else>
 				    <Option v-for="item in classRooms" :value="item.id" :key="item.id">{{ item.name }}</Option>
 				</Select>
             </FormItem>
 			
 			<FormItem label="起止时间" prop="rangeTime">
 			    <!-- <DatePicker type="datetime" :class="!voteFormEdit ? 'vote-form-disabled':''" :editable="isDateEdit" placeholder="请选择投票结束时间" v-model="voteForm.endTime"  :options="endTimeOptions"></DatePicker> -->
-				<DatePicker type="datetimerange" @on-change="onChangeRange" format="yyyy-MM-dd HH:mm" :class="!voteFormEdit ? 'vote-form-disabled':''" :editable="isDateEdit" :value="[voteForm.startTime,voteForm.endTime]" placeholder="请选择投票结束时间"></DatePicker>
+				<DatePicker type="datetimerange" transfer @on-change="onChangeRange" format="yyyy-MM-dd HH:mm" :class="!voteFormEdit ? 'vote-form-disabled':''" :editable="isDateEdit" :value="[voteForm.startTime,voteForm.endTime]" placeholder="请选择投票结束时间"></DatePicker>
 			</FormItem>
 
             <FormItem label="投票描述" prop="description">

+ 1 - 1
TEAMModelOS/ClientApp/src/css/common-style.less

@@ -49,7 +49,7 @@
 
 //标签文字 不可点击状态
 .disable-text-icon {
-    pointer-events: none;
+    /*pointer-events: none;*/
     cursor: not-allowed !important;
     color: #a5a5a5 !important;
 }

+ 1 - 0
TEAMModelOS/ClientApp/src/css/dark-wang-editor.less

@@ -25,6 +25,7 @@
     overflow-y: auto !important;
     height: 220px !important;
     z-index: 99 !important;
+    background: #404040 !important;
 }
 .dark-wang-editor .w-e-text {
     overflow-y: auto;

+ 2 - 0
TEAMModelOS/ClientApp/src/css/disabled-iview-form.less

@@ -11,10 +11,12 @@
     .ivu-select-disabled .ivu-select-selection, .ivu-input[disabled] {
         border: none;
         font-size: 16px !important;
+        cursor: auto;
     }
 
     .ivu-select-input[disabled] {
         -webkit-text-fill-color: white;
+        cursor: auto;
     }
 
     .ivu-select-single .ivu-select-selection .ivu-select-placeholder,

+ 10 - 1
TEAMModelOS/ClientApp/src/css/site.css

@@ -116,7 +116,16 @@ html[white]{ /*白色主題*/
 .leftInOut-enter, .leftInOut-leave-to /* .list-leave-active below version 2.1.8 */ {
     opacity: 0;
     transform: translateX(-150px);    
-}
+}	
+
+	.richText-audio{
+		background-image: url('../assets/icon/icon_audio.png');
+		background-size: cover;
+		width: 35px;
+		height: 35px;
+		display: inline-block;
+		cursor: pointer;
+	}
 
 	.richText-video {
 		position: relative;

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

@@ -75,7 +75,35 @@ export default {
         'student-upd':'Change student account',
         'teacher-checkTeacher':'Check teacher',
         'teacher-read':'Review teacher account',
-        'teacher-upd':'Change teacher account'
+        'teacher-upd': 'Change teacher account',
+        'managecourse ': ' curriculum management ',
+        'course-read': 'view course information',
+        'course-upd': 'modify course setting information',
+        'newCoursePlan': 'Course Scheduling Management',
+        'coursePlan-read': 'view course scheduling information',
+        'coursePlan-upd': 'modify course scheduling information',
+        'serviceDriveAuth ': ' authorization management ',
+        'auth-read': 'view authorization management information',
+        'auth-upd': 'modify authorization management information',
+        'syllabus': 'school based curriculum management',
+        'syllabus-read ': ' view the school-based curriculum information ',
+        'syllabus-upd ': ' modify the information of school-based syllabus',
+        'schoolContent ': ' school based content management ',
+        'content-read': 'view the school-based content information',
+        'content-upd': 'modify the school-based content information',
+        'schoolBank ': ' school based question bank management ',
+        'exercise-read': 'view the information of school-based question bank',
+        'exercise-upd': 'modify the information of school-based question bank',
+        'knowledge': 'knowledge base management ',
+        'knowledge-read': 'view knowledge point base information',
+        'knowledge-upd': 'modify knowledge point base information',
+        'analysis': 'learning situation analysis',
+        'analysis-read': 'view the analysis of campus learning situation',
+        'scboard': ' Campus analysis',
+        'scboard-read': ' view campus analysis',
+        'schoolAc': ' campus activities',
+        'schoolAc-read ': ' view campus activities',
+        'schoolAc-upd': ' publish campus activities'
     },
     modal:{
         text1: '此帐号权限已变更,是否要给此帐号更加合适的职称',

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

@@ -74,7 +74,35 @@ export default {
         'student-upd':'变更学生账号',
         'teacher-checkTeacher':'检查老师可否看',
         'teacher-read':'检视教师账号',
-        'teacher-upd':'变更教师账号'
+        'teacher-upd': '变更教师账号',
+        'manageCourse': '课程设置管理',
+        'course-read': '查看课程设置信息',
+        'course-upd': '修改课程设置信息',
+        'newCoursePlan': '排课管理',
+        'coursePlan-read': '查看排课信息',
+        'coursePlan-upd': '修改排课信息',
+        'serviceDriveAuth': '授权管理',
+        'auth-read': '查看授权管理信息',
+        'auth-upd': '修改授权管理信息',
+        'syllabus': '校本课纲管理',
+        'syllabus-read': '查看校本课纲信息',
+        'syllabus-upd': '修改校本课纲信息',
+        'schoolContent': '校本内容管理',
+        'content-read': '查看校本内容信息',
+        'content-upd': '修改校本内容信息',
+        'schoolBank': '校本题库管理',
+        'exercise-read': '查看校本题库信息',
+        'exercise-upd': '修改校本题库信息',
+        'knowledge': '知识点库管理',
+        'knowledge-read': '查看知识点库信息',
+        'knowledge-upd': '修改知识点库信息',
+        'totalIndex': '学情分析',
+        'analysis-read': '查看校园学情分析',
+        'scboard': '校园分析',
+        'scboard-read': '查看校园分析',
+        'schoolAc': '校园活动',
+        'schoolAc-read': '查看校园活动',
+        'schoolAc-upd':'发布校园活动'
     },
     modal:{
         text1: '此帐号权限已变更,是否要给此帐号更加合适的职称',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachContent.js

@@ -4,7 +4,7 @@ export default {
   filterAll: '全部',
   filterPicture: '圖片',
   filterVideo: '視頻',
-  filterDoc: '檔案',
+  filterDoc: '文件',
   filterOther: '其他',
   space: '空間:',
   tableC1: '檔案名稱',

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

@@ -74,7 +74,35 @@ export default {
         'student-upd':'變更學生賬號',
         'teacher-checkTeacher':'檢查老師可否看',
         'teacher-read':'檢視教師賬號',
-        'teacher-upd':'變更教師賬號'
+        'teacher-upd': '變更教師賬號',
+        'manageCourse':'課程設置管理',
+        'course-read':'查看課程設置資訊',
+        'course-upd':'修改課程設置資訊',
+        'newCoursePlan':'排課管理',
+        'coursePlan-read':'查看排課資訊',
+        'coursePlan-upd':'修改排課資訊',
+        'serviceDriveAuth':'授權管理',
+        'auth-read':'查看授權管理資訊',
+        'auth-upd':'修改授權管理資訊',
+        'syllabus':'校本課綱管理',
+        'syllabus-read':'查看校本課綱資訊',
+        'syllabus-upd':'修改校本課綱資訊',
+        'schoolContent':'校本內容管理',
+        'content-read':'查看校本內容資訊',
+        'content-upd':'修改校本內容資訊',
+        'schoolBank':'校本題庫管理',
+        'exercise-read':'查看校本題庫資訊',
+        'exercise-upd':'修改校本題庫資訊',
+        'knowledge':'知識點庫管理',
+        'knowledge-read':'查看知識點庫資訊',
+        'knowledge-upd': '修改知識點庫資訊',
+        'analysis':'學情分析',
+        'analysis-read':'查看校園學情分析',
+        'scboard':'校園分析',
+        'scboard':'查看校園分析',
+        'schoolAc':'校園活動',
+        'schoolAc-read':'查看校園活動',
+        'schoolAc-upd':'發佈校園活動'
     },
     modal:{
         text1: '此帳號權限已變更,是否要給此帳號更加合適的職稱',

+ 4 - 0
TEAMModelOS/ClientApp/src/router/routes.js

@@ -57,6 +57,10 @@ export const routes = [
 			component: resolve => require(['@/view/forgotPw/Index.vue'], resolve)
 		}]
 	},
+	{
+		path: '/joinclass',
+		component: resolve => require(['@/view/joinclass/JoinClass.vue'], resolve)
+	},
 	{
 		path: '/schoolList',
 		component: Home,

+ 1 - 1
TEAMModelOS/ClientApp/src/service/User.js

@@ -67,7 +67,7 @@ export class User {
           localStorage.removeItem('token');
           localStorage.removeItem('userAccess');
           localStorage.removeItem('userInfo');
-          localStorage.removeItem('login_schooCode')
+          localStorage.removeItem('login_schoolCode')
           localStorage.removeItem('user_details')
           localStorage.removeItem('access_token')
           localStorage.removeItem('expires_in')

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

@@ -4,7 +4,7 @@ import jwtDecode from 'jwt-decode'
 export default {
     namespaced: true,
     state: {
-        schoolCode: 'HBCN',         //HBCN 學校代碼 (現在先寫死)
+        schoolCode: undefined,         //HBCN 學校代碼 (現在先寫死)
         userDetails: [],            // 使用者詳細資訊[]
         schoolUserList: undefined,  //學校所有使用者
         userList: undefined,        //從Core.ID取得的使用者
@@ -179,6 +179,17 @@ export default {
         resetSchoolUserList(state) {
             state.schoolUserList = undefined
         },
+		resetSchoolProfile(state){
+			state.schoolCode = undefined
+			state.schoolProfile.blob_sas = undefined // 老師在學校的Blob金鑰,讀寫
+			state.schoolProfile.blob_uri = undefined // 老師在學校的Blob網址
+			state.schoolProfile.school_courses = undefined // 学校排课
+			state.schoolProfile.school_syllabus = undefined // 校本课纲
+			state.schoolProfile.school_classes = undefined // 学校班级
+			state.schoolProfile.periods = undefined // 學制
+			state.schoolProfile.grades = undefined // 年級
+			state.schoolProfile.school_base = undefined // 区班校基础数据
+		},
         setSchoolSettingAuthList(state, data) {
             state.schoolSettingAuthList = data
         },
@@ -223,12 +234,12 @@ export default {
                 if (context.state.schoolProfile.school_base) {
                     resolve(context.state.schoolProfile)
                 } else {
-                    let login_schooCode = localStorage.getItem('login_schooCode')
+                    let login_schoolCode = localStorage.getItem('login_schoolCode')
                     let id_token = localStorage.getItem('id_token')
-                    if (login_schooCode && id_token) {
+                    if (login_schoolCode && id_token) {
                         apiTools.login.getTeacherSchoolInfo({
                             id_token: id_token,
-                            school_code: login_schooCode
+                            school_code: login_schoolCode
                         }).then(res => {
                             if (!res.error) {
                                 context.dispatch('setSchoolProfile', res)
@@ -237,7 +248,9 @@ export default {
                         }).catch(err => {
                             reject(err)
                         })
-                    }
+                    }else{
+						resolve(context.state.schoolProfile)
+					}
                 }
             })
         },
@@ -572,10 +585,10 @@ export default {
             context.commit('setStudentProfile', data)
         },
         async checkSchoolProfile(context) {
-            let login_schooCode = localStorage.getItem('login_schooCode')
+            let login_schoolCode = localStorage.getItem('login_schoolCode')
             let id_token = localStorage.getItem('id_token')
 
-            if (login_schooCode && id_token) {
+            if (login_schoolCode && id_token) {
                 // 輸出暫存
                 let result;
 
@@ -586,7 +599,7 @@ export default {
 
                 await apiTools.login.getTeacherSchoolInfo({
                     id_token: id_token,
-                    school_code: login_schooCode
+                    school_code: login_schoolCode
                 }).then(res => {
                     // 沒有錯誤的話
                     if (!res.error) {
@@ -625,14 +638,15 @@ export default {
             }
         },
         checkSchoolCode(context) {
-            let login_schooCode = localStorage.getItem('login_schooCode')
-            if (login_schooCode) {
-                context.commit('setSchoolCode', login_schooCode)
+            let login_schoolCode = localStorage.getItem('login_schoolCode')
+            if (login_schoolCode) {
+                context.commit('setSchoolCode', login_schoolCode)
             }
         },
         setSchoolCode(context, data) {
 			context.rootState.userInfo.schoolCode = data
-            localStorage.setItem('login_schooCode', data)
+			context.rootState.userInfo.hasSchool = true
+            localStorage.setItem('login_schoolCode', data)
             context.commit('setSchoolCode', data)
         },
         getGradeById(context, gradeId) {

+ 224 - 0
TEAMModelOS/ClientApp/src/utils/editorTools.js

@@ -0,0 +1,224 @@
+import $api from '@/api'
+import store from '@/store'
+import $tools from './public.js'
+import E from 'wangeditor'
+
+
+export default {
+
+	addVideoUpload(vm, editor) {
+		// 获取必要的变量,这些在下文中都会用到
+		const {
+			$,
+			PanelMenu,
+			Panel
+		} = E;
+
+		// 标题菜单的 class ,可作为 DropList 菜单的参考代码
+		class myPanel extends PanelMenu {
+			constructor(editor) {
+				// 菜单栏中,标题菜单的 DOM 元素
+				// 注意,这里的 $ 不是 jQuery ,是 E.$ (wangEditor 自带的 DOM 操作工具,类似于 jQuery)
+				const $elem = $('<div class="w-e-menu" style="color:red"><i class="w-e-icon-play"></i></div>');
+				super($elem, editor);
+			}
+
+			clickHandler() {
+				this.createPanel();
+			}
+
+			createPanel() {
+				const conf = this.createPanelConf();
+				const panel = new Panel(this, conf);
+				panel.create();
+			}
+
+			createPanelConf() {
+				const inputIFrameId = 'input-iframe' + Math.random().toString().slice(2);
+				const upFileId = 'upFileId' + Math.random().toString().slice(2);
+				var tabsConf = {
+					// tab 的标题
+					title: editor.i18next.t("menus.panelMenus.video.上传本地视频 "),
+					// 模板
+					tpl: '<div class="w-e-up-img-container">\n <div id="' + inputIFrameId +
+						'" class="w-e-up-btn">\n<i class="w-e-icon-upload2"></i>\n</div>\n <div style="display:none;">\n<input id="' +
+						upFileId +
+						'" type="file" multiple="multiple" accept="video/*"/>\n</div>\n</div>',
+					// 事件绑定
+					events: [
+						// 插入视频
+						{
+							selector: "#" + inputIFrameId,
+							type: "click",
+							fn: () => {
+								var $file = $('#' + upFileId);
+								var fileElem = $file.elems[0];
+								if (fileElem) {
+									fileElem.click();
+								} else {
+									// 返回 true 可关闭 panel
+									return true;
+								}
+							},
+						},
+						{
+							// 选择视频完毕
+							selector: '#' + upFileId,
+							type: 'change',
+							fn: async function fn() {
+								var that = this
+								var $file = $('#' + upFileId);
+								var fileElem = $file.elems[0];
+								if (!fileElem) {
+									// 返回 true 可关闭 panel
+									return true;
+								}
+								// 获取选中的 file 对象列表
+								var fileList = fileElem.files;
+								if (fileList.length) {
+									$tools.doUploadVideo(vm, fileList[0], editor)
+								}
+								// 返回 true 可关闭 panel
+								return true;
+							}
+						}
+					],
+				};
+
+				const conf = {
+					width: 300,
+					height: 0,
+					tabs: [tabsConf],
+				};
+
+				return conf;
+			}
+
+			command(value) {}
+
+			// 菜单是否需要激活
+			tryChangeActive() {}
+		}
+
+		// 注册菜单
+		const videoUpload = "myPanel"; // 菜单 key ,各个菜单不能重复
+		editor.menus.extend("video", myPanel);
+
+		// 将菜单加入到 editor.config.menus 中
+		// 也可以通过配置 menus 调整菜单的顺序,参考【配置菜单】部分的文档
+		// editor.config.menus = editor.config.menus.concat(videoUpload);
+	},
+
+	addAudio(vm, editor) {
+		// 获取必要的变量,这些在下文中都会用到
+		const {
+			$,
+			PanelMenu,
+			Panel
+		} = E;
+
+		// 标题菜单的 class ,可作为 DropList 菜单的参考代码
+		class myPanel extends PanelMenu {
+			constructor(editor) {
+				// 菜单栏中,标题菜单的 DOM 元素
+				// 注意,这里的 $ 不是 jQuery ,是 E.$ (wangEditor 自带的 DOM 操作工具,类似于 jQuery)
+				const $elem = $('<div class="w-e-menu" style="color:red"><i class="w-e-icon-play"></i></div>');
+				super($elem, editor);
+			}
+
+			clickHandler() {
+				this.createPanel();
+			}
+
+			createPanel() {
+				const conf = this.createPanelConf();
+				const panel = new Panel(this, conf);
+				panel.create();
+			}
+
+			createPanelConf() {
+				const inputIFrameId = 'input-iframe' + Math.random().toString().slice(2);
+				const upFileId = 'upFileId' + Math.random().toString().slice(2);
+				var tabsConf = {
+					// tab 的标题
+					title: editor.i18next.t("menus.panelMenus.video.上传本地音频 "),
+					// 模板
+					tpl: '<div class="w-e-up-img-container">\n <div id="' + inputIFrameId +
+						'" class="w-e-up-btn">\n<i class="w-e-icon-upload2"></i>\n</div>\n <div style="display:none;">\n<input id="' +
+						upFileId +
+						'" type="file" multiple="multiple" accept="audio/*"/>\n</div>\n</div>',
+					// 事件绑定
+					events: [
+						// 插入视频
+						{
+							selector: "#" + inputIFrameId,
+							type: "click",
+							fn: () => {
+								var $file = $('#' + upFileId);
+								var fileElem = $file.elems[0];
+								if (fileElem) {
+									fileElem.click();
+								} else {
+									// 返回 true 可关闭 panel
+									return true;
+								}
+							},
+						},
+						{
+							// 选择视频完毕
+							selector: '#' + upFileId,
+							type: 'change',
+							fn: async function fn() {
+								var that = this
+								var $file = $('#' + upFileId);
+								var fileElem = $file.elems[0];
+								if (!fileElem) {
+									// 返回 true 可关闭 panel
+									return true;
+								}
+								// 获取选中的 file 对象列表
+								var fileList = fileElem.files;
+								if (fileList.length) {
+									var audioImg = require('../assets/icon/icon_audio.png')
+									var reader = new FileReader();
+									reader.readAsDataURL(fileList[0]);
+									reader.onload = function(e) {
+										// editor.cmd.do('insertHTML', '<img data-url=' + e.target.result + ' data-name=' + fileList[0].name +
+										// 	' src=' + audioImg + ' class="richText-audio"></img>');
+										editor.txt.append('<span contenteditable="false" data-url=' + e.target.result + ' data-name=' + fileList[0].name +
+											' class="richText-audio"></span>');	
+										// editor.txt.append('<audio data-name=' + fileList[0].name + ' src=' + e.target.result +
+										// 	' class="richText-audio" width="300" controls="controls"></audio>');		
+									}
+								}
+								// 返回 true 可关闭 panel
+								return true;
+							}
+						}
+					],
+				};
+
+				const conf = {
+					width: 300,
+					height: 0,
+					tabs: [tabsConf],
+				};
+
+				return conf;
+			}
+
+			command(value) {}
+
+			// 菜单是否需要激活
+			tryChangeActive() {}
+		}
+
+		// 注册菜单
+		const videoUpload = "audio"; // 菜单 key ,各个菜单不能重复
+		editor.menus.extend("audio", myPanel);
+
+		// 将菜单加入到 editor.config.menus 中
+		// 也可以通过配置 menus 调整菜单的顺序,参考【配置菜单】部分的文档
+		editor.config.menus = editor.config.menus.concat(videoUpload);
+	},
+}

+ 9 - 1
TEAMModelOS/ClientApp/src/utils/public.js

@@ -468,6 +468,12 @@ export default {
 			render: (h) => {
 				return h('div', {
 					'class': 'my-spin',
+					style:{
+						background:'#000',
+						padding:'20px',
+						borderRadius:'5px',
+						color:'#fff'
+					}
 				}, [
 					h('Icon', {
 						'class': 'demo-spin-icon-load',
@@ -495,7 +501,9 @@ export default {
 			const posterBase64 = await this.getVideoBase64(fileBlobUrl)
 			editor.txt.append('<img data-url=' + fileBlobUrl + ' data-name=' + blobFile.name + ' src=' +
 				posterBase64 + ' class="richText-video"></img>')
-			editor.change()
+			// editor.txt.append('<video data-url=' + fileBlobUrl + ' data-name=' + blobFile.name + ' src=' +
+			// 	fileBlobUrl + ' class="richText-video" width="300" controls="controls"></video>')
+			editor.change.emit()
 			vm.$Spin.hide();
 		}catch(e){
 			vm.$Message.error(e.spaceError)

+ 1 - 0
TEAMModelOS/ClientApp/src/view/Home.vue

@@ -91,6 +91,7 @@
                 //     localStorage.removeItem('userInfo')
                 //     localStorage.removeItem('userAccess')
                 //     localStorage.removeItem('user_details')
+				this.$store.commit('user/resetSchoolProfile')
                     this.$User.logout()
                     this.$router.push({
                         path: '/login'

+ 2 - 2
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue

@@ -147,7 +147,7 @@
                                             <span class="question-icon">Q</span>
                                             <div class="question-data-wrap">
                                                 <p class="text-label">教師推送了一張圖: </p>
-                                                <img width="320" @click="openViewer('https://teammodelstorage.blob.core.chinacloudapi.cn/hbcn/res/20170822170818_d41d8cd98f00b204e9800998ecf8427e_8.jpeg'+schoolSas)" :src="'https://teammodelstorage.blob.core.chinacloudapi.cn/hbcn/res/20170822170818_d41d8cd98f00b204e9800998ecf8427e_8.jpeg'+schoolSas" />
+                                                <img height="200" src="https://teammodelostest.blob.core.chinacloudapi.cn/teammodelcontest/common/20200213/%E9%86%8D%E6%91%A9%E8%B1%86_%E8%B1%86%E5%AD%90%E5%BE%BD%E7%AB%A0_20200213154333.png" @click="openViewer('https://teammodelostest.blob.core.chinacloudapi.cn/teammodelcontest/common/20200213/%E9%86%8D%E6%91%A9%E8%B1%86_%E8%B1%86%E5%AD%90%E5%BE%BD%E7%AB%A0_20200213154333.png')" />
                                                 <span class="question-time">00:03:58</span>
                                             </div>
                                         </div>
@@ -190,7 +190,7 @@
                                             <div class="question-data-wrap">
                                                 <span class="question-time">00:03:58</span>
                                                 <p class="text-label">教師推送了一个链接: </p>
-                                                <a href="https://www.habook.com.cn/">https://www.habook.com.cn/</a>
+                                                <a target="_blank" href="https://www.habook.com.cn/">https://www.habook.com.cn/</a>
                                             </div>
                                         </div>
                                     </div>

+ 28 - 22
TEAMModelOS/ClientApp/src/view/evaluation/bank/ExerciseList.vue

@@ -180,7 +180,7 @@
 
 		<Modal v-model="editExerciseModal" class-name="edit-exercise-modal" width="1200px" footer-hide @on-visible-change="editModalChange"
 		 title="编辑习题">
-			<template v-if="periodList.length">
+			<template v-if="!hasSchool || periodList.length">
 				<BaseEditExercise :exerciseItem="currentExercise" @onEditSuccess="onEditSuccess" refId="listEdit" ref="editRef"></BaseEditExercise>
 			</template>
 			<div slot="footer">
@@ -212,7 +212,7 @@
 		data() {
 			return {
 				userId: "",
-				schoolCode: "",
+				schoolCode: "null",
 				isShowSchoolBank: false,
 				dataLoading: false,
 				editExerciseModal: false,
@@ -309,23 +309,29 @@
 			/** 获取区班校信息 */
 			getSchoolInfo() {
 				this.dataLoading = true;
-				this.$store.dispatch("user/getSchoolProfile").then((res) => {
-					let schoolBaseInfo = res.school_base;
-					if (schoolBaseInfo) {
-						this.schoolInfo = schoolBaseInfo;
-						this.schoolCode = schoolBaseInfo.id;
-						this.userId = this.$store.state.userInfo.TEAMModelId;
-						this.filterOrigin = this.isShowSchoolBank ?
-							this.$store.state.userInfo.schoolCode :
-							this.$store.state.userInfo.TEAMModelId;
-						this.periodList = schoolBaseInfo.period;
-						if (schoolBaseInfo.period.length) {
-							this.gradeList = schoolBaseInfo.period[0].grades;
-							this.subjectList = schoolBaseInfo.period[0].subjects;
+				try{
+					this.$store.dispatch("user/getSchoolProfile").then((res) => {
+						let schoolBaseInfo = res.school_base;
+						if (schoolBaseInfo) {
+							this.schoolInfo = schoolBaseInfo;
+							this.schoolCode = schoolBaseInfo.id;
+							this.userId = this.$store.state.userInfo.TEAMModelId;
+							this.filterOrigin = this.isShowSchoolBank ?
+								this.$store.state.userInfo.schoolCode :
+								this.$store.state.userInfo.TEAMModelId;
+							this.periodList = schoolBaseInfo.period;
+							if (schoolBaseInfo.period.length) {
+								this.gradeList = schoolBaseInfo.period[0].grades;
+								this.subjectList = schoolBaseInfo.period[0].subjects;
+							}
 						}
 						this.doFilter();
-					}
-				});
+					});
+				}catch(e){
+					// 当前未加入学校
+					this.doFilter();
+				}
+				
 			},
 
 			/* 获取BLOB所有试题LIST */
@@ -362,10 +368,8 @@
 				this.collapseList = []; // 所有详情都收起来
 				/** 定义查询接口的参数规格 */
 				this.filterParams = {
-					// '@CURRPAGE': this.pageNum,
-					// '@PAGESIZE': this.pageSize,
 					"@DESC": this.filterSort,
-					code: this.filterOrigin,
+					code: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
 					periodId: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) && this.periodList.length ? [this.periodList[this.filterPeriod].id] : [],
 					"gradeIds[*]": (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) ?
 						this.deleteFalse(this.filterGrade) : [],
@@ -428,7 +432,10 @@
 			},
 
 			editModalChange(val) {
-				this.$refs.editRef.backToTop();
+				this.$nextTick(() => {
+					console.log(this.$refs)
+					this.$refs.editRef.backToTop();
+				})
 			},
 
 			/**
@@ -476,7 +483,6 @@
 			 */
 			onQuestionToggle(index, id, e) {
 				let curClassName = e.target.className;
-				console.log(curClassName);
 				if (
 					curClassName === "item-tools" ||
 					curClassName === "richText-video" ||

+ 351 - 347
TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.vue

@@ -1,415 +1,419 @@
 <template>
-    <div class="pl-container">
-        <!-- 条件筛选部分 -->
-        <BaseFilter @onChange="onFilterChange" :isFilterPaper="isFilterPaper"></BaseFilter>
-
-        <!-- 空数据展示 -->
-        <div v-if="paperList.length === 0" class="no-data-text">
-            <img src="@/assets/icon/no_data.svg" width="120" />
-            <span style="margin-top:15px;color:#808080">暂无数据</span>
-        </div>
-
-        <!-- 试卷列表页面 -->
-        <div class="pl-content-wrap" v-else>
-            <Loading :top="100" v-show="dataLoading" type="1" hideMask></Loading>
-            <div class="paper-item" v-for="(paper,index) in paperList" :key="index">
-                <div class="paper-item-name">
-                    <span class="paper-item-tag"  v-if="isSchool">{{ getSubjectName(paper.subjectId) }}</span>
-                    <span style="margin-left: 8px;">{{ paper.name }}</span>
-                </div>
-                <div class="paper-item-info">
-                    <span class="info-item" v-if="isSchool">适用学段:<span class="info-bold">{{ getPeriodName(paper.periodId) }}</span></span>
-                    <span class="info-item" v-if="isSchool">适用年级:<span class="info-bold" v-for="(grade,gIndex) in paper.gradeIds" :key="gIndex">{{ getGradeName(paper.periodId,grade) }} <span v-show="gIndex !== paper.gradeIds.length - 1"> / </span></span></span>
-                    <span class="info-item">题量:<span class="info-bold">{{ paper.scoring ? paper.scoring.length : 0 }}</span></span>
-                    <!-- <span class="info-item">难度系数:<span class="info-bold">{{ paper.item ? handleDiffCalc(paper.item) : 0 }}</span></span> -->
-                </div>
-                <div class="paper-item-tools">
-                    <span class="paper-item-tools-edit" @click="goToPaper(paper)"  v-if="$access.can('admin.*|teacher.*|Paper_Edit')">
+	<div class="pl-container">
+		<!-- 条件筛选部分 -->
+		<BaseFilter @onChange="onFilterChange" :isFilterPaper="isFilterPaper"></BaseFilter>
+
+		<!-- 空数据展示 -->
+		<div v-if="paperList.length === 0" class="no-data-text">
+			<img src="@/assets/icon/no_data.svg" width="120" />
+			<span style="margin-top:15px;color:#808080">暂无数据</span>
+		</div>
+
+		<!-- 试卷列表页面 -->
+		<div class="pl-content-wrap" v-else>
+			<Loading :top="100" v-show="dataLoading" type="1" hideMask></Loading>
+			<div class="paper-item" v-for="(paper,index) in paperList" :key="index">
+				<div class="paper-item-name">
+					<span class="paper-item-tag" v-if="isSchool">{{ getSubjectName(paper.subjectId) }}</span>
+					<span style="margin-left: 8px;">{{ paper.name }}</span>
+				</div>
+				<div class="paper-item-info">
+					<span class="info-item" v-if="isSchool">适用学段:<span class="info-bold">{{ getPeriodName(paper.periodId) }}</span></span>
+					<span class="info-item" v-if="isSchool">适用年级:<span class="info-bold" v-for="(grade,gIndex) in paper.gradeIds" :key="gIndex">{{ getGradeName(paper.periodId,grade) }}
+							<span v-show="gIndex !== paper.gradeIds.length - 1"> / </span></span></span>
+					<span class="info-item">题量:<span class="info-bold">{{ paper.scoring ? paper.scoring.length : 0 }}</span></span>
+					<!-- <span class="info-item">难度系数:<span class="info-bold">{{ paper.item ? handleDiffCalc(paper.item) : 0 }}</span></span> -->
+				</div>
+				<div class="paper-item-tools">
+					<span class="paper-item-tools-edit" @click="goToPaper(paper)" v-if="$access.can('admin.*|teacher.*|Paper_Edit')">
 						<Icon type="ios-create" />
 						<span>编辑</span>
 					</span>
-                    <span class="paper-item-tools-delete"  @click.stop="onDeletePaper(paper)"  v-if="$access.can('admin.*|teacher.*|Paper_Edit')">
+					<span class="paper-item-tools-delete" @click.stop="onDeletePaper(paper)" v-if="$access.can('admin.*|teacher.*|Paper_Edit')">
 						<Icon type="md-trash" />
 						<span>删除</span>
 					</span>
-                </div>
-            </div>
-
-            <!-- 底部分页区域 -->
-            <Page :total="totalNum"
-                  show-sizer
-                  show-total
-                  :page-size="pageSize"
-                  :current="pageNum"
-                  @on-page-size-change="pageSizeChange"
-                  @on-change="pageChange"
-                  :page-size-opts="[5,10,15,20]" />
-        </div>
-    </div>
+				</div>
+			</div>
+
+			<!-- 底部分页区域 -->
+			<Page :total="totalNum" show-sizer show-total :page-size="pageSize" :current="pageNum" @on-page-size-change="pageSizeChange"
+			 @on-change="pageChange" :page-size-opts="[5,10,15,20]" />
+		</div>
+	</div>
 </template>
 <script>
 	import blobTool from '@/utils/blobTool.js'
-    import Loading from '@/common/Loading.vue'
-    import BaseFilter from '../components/BaseFilter'
-    import BaseImport from '../components/BaseImport'
-    import AutoCreate from '../../learnactivity/AutoCreate'
-    export default {
-        components: {
-            Loading, BaseFilter, AutoCreate,BaseImport
-        },
-        data() {
-            return {
-				containerClient:null,
-                schoolCode: '',
-                totalNum: 0,
-                pageSize: 5,
-                pageNum: 1,
-                dataLoading: false,
-                randomModal: false,
-                isFilterPaper:true,
-                paperList: [],
-                periodList: [],
-                gradeList: [],
-                subjectList: [],
-                filterParams: {},
-                findCountParams: {},
-				originList:[],
-                schoolInfo: {},
-                filterSort: 'createTime',
-                paperInfo: {
-                    name: "",
-                    score: 100,
-                    item: []
-                }
-            }
-        },
-        created() {
-            // this.getPaperList()
+	import Loading from '@/common/Loading.vue'
+	import BaseFilter from '../components/BaseFilter'
+	import BaseImport from '../components/BaseImport'
+	import AutoCreate from '../../learnactivity/AutoCreate'
+	export default {
+		components: {
+			Loading,
+			BaseFilter,
+			AutoCreate,
+			BaseImport
+		},
+		data() {
+			return {
+				containerClient: null,
+				schoolCode: '',
+				totalNum: 0,
+				pageSize: 5,
+				pageNum: 1,
+				dataLoading: false,
+				randomModal: false,
+				isFilterPaper: true,
+				paperList: [],
+				periodList: [],
+				gradeList: [],
+				subjectList: [],
+				filterParams: {},
+				findCountParams: {},
+				originList: [],
+				schoolInfo: {},
+				filterSort: 'createTime',
+				paperInfo: {
+					name: "",
+					score: 100,
+					item: []
+				}
+			}
+		},
+		created() {
+			// this.getPaperList()
 			// this.doFilter()
 
-        },
-        methods: {
-
-            /** 执行筛选条件获取数据 */
-            doFilter() {
-                this.dataLoading = true
-                this.getPaperList(this.filterParams)
-                // this.getResultCount(this.findCountParams)
-            },
-
-            onFilterChange(filterParams) {
-                this.filterParams = {
-                    '@DESC': filterParams.filterSort,
-                    'code': filterParams.code,
-					'scope': filterParams.code === this.$store.state.userInfo.schoolCode ? 'school' : 'private',
-                    'periodId': filterParams.periodId[0],
-                    'gradeIds': filterParams.gradeIds,
-                    'subjectId': filterParams.subjectId
-                }
-                // this.findCountParams = findCountParams
-
-                //this.gradeList = this.periodList.filter(item => item.periodCode = filterParams.periodCode[0])[0].grades
-                //this.subjectList = this.periodList.filter(item => item.periodCode = filterParams.periodCode[0])[0].subjects
-                // this.pageChange(1)
+		},
+		methods: {
+
+			/** 执行筛选条件获取数据 */
+			doFilter() {
+				this.dataLoading = true
+				this.getPaperList(this.filterParams)
+			},
+
+			onFilterChange(filterParams) {
+				let isSchool = filterParams.code === this.$store.state.userInfo.schoolCode
+				this.filterParams = {
+					'@DESC': filterParams.filterSort,
+					'code': filterParams.code,
+					'scope': isSchool ? 'school' : 'private',
+					'periodId': isSchool ? filterParams.periodId[0] : [],
+					"gradeIds[*]": isSchool ? filterParams.gradeIds : [],
+					'subjectId': isSchool ? filterParams.subjectId : []
+				}
 				this.doFilter()
-            },
+			},
 
-            /** 获取试卷列表 */
-            getPaperList(params) {
-                let that = this
-                this.$api.learnActivity.FindExamPaper(params).then(async res => {
-                    this.paperList = res.papers
+			/** 获取试卷列表 */
+			getPaperList(params) {
+				let that = this
+				this.$api.learnActivity.FindExamPaper(params).then(async res => {
+					this.paperList = res.papers
 					this.originList = res.papers
 					this.totalNum = res.papers.length
 					this.pageChange(1)
-                    setTimeout(() => {
-                        that.dataLoading = false
-                    }, 1000)
-                }).catch(err => {
+					setTimeout(() => {
+						that.dataLoading = false
+					}, 1000)
+				}).catch(err => {
 					setTimeout(() => {
 						this.$Message.error('试卷数据获取失败')
-					    that.dataLoading = false
+						that.dataLoading = false
 					}, 1000)
 				})
-            },
-
-            /**
-             * 点击查看试卷详情
-             * @param paper
-             */
-            async goToPaper(paper) {
-				try{
+			},
+
+			/**
+			 * 点击查看试卷详情
+			 * @param paper
+			 */
+			async goToPaper(paper) {
+				try {
 					// 获取完整试卷数据再跳转编辑页面
 					let fullPaperJson = await this.$evTools.getFullPaper(paper)
 					fullPaperJson.code = paper.code
 					console.log(fullPaperJson)
 					this.$router.push({
-					    name: 'createPaper',
-					    params: {
-					        paper: fullPaperJson
-					    }
+						name: 'createPaper',
+						params: {
+							paper: fullPaperJson
+						}
 					})
-				}catch(e){
+				} catch (e) {
 					console.log(e)
 					this.$Message.error('获取试卷数据失败!请稍后再试!')
 				}
-				
-            },
-
-            /**
-             * 获取筛选结果数量
-             * @param data
-             */
-            getResultCount(data) {
-                this.$api.newEvaluation.FindCount(data).then(res => {
-                    this.totalNum = res.result.data[0]
-                })
-            },
-
-            /**
-             * 删除试卷
-             * @param item
-             */
-            onDeletePaper(item) {
-                this.$Modal.confirm({
-                    title: '提示',
-                    content: '<p>确认删除该试卷吗?</p>',
-                    okText: '确认',
-                    cancelText: '取消',
-                    onOk: async () => {
+
+			},
+
+			/**
+			 * 获取筛选结果数量
+			 * @param data
+			 */
+			getResultCount(data) {
+				this.$api.newEvaluation.FindCount(data).then(res => {
+					this.totalNum = res.result.data[0]
+				})
+			},
+
+			/**
+			 * 删除试卷
+			 * @param item
+			 */
+			onDeletePaper(item) {
+				this.$Modal.confirm({
+					title: '提示',
+					content: '<p>确认删除该试卷吗?</p>',
+					okText: '确认',
+					cancelText: '取消',
+					onOk: async () => {
 						let blobList = await this.getPaperFiles(item.blob.substring(1))
 						let files = blobList.blobList.map(i => i.blob)
-                        this.dataLoading = true
-                        this.$api.learnActivity.DeleteExamPaper({ id: item.id, code: item.code,scope:item.scope }).then(async res => {
-                            if (!res.error) {
+						this.dataLoading = true
+						this.$api.learnActivity.DeleteExamPaper({
+							id: item.id,
+							code: item.code,
+							scope: item.scope
+						}).then(async res => {
+							if (!res.error) {
 								this.onDeleteBlobPaper(files).then(r => {
 									this.$Message.success('删除成功')
 									this.doFilter()
 								})
-                            } else {
-                                this.$Message.warning('删除失败,错误代码:' + res.error.code + ',错误信息:' + res.error.message)
-                            }
-                        }).catch(err => {
-                            console.log(err)
-                            this.$Message.warning('删除失败')
-                        })
-                    }
-                })
-            },
-			
-			 getPaperFiles(path){
-				return new Promise(async (r,j) => {
+							} else {
+								this.$Message.warning('删除失败,错误代码:' + res.error.code + ',错误信息:' + res.error.message)
+							}
+						}).catch(err => {
+							console.log(err)
+							this.$Message.warning('删除失败')
+						})
+					}
+				})
+			},
+
+			getPaperFiles(path) {
+				return new Promise(async (r, j) => {
 					// 获取初始化Blob需要的数据
 					let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
 					//初始化Blob
-					let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas , this.isSchool ? 'school' : 'private')
+					let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.isSchool ? 'school' : 'private')
 					// 等待blob的返回结果
 					containerClient.listBlob({
-					    prefix: path
+						prefix: path
 					}).then(
-					    (res) => {
-					        r(res)
-					    },
-					    (err) => {
-					        this.$Message.error('API Error')
-					    }
+						(res) => {
+							r(res)
+						},
+						(err) => {
+							this.$Message.error('API Error')
+						}
 					)
 				})
-				
+
 			},
-			
-			onDeleteBlobPaper(files){
-				return new Promise(async (r,j) => {
+
+			onDeleteBlobPaper(files) {
+				return new Promise(async (r, j) => {
 					// 获取初始化Blob需要的数据
 					let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
 					//初始化Blob
-					let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas , this.isSchool ? 'school' : 'private')
+					let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.isSchool ? 'school' : 'private')
 					// 等待blob的返回结果
 					containerClient.deleteBlobBatch(files).then(
-					    (res) => {
-					        r(res)
-					    },
-					    (err) => {
-					        this.$Message.error('API Error')
-					    }
+						(res) => {
+							r(res)
+						},
+						(err) => {
+							this.$Message.error('API Error')
+						}
 					)
 				})
-				
+
 			},
 
-            /**
-            * 切换页码操作
-            * @param page
-            */
-            pageChange(page) {
-                this.pageNum = page
+			/**
+			 * 切换页码操作
+			 * @param page
+			 */
+			pageChange(page) {
+				this.pageNum = page
 				let start = this.pageSize * (page - 1)
 				let end = this.pageSize * page
 				// 拿到当前页码需要展示的数据
 				this.paperList = this.originList.slice(start, end)
-                // this.doFilter()
-            },
-
-            /**
-             * 切换每页显示数量
-             * @param val
-             */
-            pageSizeChange(val) {
-                this.pageSize = val
-                this.pageChange(1)
-            },
-
-            /** 前往试卷页面 */
-            goCreatePaper() {
-                this.$router.push({
-                    name: 'testPaper',
-                    params: {
-                        paper: this.paperInfo
-                    }
-                })
-            },
-
-            /** 前往手动挑题页面 */
-            goPickExercises() {
-                this.$router.push({
-                    name: 'exercisesList'
-                })
-            },
-
-            // 导入试题
-            uploadSuccess(response, file, fileList) {
-                let that = this
-                this.importLoading = true
-                if (response.error === null) {
-                    let requestData = { htmlString: response.result.data.HtmlString }
-                    this.$api.SaveAnalyzeHtml(requestData).then(res => {
-                        if (res.error === null) {
-                            setTimeout(function () {
-                                that.$Message.success('文件上传解析成功!')
-                                that.exerciseList = res.result.data
-                                that.importLoading = false
-                            }, 1000)
-                            // this.saveItemBank(res.result.data);
-                        }
-                    })
-                } else {
-                    this.$Message.error('对不起,文档解析失败!')
-                }
-            },
-
-            /**
-             * 根据SubjectCode换取SubjectName
-             * @param code
-             */
-            getSubjectName(code) {
-                return this.$jsFn.getSubjectName(JSON.parse(JSON.stringify(this.$store.state.user.schoolProfile.school_base)), code)
-            },
-
-            /**
-             * 根据SubjectCode换取SubjectName
-             * @param code
-             */
-            getPeriodName(code) {
-                return this.$jsFn.getPeriod(JSON.parse(JSON.stringify(this.$store.state.user.schoolProfile.school_base)), code).name
-            },
-
-            /**
-             * 根据GradeCode换取GradeName
-             * @param code
-             */
-            getGradeName(periodId,code) {
-                return this.$store.state.user.schoolProfile.school_base.period.filter(i => i.id === periodId)[0].grades.filter(j => j.id === code)[0].name
-            },
-
-            /**
-             * 计算试卷题目平均难度
-             * @param arr 试题集合
-             */
-            handleDiffCalc(arr) {
-                let levelArr = arr.map(i => i.level)
-                return this._.meanBy(levelArr).toFixed(1)
-            }
-
-        },
-        async mounted() {
+				// this.doFilter()
+			},
+
+			/**
+			 * 切换每页显示数量
+			 * @param val
+			 */
+			pageSizeChange(val) {
+				this.pageSize = val
+				this.pageChange(1)
+			},
+
+			/** 前往试卷页面 */
+			goCreatePaper() {
+				this.$router.push({
+					name: 'testPaper',
+					params: {
+						paper: this.paperInfo
+					}
+				})
+			},
+
+			/** 前往手动挑题页面 */
+			goPickExercises() {
+				this.$router.push({
+					name: 'exercisesList'
+				})
+			},
+
+			// 导入试题
+			uploadSuccess(response, file, fileList) {
+				let that = this
+				this.importLoading = true
+				if (response.error === null) {
+					let requestData = {
+						htmlString: response.result.data.HtmlString
+					}
+					this.$api.SaveAnalyzeHtml(requestData).then(res => {
+						if (res.error === null) {
+							setTimeout(function() {
+								that.$Message.success('文件上传解析成功!')
+								that.exerciseList = res.result.data
+								that.importLoading = false
+							}, 1000)
+							// this.saveItemBank(res.result.data);
+						}
+					})
+				} else {
+					this.$Message.error('对不起,文档解析失败!')
+				}
+			},
+
+			/**
+			 * 根据SubjectCode换取SubjectName
+			 * @param code
+			 */
+			getSubjectName(code) {
+				return this.$jsFn.getSubjectName(JSON.parse(JSON.stringify(this.$store.state.user.schoolProfile.school_base)), code)
+			},
+
+			/**
+			 * 根据SubjectCode换取SubjectName
+			 * @param code
+			 */
+			getPeriodName(code) {
+				return this.$jsFn.getPeriod(JSON.parse(JSON.stringify(this.$store.state.user.schoolProfile.school_base)), code).name
+			},
+
+			/**
+			 * 根据GradeCode换取GradeName
+			 * @param code
+			 */
+			getGradeName(periodId, code) {
+				return this.$store.state.user.schoolProfile.school_base.period.filter(i => i.id === periodId)[0].grades.filter(j =>
+					j.id === code)[0].name
+			},
+
+			/**
+			 * 计算试卷题目平均难度
+			 * @param arr 试题集合
+			 */
+			handleDiffCalc(arr) {
+				let levelArr = arr.map(i => i.level)
+				return this._.meanBy(levelArr).toFixed(1)
+			}
+
+		},
+		async mounted() {
 			let schoolProfile = await this.$store.dispatch('user/getSchoolProfile')
-            this.schoolInfo = schoolProfile.school_base
-            this.periodList = this.schoolInfo.period
-        },
-        computed: {
-            headers() {
-                let hd = {}
-                hd['Authorization'] = 'Bearer ' + localStorage.getItem('token')
-                return hd
-            },
-			isSchool(){
+			if (schoolProfile.school_base) {
+				this.schoolInfo = schoolProfile.school_base
+				this.periodList = this.schoolInfo.period
+			}
+
+
+		},
+		computed: {
+			headers() {
+				let hd = {}
+				hd['Authorization'] = 'Bearer ' + localStorage.getItem('token')
+				return hd
+			},
+			isSchool() {
 				return this.filterParams.scope === 'school' ? true : false
 			}
-        }
-    }
+		}
+	}
 </script>
 <style src="./TestPaperList.less" lang="less" scoped>
 </style>
 
 <style>
-    .pl-content-wrap .ivu-page {
-        display: flex;
-        flex-direction: row;
-        justify-content: center;
-        margin: 20px 0;
+	.pl-content-wrap .ivu-page {
+		display: flex;
+		flex-direction: row;
+		justify-content: center;
+		margin: 20px 0;
 		color: #fff;
-    }
-
-    .pl-container .ivu-checkbox-inner {
-        display: none !important;
-    }
-
-    .random-pick-modal .question-condition-wrap .question-condition-item .condition-label,
-    .random-pick-modal .question-condition-wrap .question-condition-item {
-        color: #000;
-        font-size: 14px;
-    }
-
-    .random-pick-modal .question-num-item .ivu-select-selection {
-        color: #333333;
-    }
-
-    .random-pick-modal .question-num-item .ivu-input-number,
-    .random-pick-modal .question-num-item .ivu-input-number-small input {
-        color: #000;
-    }
-
-    .random-pick-modal .auto-create-wrap {
-        background: transparent;
-    }
-
-    .random-pick-modal .auto-create-name {
-        color: #515a6e;
-        text-align: left;
-        font-size: 14px;
-        font-weight: normal;
-        margin-top: 0;
-    }
-
-    .random-pick-modal .question-condition-wrap .ivu-btn {
-        height: 40px;
-        line-height: 40px;
-        margin-top: 0;
-    }
-
-    .random-pick-modal .question-condition-wrap {
-        overflow: hidden;
-    }
-
-    .random-pick-modal .ivu-tag {
-        background: transparent !important;
-    }
-
-    .random-pick-modal .ivu-tag-color-white {
-        color: #515a6e !important;
-    }
-
-    .random-pick-modal .ivu-tag .ivu-icon-ios-close {
-        color: #515a6e !important;
-    }
+	}
+
+	.pl-container .ivu-checkbox-inner {
+		display: none !important;
+	}
+
+	.random-pick-modal .question-condition-wrap .question-condition-item .condition-label,
+	.random-pick-modal .question-condition-wrap .question-condition-item {
+		color: #000;
+		font-size: 14px;
+	}
+
+	.random-pick-modal .question-num-item .ivu-select-selection {
+		color: #333333;
+	}
+
+	.random-pick-modal .question-num-item .ivu-input-number,
+	.random-pick-modal .question-num-item .ivu-input-number-small input {
+		color: #000;
+	}
+
+	.random-pick-modal .auto-create-wrap {
+		background: transparent;
+	}
+
+	.random-pick-modal .auto-create-name {
+		color: #515a6e;
+		text-align: left;
+		font-size: 14px;
+		font-weight: normal;
+		margin-top: 0;
+	}
+
+	.random-pick-modal .question-condition-wrap .ivu-btn {
+		height: 40px;
+		line-height: 40px;
+		margin-top: 0;
+	}
+
+	.random-pick-modal .question-condition-wrap {
+		overflow: hidden;
+	}
+
+	.random-pick-modal .ivu-tag {
+		background: transparent !important;
+	}
+
+	.random-pick-modal .ivu-tag-color-white {
+		color: #515a6e !important;
+	}
+
+	.random-pick-modal .ivu-tag .ivu-icon-ios-close {
+		color: #515a6e !important;
+	}
 </style>

+ 1 - 2
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseCreateChild.vue

@@ -491,7 +491,6 @@
 
 			// 渲染编辑习题内容回显
 			async renderExercise(editItem) {
-				let schoolInfo = await this.$store.dispatch('user/getSchoolProfile');
 				this.isEdit = true;
 				this.exersicesDiff = editItem.level.toString() || "0";
 				this.exerciseScope =
@@ -529,7 +528,7 @@
 				}
 
 				this.childList = editItem.children || [];
-
+				let schoolInfo = await this.$store.dispatch('user/getSchoolProfile');
 				this.schoolInfo = schoolInfo;
 
 				this.stemContent = editItem.question;

+ 15 - 16
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseEditExercise.vue

@@ -146,7 +146,7 @@
 	import "videojs-contrib-hls.js/src/videojs.hlsjs";
 	import IconText from "@/components/evaluation/IconText.vue";
 	import BaseSingle from "@/view/evaluation/types/BaseSingle.vue";
-	import BaseMultiple from "@/view/evaluation/types/BaseMultipleNew.vue";
+	import BaseMultiple from "@/view/evaluation/types/BaseMultiple.vue";
 	import BaseCompletion from "@/view/evaluation/types/BaseCompletion.vue";
 	import BaseJudge from "@/view/evaluation/types/BaseJudge.vue";
 	import BaseSubjective from "@/view/evaluation/types/BaseSubjective.vue";
@@ -631,15 +631,28 @@
 			async renderExercise(editItem) {
 				console.log(editItem);
 				this.editInfo = editItem;
+				
 				let schoolProfile = await this.$store.dispatch('user/getSchoolProfile')
 				let schoolInfo = schoolProfile.school_base;
+				if (this.isSchool && schoolInfo) {
+					this.schoolInfo = schoolInfo;
+					this.exerciseGrade = editItem.gradeIds;
+					this.exercisePeriod = schoolInfo.period
+						.map((item) => item.id)
+						.indexOf(editItem.periodId);
+					this.subjectList = schoolInfo.period[this.exercisePeriod].subjects;
+					this.gradeList = schoolInfo.period[this.exercisePeriod].grades;
+					this.exerciseSubject = this.subjectList
+						.map((item) => item.id)
+						.indexOf(editItem.subjectId);
+				}
+				
 				this.isEdit = true;
 				this.exersicesDiff = editItem.level.toString() || "0";
 				this.exerciseScope = editItem.scope === "private" ? 0 : 1;
 				this.exersicesType = editItem.type;
 				this.exerciseField = editItem.field - 1;
 				this.exercisePoints = editItem.points;
-				console.log(this.isSchool);
 				if (editItem.level) {
 					let ac = document
 						.getElementById(this.refId)
@@ -669,20 +682,6 @@
 				}
 
 				this.childList = editItem.children || [];
-
-				if (this.isSchool) {
-					this.schoolInfo = schoolInfo;
-					this.exerciseGrade = editItem.gradeIds;
-					this.exercisePeriod = schoolInfo.period
-						.map((item) => item.id)
-						.indexOf(editItem.periodId);
-					this.subjectList = schoolInfo.period[this.exercisePeriod].subjects;
-					this.gradeList = schoolInfo.period[this.exercisePeriod].grades;
-					this.exerciseSubject = this.subjectList
-						.map((item) => item.id)
-						.indexOf(editItem.subjectId);
-				}
-
 				this.stemContent = editItem.question;
 				this.relateFileList = editItem.repairResource || [];
 				this.optionsContent = editItem.option;

+ 15 - 10
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseFilter.vue

@@ -14,7 +14,7 @@
         >
       </RadioGroup>
     </div>
-    <div class="filter-item" v-show="isShowSchoolBank">
+    <div class="filter-item" v-show="isShowSchoolBank || (filterOrigin === schoolCode)">
       <span class="filter-title">学段:</span>
       <RadioGroup
         v-model="filterPeriod"
@@ -29,7 +29,7 @@
         >
       </RadioGroup>
     </div>
-    <div class="filter-item" v-show="isShowSchoolBank">
+    <div class="filter-item" v-show="isShowSchoolBank || (filterOrigin === schoolCode)">
       <span class="filter-title">年级:</span>
       <CheckboxGroup
         v-model="filterGrade"
@@ -45,7 +45,7 @@
         >
       </CheckboxGroup>
     </div>
-    <div class="filter-item" v-show="isShowSchoolBank">
+    <div class="filter-item" v-show="isShowSchoolBank || (filterOrigin === schoolCode)">
       <span class="filter-title">科目:</span>
       <CheckboxGroup
         v-model="filterSubject"
@@ -156,9 +156,12 @@ export default {
             this.gradeList = schoolBaseInfo.period[0].grades;
             this.subjectList = schoolBaseInfo.period[0].subjects;
           }
-          this.doFilter();
         }
-      });
+		this.doFilter();
+      }).catch(err => {
+		  console.log(err)
+		  this.doFilter();
+	  })
     },
 
     /** 执行筛选条件获取数据 */
@@ -166,13 +169,15 @@ export default {
       /** 定义查询接口的参数规格 */
       this.filterParams = {
         filterSort: this.filterSort,
-        code: this.filterOrigin,
-        periodId: this.periodList.length ?  [this.periodList[this.filterPeriod].id] : [],
-        gradeIds: this.deleteFalse(this.filterGrade),
-        subjectId: this.deleteFalse(this.filterSubject),
+        code: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
+        periodId: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) && this.periodList.length ? [this.periodList[this.filterPeriod].id] : [],
+        gradeIds: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) ?
+        	this.deleteFalse(this.filterGrade) : [],
+        subjectId: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) ?
+        	this.deleteFalse(this.filterSubject) : [],
         level: this.deleteFalse(this.filterDiff),
         type: this.deleteFalse(this.filterType),
-        field: this.deleteFalse(this.filterField),
+        field: this.deleteFalse(this.filterField)
       };
 
       this.$emit("onChange", this.filterParams);

+ 29 - 22
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseImport.vue

@@ -5,37 +5,38 @@
                         :action="uploadUrl"
                         :headers="headers"
                         :format="['docx']"
-                        :max-size="102400"
                         :on-format-error="handleFormatError"
-                        :on-exceeded-size="handleMaxSize"
                         :show-upload-list="isShowList"
                         :before-upload="beforeUpload"
                         :on-success="uploadSuccess">
                         <Icon type="ios-folder" size="150" color="#878787" style="margin: 30px 0;"/>
                     <div v-show="isBtnLoading" class="import-loading-wrap">
                         <img src="@/assets/loading/loading.svg" width="100px" />
-                        <!-- <p style="font-size:16px;font-weight:bold">读取中</p> -->
                     </div>
                 </Upload>
 				<div class="import-tips">
+					<div style="display: flex;margin-bottom: 20px;">
+						<Dropdown @on-click="onTemplateSelect">
+						        <Button type="primary">
+						            多语言模板下载
+						            <Icon type="ios-arrow-down"></Icon>
+						        </Button>
+						        <DropdownMenu slot="list">
+						            <DropdownItem :name="0">中文简体(zh-CN)</DropdownItem>
+						            <DropdownItem :name="1">中文繁体(zh-TW)</DropdownItem>
+						            <DropdownItem :name="2">英文(en-US)</DropdownItem>
+						        </DropdownMenu>
+						    </Dropdown>
+						<Button type="primary" style="margin-left: 20px;" @click="onDownloadDetails">下载模板制作详情说明</Button>	
+					</div>
+					
 					<p style="font-size:18px;font-weight:bold;color: #fff;">导入注意事项</p>
 					<p>1.点击上方文件夹图标选择文件</p>
-					<p>2.暂时只支持".docx"格式的文件导入,文件大小不超过10M,请按照模板格式导入</p>
+					<p>2.只支持".docx"格式的文件导入,请按照模板格式导入</p>
 					<p>3.导入题型暂时只支持单选、多选、判断、填空、问答以及综合题型</p>
 					<p>4.{{ `请保持模板语言与当前浏览器语言(${ curLang })   一致` }}</p>
 					<p>5.更多注意事项请查看模板制作详情说明</a></p>
-					<Dropdown style="margin-top: 20px;" @on-click="onTemplateSelect">
-					        <Button type="primary">
-					            多语言模板下载
-					            <Icon type="ios-arrow-down"></Icon>
-					        </Button>
-					        <DropdownMenu slot="list">
-					            <DropdownItem :name="0">中文简体(zh-CN)</DropdownItem>
-					            <DropdownItem :name="1">中文繁体(zh-TW)</DropdownItem>
-					            <DropdownItem :name="2">英文(en-US)</DropdownItem>
-					        </DropdownMenu>
-					    </Dropdown>
-					<Button type="primary" style="margin-top: 20px;" @click="onDownloadDetails">下载模板制作详情说明</Button>	
+					
 				</div>
             </div>
     </div>
@@ -141,7 +142,7 @@
              * @param
              */
             handleFormatError() {
-                this.$Message.error('上传格式有误,请重新上传!')
+                this.$Message.error('上传格式仅支持 docx,请重新上传! ')
                 this.isBtnLoading = false
 				this.isSelectFinish = false
             },
@@ -165,11 +166,17 @@
                     let requestData = { lang:localStorage.getItem('local'), htmlString: response.HtmlString }
                     this.$api.SaveAnalyzeHtml(requestData).then(res => {
                         if (!res.error) {
-                                this.$Message.success('试题数据读取完成!')
-                                this.$emit('importFinish',res)
-                                this.isImportFinish = false
-                                this.isBtnLoading = false
-                                this.exerciseList = []
+							if(res.length){
+								this.$Message.success('试题数据读取完成!')
+								this.$emit('importFinish',res)
+								this.isImportFinish = false
+								this.isBtnLoading = false
+								this.exerciseList = []
+							}else{
+								this.$Message.error('未解析出符合条件的试题,请检查导入格式是否按照模板文件修改!')
+								this.isBtnLoading = false
+							}
+                                
                         }else{
 							this.$Message.error('抱歉,文档解析失败!')
 							this.isBtnLoading = false

+ 2 - 8
TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.less

@@ -205,9 +205,9 @@ exersices-attr-diff {
 
 .ev-container .option-delete {
     font-size: 20px;
-    margin-left: 15px;
+    margin-right: 10px;
     cursor: pointer;
-    color: #a0a0a0;
+    color: red;
 }
 
 .fl-center {
@@ -282,12 +282,6 @@ exersices-attr-diff {
 	background-color: transparent !important;
 }
 
-.ivu-spin-main{
-	background-color: #525252;
-	color:#fff;
-	padding: 30px 20px;
-	border-radius: 10px;
-}
 
 
 

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

@@ -148,7 +148,7 @@
 	import blobTool from "@/utils/blobTool.js";
 	import IconText from "@/components/evaluation/IconText.vue";
 	import BaseSingle from "@/view/evaluation/types/BaseSingle.vue";
-	import BaseMultiple from "@/view/evaluation/types/BaseMultipleNew.vue";
+	import BaseMultiple from "@/view/evaluation/types/BaseMultiple.vue";
 	import BaseCompletion from "@/view/evaluation/types/BaseCompletion.vue";
 	import BaseJudge from "@/view/evaluation/types/BaseJudge.vue";
 	import BaseSubjective from "@/view/evaluation/types/BaseSubjective.vue";
@@ -160,7 +160,7 @@
 	// 默认创建题目模板
 	const defaultExercise = {
 		question: "",
-		options: [],
+		option: [],
 		level: 1,
 		answer: [],
 		explain: "",
@@ -225,8 +225,11 @@
 		},
 		created() {
 			let scope = this.$route.params.scope; // 编辑题目
-			this.exerciseScope = scope === "private" ? 0 : 1;
-			this.fromScope = scope;
+			if(scope){
+				this.exerciseScope = scope === "private" ? 0 : 1;
+				this.fromScope = scope;
+			}
+			
 			// 初始化区班校信息
 			this.getSchoolInfo();
 		},

+ 15 - 9
TEAMModelOS/ClientApp/src/view/evaluation/index/CreatePaper.vue

@@ -154,6 +154,7 @@
 			this.evaluationInfo.type = scope || 'private'
 
 			this.getSchoolBaseInfo().then(res => {
+				if(!res) return
 				this.schoolInfo = res
 				this.onPeriodChange(0)
 			})
@@ -324,6 +325,8 @@
 						let schoolBaseInfo = res.school_base;
 						if (schoolBaseInfo) {
 							r(schoolBaseInfo)
+						}else{
+							r(null)
 						}
 					});
 				})
@@ -560,10 +563,10 @@
 						id: this.evaluationInfo.id || guid,
 						code: this.editPaper ? this.editPaper.code : (this.isSchool ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId),
 						scope: this.isSchool ? 'school' : 'private',
-						gradeIds: this.evaluationInfo.paperGrade.length ? this.evaluationInfo.paperGrade : this.gradeList.map(i => i.id),
-						subjectId: this.subjectList[this.evaluationInfo.paperSubject].id,
-						subjectName: this.subjectList[this.evaluationInfo.paperSubject].name,
-						periodId: this.schoolInfo.period[this.evaluationInfo.paperPeriod].id,
+						gradeIds: this.isSchool ? (this.evaluationInfo.paperGrade.length ? this.evaluationInfo.paperGrade : this.gradeList.map(i => i.id)) : [],
+						subjectId: this.isSchool ? this.subjectList[this.evaluationInfo.paperSubject].id : null,
+						subjectName: this.isSchool ? this.subjectList[this.evaluationInfo.paperSubject].name : '',
+						periodId: this.isSchool ? this.schoolInfo.period[this.evaluationInfo.paperPeriod].id : null,
 						name: this.evaluationInfo.name,
 						points:this.getPaperPoints(this.evaluationInfo.item),
 						scoring: this.getAnswers(this.evaluationInfo.item),
@@ -682,16 +685,19 @@
 			async doRender(paper) {
 				console.log('传进来的paper')
 				console.log(paper)
-				this.schoolInfo = await this.getSchoolBaseInfo()
-				this.subjectList = this.schoolInfo.period.filter(i => i.id === paper.periodId)[0].subjects
+				let schoolInfo = await this.getSchoolBaseInfo()
+				console.log(schoolInfo)
+				if(paper.scope === 'school'){
+					this.subjectList = schoolInfo ? this.schoolInfo.period.filter(i => i.id === paper.periodId)[0].subjects : []
+				}
 				this.evaluationInfo = {
 					id: paper.id,
 					name: paper.name,
 					code:paper.code,
 					type: paper.scope,
-					paperPeriod: this.schoolInfo.period.map(i => i.id).indexOf(paper.periodId),
-					paperGrade: paper.gradeIds,
-					paperSubject: this.subjectList.map(i => i.id).indexOf(paper.subjectId),
+					paperPeriod: schoolInfo && paper.scope === 'school' ? this.schoolInfo.period.map(i => i.id).indexOf(paper.periodId) : null,
+					paperGrade: schoolInfo && paper.scope === 'school' ? paper.gradeIds : [],
+					paperSubject: schoolInfo && paper.scope === 'school' ? this.subjectList.map(i => i.id).indexOf(paper.subjectId) : [],
 					score: paper.score,
 					item: paper.item,
 					multipleRule:paper.multipleRule,

+ 0 - 1
TEAMModelOS/ClientApp/src/view/evaluation/index/PickExercise.css

@@ -125,7 +125,6 @@
         padding: 10px 20px 10px 20px;
         margin-top: 10px;
         font-size: 16px;
-        font-weight: 600;
         background: #fff;
 		border: 2px solid transparent;
         cursor:pointer;

+ 1 - 10
TEAMModelOS/ClientApp/src/view/evaluation/index/index.vue

@@ -9,14 +9,6 @@
                 </div>
             </div>
         </vuescroll>
-        <div class="slide-menu animated" style="display:none">
-            <ul>
-                <li @click="goRouter('createExercises')">创建习题</li>
-                <li @click="goRouter('exercisesList')">组卷中心</li>
-                <li @click="goRouter('personalBank')">试卷试题库</li>
-            </ul>
-            <!--<Icon type="md-list" />-->
-        </div>
     </div>
 
 </template>
@@ -69,10 +61,9 @@
 
   .ev-body {
     /*width:98%;*/
-    min-width:1200px;
+    /* min-width:1200px; */
     min-height:700px;
     margin:auto;
-    /*padding:10px 20px 50px 20px;*/
     display:flex;
     flex-direction:row;
     justify-content:space-between;

+ 324 - 221
TEAMModelOS/ClientApp/src/view/evaluation/types/BaseMultiple.vue

@@ -1,238 +1,341 @@
 <template>
-    <div>
-        <div class="exersices-content">
-            <IconText :text="'题目'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
-            <div>
-                <div ref="editor" style="text-align:left"></div>
-            </div>
-        </div>
-        <div class="exersices-option">
-            <IconText :text="'多选选项'" :color="'#FF871C'" :icon="'md-reorder'"></IconText>
-            <div v-for="(item,index) in options" :key="index" :class="'editor-wrap-'+item" style="margin-top:10px;display:flex">
-                <span class="fl-center option-order">{{String.fromCharCode(64 + parseInt(index+1))}}</span>
-                <div :ref="'multipleEditor'+item" style="text-align:left" class="option-editor" @click="optionClick(item)"></div>
-                <span :class="['fl-center', 'option-setting', trueArr.indexOf(item) > -1 ? 'option-true':'']" @click="settingAnswer(item,index)">{{ trueIndex.indexOf(item) > -1 ? '正确答案' :'设为答案' }}</span>
-                <span class="fl-center option-delete" @click="deleteOption(item,index)"><Icon type="ios-close-circle" /></span>
-            </div>
-            <p class="option-add"><span @click="addOption()">+ 添加选项 </span><span style="color:rgb(60,196,82);margin-left:15px;font-weight:bold">正确答案 :{{showTrueAnswers}}</span></p>
-        </div>
-    </div>
+	<div>
+		<div class="exersices-content">
+			<IconText :text="'题目'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
+			<div @click="onRichTextClick($event)">
+				<div ref="singleEditor" style="text-align:left"></div>
+			</div>
+		</div>
+		<div class="exersices-option">
+			<IconText :text="'多选选项'" :color="'#FF871C'" :icon="'md-reorder'"></IconText>
+			<div v-for="(item,index) in options" :key="index" :ref="'optionBox' + index" :class="'editor-wrap-'+item" style="margin-top:10px;display:flex"
+			 @click="onRichTextClick($event)">
+				<span class="fl-center option-delete" @click="deleteOption(index,item)"><Icon type="md-remove-circle" /></span>
+				<span class="fl-center option-order" :ref="'optionOrder' + index" :data-index="index">{{ renderIndex(index) }}</span>
+				<div :ref="'singleOption'+index" style="text-align:left" class="option-editor" @click="optionClick(item)"></div>
+				<span :class="['fl-center', 'option-setting', trueArr.indexOf(index) > -1 ? 'option-true':'']" @click="settingAnswer(index)">{{ trueArr.indexOf(index) > -1  ? '正确答案' :'设为答案' }}</span>
+
+			</div>
+			<p class="option-add"><span @click="addOption()">+ 添加选项 </span><span style="color:rgb(60,196,82);margin-left:15px;font-weight:bold">正确答案:{{ multipleAnswers.join('') }}</span></p>
+		</div>
+	</div>
 </template>
 <script>
-    import E from '@/utils/wangEditor.js'
-    import IconText from '@/components/evaluation/IconText.vue'
-    export default {
-        components: {
-            IconText
-        },
-        props: ['editInfo'],
-        data() {
-            return {
-                options: [...new Array(4).keys()], // 默认四个选项
-                existOptions: [...new Array(4).keys()],
-                initFlag: true,
-                trueArr: [0],
-                trueIndex: [0],
-                stemContent: '',
-                stemEditor: null,
-                transferArr: [],
-                optionsContent: [],
-                defaultConfig: {
-                	uploadImgShowBase64:true,
-                    menus: this.$tools.wangEditorMenu
-                },
-            }
-        },
-        created() {
-            if (Object.keys(this.editInfo).length > 0) {
-                this.options = [...new Array(this.editInfo.option.length).keys()]
-            }
-        },
-        methods: {
-            initEditors() {
-                // Editor默认配置
-                for (let i of this.options) {
-                    let that = this
-                    let editor = new E(that.$refs['multipleEditor' + i][0])
-                    editor.customConfig = this.defaultConfig
-                    editor.customConfig.onblur = function () {
-                        let allToolbars = document.getElementsByClassName('option-editor')
-                        for (let i = 0; i < allToolbars.length; i++) {
-                            if (allToolbars[i].children.length) {
-                                allToolbars[i].children[0].style.visibility = 'hidden'
-                            }
-                        }
-                    }
-					editor.customConfig.onVideoWarning = (text) => {
-						this.$Message.warning(text)
-					},
-                    editor.customConfig.onchange = (html) => {
-                        let key = String.fromCharCode(64 + parseInt(i + 1))
-                        let codeArr = this.optionsContent.map(item => item.code)
-                        // 如果已经编辑过则 修改选项内容
-                        if (codeArr.indexOf(key) !== -1) {
-                            this.optionsContent[codeArr.indexOf(key)].value = html
-                        } else { // 否则创建新选项
-                            let option = {
-                                code: key,
-                                value: html
-                            }
-                            this.optionsContent.push(option)
-                        }
-                    }
-                    editor.create()
+	import E from '@/utils/wangEditor.js'
+	import IconText from '@/components/evaluation/IconText.vue'
+	export default {
+		components: {
+			IconText
+		},
+		props: ['editInfo'],
+		data() {
+			return {
+				options: [...new Array(4).keys()], // 默认四个选项
+				existOptions: [...new Array(4).keys()],
+				initFlag: true,
+				trueIndex: 0,
+				optionTrueIndex:0,
+				trueArr:[0],
+				optionTrueArr:[0],
+				multipleAnswers:['A'],
+				editSingleInfo: {},
+				stemEditor: null,
+				stemContent: '',
+				transferArr:[],
+				optionsContent: [],
+				optionEditors: [],
+				defaultConfig: {
+					uploadImgShowBase64: true,
+					menus: this.$tools.wangEditorMenu
+				}
+			}
+		},
+		created() {},
+		methods: {
+			initEditors() {
+				// Editor默认配置
+				if (this.options.length > 0) {
+					this.options.forEach((item, i) => {
+						let that = this
+						let editor = new E(that.$refs['singleOption' + i][0])
+						editor.customConfig = this.defaultConfig
+						editor.customConfig.uploadVideoDisable = true,
+							// editor.customConfig.zIndex = 100
+
+							// 选项编辑器失焦隐藏工具栏
+							editor.customConfig.onblur = function() {
+								let allToolbars = document.getElementsByClassName('option-editor')
+								for (let i = 0; i < allToolbars.length; i++) {
+									if (allToolbars[i].children.length) {
+										allToolbars[i].children[0].style.visibility = 'hidden'
+									}
+								}
+							}
 
-                    // 如果是编辑状态 则将选项内容回显
-                    if (Object.keys(this.editInfo).length > 0) {
-                        editor.txt.html(this.editInfo.option[i].value)
-                    }
-                }
-            },
-            // 设置正确答案
-            settingAnswer(item, index) {
-                this.$nextTick(() => {
-                    if (this.trueArr.indexOf(item) > -1) {
-                        this.trueArr.splice(this.trueArr.indexOf(item), 1)
-                        this.trueIndex.splice(this.trueIndex.indexOf(index), 1)
-                    } else {
-                        this.trueArr.push(item)
-                        this.trueIndex.push(index)
-                        this.trueArr = this.trueArr.sort() // 选项排序
-                        this.trueIndex = this.trueIndex.sort() // 选项排序
-                    }
-                })
-            },
-            // 添加选项
-            addOption() {
-                let that = this
-                let newIndex = parseInt(this.options[this.options.length - 1]) + 1
-                let optionsLength = this.options.length
-                if (optionsLength < 10) {
-                    this.options.push(newIndex)
-                    this.$nextTick(() => {
-                        let editor = new E(that.$refs['multipleEditor' + newIndex][0])
-                        editor.customConfig = this.defaultConfig
+						editor.customConfig.onVideoWarning = (text) => {
+								this.$Message.warning(text)
+							},
 
-                        editor.customConfig.onchange = (html) => {
-                            let key = String.fromCharCode(64 + parseInt(newIndex + 1))
-                            let codeArr = this.optionsContent.map(item => item.code)
-                            // 如果已经编辑过则 修改选项内容
-                            if (codeArr.indexOf(key) !== -1) {
-                                this.optionsContent[codeArr.indexOf(key)].value = html
-                                console.log(this.optionsContent.map(item => item.code))
-                                console.log(this.optionsContent.map(item => item.value))
-                            } else { // 否则创建新选项
-                                let option = {
-                                    code: key,
-                                    value: html
-                                }
-                                this.optionsContent.push(option)
-                                console.log(this.optionsContent.map(item => item.code))
-                                console.log(this.optionsContent.map(item => item.value))
-                            }
-                        }
-                        editor.create()
-                    })
-                } else {
-                    this.$Message.warning('最多只有10个选项!')
-                }
-            },
-            // 删除选项
-            deleteOption(item, index) {
-                let letter = String.fromCharCode(64 + parseInt(index + 1))
-                if (this.options.length > 2) {
-                    this.options.splice(this.options.indexOf(item), 1)
-                    this.optionsContent.splice(index, 1)
-                    // 如果删除了已有选项 后面的code要降1
-                    for (let i in this.optionsContent) {
-                        if (i >= index) {
-                            this.optionsContent[i].code = String.fromCharCode(64 + parseInt(parseInt(i) + 1))
-                        }
-                    }
-                    if (this.transferArr.indexOf(letter) > -1) {
-                        this.trueIndex.splice(this.trueIndex.length - 1, 1)// 从正确索引中删除
-                        this.trueArr.splice(this.trueArr.indexOf(item), 1)// 从正确选项中删除
-                    } else {
-                        this.trueIndex = this.trueIndex.map(item => item > index ? item - 1 : item) // 如果删除错误选项 则后面的正确选项要前移动一位
-                    }
-                } else {
-                    this.$Message.warning('至少保留两个选项!')
-                }
-            },
-            // 选项点击事件聚焦
-            optionClick(index) {
-                let allToolbars = document.getElementsByClassName('option-editor')
-                let that = this
-                for (let i = 0; i < allToolbars.length; i++) {
-                    allToolbars[i].children[0].style.visibility = 'hidden'
-                }
-                setTimeout(function () {
-                    let currentToolBar = that.$refs['multipleEditor' + index][0].children[0]
-                    currentToolBar.style.visibility = 'visible'
-                }, 100)
-            }
-        },
-        mounted() {
-            let stemEditor = new E(this.$refs.editor)
-            stemEditor.customConfig = this.defaultConfig
-            stemEditor.customConfig.onchange = (html) => {
-                this.stemContent = html
-            }
+							// 选项编辑器内容发生变化时
+							editor.customConfig.onchange = (html) => {
+								let key = String.fromCharCode(64 + parseInt(i + 1))
+								let codeArr = this.optionsContent.map(item => item.code)
+								// 如果已经编辑过则 修改选项内容
+								if (codeArr.indexOf(key) !== -1) {
+									this.optionsContent[codeArr.indexOf(key)].value = html
+								} else { // 否则创建新选项
+									let option = {
+										code: key,
+										value: html
+									}
+									this.optionsContent.push(option)
+								}
+							}
+						editor.create()
+						this.optionEditors.push(editor)
+						that.$refs["singleOption" + i][0].dataset.editorId = editor.id
+
+						// 如果是编辑状态 则将选项内容回显
+						if (Object.keys(this.editSingleInfo).length > 0) {
+							editor.txt.html(this.editSingleInfo.option[i].value)
+						}
+					})
+				}
+			},
+
+			onRichTextClick(e) {
+				this.$parent.onRichTextClick(e)
+			},
+			/* 添加选项 */
+			addOption() {
+				let that = this
+				let wraps = document.getElementsByClassName('option-editor')
+				let optionsLength = wraps.length;
+				let newIndex = parseInt(this.options[this.options.length - 1]) + 1
+				// let optionsLength = this.options.length
+				if (optionsLength < 10) {
+					this.options.push(newIndex)
+					this.existOptions.push(newIndex)
+					this.$nextTick(() => {
+						let editor = new E(that.$refs['singleOption' + newIndex][0])
+						editor.customConfig = this.defaultConfig
+
+						editor.customConfig.onchange = (html) => {
+							let key = String.fromCharCode(64 + parseInt(newIndex + 1))
+							let codeArr = this.optionsContent.map(item => item.code)
+							// 如果已经编辑过则 修改选项内容
+							if (codeArr.indexOf(key) !== -1) {
+								this.optionsContent[codeArr.indexOf(key)].value = html
+								console.log(this.optionsContent.map(item => item.code))
+								console.log(this.optionsContent.map(item => item.value))
+							} else { // 否则创建新选项
+								let option = {
+									code: key,
+									value: html
+								}
+								this.optionsContent.push(option)
+							}
+						}
+						editor.create()
+						this.optionEditors.push(editor);
+						this.$refs["singleOption" + newIndex][0].dataset.editorId = editor.id
+						this.refreshOrder()
+					})
+				} else {
+					this.$Message.warning('最多只有10个选项!')
+				}
+			},
 			
-			stemEditor.customConfig.onVideoWarning = (text) => {
-				this.$Message.warning(text)
+			
+			/* 设置正确答案 */
+			settingAnswer(index) {
+				this.$nextTick(() => {
+				    if (this.trueArr.indexOf(index) > -1) {
+						if(this.trueArr.length === 1){
+							this.$Message.warning('至少保留一个正确答案!')
+						}else{
+							this.trueArr.splice(this.trueArr.indexOf(index), 1)
+						}
+				    } else {
+				        this.trueArr.push(index)
+				        this.trueArr = this.trueArr.sort() // 选项排序
+				    }
+					this.getAnswerOrder(this.trueArr)
+				})
 			},
 			
-			// 选择视频文件后的上传Blob操作
-			stemEditor.customConfig.onVideoSelected = async (file) => {
-					this.$tools.doUploadVideo(this,file,stemEditor)
+			/* 获取最新答案选项 */
+			getAnswerOrder(arr){
+				let arr2 = []
+				arr.forEach(i => {
+					arr2.push(this.getOrderCode(i))
+				})
+				this.multipleAnswers = arr2.sort()
 			},
 			
-            stemEditor.create()
-            this.stemEditor = stemEditor
-            // 初始化选项编辑器
-            this.initEditors()
+			/* 根据index获取对应选项字母的值 */
+			getOrderCode(index){
+				let wraps = document.getElementsByClassName('option-order')
+				for(let i=0;i<wraps.length;i++){
+					let item = wraps[i]
+					if(+index === +item.dataset.index){
+						return item.innerText
+						break;
+					}
+				}
+			},
 			
-			if(this.editInfo && this.editInfo.question){
-				console.log('进入多选题Mounted编辑')
-				console.log(this.editInfo)
-				this.stemContent = this.editInfo.question
-				this.optionsContent = this.editInfo.option
-				this.trueIndex = this.editInfo.answer.map(item => item.charCodeAt() - 65)
-				this.trueArr = this.editInfo.answer.map(item => item.charCodeAt() - 65)
-				this.options = this.editInfo.option.map((item, index) => index)
-				this.$nextTick(() => {
-				    this.initEditors()
-					this.stemEditor.txt.html(this.editInfo.question)
+			/* 根据页面上的选项DOM数量,刷新每个选项的Order显示 */
+			refreshOrder() {
+				let wraps = document.getElementsByClassName('option-order')
+				wraps.forEach((item, index) => {
+					item.innerHTML = this.renderIndex(index)
 				})
-			}
-        },
-        computed: {
-            // 选项顺序转化成字母
-            showTrueAnswers() {
-                let arr = this.trueIndex.map(item => String.fromCharCode(64 + parseInt(item + 1)))
-                this.transferArr = arr
-                return this.transferArr.sort().join('')
-            }
-        },
-		watch:{
-			editInfo:{
-				handler(n){
-					console.log('多选富文本接收到的数据')
-					console.log(n)
-					if(n){
-						this.stemEditor.txt.html(this.editInfo.question)
-						this.stemContent = this.editInfo.question
-						this.optionsContent = this.editInfo.option
-						this.trueIndex = this.editInfo.answer.map(item => item.charCodeAt() - 65)
-						this.trueArr = this.editInfo.answer.map(item => item.charCodeAt() - 65)
-						this.options = this.editInfo.option.map((item, index) => index)
-						this.$nextTick(() => {
-						    this.initEditors()
-						})
+			},
+			
+			/* 根据下标渲染对应的字母顺序 */
+			renderIndex(index) {
+				return String.fromCharCode(64 + parseInt(index + 1))
+			},
+			
+			
+
+			/* 删除选项 */
+			deleteOption(index,item) {
+				// 拿到所有选项
+				if (this.existOptions.length > 2 ) {
+					// 如果删除的是正确答案 则重置正确答案
+					if(this.trueArr.indexOf(index) > -1){
+						if(this.trueArr.length === 1){
+							this.$Message.warning('至少保留一个正确答案!')
+						}else{
+							this.trueArr.splice(this.trueArr.indexOf(index),1)
+							// 确保当前存在的options保持同步
+							this.existOptions.splice(this.existOptions.indexOf(item), 1)
+							this.optionsContent.splice(index, 1)
+							// 删除操作 移除选项DOM
+							let textWrap = this.$refs['optionBox' + index][0]
+							textWrap.remove()
+							// 刷新选项序号显示
+							this.refreshOrder()
+							this.getAnswerOrder(this.trueArr)
+						}
+					}else{
+						// 确保当前存在的options保持同步
+						this.existOptions.splice(this.existOptions.indexOf(item), 1)
+						this.optionsContent.splice(index, 1)
+						// 删除操作 移除选项DOM
+						let textWrap = this.$refs['optionBox' + index][0]
+						textWrap.remove()
+						// 刷新选项序号显示
+						this.refreshOrder()
+						this.getAnswerOrder(this.trueArr)
 					}
+					
+				} else {
+					this.$Message.warning('至少保留两个选项!')
 				}
+			},
+
+			/* 保存试题 获取最新选项数据 */
+			doSave() {
+				// 拿到当前还剩的选项DOM
+				let wraps = document.getElementsByClassName('option-editor')
+				let arr = []
+				wraps.forEach((item, index) => {
+					// 遍历选项 找到对应的 Editor 然后获取编辑器里面的内容
+					let id = item.dataset.editorId
+					let curEditor = this.optionEditors.filter(i => i.id === id)[0]
+					if(curEditor){
+						// 生成新的选项对象
+						let obj = {
+							code: String.fromCharCode(64 + parseInt(index + 1)),
+							value: curEditor.txt.html()
+						}
+						arr.push(obj)
+					}
+					
+				})
+				this.optionsContent = arr
+			},
+
+			/* 模拟选项聚焦事件 */
+			optionClick(index) {
+				let allToolbars = document.getElementsByClassName('option-editor')
+				let that = this
+				for (let i = 0; i < allToolbars.length; i++) {
+					allToolbars[i].children[0].style.visibility = 'hidden'
+				}
+				setTimeout(function() {
+					let currentToolBar = that.$refs['singleOption' + index][0].children[0]
+					currentToolBar.style.visibility = 'visible'
+				}, 100)
+			},
+			/* 渲染多选题 */
+			doRender(editInfo){
+				this.editSingleInfo = editInfo
+				this.stemContent = editInfo.question
+				this.optionsContent = editInfo.option
+				this.multipleAnswers = editInfo.answer
+				this.trueArr = editInfo.answer.map(item => item.charCodeAt() - 65)
+				this.options = editInfo.option.map((item, index) => index)
+				this.existOptions = editInfo.option.map((item, index) => index)
+				this.$nextTick(() => {
+					this.initEditors()
+					this.stemEditor.txt.html(editInfo.question)
+				})
 			}
+		},
+		mounted() {
+			let stemEditor = new E(this.$refs.singleEditor)
+			stemEditor.customConfig = this.defaultConfig
+			stemEditor.customConfig.uploadVideoDisable = false
+			stemEditor.customConfig.onchange = (html) => {
+				this.stemContent = html
+			}
+			stemEditor.customConfig.onVideoWarning = (text) => {
+					this.$Message.warning(text)
+				},
+
+			// 选择视频文件后的上传Blob操作
+			stemEditor.customConfig.onVideoSelected = async (file) => {
+					this.$tools.doUploadVideo(this, file, stemEditor)
+				},
+			stemEditor.create()
+			this.stemEditor = stemEditor
+			this.initEditors()
+
+			if (this.editInfo && this.editInfo.question) {
+				console.log('进入多选题Mounted编辑')
+				this.doRender(this.editInfo)
+			}
+		},
+		computed: {
+		    // 选项顺序转化成字母
+		    showTrueAnswers() {
+		        let arr = this.trueArr.map(item => String.fromCharCode(64 + parseInt(item + 1)))
+		        this.transferArr = arr
+		        return this.transferArr.sort().join('')
+		    }
+		},
+		watch: {
+			editInfo: {
+				handler(newValue, oldValue) {
+					if (newValue) {
+						console.log('多选接收到的数据')
+						console.log(newValue)
+						this.editSingleInfo = newValue
+						if (Object.keys(newValue).length > 0) {
+							this.doRender(newValue)
+						}
+					}
+				},
+				// immediate:true
+			},
+
 		}
-    }
+	}
 </script>
+<style lang="less" scoped>
+	@import"../index/CreateExercises.less";
+</style>

+ 2 - 2
TEAMModelOS/ClientApp/src/view/evaluation/types/BaseSingle.vue

@@ -10,12 +10,12 @@
 			<IconText :text="'单选选项'" :color="'#FF871C'" :icon="'md-reorder'"></IconText>
 			<div v-for="(item,index) in options" :key="index" :ref="'optionBox' + index" :class="'editor-wrap-'+item" style="margin-top:10px;display:flex"
 			 @click="onRichTextClick($event)">
+				<span class="fl-center option-delete" @click="deleteOption(index,item)"><Icon type="md-remove-circle" /></span>
 				<span class="fl-center option-order" :ref="'optionOrder' + index" :data-index="index">{{ renderIndex(index) }}</span>
 				<!-- <span class="fl-center option-order">{{String.fromCharCode(64 + parseInt(index+1))}}</span> -->
 				<div :ref="'singleOption'+index" style="text-align:left" class="option-editor" @click="optionClick(item)"></div>
 				<span :class="['fl-center', 'option-setting', optionTrueIndex === index ? 'option-true':'']" @click="settingAnswer(index)">{{ optionTrueIndex === index ? '正确答案' :'设为答案' }}</span>
-				<span class="fl-center option-delete" @click="deleteOption(index,item)">
-					<Icon type="ios-close-circle" /></span>
+				
 			</div>
 			<p class="option-add"><span @click="addOption()">+ 添加选项 </span><span style="color:rgb(60,196,82);margin-left:15px;font-weight:bold">正确答案:{{ renderIndex(trueIndex) }}</span></p>
 		</div>

+ 56 - 101
TEAMModelOS/ClientApp/src/view/evaluation/types/BaseMultipleNew.vue

@@ -7,22 +7,22 @@
 			</div>
 		</div>
 		<div class="exersices-option">
-			<IconText :text="'选选项'" :color="'#FF871C'" :icon="'md-reorder'"></IconText>
+			<IconText :text="'选选项'" :color="'#FF871C'" :icon="'md-reorder'"></IconText>
 			<div v-for="(item,index) in options" :key="index" :ref="'optionBox' + index" :class="'editor-wrap-'+item" style="margin-top:10px;display:flex"
 			 @click="onRichTextClick($event)">
+				<span class="fl-center option-delete" @click="deleteOption(index,item)"><Icon type="md-remove-circle" /></span>
 				<span class="fl-center option-order" :ref="'optionOrder' + index" :data-index="index">{{ renderIndex(index) }}</span>
 				<!-- <span class="fl-center option-order">{{String.fromCharCode(64 + parseInt(index+1))}}</span> -->
 				<div :ref="'singleOption'+index" style="text-align:left" class="option-editor" @click="optionClick(item)"></div>
-				<span :class="['fl-center', 'option-setting', trueArr.indexOf(index) > -1 ? 'option-true':'']" @click="settingAnswer(index)">{{ trueArr.indexOf(index) > -1  ? '正确答案' :'设为答案' }}</span>
-				<span class="fl-center option-delete" @click="deleteOption(index,item)">
-					<Icon type="ios-close-circle" /></span>
+				<span :class="['fl-center', 'option-setting', optionTrueIndex === index ? 'option-true':'']" @click="settingAnswer(index)">{{ optionTrueIndex === index ? '正确答案' :'设为答案' }}</span>
+				
 			</div>
-			<p class="option-add"><span @click="addOption()">+ 添加选项 </span><span style="color:rgb(60,196,82);margin-left:15px;font-weight:bold">正确答案:{{ multipleAnswers.join('') }}</span></p>
+			<p class="option-add"><span @click="addOption()">+ 添加选项 </span><span style="color:rgb(60,196,82);margin-left:15px;font-weight:bold">正确答案:{{ renderIndex(trueIndex) }}</span></p>
 		</div>
 	</div>
 </template>
 <script>
-	import E from '@/utils/wangEditor.js'
+	import E from 'wangeditor'
 	import IconText from '@/components/evaluation/IconText.vue'
 	export default {
 		components: {
@@ -36,13 +36,9 @@
 				initFlag: true,
 				trueIndex: 0,
 				optionTrueIndex:0,
-				trueArr:[0],
-				optionTrueArr:[0],
-				multipleAnswers:['A'],
 				editSingleInfo: {},
 				stemEditor: null,
 				stemContent: '',
-				transferArr:[],
 				optionsContent: [],
 				optionEditors: [],
 				defaultConfig: {
@@ -150,40 +146,21 @@
 			
 			/* 设置正确答案 */
 			settingAnswer(index) {
-				this.$nextTick(() => {
-				    if (this.trueArr.indexOf(index) > -1) {
-						if(this.trueArr.length === 1){
-							this.$Message.warning('至少保留一个正确答案!')
-						}else{
-							this.trueArr.splice(this.trueArr.indexOf(index), 1)
-						}
-				    } else {
-				        this.trueArr.push(index)
-				        this.trueArr = this.trueArr.sort() // 选项排序
-				    }
-					this.getAnswerOrder(this.trueArr)
-				})
-			},
-			
-			/* 获取最新答案选项 */
-			getAnswerOrder(arr){
-				let arr2 = []
-				arr.forEach(i => {
-					arr2.push(this.getOrderCode(i))
-				})
-				this.multipleAnswers = arr2.sort()
-			},
-			
-			/* 根据index获取对应选项字母的值 */
-			getOrderCode(index){
+				console.log(index)
+				this.optionTrueIndex = index
 				let wraps = document.getElementsByClassName('option-order')
 				for(let i=0;i<wraps.length;i++){
 					let item = wraps[i]
 					if(+index === +item.dataset.index){
-						return item.innerText
+						this.trueIndex = item.innerText.charCodeAt() - 65
 						break;
 					}
 				}
+				// wraps.forEach((item, orderIndex) => {
+				// 	console.log(item)
+				// 	console.log(item.dataset.index)
+					
+				// })
 			},
 			
 			/* 根据页面上的选项DOM数量,刷新每个选项的Order显示 */
@@ -203,36 +180,23 @@
 
 			/* 删除选项 */
 			deleteOption(index,item) {
+				// 如果删除的是正确答案前面的选项 则正确答案需要往前排一位
+				if(index < this.optionTrueIndex){ this.trueIndex-- }
 				// 拿到所有选项
-				if (this.existOptions.length > 2 ) {
+				if (this.existOptions.length > 2) {
+					// 确保当前存在的options保持同步
+					this.existOptions.splice(this.existOptions.indexOf(item), 1)
+					this.optionsContent.splice(index, 1)
+					// 删除操作 移除选项DOM
+					let textWrap = this.$refs['optionBox' + index][0]
+					textWrap.remove()
 					// 如果删除的是正确答案 则重置正确答案
-					if(this.trueArr.indexOf(index) > -1){
-						if(this.trueArr.length === 1){
-							this.$Message.warning('至少保留一个正确答案!')
-						}else{
-							this.trueArr.splice(this.trueArr.indexOf(index),1)
-							// 确保当前存在的options保持同步
-							this.existOptions.splice(this.existOptions.indexOf(item), 1)
-							this.optionsContent.splice(index, 1)
-							// 删除操作 移除选项DOM
-							let textWrap = this.$refs['optionBox' + index][0]
-							textWrap.remove()
-							// 刷新选项序号显示
-							this.refreshOrder()
-							this.getAnswerOrder(this.trueArr)
-						}
-					}else{
-						// 确保当前存在的options保持同步
-						this.existOptions.splice(this.existOptions.indexOf(item), 1)
-						this.optionsContent.splice(index, 1)
-						// 删除操作 移除选项DOM
-						let textWrap = this.$refs['optionBox' + index][0]
-						textWrap.remove()
-						// 刷新选项序号显示
-						this.refreshOrder()
-						this.getAnswerOrder(this.trueArr)
+					if(index === this.optionTrueIndex){
+						this.optionTrueIndex = this.existOptions[0]
+						this.trueIndex = 0
 					}
-					
+					// 刷新选项序号显示
+					this.refreshOrder()
 				} else {
 					this.$Message.warning('至少保留两个选项!')
 				}
@@ -271,63 +235,54 @@
 					let currentToolBar = that.$refs['singleOption' + index][0].children[0]
 					currentToolBar.style.visibility = 'visible'
 				}, 100)
-			},
-			/* 渲染多选题 */
-			doRender(editInfo){
-				this.editSingleInfo = editInfo
-				this.stemContent = editInfo.question
-				this.optionsContent = editInfo.option
-				this.multipleAnswers = editInfo.answer
-				this.trueArr = editInfo.answer.map(item => item.charCodeAt() - 65)
-				this.options = editInfo.option.map((item, index) => index)
-				this.existOptions = editInfo.option.map((item, index) => index)
-				this.$nextTick(() => {
-					this.initEditors()
-					this.stemEditor.txt.html(editInfo.question)
-				})
 			}
 		},
 		mounted() {
 			let stemEditor = new E(this.$refs.singleEditor)
-			stemEditor.customConfig = this.defaultConfig
-			stemEditor.customConfig.uploadVideoDisable = false
-			stemEditor.customConfig.onchange = (html) => {
+			// stemEditor.config = this.defaultConfig
+			stemEditor.config.onchange = (html) => {
 				this.stemContent = html
 			}
-			stemEditor.customConfig.onVideoWarning = (text) => {
-					this.$Message.warning(text)
-				},
-
-			// 选择视频文件后的上传Blob操作
-			stemEditor.customConfig.onVideoSelected = async (file) => {
-					this.$tools.doUploadVideo(this, file, stemEditor)
-				},
+			stemEditor.config.uploadImgShowBase64 = true;
+			this.$editorTools.addVideoUpload(this,stemEditor)
+			this.$editorTools.addAudio(this,stemEditor)
 			stemEditor.create()
 			this.stemEditor = stemEditor
 			this.initEditors()
 
 			if (this.editInfo && this.editInfo.question) {
-				console.log('进入多选题Mounted编辑')
-				this.doRender(this.editInfo)
+				console.log('进入单选题Mounted编辑')
+				this.editSingleInfo = this.editInfo
+				this.stemContent = this.editSingleInfo.question
+				this.optionsContent = this.editSingleInfo.option
+				this.trueIndex = this.editSingleInfo.answer[0].charCodeAt() - 65
+				this.optionTrueIndex = this.editSingleInfo.answer[0].charCodeAt() - 65
+				this.options = this.editSingleInfo.option.map((item, index) => index)
+				this.existOptions = this.editSingleInfo.option.map((item, index) => index)
+				this.$nextTick(() => {
+					this.initEditors()
+					this.stemEditor.txt.html(this.editSingleInfo.question)
+				})
 			}
 		},
-		computed: {
-		    // 选项顺序转化成字母
-		    showTrueAnswers() {
-		        let arr = this.trueArr.map(item => String.fromCharCode(64 + parseInt(item + 1)))
-		        this.transferArr = arr
-		        return this.transferArr.sort().join('')
-		    }
-		},
 		watch: {
 			editInfo: {
 				handler(newValue, oldValue) {
 					if (newValue) {
-						console.log('选接收到的数据')
+						console.log('单选接收到的数据')
 						console.log(newValue)
 						this.editSingleInfo = newValue
 						if (Object.keys(newValue).length > 0) {
-							this.doRender(newValue)
+							this.stemContent = this.editSingleInfo.question
+							this.optionsContent = this.editSingleInfo.option
+							this.trueIndex = this.editSingleInfo.answer[0].charCodeAt() - 65
+							this.optionTrueIndex = this.editSingleInfo.answer[0].charCodeAt() - 65
+							this.options = this.editSingleInfo.option.map((item, index) => index)
+							this.existOptions = this.editSingleInfo.option.map((item, index) => index)
+							this.$nextTick(() => {
+								this.initEditors()
+								this.stemEditor.txt.html(this.editSingleInfo.question)
+							})
 						}
 					}
 				},

+ 20 - 0
TEAMModelOS/ClientApp/src/view/joinclass/JoinClass.vue

@@ -0,0 +1,20 @@
+<template>
+    <div>
+        <h1 style="text-align:center;margin-top:100px;font-size:22px;">学生扫码加入名单功能即将上线!</h1>
+    </div>
+</template>
+<script>
+    export default {
+        data() {
+            return {
+
+            }
+        },
+        methods: {
+
+        }
+    }
+</script>
+<style scoped>
+
+</style>

+ 0 - 7
TEAMModelOS/ClientApp/src/view/knowledge-point/index/Index.vue

@@ -62,19 +62,12 @@
 							 @on-clear="onSearchClear" />
 						</span>
 						<div>
-							<!-- <Icon type="md-apps" title="切换到知识点视图" v-if="!isShowPoints" color="#fff" size="20" style="cursor:pointer;margin-right:10px" @click="onChangeShowType" /> -->
-							<!-- <Icon type="ios-photos" title="切换到知识块视图" v-if="isShowPoints" color="#fff" size="18" style="cursor:pointer;margin-right:10px" @click="onChangeShowType" /> -->
 							<Icon type="md-add" v-if="($access.can('admin.*|Point_Add')) && subjectList.length" color="#fff" size="18" style="cursor:pointer;margin-right:10px"
 							 @click="onAddPoint" />
-							<!-- <Icon type="ios-search" v-if="blockList.length !== 0" color="#fff" size="18" style="cursor:pointer" @click="isSearchPoint = true" /> -->
-
 							<Button class="btn-compose-block" v-if="checkedPointList.length" @click="onComposeBlock">组成知识块</Button>
 						</div>
 					</div>
 					<div class="ns-header-search" v-else>
-						<!-- 搜索知识点部分 -->
-						<!-- <Input icon="ios-close" v-model="searchPoint" placeholder="搜索知识点..." autofocus style="width: 100%" @on-click="isSearchPoint = false"
-						 @on-blur="isSearchPoint = false" @on-change="onSearchPointChange" @on-enter="onSearchPointChange" /> -->
 					</div>
 					<div>
 						<div v-if="pointList.length === 0">

+ 33 - 24
TEAMModelOS/ClientApp/src/view/newcourse/ManageCourse.vue

@@ -7,11 +7,11 @@
                     <Icon type="md-create" size="18" />
                     <span>编辑课程</span>
                 </span>-->
-                <span @click="showConfirmDel(-1)" :class="selections.length == 0 ? 'action-btn-disabled action-btn':'action-btn'">
+                <span v-if="$access.can('admin.*|course-upd')" @click="showConfirmDel(-1)" :class="selections.length == 0 ? 'action-btn-disabled action-btn':'action-btn'">
                     <Icon type="md-trash" size="18" />
                     <span>批量删除</span>
                 </span>
-                <span @click="showAddCourse(0)" class="action-btn">
+                <span v-if="$access.can('admin.*|course-upd')" @click="showAddCourse(0)" class="action-btn">
                     <Icon type="md-add" size="18" />
                     <span>添加课程</span>
                 </span>
@@ -39,7 +39,7 @@
                     <span>{{row.subject.name}}</span>
                 </template>
                 <template slot-scope="{ row,index }" slot="action">
-                    <div class="item-tools" v-if="$access.can('admin.*|student-upd')">
+                    <div class="item-tools" v-if="$access.can('admin.*|course-upd')">
                         <Icon type="md-create" style="margin-right:10px;cursor:pointer;" size="18" color="white" @click="editCus(index)" />
                         <Icon type="md-trash" style="margin-left:10px;cursor:pointer;" size="18" color="white" @click="showConfirmDel(index)" />
                     </div>
@@ -105,7 +105,9 @@
                 }
             }
             return {
-                schoolBase: undefined,
+                schoolBase: {
+                    period:[]
+                },
                 tableHeight:780,
                 teacherId:[],
                 actionType:0, //0新增 1编辑
@@ -284,27 +286,31 @@
                         this.$Message.warning('请选择课程')
                     } else {
                         this.delCusList.push(...this.selections)
-                        this.delCusStatus = true
+                        //this.delCusStatus = true
                     }
                 } else {
                     this.delCusList.push(this.courseListShow[index])
-                    this.delCusStatus = true
+                    //this.delCusStatus = true
                 }
+                let cusNames = this.delCusList.map(item => {
+                    return item.name
+                })
+                this.$Modal.confirm({
+                    title: '刪除課程',
+                    content: `确认删除${cusNames.join(', ')}吗?`,
+                    onOk: () => {
+                        this.tableLoading = true
+                        this.confirmDelCus()
+                    }
+                })
             },
             //确认删除课程
             confirmDelCus() {
-
-                //let requestData = this.delCusList.map((item) => {
-                //    return {
-                //        id: item.id,
-                //        pk: item.code
-                //    }
-                //})
                 if (this.delCusList.length) {
                     let ids = this.delCusList.map((item) => {
                         return item.id
                     })
-                    let code = this.delCusList[0].code
+                    let code = this.$store.state.userInfo.schoolCode
                     this.$api.courseMgmt.deleteCourseAll({
                         ids, code
                     }).then(
@@ -314,7 +320,6 @@
                                 let ids = this.delCusList.map((item) => {
                                     return item.id
                                 })
-                                let indexes = []
                                 for (let index in this.courseList) {
                                     if (ids.indexOf(this.courseList[index].id) !== -1) {
                                         this.courseList.splice(index, 1)
@@ -329,7 +334,9 @@
                         err => {
                             this.$Message.error('删除失败!')
                         }
-                    )
+                    ).finally(() => {
+                        this.tableLoading = false
+                    })
                 }
                 
             },
@@ -358,9 +365,8 @@
                         let option = this.courseBaseInfo.option
                         if (!option) {
                             option = 'update'
-                        } else {
-                            this.courseBaseInfo.code = this.$store.state.userInfo.schoolCode
                         }
+                        this.courseBaseInfo.code = this.$store.state.userInfo.schoolCode
                         this.$api.courseMgmt.saveOrUpdateCourse({
                             course: this.courseBaseInfo,
                             option: option
@@ -402,12 +408,15 @@
                 }
             })
             //直接读取登录成功拿到得学校基础信息
-            this.schoolBase = JSON.parse(JSON.stringify(this.$store.state.user.schoolProfile.school_base))
-            this.classList = JSON.parse(JSON.stringify(this.$store.state.user.schoolProfile.school_classes))
-            if (!this.schoolBase) {
-                this.$Message.warning('尚未加入学校,没有学校数据')
-            }
-            //this.$store.dispatch('schoolBaseInfo/getClassroom').then(res => { })
+            this.$store.dispatch('user/getSchoolProfile').then(
+                res => {
+                    this.schoolBase = res.school_base
+                    this.classList = JSON.parse(JSON.stringify(this.$store.state.user.schoolProfile.school_classes))
+                },
+                err => {
+                    this.$Message.warning('尚未加入学校,没有学校数据')
+                }
+            )
             this.$store.dispatch('teachers/getTeacherList').then(res => {
             })
         }

+ 8 - 6
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue

@@ -10,7 +10,7 @@
                         <div slot="extra">
                             <transition name="fade">
                                 <div style="margin-top:5px;">
-                                    <Icon type="md-create" class="add-icon" title="编辑课程" @click="editCus()" />
+                                    <Icon type="md-create" v-show="(listType == 'school' && courseListS.length) || (listType == 'private' && courseListP.length) " class="add-icon" title="编辑课程" @click="editCus()" />
                                     <Icon type="md-add" v-show="listType == 'private'" class="add-icon" title="新增课程" @click="showAddCourse()" />
                                     <Icon type="md-trash" v-show="listType == 'private'" class="add-icon" title="删除课程" @click="delCourse" />
                                 </div>
@@ -442,6 +442,7 @@
                     }
                     //保存操作
                     this.listLoading = true
+                    this.courseListP[this.curCusIndex].code = this.$store.state.userInfo.TEAMModelId
                     this.$api.courseMgmt.upsertPrivateCus({
                         course: this.courseListP[this.curCusIndex],
                         option: 'update'
@@ -505,6 +506,7 @@
             //确认修改班级信息
             confirmUpdClass() {
                 this.listLoading = true
+                this.courseListP[this.curCusIndex].code = this.$store.state.userInfo.TEAMModelId
                 this.$api.courseMgmt.upsertPrivateCus({
                     course: this.courseListP[this.curCusIndex],
                     option: 'update'
@@ -562,6 +564,7 @@
             //保存个人课程
             saveNotice() {
                 this.listLoading = true
+                this.courseListP[this.curCusIndex].code = this.$store.state.userInfo.TEAMModelId
                 this.$api.courseMgmt.upsertPrivateCus({
                     course: this.courseListP[this.curCusIndex],
                     option: 'update'
@@ -590,8 +593,7 @@
                         this.saveNotice()
                     } else {
                         this.baseEditStatus = !this.baseEditStatus
-                        console.log(this.courseListS)
-                        //this.$Message.warning('暂未对接API!')
+                        this.courseListS[this.curCusIndex][this.curClassIndex].code = this.$store.state.userInfo.schoolCode
                         this.$api.courseMgmt.upsertNotice(this.courseListS[this.curCusIndex][this.curClassIndex]).then(
                             res => {
                                 if (!res.error) {
@@ -661,7 +663,7 @@
             },
             showQrCode() {
                 this.showQrStatus = true
-                this.createQRCode('https://www.habook.com.cn/')
+                this.createQRCode('http://teammodelos-test.chinacloudsites.cn/joinclass')
             },
             
             //添加上课班级
@@ -690,6 +692,7 @@
                     name: this.$store.state.userInfo.name
                 }
                 this.courseListP[this.curCusIndex].classes.push(this.privateClass)
+                this.courseListP[this.curCusIndex].code = this.$store.state.userInfo.TEAMModelId
                 this.$api.courseMgmt.upsertPrivateCus({
                     course: this.courseListP[this.curCusIndex],
                     option:'update'
@@ -777,10 +780,9 @@
                     title: '删除课程',
                     content: `确认删除${this.courseListP[this.curCusIndex].name}吗?`,
                     onOk:()=> {
-                        //this.$Message.warning('暂未对接API')
                         this.$api.courseMgmt.deleteCourse({
                             id: this.courseListP[this.curCusIndex].id,
-                            code: this.courseListP[this.curCusIndex].code,
+                            code: this.$store.state.userInfo.TEAMModelId,
                             scope: this.courseListP[this.curCusIndex].scope
                         }).then(
                             res => {

+ 8 - 8
TEAMModelOS/ClientApp/src/view/newcourse/NewCoursePlan.vue

@@ -36,28 +36,28 @@
         <div class="cus-table-wrap">
             <div class="cus-table-header common-save-btn">
                 <span>课程安排</span>
-                <Button style="float:right;margin-right:10px;margin-top:6px;" :loading="isLoading" :disabled="!updated" icon="ios-albums-outline" @click="saveCusPlan()">
+                <Button v-if="$access.can('admin.*|coursePlan-upd')" style="float:right;margin-right:10px;margin-top:6px;" :loading="isLoading" :disabled="!updated" icon="ios-albums-outline" @click="saveCusPlan()">
                     {{$t('schoolBaseInfo.saveInfo')}}
                 </Button>
-                <Button style="float:right;margin-right:10px;margin-top:6px;" :disabled="true" @click="showImportCus" icon="md-arrow-round-up">导入安排</Button>
+                <Button v-if="$access.can('admin.*|coursePlan-upd')" style="float:right;margin-right:10px;margin-top:6px;" :disabled="true" @click="showImportCus" icon="md-arrow-round-up">导入安排</Button>
             </div>
             <div class="cus-table-content dark-iview-select">
                 <vuescroll>
                     <div style="min-height:500px;padding-bottom:30px;padding-right:15px;">
-                        <div class="course-setting-wrap" style="padding-bottom:50px;">
+                        <div :class="$access.can('admin.*|coursePlan-upd') ? 'course-setting-wrap':'course-setting-wrap disabled-iview-select'" style="padding-bottom:50px;">
                             <div v-if="classListShow[curClassIndex] && classListShow[curClassIndex].cusSetting">
                                 <div v-for="(cusItem,cusIndex) in classListShow[curClassIndex].cusSetting.courses" :key="cusIndex" style="margin-top:10px;">
                                     <span class="label-text">课程{{ cusIndex + 1 }}:</span>
-                                    <Select @on-change="selectCus($event,cusIndex)" v-model="classListShow[curClassIndex].cusSetting.courses[cusIndex].course.id" filterable label-in-value style="width:200px;" placeholder="请选择课程" >
+                                    <Select :disabled="!$access.can('admin.*|coursePlan-upd')" @on-change="selectCus($event,cusIndex)" v-model="classListShow[curClassIndex].cusSetting.courses[cusIndex].course.id" filterable label-in-value style="width:200px;" placeholder="请选择课程" >
                                         <Option v-for="(item,index) in courseList" :value="item.id" :key="item.id">{{ item.name }}</Option>
                                     </Select>
-                                    <Select  @on-change="selectTea($event,cusIndex)" v-model="selectTeaIds[cusIndex]" multiple filterable label-in-value style="width:calc(100% - 360px);margin-left:10px;" placeholder="请选择上课老师">
+                                    <Select :disabled="!$access.can('admin.*|coursePlan-upd')" @on-change="selectTea($event,cusIndex)" v-model="selectTeaIds[cusIndex]" multiple filterable label-in-value style="width:calc(100% - 360px);margin-left:10px;" placeholder="请选择上课老师">
                                         <Option @click.native="isInit = false" v-for="(item,index) in getCusTeaList(cusItem.course.id)" :value="item.id" :key="item.id">{{ item.name }}</Option>
                                     </Select>
-                                    <Icon type="md-remove-circle" color="#ed4014" size="20" style="margin-left:10px;cursor:pointer" @click="delCusSetting(cusIndex)" />
-                                    <Icon v-show="(cusIndex + 1) == classListShow[curClassIndex].cusSetting.courses.length" type="md-add-circle" color="white" size="20" style="margin-left:10px;cursor:pointer" @click="addCusSetting" />
+                                    <Icon v-if="$access.can('admin.*|coursePlan-upd')" type="md-remove-circle" color="#ed4014" size="20" style="margin-left:10px;cursor:pointer" @click="delCusSetting(cusIndex)" />
+                                    <Icon v-if="$access.can('admin.*|coursePlan-upd')" v-show="(cusIndex + 1) == classListShow[curClassIndex].cusSetting.courses.length" type="md-add-circle" color="white" size="20" style="margin-left:10px;cursor:pointer" @click="addCusSetting" />
                                 </div>
-                                <div v-if="classListShow[curClassIndex].cusSetting.courses.length == 0" class="add-cus-box" @click="addCusSetting">
+                                <div v-if="$access.can('admin.*|coursePlan-upd') && classListShow[curClassIndex].cusSetting.courses.length == 0" class="add-cus-box" @click="addCusSetting">
                                     <Icon type="ios-add-circle" size="40" />
                                     <span>添加课程安排</span>
                                 </div>

+ 9 - 6
TEAMModelOS/ClientApp/src/view/questionnaire/ManageQuestionnaire.vue

@@ -13,8 +13,8 @@
 				<div class="qn-box-header">
 					<span>问卷列表</span>
 					<div>
-						<Icon type="md-trash" class="to-create-icon" @click="onDeleteQn" style="margin-left: 10px" v-show="qnList.length" />
-						<Icon type="md-add" class="to-create-icon" @click="goToCreate" />
+						<Icon type="md-trash" class="to-create-icon" @click="onDeleteQn" style="margin-left: 10px" v-if="qnList.length && ($access.can('admin.*|schoolAc-upd') || isPrivate)" />
+						<Icon type="md-add" class="to-create-icon" @click="goToCreate"  v-if="($access.can('admin.*|schoolAc-upd') || isPrivate)"/>
 					</div>
 				</div>
 				<vuescroll>
@@ -62,7 +62,7 @@
 						<!-- <span class="qn-box-header-tools-tool" v-show="currentQn.status !== 300 && qnList.length">
 							<Icon type="md-create" size="18" title="编辑" @click="onEditQn" /></span> -->
 						<span class="qn-box-header-tools-tool" v-show="currentQn.progress === 'going' && qnList.length">
-							<Icon type="md-undo" size="18" title="取消发布" @click="onCancelQn" style="margin-left: 8px" /></span>
+							<Icon type="md-undo" size="18" title="取消发布" @click="onCancelQn" style="margin-left: 8px" v-if="($access.can('admin.*|schoolAc-upd') || isPrivate)"/></span>
 					</div>
 				</div>
 				<vuescroll ref="qnDetailsScroll">
@@ -98,7 +98,7 @@
 							<Icon type="md-podium" color="#dcdcdc" />
 							<span>查看统计数据</span>
 						</div> -->
-						<div class="qn-box-header-tools-tool" @click="onEditQn" v-show="currentQn.progress === 'pending' && qnList.length && !editable">
+						<div class="qn-box-header-tools-tool" @click="onEditQn" v-show="currentQn.progress === 'pending' && qnList.length && !editable && ($access.can('admin.*|schoolAc-upd') || isPrivate)">
 							<Icon type="md-create" color="#209460" />
 							<span>编辑问卷</span>
 						</div>
@@ -170,7 +170,7 @@
 						endTime: "",
 						startTime: "",
 						description: "",
-						rangeTime:[],
+						rangeTime: [],
 						isReset: [],
 						progress: "pending",
 						other: [],
@@ -273,7 +273,7 @@
 			 * @param index
 			 */
 			async onQnClick(item, index) {
-				if (this.activeQnIndex === index && this.currentQn.id && this.currentQn.id === item.id ) return
+				if (this.activeQnIndex === index && this.currentQn.id && this.currentQn.id === item.id) return
 				console.log(item, index);
 				/* 判断是否有新增但是无效的ITEM  如果有 则清空 需要重新添加 */
 				let hasNewQn = this.qnList.filter((i) => !i.id).length;
@@ -485,6 +485,9 @@
 			getCurScope() {
 				return this.$route.name === "personalSurvey" ? "private" : "school";
 			},
+			isPrivate(){
+				return this.$route.name === 'personalSurvey'
+			}
 		},
 		watch: {
 			$route: {

+ 1 - 0
TEAMModelOS/ClientApp/src/view/schoolList/Index.vue

@@ -243,6 +243,7 @@ export default {
             // })
         },
         logout(){
+			this.$store.commit('user/resetSchoolProfile')
             User.logout()
         }
     }

+ 57 - 45
TEAMModelOS/ClientApp/src/view/schoolmgmt/ClassroomSetting/ClassroomSetting.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="class-mgt-container" @click="editStatus = noStatus">
+    <div class="class-mgt-container">
         <Loading v-show="isListLoading"></Loading>
         <div class="class-list-wrap">
             <!--班级列表-->
@@ -10,15 +10,15 @@
                         <!--{{ '班级列表' }}-->
                         <Icon type="ios-arrow-down" style="margin-left:8px;"></Icon>
                     </span>
-                    <DropdownMenu slot="list" v-for="(item,index) in $store.state.user.schoolProfile.school_base.period" :value="item.id" :key="index">
+                    <DropdownMenu slot="list" v-for="(item,index) in schoolBase.period" :value="item.id" :key="index">
                         <DropdownItem :name="item.id">{{ item.name }}</DropdownItem>
                     </DropdownMenu>
                 </Dropdown>
 
                 <div v-if="!isSearch" style="float:right;">
                     <Icon class="action-btn-icon" type="ios-search" @click="isSearch = true" />
-                    <Icon class="action-btn-icon" type="md-trash"  @click.stop="showConfirmDelete()" />
-                    <Icon class="action-btn-icon" type="md-add" @click="addClassroom()" />
+                    <Icon v-if="$access.can('admin.*|classroom-upd')" class="action-btn-icon" type="md-trash"  @click.stop="showConfirmDelete()" />
+                    <Icon v-if="$access.can('admin.*|classroom-upd')" class="action-btn-icon" type="md-add" @click="addClassroom()" />
                 </div>
                 <div v-else class="dark-iview-input" style="float:right;width:calc(100% - 100px);padding-right:10px;">
                     <Input icon="ios-close"
@@ -39,9 +39,9 @@
                             <Icon type="ios-arrow-down"></Icon>
                         </span>
                         <DropdownMenu slot="list">
-                            <DropdownItem name="id">{{ '依教室編號排序' }}</DropdownItem>
-                            <DropdownItem name="state">{{ '依智慧教室排序' }}</DropdownItem>
-                            <DropdownItem name="total">{{ '依學生數排序' }}</DropdownItem>
+                            <DropdownItem name="id">依教室編號排序</DropdownItem>
+                            <DropdownItem name="state">依智慧教室排序</DropdownItem>
+                            <DropdownItem name="total">依學生數排序</DropdownItem>
                         </DropdownMenu>
                     </Dropdown>
                 </div>
@@ -56,7 +56,7 @@
                                     {{item.name}}
                                 </span>    
                                 <span class="class-id-tag">
-                                    {{item.id}}
+                                    {{item.no}}
                                 </span>
                             </p>
                             <p class="class-type">
@@ -100,7 +100,7 @@
                 <span :class="currentTabIndex == 1 ? 'main-header-tab line-bottom line-bottom-active':'main-header-tab line-bottom'" @click="selectTab(1)">
                     位置设定
                 </span>
-                <Button class="save-btn" :loading="isSaveLoading" :disabled="!updated" icon="ios-albums-outline" @click="saveClassroom()">{{$t('schoolBaseInfo.saveInfo')}}</Button>
+                <Button  v-if="$access.can('admin.*|classroom-upd')" class="save-btn" :loading="isSaveLoading" :disabled="!updated" icon="ios-albums-outline" @click="saveClassroom()">{{$t('schoolBaseInfo.saveInfo')}}</Button>
             </div>
             <div class="class-info-content">
                 <!--基础信息-->
@@ -113,9 +113,9 @@
                                     <span slot="label" class="class-attr-wrap-label">{{$t('schoolBaseInfo.classroomName')}}</span>
                                     <Input @on-change="watchUpdate" :disabled="editStatus" v-model="classroomListShow[curClassIndex].name" clearable :placeholder="$t('schoolBaseInfo.classroomNameHolder')" />
                                 </FormItem>
-                                <FormItem prop="id" @click.native.stop class="requird-color">
+                                <FormItem prop="no" @click.native.stop class="requird-color">
                                     <span slot="label" class="class-attr-wrap-label">{{$t('schoolBaseInfo.classroomCode')}}</span>
-                                    <Input @on-change="watchUpdate" :disabled="editStatus" v-model="classroomListShow[curClassIndex].id" clearable :placeholder="$t('schoolBaseInfo.classroomCodeHolder')" />
+                                    <Input @on-change="watchUpdate" :disabled="editStatus" v-model="classroomListShow[curClassIndex].no" clearable :placeholder="$t('schoolBaseInfo.classroomCodeHolder')" />
                                 </FormItem>
                                 <FormItem prop="openType" @click.native.stop class="requird-color">
                                     <span slot="label" class="class-attr-wrap-label">班级属性</span>
@@ -453,6 +453,9 @@
                 }
             }
             return {
+                schoolBase: {
+                    period:[]
+                },
                 tblFlag: false,
                 stdFlag: false,
                 proFlag: false,                
@@ -636,7 +639,6 @@
                 if (data) {
                     this.updated = true
                 }
-                console.log(data)
             },
             dataSort(data){
                 switch (this.orderBy) {
@@ -1015,12 +1017,13 @@
             },
             getClassroom() {
                 this.isListLoading = true
-                //直接读取登录成功拿到得学校基础信息
-                
+                console.log('classroom')
                 this.$store.dispatch('user/getSchoolProfile').then(
                     (res) => {
                         if (res) {
-                            this.classroomList = this.$store.state.user.schoolProfile.school_classes
+                            console.log('res',res)
+                            this.classroomList = res.school_classes
+                            this.schoolBase = res.school_base
                             if (this.classroomList.length > 0) {
                                 this.updateBefore = JSON.stringify(this.classroomList[0])
                             }
@@ -1032,6 +1035,7 @@
                         }
                     },
                     (err) => {
+                        console.log(err)
                         this.$Message.error('API error!')
                     }
                 ).finally(() => {
@@ -1042,14 +1046,17 @@
             },
             /**显示确认删除班级对话框 */
             showConfirmDelete() {
-                console.log(this.classroomListShow[this.curClassIndex])
-                this.$Modal.confirm({
-                    title: '删除班级',
-                    content: '删除' + this.classroomListShow[this.curClassIndex].name + '后与之关联的数据将不能查询,确认删除吗?',
-                    onOk: () => {
-                        this.delClassroom(this.curClassIndex)
-                    }
-                })
+                if (this.$access.can('admin.*|classroom-upd')) {
+                    this.$Modal.confirm({
+                        title: '删除班级',
+                        content: '删除' + this.classroomListShow[this.curClassIndex].name + '后与之关联的数据将不能查询,确认删除吗?',
+                        onOk: () => {
+                            this.delClassroom(this.curClassIndex)
+                        }
+                    })
+                } else {
+                    this.$Message.warning('您暂无次操作权限!')
+                }
             },
 
             delClassroom(index) {
@@ -1223,27 +1230,32 @@
                 }
             },
             addClassroom() {
-                this.keyword = ''
-                this.classroomListShow.unshift({
-                    id: '',
-                    name: this.$t('schoolBaseInfo.presetClassroomName') + (this.classroomList.length + 1),
-                    style: 'normal',
-                    sn: '',
-                    openType: '1',
-                    teacher: {
-                        id: '',
-                        name: ''
-                    },
-                    periodId: this.filterPeriod,
-                    gradeId: '',
-                    x: 20 * (this.classroomList.length % 5),
-                    y: 20 * (this.classroomList.length / 5).toFixed(0),
-                    scope:'school',
-                    option:'insert'
-                })
-                this.drawIcon(5, 6)
-                this.curClassIndex = 0
-                this.updateBefore = JSON.stringify(this.classroomListShow[this.curClassIndex])
+                if (this.$access.can('admin.*|classroom-upd')) {
+                    this.keyword = ''
+                    this.classroomListShow.unshift({
+                        id: this.$jsFn.uuid(),
+                        name: this.$t('schoolBaseInfo.presetClassroomName') + (this.classroomList.length + 1),
+                        style: 'normal',
+                        sn: '',
+                        no: '',
+                        openType: '1',
+                        teacher: {
+                            id: '',
+                            name: ''
+                        },
+                        periodId: this.filterPeriod,
+                        gradeId: '',
+                        x: 20 * (this.classroomList.length % 5),
+                        y: 20 * (this.classroomList.length / 5).toFixed(0),
+                        scope: 'school',
+                        option: 'insert'
+                    })
+                    this.drawIcon(5, 6)
+                    this.curClassIndex = 0
+                    this.updateBefore = JSON.stringify(this.classroomListShow[this.curClassIndex])
+                } else {
+                    this.$Message.warning('您暂无次操作权限!')
+                }
             }
         },
         mounted() {
@@ -1279,7 +1291,7 @@
         watch: {
         },
         created() {
-            this.editStatus = this.noStatus
+            if (this.$access.can('admin.*|classroom-upd')) this.editStatus = this.noStatus
             this.getClassroom()
             this.$store.dispatch('teachers/getTeacherList').then(res => { })
         }

+ 14 - 15
TEAMModelOS/ClientApp/src/view/schoolmgmt/SystemSetting/SystemSetting.vue

@@ -13,11 +13,8 @@
                     <Option v-for="(item,index) in timeZoneList" :value="item.value" :key="index" @click.native="setTimeZone(item)">{{ item.label }}</Option>
                 </Select>
             </div>
-            <Button class="school-tools" :loading="isLoading" :disabled="!updated" icon="ios-albums-outline" @click="saveData()">{{$t('schoolBaseInfo.saveInfo')}}</Button>
-            <!--<span style="float:right;line-height:60px;margin-right:30px;cursor:pointer;" @click="drawerStatus = !drawerStatus ">
-            <Icon type="ios-settings" color="white" size="16" />
-            <span style="margin-left:4px;">学情参数</span>
-        </span>-->
+            <Button v-if="$access.ability('admin','schoolSetting-upd').validateAll" class="school-tools" :loading="isLoading" :disabled="!updated" icon="ios-albums-outline" @click="saveData()">{{$t('schoolBaseInfo.saveInfo')}}</Button>
+            
         </div>
         <div class="sm-system-body dark-iview-split disabled-iview-select text-cursor-disabled">
             <Split v-model="split1">
@@ -34,7 +31,7 @@
                             <Draggable ghost-class="ghost" class="period-list list-group" :list="schoolSetting.period" :animation='200'>
                                 <div class="period-item list-group-item" v-for="(item,index) in schoolSetting.period" :key="index" @click.capture="choosePeriod(index)" :class="index == curPriodIndex ? 'block-bg-active block-bg':'block-bg'">
                                     <p class="period-item-name semester-name-label dark-iview-input" @click.stop>
-                                        <Input @dblclick.native="editPrdIndex = curPriodIndex"  v-model="item.name" :disabled="editPrdIndex !== index" placeholder="设置学段..." style="width: 180px" />
+                                        <Input v-model="item.name" :disabled="editPrdIndex !== index" placeholder="设置学段..." style="width: 180px" />
                                         <span class="campus-label" @click="setCampus">
                                             {{item.campusId === null ? '请设置校区': $JSONPath.query(schoolSetting, "$..campuses[?(@.id=='" + item.campusId + "')]").length > 0 ? $JSONPath.query(schoolSetting, "$..campuses[?(@.id=='" + item.campusId + "')]")[0].name : '请设置校区' }}
                                         </span>
@@ -60,15 +57,15 @@
                                         <div v-for="(item,index) in schoolSetting.period[curPriodIndex].semesters" :key="index" :class="index == curSemIndex ? 'term-item block-bg block-bg-active':'term-item block-bg'" @click.capture="chooseSemester(index)">
                                             <span class="term-item-name-line" :style="{backgroundColor: colorList[index]}"></span>
                                             <p class="semester-name-label" @click.stop>
-                                                <Input @dblclick.native="editSemIndex = curSemIndex" v-model="item.name" :disabled="editSemIndex !== index" placeholder="设置学期..." style="width: 180px" />
+                                                <Input v-model="item.name" :disabled="editSemIndex !== index" placeholder="设置学期..." style="width: 180px" />
                                             </p>
                                             <div class="term-item-start" @click.stop>
                                                 <span>{{$t('schoolBaseInfo.startDate')}}</span>
-                                                <Select  @dblclick.native="editSemIndex = curSemIndex" v-model="item.month" style="width:50px" placeholder="月" :disabled="editSemIndex !== index">
+                                                <Select v-model="item.month" style="width:50px" placeholder="月" :disabled="editSemIndex !== index">
                                                     <Option v-for="(item,index) in monthList" :value="(index + 1)" :key="index" @click.native="countSemDays">{{ item }}</Option>
                                                 </Select>
                                                 <span> / </span>
-                                                <Select  @dblclick.native="editSemIndex = curSemIndex" v-model="item.day" style="width:50px" placeholder="日" :disabled="editSemIndex !== index">
+                                                <Select v-model="item.day" style="width:50px" placeholder="日" :disabled="editSemIndex !== index">
                                                     <Option v-for="(item,index) in dayList" :value="(index + 1)" :key="index" @click.native="countSemDays">{{ item }}</Option>
                                                 </Select>
                                             </div>
@@ -111,7 +108,7 @@
                                 <Draggable ghost-class="ghost" class="grade-list list-group" :list="schoolSetting.period[curPriodIndex].grades" :animation='200'>
                                     <div class="grade-item list-group-item" v-for="(item,index) in schoolSetting.period[curPriodIndex].grades" :key="index" @click.stop>
                                         <span class="grade-order">{{index + 1}}</span>
-                                        <Input  @dblclick.native="editGraStatus = true" class="grade-name" v-model="item.name" :disabled="!editGraStatus" placeholder="设置年级..." :style="{width: getWidth(index,item.name)+'px'}" />
+                                        <Input class="grade-name" v-model="item.name" :disabled="!editGraStatus" placeholder="设置年级..." :style="{width: getWidth(index,item.name)+'px'}" />
                                         <Icon type="md-close" @click.stop="showDelGrade(index)" style="cursor:pointer;flex:0.1" v-show="delGraStatus" />
                                     </div>
                                 </Draggable>
@@ -128,7 +125,7 @@
                             <div class="subject-body dark-iview-input disabled-iview-input" style="height:40%;">
                                 <div class="tag-item item-active" @click.stop v-for="(item,index) in schoolSetting.period[curPriodIndex].subjects" :key="index">
                                     <!--<span class="tag-item-icon"></span>-->
-                                    <Input @dblclick.native="editSubStatus = true"  v-model="item.name" :disabled="!editSubStatus" placeholder="设置学科..." :style="{width: getWidth(index,item.name)+'px'}" />
+                                    <Input  v-model="item.name" :disabled="!editSubStatus" placeholder="设置学科..." :style="{width: getWidth(index,item.name)+'px'}" />
                                     <Icon type="md-close" @click="delSubject(index)" v-show="delSubStatus" />
                                 </div>
                                 <EmptyData v-if="schoolSetting.period[curPriodIndex].subjects.length == 0" textContent="暂无学科"></EmptyData>
@@ -147,7 +144,7 @@
                                     </p>
                                     <div class="attr-content">
                                         <div class="tag-item item-active" @click.stop v-for="(item,index) in schoolSetting.period[curPriodIndex].analysis.type" :key="index">
-                                            <Input @dblclick.native="editAnaStatus = true" v-model="item.name" :disabled="!editAnaStatus" placeholder="设置考试类型..." :style="{width: getWidth(index,item.name)+'px'}" />
+                                            <Input v-model="item.name" :disabled="!editAnaStatus" placeholder="设置考试类型..." :style="{width: getWidth(index,item.name)+'px'}" />
                                             <Icon type="md-close" @click="confirmDelAna(index)" v-show="delAnaStatus" />
                                         </div>
                                         <span v-if="!schoolSetting.period[curPriodIndex].analysis.type" style="line-height:32px;">暂无考试类型</span>
@@ -161,7 +158,7 @@
                                         <span>优生率:</span>
                                     </p>
                                     <div class="attr-content" @click.stop>
-                                        <InputNumber  @dblclick.native="editAnaStatus = true" :max="100" :min="0" :disabled="!editAnaStatus"
+                                        <InputNumber :max="100" :min="0" :disabled="!editAnaStatus"
                                                      v-model="schoolSetting.period[curPriodIndex].analysis.eugenics"
                                                      :formatter="value => `${value}%`"
                                                      :parser="value => value.replace('%', '')"></InputNumber>
@@ -175,7 +172,7 @@
                                         <span>进线率:</span>
                                     </p>
                                     <div class="attr-content" @click.stop>
-                                        <InputNumber @dblclick.native="editAnaStatus = true" :max="100" :min="0" :disabled="!editAnaStatus"
+                                        <InputNumber :max="100" :min="0" :disabled="!editAnaStatus"
                                                      v-model="schoolSetting.period[curPriodIndex].analysis.income"
                                                      :formatter="value => `${value}%`"
                                                      :parser="value => value.replace('%', '')"></InputNumber>
@@ -189,7 +186,7 @@
                                         <span>踩线生:</span>
                                     </p>
                                     <div class="attr-content" @click.stop>
-                                        <InputNumber @dblclick.native="editAnaStatus = true" :max="100" :min="0" :disabled="!editAnaStatus"
+                                        <InputNumber :max="100" :min="0" :disabled="!editAnaStatus"
                                                      v-model="schoolSetting.period[curPriodIndex].analysis.touch"
                                                      :formatter="value => `${value}分`"
                                                      :parser="value => value.replace('分', '')"></InputNumber>
@@ -605,6 +602,8 @@
                 this.editPrdIndex = -1
                 if (this.$access.ability('admin', 'schoolSetting-upd').validateAll) {
                     this.campusStatus = true
+                } else {
+                    this.$Message.warning('您暂无此操作权限!')
                 }
             },
 

+ 2 - 1
TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.less

@@ -117,12 +117,13 @@
 		flex: 1;
 		height: 100%;
 		
-		.search-wrap{
+		.school-container-header{
 			width: 100%;
 			height: 50px;
 			border-bottom: 1px solid @borderColor;
 			display: flex;
 			align-items: center;
+			justify-content: space-between;
 			padding: 0 20px;
 		}
 		

+ 30 - 25
TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.vue

@@ -4,11 +4,6 @@
 		<div class="school-container-left">
 			<div class="school-container-header">
 				<span>已添加或申请学校</span>
-				<span>
-					<Input placeholder="输入要搜索的学校名称..." @on-change="onSearchChange" v-model="mySchoolSearch">
-					<Icon type="ios-search" slot="prefix" />
-					</Input>
-				</span>
 			</div>
 			<vuescroll>
 				<div class="school-list-wrap">
@@ -76,20 +71,12 @@
 		<div class="school-container-right">
 			<div class="school-container-header">
 				<span>申请加入学校</span>
-			</div>
-			<div class="search-wrap">
-				<Input placeholder="输入要搜索的学校名称或者代码..." @on-change="onSearchList" v-model="schoolListSearch">
-				<Icon type="ios-search" slot="prefix" />
-				</Input>
-				<!-- <Select v-model="curArea">
-					<Option value="default">大陆地区</Option>
-				</Select>
-				<Select v-model="curProvince">
-					<Option value="default">黑龙江</Option>
-				</Select>
-				<Select v-model="curCity">
-					<Option value="default">所有省辖市/界</Option>
-				</Select> -->
+				<div>
+					<Input placeholder="输入要搜索的学校名称" @on-change="onSearchList" v-model="schoolListSearch">
+					<Icon type="ios-search" slot="prefix" />
+					</Input>
+				</div>
+				
 			</div>
 			<div class="table-wrap">
 				<Table stripe :columns="schoolColumns" :data="schoolList"></Table>
@@ -147,20 +134,28 @@
 					{
 						title: '操作',
 						render: (h, params) => {
-							return h('div', [
+							return this.tbStatusFilter(params.row.id) === '申请加入' ? 
+							h('div', [
 								h('Button', {
 									props: {
 										type: 'primary'
 									},
 									style: {
-										display: this.originMySchoolList.length ? (this.originMySchoolList.map(i => i.schoolId).indexOf(params.row.id)  > -1 ? 'none' : 'unset') : 'unset'
+										// display: this.tbStatusFilter(params.row.id) === '申请加入' ? 'unset' : 'none'
 									},
 									on: {
 										click: () => {
 											this.onJoinSchool(params.row)
 										}
 									}
-								}, '申请加入')
+								}, this.tbStatusFilter(params.row.id)),
+							]) : h('div', [
+								h('span', {
+									style: {
+										// display: this.tbStatusFilter(params.row.id) !== '申请加入' ? 'unset' : 'none',
+										color:'#1cc0f3'
+									}
+								}, this.tbStatusFilter(params.row.id))
 							]);
 						}
 					}
@@ -295,13 +290,14 @@
 								if (!res.error) {
 									this.$Message.success("加入成功!")
 									// 如果之前用户没有加入任何学校
-									if(teacherInfo.schools && this.mySchoolList.filter(i => i.status === 'join').length === 0){
+									if(this.mySchoolList.length && this.mySchoolList.filter(i => i.status === 'join').length === 0){
 										let teacherInfo = await this.getTeacherInfo()
-										let schoolCode = teacherInfo.schools[0].schoolId
+										let schoolCode = item.schoolId
 										let schoolInfo = await this.getTeacherSchoolInfo(schoolCode)
 										this.$EventBus.$emit('onChangeSchool', {
 											user:teacherInfo,
-											schoolCode:schoolCode
+											schoolCode:schoolCode,
+											isFirst:true
 										})
 										this.$EventBus.$off('onChangeSchool')
 									}else{
@@ -352,6 +348,15 @@
 					return status === 'join' ? '#1CC0F3' : status === 'invite' ? '#ea6223' : '#019eff'
 				}
 			},
+			tbStatusFilter(){
+				return id => {
+					// 判断当前学校是否已加入
+					let isJoin =  this.mySchoolList.filter(i => i.status === 'join').map(j => j.schoolId).indexOf(id)  > -1 
+					let isInvite =  this.mySchoolList.filter(i => i.status === 'invite').map(j => j.schoolId).indexOf(id)  > -1 
+					let isRequest =  this.mySchoolList.filter(i => i.status === 'request').map(j => j.schoolId).indexOf(id)  > -1 
+					return isJoin ? '已加入' : isInvite ? '收到邀请' : isRequest ? '申请中' : '申请加入'
+				}
+			},
 			curSchool(){
 				return this.$store.state.userInfo.schoolCode
 			}

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

@@ -13,7 +13,6 @@
                 <!-- 學制Select -->
                 <Select v-model="searchPeriod" style="width:120px;" :placeholder="$t('stuAccount.periodHolder')" clearable @on-change="filterData">
                     <Option v-for="(item,index) in periods" :value="item.id" :key="index">{{ item.name }}</Option>
-                    
                 </Select>
                 <!-- 學級Select -->
                 <Select v-model="searchGrade" style="width:120px;margin-left:5px;" :placeholder="$t('stuAccount.gradeHolder')"
@@ -67,7 +66,8 @@
                         <Icon custom="iconfont icon-auth-key" size="25" color="#565656" />
                     </template>
                     <template slot-scope="{ row,index }" slot="header">
-                        <span class="name-header" :style="{background:bgColor[index % 12]}">{{getFirstChart(row.name)}}</span>
+                        <!--<span class="name-header" :style="{background:bgColor[index % 12]}">{{getFirstChart(row.name)}}</span>-->
+                        <PersonalPhoto :name="row.name" :picture="row.picture" :color="bgColor[index % 12]" />
                     </template>
                     <template slot-scope="{ row }" slot="gradeId">
                         <span>{{ getGradeName(row.gradeId) }}</span>
@@ -113,6 +113,7 @@
 </template>
 
 <script>
+    import PersonalPhoto from '@/components/public/personalPhoto/Index.vue'
     import AddStudent from './AddStudent'
     import ImportStudent from './ImportStudent'
     import Authorization from './Authorization'
@@ -121,7 +122,8 @@
         components: {
             AddStudent,
             ImportStudent,
-            Authorization
+            Authorization,
+            PersonalPhoto
         },
         data() {
             return {

+ 1 - 0
TEAMModelOS/ClientApp/src/view/student-web/App.vue

@@ -437,6 +437,7 @@ export default {
       }
     },
     onQuit() {
+		this.$store.commit('user/resetSchoolProfile')
       this.$User.logout()
       this.$router.push({
           path: '/login'

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

@@ -82,11 +82,11 @@
                             <span>{{item}}</span>
                         </Checkbox>
                     </CheckboxGroup>
-                    <span :class="((rangeType == 0 && $access.can('admin.*|content-school-upd')) || rangeType == 1) ? 'action-btn-wrap' : 'disable-text-icon action-btn-wrap'" @click="delFileBatch">
+                    <span v-if="$access.can('admin.*|content-upd')" class="action-btn-wrap" @click="delFileBatch">
                         <Icon type="md-trash" class="toggle-btn-icon" />
                         批量删除
                     </span>
-                    <span @click="showUpload" :class="((rangeType == 0 && $access.can('admin.*|content-school-upd')) || rangeType == 1) ? 'action-btn-wrap' : 'disable-text-icon action-btn-wrap'">
+                    <span v-if="$access.can('admin.*|content-upd')" @click="showUpload" class="action-btn-wrap">
                         <Icon type="md-cloud-upload" class="toggle-btn-icon" size="16" />
                         上传资源
                     </span>
@@ -174,10 +174,10 @@
         <!--文件预览-->
         <div v-if="previewStatus" class="image-viewer">
             <Icon type="md-close" class="close-icon" @click="closePreview" />
-            <video v-if="previewFile.type == 'video'" id="previewVideo" :src="previewFile.url" width="870" controls="controls">
+            <video v-if="previewFile.type == 'video'" id="previewVideo" :src="previewFile.url" width="870" controls="controls" style="max-height: 800px;">
                 {{$t('teachContent.tips8')}}
             </video>
-            <img v-else-if="previewFile.type == 'image'" :src="previewFile.url" width="870" style="border-radius:5px;" />
+            <img v-else-if="previewFile.type == 'image'" :src="previewFile.url" width="870" style="border-radius: 5px;max-height: 800px;" />
             <embed v-else-if="previewFile.extension == 'PDF'" :src="previewFile.url" width="870" height="720" />
             <iframe v-else :src="'https://view.officeapps.live.com/op/view.aspx?src=' + escapeBlobUrl" width='870' height='700' frameborder='1'></iframe>
         </div>
@@ -219,7 +219,7 @@
                 rangeType: 0,//0:校本 1:个人
                 contentTypeList: [],
                 mk: {},
-                sizeInfo:{
+                sizeInfo: {
                     total: 0,   //所有
                     image: 0,   //内容模块图片
                     res: 0,     //内容模块教材
@@ -324,7 +324,7 @@
                                 break
                         }
                     }
-                    
+
                 }
                 let updComp = this.$refs['uploadFile']
                 updComp.uploadedList = []
@@ -352,7 +352,7 @@
              */
             scrollReachBottom() {
                 this.$refs['vueWaterfall'].isPreloading = false
-                this.$jsFn.debounce(()=> {
+                this.$jsFn.debounce(() => {
                     if (this.mk[this.activeType] == 'end') {
                         this.$Message.warning('已经加载全部')
                         this.$refs['vueWaterfall'].setOverTipPos()
@@ -538,7 +538,7 @@
                                     this.fileListShow = this._.cloneDeep(fs)
                                 },
                                 err => {
-									console.log(err)
+                                    console.log(err)
                                     this.$Message.error('删除失败')
                                 }
                             ).finally(() => {
@@ -554,7 +554,7 @@
              * 删除单个文件
              * @param index
              */
-            delFile(file,index) {
+            delFile(file, index) {
                 let filePath = file.url
                 filePath = filePath.substring((this.urlString + this.containerName).length + 1)
                 filePath = filePath.substring(0, filePath.lastIndexOf('?'))
@@ -604,7 +604,7 @@
                 if (this.containerClient) {
                     this.isLoading = true
                     let option = {
-                        maxPageSize:20
+                        maxPageSize: 20
                     }
                     if (this.mk[this.activeType]) {
                         option.continuationToken = this.mk[this.activeType]
@@ -631,7 +631,7 @@
                                     this.isLoading = false
                                 }, 500)
                             }
-                            
+
                             this.searchBefore = this.fileList[this.activeType]
                             this.getFilesExtension()
                         },
@@ -688,7 +688,7 @@
                     }, 500)
                 }
             },
-            
+
             /**
              * 关键词搜索
              * */

+ 1 - 0
TEAMModelOS/ClientApp/src/view/teachermgmt/components/userList/Index.vue

@@ -435,6 +435,7 @@ export default {
             authstatusMulti: 'user/getTeacherAuthStatusMulti' //製作老師(複數)權限設定值列表
         }),
         authListAll: function () { // 所有權限列表(階層構造)
+            console.log('auth',this.authData.authListFormed)
             return this.authData.authListFormed
         },
         authdisable: { // (i-switch用)權限開關控制disable資料

+ 6 - 3
TEAMModelOS/ClientApp/src/view/vote/ManageVote.vue

@@ -13,8 +13,8 @@
 				<div class="hw-box-header">
 					<span>投票活动列表</span>
 					<span>
-						<Icon type="md-trash" class="to-create-icon" @click="onDeleteVote" style="margin-left:10px" v-show="voteList.length" />
-						<Icon type="md-add" class="to-create-icon" @click="goToCreate" />
+						<Icon type="md-trash" class="to-create-icon" @click="onDeleteVote" style="margin-left:10px" v-if="voteList.length && ($access.can('admin.*|schoolAc-upd') || isPrivate)" />
+						<Icon type="md-add" class="to-create-icon" @click="goToCreate" v-if="($access.can('admin.*|schoolAc-upd') || isPrivate)"/>
 					</span>
 				</div>
 				<vuescroll>
@@ -45,7 +45,7 @@
 					<span>投票详情</span>
 					<div class="hw-box-header-tools">
 						<span class="hw-box-header-tools-tool" v-show="currentVote.progress === 'pending'">
-							<Icon type="md-create" size="18" title="编辑" @click="onEditVote" /></span>
+							<Icon type="md-create" size="18" title="编辑" @click="onEditVote" v-if="($access.can('admin.*|schoolAc-upd') || isPrivate)"/></span>
 					</div>
 				</div>
 				<vuescroll>
@@ -358,6 +358,9 @@
 			},
 			getCurScope(){
 				return this.$route.name === 'personalVote' ? 'private' : 'school'
+			},
+			isPrivate(){
+				return this.$route.name === 'personalVote'
 			}
 		},
         watch: {

+ 1 - 1
TEAMModelOS/Controllers/School/ClassRoomController.cs

@@ -212,7 +212,7 @@ namespace TEAMModelOS.Controllers
             var client = _azureCosmos.GetCosmosClient();
             List<object> classrooms = new List<object>();
             StringBuilder sql = new StringBuilder();
-            sql.Append("select c.id,c.point,c.name,c.teacher,c.periodId,c.gradeId,c.sn,c.style,c.scope,c.type,c.code,c.openType,c.x,c.y,ARRAY_LENGTH(c.students) AS studCount from c ");
+            sql.Append("select c.id,c.no,c.point,c.name,c.teacher,c.periodId,c.gradeId,c.sn,c.style,c.scope,c.type,c.code,c.openType,c.x,c.y,ARRAY_LENGTH(c.students) AS studCount from c ");
             Dictionary<string, object> dict = new Dictionary<string, object>();
             var emobj = requert.EnumerateObject();
             while (emobj.MoveNext())

+ 15 - 15
TEAMModelOS/Controllers/School/CourseController.cs

@@ -71,25 +71,25 @@ namespace TEAMModelOS.Controllers
                 var client = _azureCosmos.GetCosmosClient();
                 course.ttl = -1;
                 course.pk = typeof(Course).Name;
-
+                string code = course.code;
+                course.code = typeof(Course).Name + "-" + course.code;
                 if (option.ToString().Equals("insert"))
                 {
-                    var response = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(course.id, new PartitionKey($"Course-{course.code}"));
+                    var response = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(course.id, new PartitionKey($"Course-{code}"));
                     if (response.Status == 200)
                     {
                         return Ok(new { error = ResponseCode.DATA_EXIST, V = "课程编码已经存在!" });
                     }
                     else
                     {
-                        string code = course.code;
-                        course.code = typeof(Course).Name + "-" + course.code;
+
                         course = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").CreateItemAsync(course, new PartitionKey($"Course-{code}"));
 
                     }
                 }
                 else
                 {
-                    course = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").UpsertItemAsync(course, new PartitionKey($"{course.code}"));
+                    course = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").UpsertItemAsync(course, new PartitionKey($"Course-{code}"));
                 }
                 return Ok(new { course });
             }
@@ -153,11 +153,11 @@ namespace TEAMModelOS.Controllers
                 if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
                 if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
                 if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
-                string school_code = code.ToString().Substring(typeof(Course).Name.Length + 1);
+                //string school_code = code.ToString().Substring(typeof(Course).Name.Length + 1);
                 var client = _azureCosmos.GetCosmosClient();
                 if (scope.ToString().Equals("school")){
                     List<CourseManagement> managements = new List<CourseManagement>();
-                    await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"select value(c) from c join A0 in c.courses where A0.course.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"CourseManagement-{school_code}") }))
+                    await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"select value(c) from c join A0 in c.courses where A0.course.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"CourseManagement-{code}") }))
                     {
                         using var json = await JsonDocument.ParseAsync(item.ContentStream);
                         if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
@@ -187,7 +187,7 @@ namespace TEAMModelOS.Controllers
                         }
                     }
                     } else {
-                    await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Course-{school_code}"));
+                    await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Course-{code}"));
                 }                                             
                 //IdPk idPk=  await _azureCosmos.DeleteAsync<Course>(request);
                 return Ok(new { id });
@@ -222,7 +222,7 @@ namespace TEAMModelOS.Controllers
                 if (request.ids.IsNotEmpty()) {
                     dict.Add("id", request.ids.ToArray());
                 }
-                string school_code = request.code.Substring(typeof(Course).Name.Length + 1);
+                string school_code = request.code;
                 AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
                 List<Course> courses = new List<Course>();
                 await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{school_code}") }))
@@ -580,7 +580,7 @@ namespace TEAMModelOS.Controllers
             dict.Add("courses[*].teachers[*].id", teachers.id);
             //dict.Add("id", classroom.id);
             AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
-			await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+			await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"CourseManagement-{code}") }))
 			{
 				using var json = await JsonDocument.ParseAsync(item.ContentStream);
 				if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
@@ -663,24 +663,24 @@ namespace TEAMModelOS.Controllers
                 course = room.ToObject<TeacherCourse>();
                 var client = _azureCosmos.GetCosmosClient();
                 course.pk = typeof(Course).Name;
+                string code = course.code;
+                course.code = typeof(Course).Name + "-" + course.code;
                 if (option.ToString().Equals("insert"))
                 {
-                    var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(course.id, new PartitionKey($"Course-{course.code}"));
+                    var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(course.id, new PartitionKey($"Course-{code}"));
                     if (response.Status == 200)
                     {
                         return Ok(new { error = ResponseCode.DATA_EXIST, V = "课程编码已经存在!" });
                     }
                     else
-                    {
-                        string code = course.code;
-                        course.code = typeof(Course).Name + "-" + course.code;
+                    {                       
                         course = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(course, new PartitionKey($"Course-{code}"));
 
                     }
                 }
                 else
                 {
-                    course = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(course,course.id, new PartitionKey($"{course.code}"));
+                    course = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(course,course.id, new PartitionKey($"Course-{code}"));
                 }
                 return Ok(new { course });
             }

+ 1 - 1
TEAMModelOS/Controllers/Teacher/InitController.cs

@@ -230,7 +230,7 @@ namespace TEAMModelOS.Controllers
 
             //取得教室
             List<object> school_classes = new List<object>();
-            await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id,c.x,c.y,c.name,c.teacher,c.periodId,c.gradeId,c.sn,c.style,c.status,c.openType,c.scope FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{school_code}") }))
+            await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id,c.x,c.y,c.name,c.teacher,c.periodId,c.gradeId,c.sn,c.no,c.style,c.status,c.openType,c.scope FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{school_code}") }))
             {
                 var jsonc = await JsonDocument.ParseAsync(item.ContentStream);
                 foreach (var classeinfo in jsonc.RootElement.GetProperty("Documents").EnumerateArray())

+ 1 - 0
TEAMModelOS/Models/SchoolInfo/Classroom.cs

@@ -71,6 +71,7 @@ namespace TEAMModelOS.Models.SchoolInfo
         /// </summary>
         public string openType { get; set; }
         public string scope { get; set; }
+        public string no { get; set; }
     }
 }