Bläddra i källkod

Merge branch 'develop6.0-tmd' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop6.0-tmd

Li 3 år sedan
förälder
incheckning
2661ed4d79
50 ändrade filer med 1399 tillägg och 1022 borttagningar
  1. 34 24
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  2. 80 23
      TEAMModelOS/ClientApp/src/access/index.js
  3. 140 0
      TEAMModelOS/ClientApp/src/access/login.js
  4. 2 1
      TEAMModelOS/ClientApp/src/api/http.js
  5. 12 4
      TEAMModelOS/ClientApp/src/api/login.js
  6. 16 1
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-view.css
  7. 2 0
      TEAMModelOS/ClientApp/src/boot-app.js
  8. 3 3
      TEAMModelOS/ClientApp/src/common/BaseUserPoptip.vue
  9. 2 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContent.vue
  10. 1 1
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue
  11. 65 56
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperView.vue
  12. 2 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue
  13. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/cusMgt.js
  14. 2 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js
  15. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/studentWeb.js
  16. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/cusMgt.js
  17. 2 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/learnActivity.js
  18. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/studentWeb.js
  19. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/cusMgt.js
  20. 2 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/learnActivity.js
  21. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/studentWeb.js
  22. 19 0
      TEAMModelOS/ClientApp/src/router/index.js
  23. 1 1
      TEAMModelOS/ClientApp/src/router/routes.js
  24. 106 96
      TEAMModelOS/ClientApp/src/service/User.js
  25. 2 2
      TEAMModelOS/ClientApp/src/store/index.js
  26. 4 4
      TEAMModelOS/ClientApp/src/store/module/user.js
  27. 5 5
      TEAMModelOS/ClientApp/src/view/Home.vue
  28. 5 5
      TEAMModelOS/ClientApp/src/view/areaMgmt/AreaBase.vue
  29. 8 2
      TEAMModelOS/ClientApp/src/view/evaluation/bank/PaperDownload.vue
  30. 1 1
      TEAMModelOS/ClientApp/src/view/evaluation/index/index.vue
  31. 1 1
      TEAMModelOS/ClientApp/src/view/forgotPw/Index.vue
  32. 1 1
      TEAMModelOS/ClientApp/src/view/joinclass/JoinClass.vue
  33. 10 3
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.less
  34. 89 22
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.vue
  35. 7 3
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.less
  36. 32 23
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue
  37. 43 45
      TEAMModelOS/ClientApp/src/view/login/Index.vue
  38. 2 2
      TEAMModelOS/ClientApp/src/view/login/jinniu/Index.vue
  39. 3 3
      TEAMModelOS/ClientApp/src/view/login/jinniu/Student.vue
  40. 1 1
      TEAMModelOS/ClientApp/src/view/login/jinniu/Teacher.vue
  41. 628 633
      TEAMModelOS/ClientApp/src/view/login/page/Student.vue
  42. 5 4
      TEAMModelOS/ClientApp/src/view/login/page/Teacher.vue
  43. 35 26
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue
  44. 1 1
      TEAMModelOS/ClientApp/src/view/regist/Index.vue
  45. 8 8
      TEAMModelOS/ClientApp/src/view/student-web/App.vue
  46. 2 2
      TEAMModelOS/ClientApp/src/view/user/UserCenter.vue
  47. 1 1
      TEAMModelOS/ClientApp/src/view/video/Video.vue
  48. 1 1
      TEAMModelOS/ClientApp/src/view/video/VideoReview.vue
  49. 1 1
      TEAMModelOS/ClientApp/src/view/vote/ManageVote.vue
  50. 6 6
      TEAMModelOS/Controllers/Analysis/ClassAnalysisController.cs

+ 34 - 24
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -24,6 +24,7 @@ using Microsoft.Azure.Functions.Worker;
 using TEAMModelOS.SDK.Services;
 using Azure.Storage.Blobs.Models;
 using System.IO;
+using Azure;
 
 namespace TEAMModelOS.FunctionV4.ServiceBus
 {
@@ -960,30 +961,9 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 msgs.Add(update);
                                 break;
                             //更新 基础统计信息
-                            case "up-base":
-                                try {
-                                    BlobDownloadResult baseblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/{_lessonId}/IES/base.json").DownloadContentAsync();
-                                    LessonBase lessonBase = baseblobDownload.Content.ToObjectFromJson<LessonBase>();
-                                    if (lessonBase != null) {
-                                        lessonRecord.attendCount = lessonRecord.attendCount;
-                                        lessonRecord.clientCount = lessonRecord.clientCount;
-                                        lessonRecord.attendRate = lessonRecord.attendRate;
-                                        lessonRecord.groupCount = lessonRecord.groupCount;
-                                        lessonRecord.collateTaskCount = lessonRecord.collateTaskCount;
-                                        lessonRecord.collateCount = lessonRecord.collateCount;
-                                        lessonRecord.pushCount = lessonRecord.pushCount;
-                                        lessonRecord.totalPoint = lessonRecord.totalPoint;
-                                        lessonRecord.examQuizCount = lessonRecord.examQuizCount;
-                                        lessonRecord.interactionCount = lessonRecord.interactionCount;
-                                        lessonRecord.examPointRate = lessonRecord.examPointRate;
-                                        lessonRecord.clientInteractionCount = lessonRecord.clientInteractionCount;
-                                        lessonRecord.clientInteractionAverge = lessonRecord.clientInteractionAverge;
-                                    }
-                                    msgs.Add(update);
-                                } catch (Exception ex) {
-                                    await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}课程读取base.json,{_lessonId}\n{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
-                                }
-                                break;
+                            //case "up-base":
+                               
+                            //    break;
 
                             //更新 时间线
                             case "up-TimeLine":
@@ -1112,6 +1092,36 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                     }
                     //如果被删除则不能再被更新
                     if (isReplace) {
+                        //如果有更新 则去读取/{_lessonId}/IES/base.json
+                        try
+                        {
+                            BlobDownloadResult baseblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/{_lessonId}/IES/base.json").DownloadContentAsync();
+                            LessonBase lessonBase = baseblobDownload.Content.ToObjectFromJson<LessonBase>();
+                            if (lessonBase != null)
+                            {
+                                lessonRecord.attendCount = lessonRecord.attendCount;
+                                lessonRecord.clientCount = lessonRecord.clientCount;
+                                lessonRecord.attendRate = lessonRecord.attendRate;
+                                lessonRecord.groupCount = lessonRecord.groupCount;
+                                lessonRecord.collateTaskCount = lessonRecord.collateTaskCount;
+                                lessonRecord.collateCount = lessonRecord.collateCount;
+                                lessonRecord.pushCount = lessonRecord.pushCount;
+                                lessonRecord.totalPoint = lessonRecord.totalPoint;
+                                lessonRecord.examQuizCount = lessonRecord.examQuizCount;
+                                lessonRecord.interactionCount = lessonRecord.interactionCount;
+                                lessonRecord.examPointRate = lessonRecord.examPointRate;
+                                lessonRecord.clientInteractionCount = lessonRecord.clientInteractionCount;
+                                lessonRecord.clientInteractionAverge = lessonRecord.clientInteractionAverge;
+                            }
+                            msgs.Add(new LessonUpdate { grant_type = "up-base" });
+                        }
+                        catch (RequestFailedException ex) when (ex.Status == 404)
+                        {
+                            msgs.Add(new LessonUpdate { grant_type = "up-base-404" });
+                        }
+                        catch (Exception ex) {
+                            await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}课程读取base.json,{_lessonId}\n{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                        }
                         await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<LessonRecord>(lessonRecord, lessonId, new PartitionKey(code));
                     }
                     //计算课堂更新前后的差值

+ 80 - 23
TEAMModelOS/ClientApp/src/access/index.js

@@ -5,16 +5,20 @@ import Vue from 'vue';
 import {
 	User
 } from '../service/User';
-
+import {
+	app
+} from '@/boot-app.js'
+import loginTools from '@/access/login'
+import $router from '@/router/index'
 Vue.use(VueAccessControl, {
 	vueRouter: true,
 	globalMiddleWares: ['login?'], // 定义默认的中间件
 	loginRoute: { // 登入路由
 		path: '/login'
 	},
-	permissionDenyRedirectRoute: { // 權限拒絕重定向路由
-		path: '/403'
-	},
+	// permissionDenyRedirectRoute: { // 權限拒絕重定向路由
+	// 	path: '/403'
+	// },
 	defaultRoute: { // 基本路由
 		name: 'home'
 	},
@@ -22,32 +26,85 @@ Vue.use(VueAccessControl, {
 
 
 LoginMiddleware.handleExtend = function(next, ...arg) {
-	let identity = localStorage.getItem('identity')
 	let toNextPath = arg[1].path
 	let toNextFullPath = arg[1].fullPath
 	localStorage.setItem('target_path', toNextFullPath)
-	let userAccess, userInfo
-
-	if (localStorage.userAccess) {
-		userAccess = JSON.parse(decodeURIComponent(localStorage.userAccess, "utf-8"))
-	}
-	if (localStorage.userInfo) {
-		userInfo = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"))
-	}
-	
-	if (userAccess && userInfo) {
-		if (toNextPath === '/login' && userAccess.isLogin) {
-			window.location.href = identity == 'student' ? '/studentWeb' : '/home'
+	let userAccess, userInfo;
+	// 判断前往的路由地址是教师端还是学生端
+	let toNextIdentity = toNextPath.includes('/studentWeb') ? 'student' : 'teacher'
+	// 根据前往的身份去获取对应的id_token
+	let role_id_token = toNextIdentity === 'teacher' ? localStorage.getItem('id_token') : localStorage.getItem('stu_id_token')
+	let identity = sessionStorage.getItem('identity')
+	console.error(toNextFullPath, role_id_token)
+	// 如果对应的id_token存在 则证明当前已经登录了该身份 正常执行 如果发现未登录 则跳转到登录页面
+	if (role_id_token) {
+		let role_access = identity == 'student' ? localStorage.getItem('s_access') : localStorage.getItem('t_access')
+		let role_userInfo = identity == 'student' ? localStorage.getItem('s_userInfo') : localStorage.getItem('t_userInfo')
+		let userAccess = role_access ? JSON.parse(decodeURIComponent(role_access, "utf-8")) : null
+		let userInfo = role_userInfo ? JSON.parse(decodeURIComponent(role_userInfo, "utf-8")) : null
+		console.log(userAccess, userInfo, toNextPath);
+		if (userAccess && userInfo) {
+			sessionStorage.setItem('identity',toNextIdentity)
+			sessionStorage.setItem('userAccess',role_access)
+			sessionStorage.setItem('userInfo',role_userInfo)
+			if (toNextPath === '/login' && userAccess.isLogin) {
+				window.location.href = identity == 'student' ? '/studentWeb' : '/home'
+			} else {
+				User.freshLogin(identity).then(() => {
+					console.error('refresh Suc2',User.$access)
+					next(true);
+				}).catch(() => {
+					console.error('refresh Error')
+					next(false);
+				});
+			}
 		} else {
-			User.freshLogin().then(() => {
-				next(true);
-			}).catch(() => {
-				next(false);
-			});
+			next(false);
 		}
 	} else {
-		next(false);
+		$router.push({
+			path: '/login'
+		})
+		next(true)
 	}
+	// let access_token = localStorage.getItem('access_token')
+	// let expires_in = localStorage.getItem('expires_in')
+	// if(identity && toNextIdentity && identity !== toNextIdentity){
+	// 	console.log('身份不匹配')
+	// 	if(id_token){
+	// 		if(toNextIdentity === 'student'){
+	// 			loginTools.stuLoginById(id_token)
+	// 		}else{
+	// 			loginTools.teacherLogin({ id_token:id_token,access_token:access_token,expires_in:expires_in })
+	// 		}
+	// 	}else{
+	// 		$router.push({ path:'/login' })
+	// 	}
+	// 	next(true);
+	// 	return
+	// }else{
+	// 	if (localStorage.userAccess) {
+	// 		userAccess = JSON.parse(decodeURIComponent(localStorage.userAccess, "utf-8"))
+	// 	}
+	// 	if (localStorage.userInfo) {
+	// 		userInfo = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"))
+	// 	}
+	// 	if (userAccess && userInfo) {
+	// 		if (toNextPath === '/login' && userAccess.isLogin) {
+	// 			window.location.href = identity == 'student' ? '/studentWeb' : '/home'
+	// 		} else {
+	// 			User.freshLogin().then(() => {
+	// 				next(true);
+	// 			}).catch(() => {
+	// 				next(false);
+	// 			});
+	// 		}
+	// 	} else {
+	// 		next(false);
+	// 	}
+	// }
+
+
 };
 
 const access = new VueAccessControl.Access({

+ 140 - 0
TEAMModelOS/ClientApp/src/access/login.js

@@ -0,0 +1,140 @@
+import $api from '@/api'
+import $store from '@/store'
+import jwtDecode from 'jwt-decode'
+import { User } from '@/service/User'
+import { app } from '@/boot-app.js'
+export default {
+	/* 教师醍摩豆ID登录 */
+	async teacherLogin(item,schoolCode){
+		try{
+			let { id_token,access_token,expires_in } = item
+			// 設定Token和保存時間
+			localStorage.setItem("id_token", id_token)
+			localStorage.setItem("access_token", access_token)
+			localStorage.setItem("expires_in", expires_in)
+			// 根据id_token去获取教师的基础信息
+			let teacherInfo = await $api.login.getTeacherInfo({ id_token:id_token })
+			localStorage.setItem("auth_token", teacherInfo.auth_token)
+			localStorage.setItem("location", teacherInfo.location)
+			$store.dispatch('user/setUserProfile', teacherInfo)
+			// 检查老师是否加入了学校 再去设定需要去获取哪个学校的基础信息
+			let hasJoinSchool = teacherInfo.schools && teacherInfo.schools.length && teacherInfo.schools.find(i => i.status === 'join')
+			let joinSchools = hasJoinSchool ? teacherInfo.schools.filter(i => i.status === 'join') : []
+			let defaultschool = schoolCode || teacherInfo.defaultschool || (joinSchools.length ? joinSchools[0].schoolId : null)
+			let authByUser = jwtDecode(teacherInfo.auth_token)
+			let t_Data = jwtDecode(id_token)
+			let areas = teacherInfo.areas
+			// 初始化老师登录后返回的数据
+			let info = {
+				id: t_Data.sub,
+				name: authByUser.name,
+				roles: authByUser.roles,
+				permissions: authByUser.permissions == null ? [] : authByUser.permissions,
+				picture: t_Data.picture ? t_Data.picture : '',
+				toArea: areas.length && !joinSchools.length
+			}
+			// 如果有默认学校 则需要去登录到该学校 获取学校基础信息 并完善返回数据info
+			if (defaultschool && defaultschool != 'null') {
+				let schoolInfo = await $api.login.getTeacherSchoolInfo({ id_token:id_token,school_code: defaultschool })
+				// 儲存大雲Token
+				localStorage.setItem("auth_token", schoolInfo.auth_token)
+				localStorage.setItem("hpAppraise", schoolInfo.school_base.hpappraise)
+				localStorage.setItem("currArea", JSON.stringify((schoolInfo.currArea && schoolInfo.currArea.homeworkType) ? schoolInfo.currArea.homeworkType : []))
+				$store.dispatch('user/setSchoolCode', defaultschool)
+				$store.dispatch('user/setSchoolProfile', schoolInfo)
+				// 如果老师加入了学校 则需要把学校信息里面的auth等权限信息替换老师原本默认的信息
+				let authBySchool = jwtDecode(schoolInfo.auth_token)
+				info.roles = authBySchool.roles
+				info.defaultschool = defaultschool
+				info.permissions = authBySchool.permissions == null ? [] : authBySchool.permissions
+			}
+			//进行登录权限写入
+			User.login(info,'teacher').then(res => {
+			    if (res) {
+					$store.commit('setUserInfo', {
+			            TEAMModelId: info.id,
+			            name: info.name,
+			            schoolCode: info.defaultschool
+			        })
+					// 前往区级平台
+			        if (info.toArea) {
+			            localStorage.setItem('platform', 'area')
+			            app.$router.push({ path: '/area' })
+			        } else {
+						// 前往校级平台 判断是否有记录的目标地址 如果没有则按照站点来进行对应跳转固定页面
+						let targetPath = localStorage.getItem('target_path')
+						let defaultPath = $store.state.config.srvAdr == 'China' ? '/home' : '/home/myCourse'
+			            let homePath = targetPath ? (targetPath.includes('home/') ? targetPath : defaultPath) : defaultPath
+			            localStorage.setItem('platform', 'school')
+						localStorage.setItem('target_path','')
+						console.log('教师登录成功!',info)
+			            app.$router.push({ path: homePath })
+			        }
+			    }
+			})
+		}catch(e){
+			console.error(e)
+		}
+	},
+	/* 学生醍摩豆ID登录 */
+	async stuLoginById(id_token){
+		try{
+			let studentInfo = await $api.login.getStudentInfo({ id_token:id_token })
+			console.log('学生醍摩豆ID登录后的学生信息 > ', studentInfo)
+			// 儲存大雲Token
+			localStorage.setItem("stu_id_token", id_token)
+			localStorage.setItem("stu_auth_token", studentInfo.auth_token)
+			// 更新vuex学生基础信息
+			$store.dispatch('user/setStudentProfile', studentInfo)
+			// 注入身份权限
+			let t_Data = jwtDecode(id_token)
+			User.login({
+			    id: t_Data.sub,
+			    roles: ['student'],
+			    permissions: []
+			},'student').then(r => {
+			    if (r) {
+			        sessionStorage.setItem('identity', 'student')
+					let targetPath = localStorage.getItem('target_path')
+					let toPath = targetPath ? (targetPath.includes('studentWeb/') ? targetPath : '/studentWeb') : '/studentWeb'
+			        app.$router.push({ path: toPath })
+					localStorage.setItem('target_path','')
+			    }
+			})
+		}catch(e){
+			console.error(e)
+		}
+	},
+	/* 学生校内账号登录 与醍摩豆ID无关 */
+	async stuLoginByAccount(params){
+		try{
+			let studentInfo = await $api.login.getStudentInfoByAccount(params)
+			console.log('学生校内账号登录后的学生信息 > ', studentInfo)
+			// 儲存大雲Token
+			localStorage.setItem("access_token", studentInfo.token.access_token)
+			localStorage.setItem("stu_auth_token", studentInfo.auth_token)
+			localStorage.setItem("stu_id_token", studentInfo.token.id_token)
+			// 更新vuex学生基础信息
+			$store.dispatch('user/setSchoolCode', params.school_code)
+			$store.dispatch('user/setStudentProfile', studentInfo)
+			// 注入身份权限
+			let auth = jwtDecode(studentInfo.auth_token)
+			User.login({
+			    id: params.id,
+			    roles: ['student'],
+			    permissions: auth.permissions == null ? [] : auth.permissions,
+			    picture: ''
+			},'student').then(r => {
+			    if (r) {
+			        sessionStorage.setItem('identity', 'student')
+					let targetPath = localStorage.getItem('target_path')
+					let toPath = targetPath ? (targetPath.includes('studentWeb/') ? targetPath : '/studentWeb') : '/studentWeb'
+			        app.$router.push({ path: toPath })
+					localStorage.setItem('target_path','')
+			    }
+			})
+		}catch(e){
+			console.log(e)
+		}
+	}
+}

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

@@ -92,7 +92,8 @@ axios.interceptors.request.use(
          * 获取auth_token之后的API
          * 1、检查auth_token是否存在
          */
-        let auth_token = localStorage.getItem('auth_token')
+		let identity = sessionStorage.getItem('identity')
+        let auth_token = identity === 'student' ? localStorage.getItem('stu_auth_token') : localStorage.getItem('auth_token')
         if (!auth_token) {
             console.log('auth_token失败', config)
             loginOut()

+ 12 - 4
TEAMModelOS/ClientApp/src/api/login.js

@@ -19,6 +19,10 @@ export default {
 	getStudentInfo: function (data) {
 		return post('/tmduser/init/get-tmduser-info', data)
 	},
+	//校内账号登录学生端后获取学生信息
+	getStudentInfoByAccount: function (data) {
+		return post('/student/login', data)
+	},
 
 	/**
 	 * TEAMModelId登入驗證
@@ -144,8 +148,10 @@ export default {
 			this.getStudentInfo({
 				id_token: data.id_token
 			}).then(res => {
+				console.log('学生醍摩豆ID登录数据 > ',res,data)
 				localStorage.setItem("id_token", data.id_token)
-				localStorage.setItem("auth_token", res.auth_token)
+				// localStorage.setItem("auth_token", res.auth_token)
+				localStorage.setItem("stu_auth_token", res.auth_token)
 				store.dispatch('user/setStudentProfile', res)
 				let t_Data = jwtDecode(data.id_token)
 				r(Object.assign(t_Data, res))
@@ -173,10 +179,11 @@ export default {
 			// 進行API呼叫
 			await post('/student/login', data).then(res => {
 				if (res.error == 0) {
+					console.log('学生账号登录数据 > ',res,data)
 					// 儲存大雲Token
 					localStorage.setItem("access_token", res.token.access_token)
-					localStorage.setItem("auth_token", res.auth_token)
-					console.log('保存学生token')
+					// localStorage.setItem("auth_token", res.auth_token)
+					localStorage.setItem("stu_auth_token", res.auth_token)
 					store.dispatch('user/setSchoolCode', data.school_code)
 					store.dispatch('user/setStudentProfile', res)
 					result = res
@@ -190,7 +197,8 @@ export default {
 			if (error == '') {
 				let auth = jwtDecode(result.auth_token)
 				// 一樣要存auth_token
-				localStorage.setItem("auth_token", result.auth_token)
+				// localStorage.setItem("auth_token", result.auth_token)
+				localStorage.setItem("stu_auth_token", result.auth_token)
 
 				// 預計返回內容
 				let info = {

+ 16 - 1
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-view.css

@@ -1,3 +1,7 @@
+.lesson-test {
+    height: 90vh;
+    padding-top: calc(1% + 15px);
+}
 .lesson-test .ivu-tabs-nav {
   float: left !important;
   position: relative;
@@ -177,6 +181,17 @@
 }
 
 
-
+.lesson-test .top-icon {
+    position: fixed;
+    right: 50px;
+    bottom: 20px;
+    width: 50px;
+    height: 50px;
+    line-height: 55px;
+    text-align: center;
+    background: #ccc;
+    border-radius: 5px;
+    cursor: pointer;
+}
 
 

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

@@ -13,6 +13,7 @@ import editorTools from '@/utils/editorTools.js'
 import jsFn from '@/utils/js-fn.js'
 import specialChar from '@/utils/directive.js'
 import apiTools from '@/api'
+import loginTools from '@/access/login'
 import mockTools from '@/mock'
 import axios from 'axios'
 import { fetch, post } from '@/api/http'
@@ -91,6 +92,7 @@ Vue.prototype.$vuescrollConfig =  tools.vueScrollOpt
 Vue.prototype.$EventBus = new Vue()
 // 全局API请求
 Vue.prototype.$api = apiTools
+Vue.prototype.$loginTools = loginTools
 Vue.prototype.$post = post
 Vue.prototype.$get = fetch
 Vue.prototype.$axios = axios

+ 3 - 3
TEAMModelOS/ClientApp/src/common/BaseUserPoptip.vue

@@ -140,7 +140,7 @@ export default {
             })
         },
         doRefresh() {
-            this.user = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"));
+            this.user = JSON.parse(decodeURIComponent(sessionStorage.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]
@@ -161,11 +161,11 @@ export default {
             }
         },
         onRoleSelect(val) {
-            if (localStorage.getItem('identity') != val) {
+            if (sessionStorage.getItem('identity') != val) {
                 this.curRole = val
                 let homePath = this.$store.state.config.srvAdr == 'China' ? 'home' : 'myCourse'
                 let path = val === 'student' ? 'studentWeb' : homePath
-                localStorage.setItem('identity', val)
+                sessionStorage.setItem('identity', val)
                 this.$router.push({ path: path })
             }
         },

+ 2 - 3
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContent.vue

@@ -2,7 +2,7 @@
     <!-- <div class="event-content"> -->
     <div class="eventContentArea-view">
         <!--<VoteHint v-if="this.$store.getters.getisVoteResulthover==true"/>-->
-        <div v-if="getIsSelectedNow">
+        <template v-if="getIsSelectedNow">
 
             <!--<div v-if="getItemTitle.eventType=='preview'">
               <PreviewMission/>
@@ -19,12 +19,11 @@
             <div v-if="getItemTitle.eventType == 'Survey'">
                 <QuesNaire />
             </div>
-        </div>
+        </template>
         <!-- 如果篩選時未選的時候預設顯示列表第一個-->
         <div class="noSelected" v-if="!getIsSelectedNow">
             <h3>{{$t("studentWeb.event.selectActivity")}}</h3>
         </div>
-
     </div>
 </template>
 

+ 1 - 1
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue

@@ -450,7 +450,7 @@
             // this.papers = this.$route.params.papers
             if(!Object.keys(this.getItemTitle).length) {
                 this.$store.commit("ChangeItemName", JSON.parse(decodeURIComponent(localStorage.getItem("Item"))));
-                this.$store.commit("setUserInfo", JSON.parse(decodeURIComponent(localStorage.getItem("userInfo"))));
+                this.$store.commit("setUserInfo", JSON.parse(decodeURIComponent(sessionStorage.getItem("userInfo"))));
                 this.$store.commit("SetExamInfo", JSON.parse(decodeURIComponent(localStorage.getItem("examInfo"))));
                 this.$store.commit("SetPaperInfo", JSON.parse(decodeURIComponent(localStorage.getItem("paperInfo"))));
                 this.$store.commit("ToggleLessonTestPopWithSubject", JSON.parse(decodeURIComponent(localStorage.getItem("subjectNow"))));

+ 65 - 56
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperView.vue

@@ -1,7 +1,7 @@
 <template>
-    <div class="lesson-test">
+    <div class="lesson-test" id="paperView">
         <!-- <PaperTest :papers="selectData" v-if="getisOpenLessonTestPopNow" />  -->
-        <div>
+            <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
             <!-- <div class="load-box">
                 <load :active.sync="isLoad"
                       background-color="#000">
@@ -10,67 +10,70 @@
                     </template>
                 </load>
             </div> -->
-            <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
-            <EventBasicInfo :info="nowActive" :paper="paperData" />
-            <!--多學科試卷-->
-            <div v-if="paperData.length ">
-                <div class="item-box" style="margin-bottom: 25px">
-                    <div v-for="(item, index) in paperData"
-                        :key="index"
-                        style="display: inline-flex;"
-                        @click="opentestWithSubject(item, index)"
-                    >
-                        <div v-if="getItemTitle.owner === 'school'" :class="['paper-item-school', index === activeIndex ? 'paper-choose-school' : '']">
-                            <span>{{ item.subject.name }}</span>
-                            <span>
-                                {{ item.subject.name }}{{ $t('studentWeb.exam.isSubject') }}
-                                <Icon type="md-checkmark-circle-outline"
-                                    v-if="item.stuAns != undefined && item.stuAns.length != 0"
-                                    color="#00ad6c"
-                                    size="18"
-                                    style="margin-left: 5px;"
-                                />
-                            </span>
-                        </div>
-                        <div v-else :class="['paper-item', index === activeIndex ? 'paper-choose' : '']">
-                            <svg-icon icon-class="test" class="title-icon" />
-                            <span style="margin-top:5px">{{ item.subject.name }}</span>
-                            <div v-show="item.stuAns != undefined && item.stuAns.length != 0">
-                                <div style="margin-left: 10px; margin-top: 5px; margin-right: 10px;">
-                                <!-- <div :class="{ unfinished: item.stuAns.length === 0 ,finished: item.stuAns.length != 0 }"> -->
-                                    <Icon type="md-checkmark-circle-outline" size="23" />
-                                    <!-- <Icon style="margin-top: -10px; margin-left: -8px;" type="ios-checkmark" size="36" /> -->
+        <!-- <div> -->
+                <EventBasicInfo :info="nowActive" :paper="paperData" />
+                <!--多學科試卷-->
+                <div v-if="paperData.length ">
+                    <div class="item-box" style="margin-bottom: 25px">
+                        <div v-for="(item, index) in paperData"
+                            :key="index"
+                            style="display: inline-flex;"
+                            @click="opentestWithSubject(item, index)"
+                        >
+                            <div v-if="getItemTitle.owner === 'school'" :class="['paper-item-school', index === activeIndex ? 'paper-choose-school' : '']">
+                                <span>{{ item.subject.name }}</span>
+                                <span>
+                                    {{ item.subject.name }}{{ $t('studentWeb.exam.isSubject') }}
+                                    <Icon type="md-checkmark-circle-outline"
+                                        v-if="item.stuAns != undefined && item.stuAns.length != 0"
+                                        color="#00ad6c"
+                                        size="18"
+                                        style="margin-left: 5px;"
+                                    />
+                                </span>
+                            </div>
+                            <div v-else :class="['paper-item', index === activeIndex ? 'paper-choose' : '']">
+                                <svg-icon icon-class="test" class="title-icon" />
+                                <span style="margin-top:5px">{{ item.subject.name }}</span>
+                                <div v-show="item.stuAns != undefined && item.stuAns.length != 0">
+                                    <div style="margin-left: 10px; margin-top: 5px; margin-right: 10px;">
+                                    <!-- <div :class="{ unfinished: item.stuAns.length === 0 ,finished: item.stuAns.length != 0 }"> -->
+                                        <Icon type="md-checkmark-circle-outline" size="23" />
+                                        <!-- <Icon style="margin-top: -10px; margin-left: -8px;" type="ios-checkmark" size="36" /> -->
+                                    </div>
                                 </div>
                             </div>
                         </div>
                     </div>
                 </div>
-            </div>
-            <Tabs :value="selectTab" v-if="paperData.length">
-                <!-- 评测内容 -->
-                <TabPane :label='$t("studentWeb.exam.examData")' name="test">
-                    <!-- <div class="title-rect-group">
-                        <h2 class="title-rect-name">{{$t("studentWeb.exam.examLink")}}</h2>
-                    </div> -->
-                    <div class="title-rect-group">
-                        <div v-if="chooseData.subject !== undefined">
+                <Tabs :value="selectTab" v-if="paperData.length">
+                    <!-- 评测内容 -->
+                    <TabPane :label='$t("studentWeb.exam.examData")' name="test">
+                        <!-- <div class="title-rect-group">
+                            <h2 class="title-rect-name">{{$t("studentWeb.exam.examLink")}}</h2>
+                        </div> -->
+                        <div class="title-rect-group">
+                            <div v-if="chooseData.subject !== undefined">
+                                <!-- <div class="title-rect" /> -->
+                                <!-- <h2 class="title-rect-name">{{$t("studentWeb.exam.subjectNow")}}:{{chooseData.subject.name}}</h2> -->
+                                <LessonTestReport :paperInfo="selectData" :examInfo="chooseData" :chartsData="chartsData" :average="average[activeIndex]" />
+                            </div>
+                        </div>
+                    </TabPane>
+                    <!-- 成绩分析 -->
+                    <TabPane :label="$t('studentWeb.exam.gradeReport')" v-if="isTestOver && getItemTitle.owner == 'school'" name="analyse">
+                        <div class="title-rect-group">
                             <!-- <div class="title-rect" /> -->
-                            <!-- <h2 class="title-rect-name">{{$t("studentWeb.exam.subjectNow")}}:{{chooseData.subject.name}}</h2> -->
-                            <LessonTestReport :paperInfo="selectData" :examInfo="chooseData" :chartsData="chartsData" :average="average[activeIndex]" />
+                            <h2 class="title-rect-name">{{$t("studentWeb.exam.gradeAnalyse")}}</h2>
                         </div>
-                    </div>
-                </TabPane>
-                <!-- 成绩分析 -->
-                <TabPane :label="$t('studentWeb.exam.gradeReport')" v-if="isTestOver && getItemTitle.owner == 'school'" name="analyse">
-                    <div class="title-rect-group">
-                        <!-- <div class="title-rect" /> -->
-                        <h2 class="title-rect-name">{{$t("studentWeb.exam.gradeAnalyse")}}</h2>
-                    </div>
-                    <div class="student-score">
-                        <StudentScore :examData="paperData" :stuData="stuData"></StudentScore>
-                    </div>
-                </TabPane>
-            </Tabs>
+                        <div class="student-score">
+                            <StudentScore :examData="paperData" :stuData="stuData"></StudentScore>
+                        </div>
+                    </TabPane>
+                </Tabs>
+        <!-- </div> -->
+        <div class="top-icon" @click="gotoTop">
+            <Icon type="ios-arrow-up" size="30" color="#249e35" />
         </div>
     </div>
 </template>
@@ -339,6 +342,12 @@
             opentest: function () {
                 this.$store.commit("ToggleLessonTestPop");
             },
+            gotoTop() {
+                // this.$refs["train-info"].scrollIntoView('paperView', 500)
+                document.getElementsByClassName("lesson-test")[0].scrollIntoView()
+                // document.getElementsByClassName("lesson-test")[0].scrollTop = 0
+                // document.documentElement.scrollIntoView
+            },
         },
         computed: {
             ...mapGetters([

+ 2 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue

@@ -531,6 +531,8 @@ import { mapGetters, mapState } from 'vuex';
                                 })
                                 if(nowIn != -1) {
                                     this.sentSelectedEventTitle(this.eventShow[nowIn])
+                                } else {
+                                    this.$Message.warning(this.$t("studentWeb.exam.message.nojoin"))
                                 }
                             } else {
                                 // 没有选择的时候,默认展示第一个

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/cusMgt.js

@@ -146,6 +146,7 @@ export default {
     listSchoolTips1:'當前名單已有',
     listSchoolTips2:'學校學生,個人名單不能添加跨校學生。',
     listSchoolTips3:'其他',
+    qrcodeErr:'二維碼生成失敗',
 
     //ManageClass.vue
     stuMgt: 'Student Management',

+ 2 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js

@@ -75,7 +75,8 @@ export default {
         shareText8:'掃碼進行線上活動',
         copy:'復製',
         copyTitle:'復製評測',
-        copyContent:'確認復製當前評測嗎?'
+        copyContent:'確認復製當前評測嗎?',
+        copyContent1:'課中評測不能進行復製操作。'
     },
 
     //CreateEv

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/studentWeb.js

@@ -640,6 +640,7 @@ export default {
         message: {
             noWrong: "This assessment does not have incorrectly answered questions!",
             noStar: "This assessment does not have starred questions!",
+            nojoin: "您沒有加入該活動",
         }
     },
     queNaire: {

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

@@ -146,6 +146,7 @@ export default {
     listSchoolTips1:'当前名单已有',
     listSchoolTips2:'学校学生,个人名单不能添加跨校学生。',
     listSchoolTips3:'其他',
+    qrcodeErr:'二维码生成失败',
 
     //ManageClass.vue
     stuMgt:'学生管理',

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

@@ -76,7 +76,8 @@ export default {
         shareText8:'扫码进行线上活动',
         copy:'复制',
         copyTitle:'复制评测',
-        copyContent:'确认复制当前评测吗?'
+        copyContent:'确认复制当前评测吗?',
+        copyContent1:'课中评测不能进行复制操作。'
     },
 
     //CreateEv

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

@@ -640,6 +640,7 @@ export default {
         message: {
             noWrong: "当前评量无错题可进行练习!",
             noStar: "当前评量无标星题目!",
+            nojoin: "您没有加入该活动",
         }
     },
     queNaire: {

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

@@ -146,6 +146,7 @@ export default {
     listSchoolTips1:'當前名單已有',
     listSchoolTips2:'學校學生,個人名單不能添加跨校學生。',
     listSchoolTips3:'其他',
+    qrcodeErr:'二維碼生成失敗',
 
     //ManageClass.vue
     stuMgt: '學生管理',

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

@@ -76,7 +76,8 @@ export default {
         shareText8:'掃碼進行線上活動',
         copy:'復製',
         copyTitle:'復製評測',
-        copyContent:'確認復製當前評測嗎?'
+        copyContent:'確認復製當前評測嗎?',
+        copyContent1:'課中評測不能進行復製操作。'
     },
 
     //建立評量學校/個人

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

@@ -640,6 +640,7 @@ export default {
         message: {
             noWrong: "當前評量無錯題可進行練習!",
             noStar: "當前評量無標星題目!",
+            nojoin: "您沒有加入該活動",
         }
     },
     queNaire: {

+ 19 - 0
TEAMModelOS/ClientApp/src/router/index.js

@@ -2,6 +2,7 @@ import Vue from 'vue'
 import VueRouter from 'vue-router'
 import { routes } from './routes'
 import { afterEach, beforeEach } from '@lywzx/vue.access.control';
+import $api from '@/api'
 
 Vue.use(VueRouter)
 let router = new VueRouter(
@@ -18,6 +19,7 @@ let router = new VueRouter(
 }
 )
 
+
 // 解决NavigationDuplicated 报错
 const originalPush = VueRouter.prototype.push
 VueRouter.prototype.push = function push(location) {
@@ -27,4 +29,21 @@ VueRouter.prototype.push = function push(location) {
 router.beforeEach(beforeEach.bind(router));
 router.afterEach(afterEach.bind(router));
 
+router.beforeEach((to, from, next) => {
+	// 无法匹配的路径 需要检查是否为短网址 如果是短网址 则需要进行解析换取长网址
+   if(to.name === '404' && to.redirectedFrom){
+	   $api.getLongUrl(window.location.origin + to.redirectedFrom).then(res => {
+		   if(!res.error){
+			   let toNextIdentity = res.result.includes('/studentWeb') ? 'student' : 'teacher'
+			   sessionStorage.setItem('identity',toNextIdentity)
+			   window.location.href = res.result
+		   }else{
+			   next()
+		   }
+	   })
+   }else{
+	   next()
+   }
+});
+
 export default router

+ 1 - 1
TEAMModelOS/ClientApp/src/router/routes.js

@@ -4,7 +4,7 @@ import FrontEndMain from '@/components/public/frontEndMain/Index.vue'
 // import HTTP404 from '@/view/404'
 // import { resolve } from 'url'
 
-let identity = localStorage.getItem('identity')
+let identity = sessionStorage.getItem('identity')
 
 export const routes = [{
 	path: '*',

+ 106 - 96
TEAMModelOS/ClientApp/src/service/User.js

@@ -1,102 +1,112 @@
 export class User {
 
-    static model = {
-        login: null,
-        logout: null,
-        userInfo: null
-    }
+	static model = {
+		login: null,
+		logout: null,
+		userInfo: null
+	}
 
-    /**
-     * @type Access
-     */
-    static $access;
+	/**
+	 * @type Access
+	 */
+	static $access;
 
-    static async login(userInfo) {
-      let userAccess = {
-          userId: userInfo.id,
-          roles: userInfo.roles,
-          permissions: userInfo.permissions,
-          isLogin: true
-      }
+	static async login(userInfo,identity) {
+		let userAccess = {
+			userId: userInfo.id,
+			roles: userInfo.roles,
+			permissions: userInfo.permissions,
+			isLogin: true
+		}
+		if(sessionStorage.getItem('identity') === 'teacher'){
+			localStorage.setItem('t_access',encodeURIComponent(JSON.stringify(userAccess), 'utf-8'))
+			localStorage.setItem('t_userInfo',encodeURIComponent(JSON.stringify(userInfo), 'utf-8'))
+		}else{
+			localStorage.setItem('s_access',encodeURIComponent(JSON.stringify(userAccess), 'utf-8'))
+			localStorage.setItem('s_userInfo',encodeURIComponent(JSON.stringify(userInfo), 'utf-8'))
+		}
+		sessionStorage.setItem('userAccess', encodeURIComponent(JSON.stringify(userAccess), 'utf-8')); // 權限
+		sessionStorage.setItem('userInfo', encodeURIComponent(JSON.stringify(userInfo), 'utf-8')); // 基本信息
+		return new Promise(function(resolve, reject) {
+			User.$access.reset();
+			//     // 配置登录用户的角色用对应的权限信息
+			User.$access.setLoginUserInfo(userAccess);
+			//     // 配置角色基本信息
+			User.$access.setExtendInfo({
+				'userAccess': userAccess,
+				'userInfo': userInfo
+			});
+			resolve(true);
+		});
+	}
 
-      localStorage.setItem('userAccess', encodeURIComponent(JSON.stringify(userAccess), 'utf-8')); // 權限
-      localStorage.setItem('userInfo', encodeURIComponent(JSON.stringify(userInfo), 'utf-8')); // 基本信息
+	// 刷新登录信息,这个方法可以获取至当前登录用户的角色及权限等信息
+	static freshLogin() {
+		return new Promise(function(resolve, reject) {
+			let identity = sessionStorage.getItem('identity')
+			let role_access = identity == 'student' ? localStorage.getItem('s_access') : localStorage.getItem('t_access')
+			let role_userInfo = identity == 'student' ? localStorage.getItem('s_userInfo') : localStorage.getItem('t_userInfo')
+			let userAccess = JSON.parse(decodeURIComponent(role_access, "utf-8"));
+			let userInfo = JSON.parse(decodeURIComponent(role_userInfo, "utf-8"));
+			setTimeout(() => {
+				User.$access.reset();
+				// 配置角色基本信息
+				User.$access.setExtendInfo({
+					'userAccess': userAccess,
+					'userInfo': userInfo
+				});
+				// 配置登录用户的角色用对应的权限信息
+				User.$access.setLoginUserInfo(userAccess);
+				resolve();
+			}, 100);
+		});
+	}
 
-      return new Promise(function(resolve, reject) {
-          User.$access.reset();
-      //     // 配置登录用户的角色用对应的权限信息
-          User.$access.setLoginUserInfo(userAccess);
-      //     // 配置角色基本信息
-          User.$access.setExtendInfo({
-              'userAccess': userAccess,
-              'userInfo' : userInfo
-            });
-          resolve(true);
-      });
-    }
-    
-    // 刷新登录信息,这个方法可以获取至当前登录用户的角色及权限等信息
-    static freshLogin() {        
-      return new Promise(function(resolve, reject) {
-          // 把信息放到access当中,类似vuex状态管理,在组件中,可以通过`computed`再获取到信息 
-            // computed: {
-            //    user() { return this.$access.getExtendInfo('userInfo');}
-            // }
-            //
-          let userAccess = JSON.parse(decodeURIComponent(localStorage.userAccess,"utf-8"));
-          let userInfo = JSON.parse(decodeURIComponent(localStorage.userInfo,"utf-8"));
-
-          setTimeout(() => {
-            User.$access.reset();
-            // 配置角色基本信息
-            User.$access.setExtendInfo({
-              'userAccess': userAccess,
-              'userInfo' : userInfo
-            });
-            // 配置登录用户的角色用对应的权限信息
-            User.$access.setLoginUserInfo(userAccess);
-            resolve();
-        }, 100);
-      });
-    }
-    
-    // 用户退出登录
-    static logout() {
-      return new Promise(function(resolve) {
-        setTimeout(() => {
-          localStorage.removeItem('token');
-          localStorage.removeItem('userAccess');
-          localStorage.removeItem('userInfo');
-          localStorage.removeItem('login_schoolCode')
-          localStorage.removeItem('user_details')
-          localStorage.removeItem('access_token')
-          localStorage.removeItem('expires_in')
-          localStorage.removeItem('id_token')
-          localStorage.removeItem('auth_token')
-          localStorage.removeItem('user_profile')
-          localStorage.removeItem('school_profile')
-          localStorage.removeItem('student_profile')
-          localStorage.removeItem('filterConditions')
-          localStorage.removeItem('cacheSchoolFiles')
-          localStorage.removeItem('cachePrivFiles')
-          localStorage.removeItem('platform')
-          localStorage.removeItem('curPeriod')
-          localStorage.removeItem('hpAppraise')
-          localStorage.removeItem('currArea')
-		  localStorage.removeItem('msgs')
-          sessionStorage.removeItem('areaName')
-          sessionStorage.removeItem('areaId')
-          
-          // 重置登录状态
-          User.$access.reset();
-          // 清空登录信息
-          User.$access.setExtendInfo({
-            'userAccess': {},
-            'userInfo' : {}
-          });          
-          // window.location.href = '/'
-          resolve(true);
-        }, 100);
-      });
-    }
-}
+	// 用户退出登录
+	static logout() {
+		return new Promise(function(resolve) {
+			setTimeout(() => {
+				let curIdentity = sessionStorage.getItem('identity')
+				if(curIdentity === 'teacher'){
+					localStorage.removeItem('school_profile')
+					localStorage.removeItem('t_access')
+					localStorage.removeItem('t_userInfo')
+					localStorage.removeItem('auth_token')
+					localStorage.removeItem('id_token')
+					localStorage.removeItem('login_schoolCode')
+					localStorage.removeItem('curPeriod')
+					localStorage.removeItem('filterConditions')
+					localStorage.removeItem('cacheSchoolFiles')
+					localStorage.removeItem('cachePrivFiles')
+					localStorage.removeItem('platform')
+					localStorage.removeItem('hpAppraise')
+					localStorage.removeItem('currArea')
+					localStorage.removeItem('msgs')
+					sessionStorage.removeItem('areaName')
+					sessionStorage.removeItem('areaId')
+				}else{
+					localStorage.removeItem('s_access')
+					localStorage.removeItem('s_userInfo')
+					localStorage.removeItem('student_profile')
+					localStorage.removeItem('stu_auth_token')
+					localStorage.removeItem('stu_id_token')
+				}
+				sessionStorage.removeItem('userAccess');
+				sessionStorage.removeItem('userInfo');
+				localStorage.removeItem('user_details')
+				// localStorage.removeItem('access_token')
+				localStorage.removeItem('expires_in')
+				// localStorage.removeItem('user_profile')
+				// 重置登录状态
+				User.$access.reset();
+				// 清空登录信息
+				User.$access.setExtendInfo({
+					'userAccess': {},
+					'userInfo': {}
+				});
+				// window.location.href = '/'
+				resolve(true);
+			}, 100);
+		});
+	}
+}

+ 2 - 2
TEAMModelOS/ClientApp/src/store/index.js

@@ -70,9 +70,9 @@ const mutations = {
         state.userInfo.hasSchool = obj !== GLOBAL.DEFAULT_SCHOOL_CODE
     },
     setUserName(state, data) {
-        let userInfo = JSON.parse(decodeURIComponent(localStorage.getItem('userInfo') || '{}', "utf-8"))
+        let userInfo = JSON.parse(decodeURIComponent(sessionStorage.getItem('userInfo') || '{}', "utf-8"))
         userInfo.name = data
-        localStorage.setItem('userInfo', encodeURIComponent(JSON.stringify(userInfo)))
+        sessionStorage.setItem('userInfo', encodeURIComponent(JSON.stringify(userInfo)))
         state.userInfo.name = data
     },
     //登录成功后设置个人空间大小

+ 4 - 4
TEAMModelOS/ClientApp/src/store/module/user.js

@@ -792,15 +792,15 @@ export default {
                 info.roles = authBySchool.roles
                 info.permissions = authBySchool.permissions == null ? [] : authBySchool.permissions
 
-                let userInfo = JSON.parse(decodeURIComponent(localStorage.getItem('userInfo'), "utf-8"))
+                let userInfo = JSON.parse(decodeURIComponent(sessionStorage.getItem('userInfo'), "utf-8"))
                 userInfo.roles = info.roles
                 userInfo.permissions = info.permissions
-                localStorage.setItem('userInfo', encodeURIComponent(JSON.stringify(userInfo), "utf-8"))
+                sessionStorage.setItem('userInfo', encodeURIComponent(JSON.stringify(userInfo), "utf-8"))
 
-                let userAccess = JSON.parse(decodeURIComponent(localStorage.getItem('userAccess'), "utf-8"))
+                let userAccess = JSON.parse(decodeURIComponent(sessionStorage.getItem('userAccess'), "utf-8"))
                 userAccess.roles = info.roles
                 userAccess.permissions = info.permissions
-                localStorage.setItem('userAccess', encodeURIComponent(JSON.stringify(userAccess), "utf-8"))
+                sessionStorage.setItem('userAccess', encodeURIComponent(JSON.stringify(userAccess), "utf-8"))
 
                 return true
             } else {

+ 5 - 5
TEAMModelOS/ClientApp/src/view/Home.vue

@@ -89,18 +89,18 @@
 			this.$Message.config({
 				duration: 3
 			});
-			// 检查超时操作页面,清空缓存数据
+			// 检查超时操作页面,清空缓存数据
 			let webEndTime = localStorage.getItem('webEndTime')
 			let time_now = new Date().getTime()
 			if (webEndTime && time_now > webEndTime) {
 				console.log('长时间未操作,清空storage,重新登录')
 				this.loginOut()
 			}
-			this.$store.dispatch('user/checkSchoolCode'); // 設定登入成功的學校簡碼
-			this.$store.dispatch('user/checkUserProfile'); // 檢查使用者個人詳細資訊
-			this.$store.dispatch('user/checkStudentProfile'); // 檢查學生的詳細資訊
+			this.$store.dispatch('user/checkSchoolCode'); // 設定登入成功的學校簡碼
+			this.$store.dispatch('user/checkUserProfile'); // 檢查使用者個人詳細資訊
+			this.$store.dispatch('user/checkStudentProfile'); // 檢查學生的詳細資訊
 
-			let user = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"))
+			let user = JSON.parse(decodeURIComponent(sessionStorage.userInfo, "utf-8"))
 			let user_profile = JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"))
 			this.location = user_profile.location
 			if (user_profile.schools) {

+ 5 - 5
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaBase.vue

@@ -41,19 +41,19 @@ export default {
 		this.$Message.config({
 		    duration: 3
 		});
-		// 检查超时操作页面,清空缓存数据
+		// 检查超时操作页面,清空缓存数据
 		let webEndTime = localStorage.getItem('webEndTime')
 		let time_now = new Date().getTime()
 		if (webEndTime && time_now > webEndTime) {
 		    console.log('长时间未操作,清空storage,重新登录')
 		    this.loginOut()
 		}
-		this.$store.dispatch('user/checkSchoolCode');// 設定登入成功的學校簡碼
-		this.$store.dispatch('user/checkUserProfile');// 檢查使用者個人詳細資訊
-		this.$store.dispatch('user/checkStudentProfile');// 檢查學生的詳細資訊
+		this.$store.dispatch('user/checkSchoolCode');// 設定登入成功的學校簡碼
+		this.$store.dispatch('user/checkUserProfile');// 檢查使用者個人詳細資訊
+		this.$store.dispatch('user/checkStudentProfile');// 檢查學生的詳細資訊
 		
 		
-        let user = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"))
+        let user = JSON.parse(decodeURIComponent(sessionStorage.userInfo, "utf-8"))
         let user_profile = JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"))
         console.log(user_profile)
         if (user_profile.schools) {

+ 8 - 2
TEAMModelOS/ClientApp/src/view/evaluation/bank/PaperDownload.vue

@@ -120,6 +120,7 @@
 		},
 		data() {
 			return {
+				scrollTop:0,
 				isDownloading:false,
 				pageArr:[0,1],
 				stepDomArr:[],
@@ -235,7 +236,7 @@
 			},
 			/* 进行跨页渲染 */
 			doRender(){
-				document.getElementById('paperDom').scrollIntoView()
+				// console.log(this.scrollTop)
 				setTimeout(() => {
 					// 获取到所有的splitDom
 					let splitDomArr = Array.from(document.getElementsByClassName('split-dom'))
@@ -255,7 +256,7 @@
 						// 每个页面的边距
 						let pageMargin = 40
 						// 计算当前DOM距离当前页面的Y值 70是减去header+margin距离 再减去已经超出的页面距离 再加上跨页造成的下移距离
-						let domY = (dom.getBoundingClientRect().top - 70) - (pageHeight * curPage) + extraMarTop
+						let domY = (dom.getBoundingClientRect().top + this.scrollTop - 70) - (pageHeight * curPage) + extraMarTop
 						let domH = dom.getBoundingClientRect().height
 						dom.style.marginTop = '0px'
 						dom.style.backgroundColor = 'transparent'
@@ -284,6 +285,11 @@
 		},
 		mounted() {
 			this.doRender()
+			/* 监听当前页面滚动距离 */
+			this.$EventBus.$off('evScroll')
+			this.$EventBus.$on('evScroll',val => {
+				this.scrollTop = val
+			})
 		},
 		computed:{
 			getFlatIndex(){

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

@@ -42,7 +42,7 @@
       },
 	  // 判断容器滚动距离
 	  handleScroll(vertical, horizontal, nativeEvent) {
-	  	// console.log(vertical.scrollTop)
+		this.$EventBus.$emit('evScroll',vertical.scrollTop)
 		// let anchorBarDom = document.getElementById('AnchorBar')
 		// console.log(anchorBarDom.getBoundingClientRect().top)
 	  },

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

@@ -273,7 +273,7 @@ export default {
                                     })
                                 } else {
                                     let result = res
-                                    let identity = localStorage.getItem('identity')
+                                    let identity = sessionStorage.getItem('identity')
                                     //登录学生端
                                     if (identity === 'student') {
                                         await this.$api.login.studLoginbyID(result).then(res => {

+ 1 - 1
TEAMModelOS/ClientApp/src/view/joinclass/JoinClass.vue

@@ -131,7 +131,7 @@ export default {
                         } else if (res.status == 0) {//正常加入
                             this.$Message.success(this.$t('cusMgt.join.joinOk'))
                             this.isJoin = true
-                            localStorage.setItem('identity', 'student')
+                            sessionStorage.setItem('identity', 'student')
                         }
                     } else {
                         this.$Message.error(this.$t('cusMgt.join.joinErr'))

+ 10 - 3
TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.less

@@ -308,9 +308,13 @@
     user-select: none;
 }
 .ev-qr-tag{
-    padding: 1px;
-    color: white;
-    background: #2d8cf0;
+    text-align: center;
+    padding: 1px 2px 1px 1px;
+    color: #2d8cf0;
+    position: absolute;
+    right: 15px;
+    top: 50%;
+    margin-top: -10px;
 }
 .qr-code-wrap {
     position: fixed;
@@ -350,4 +354,7 @@
     color: #2d8cf0;
     user-select: none;
     text-align: center;
+}
+.filter-item{
+    margin: 10px 5px;
 }

+ 89 - 22
TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.vue

@@ -6,10 +6,41 @@
             <div class="evaluation-list-wrap" slot="left">
                 <div class="evaluation-list-title">
                     <span>{{$t('learnActivity.mgtScEv.listLabel')}}</span>
-                    <Icon type="md-add" class=" to-create-icon" @click="goToCreate" :title="$t('learnActivity.mgtScEv.create')" />
-                    <Icon type="md-copy" class=" to-create-icon" @click="copyEv" :title="$t('learnActivity.mgtScEv.copy')" />
-                    <Icon type="md-trash" v-show="evaListShow.length" class="to-create-icon" :title="$t('learnActivity.mgtScEv.delete')" @click="deleteEvaluation" />
-                    <Icon type="md-create" v-show="evaListShow.length && evaListShow[curEvaIndex].progress == 'pending'" class="to-create-icon" @click="editEvaluation" :title="$t('learnActivity.mgtScEv.edit')" />
+                    <template v-if="!isSearch">
+                        <Icon type="md-add" class=" to-create-icon" @click="goToCreate" :title="$t('learnActivity.mgtScEv.create')" />
+                        <Icon type="md-copy" class=" to-create-icon" @click="copyEv" :title="$t('learnActivity.mgtScEv.copy')" />
+                        <Icon type="md-trash" v-show="evaListShow.length" class="to-create-icon" :title="$t('learnActivity.mgtScEv.delete')" @click="deleteEvaluation" />
+                        <!-- 筛选 -->
+                        <Poptip style="float:right" trigger="click" :offset="-10" theme="light">
+                            <Icon type="ios-funnel" class="to-create-icon" />
+                            <div slot="content">
+                                <div class="filter-item">
+                                    <span>{{$t('learnActivity.mgtScEv.ftStatus')}}</span>
+                                    <Select v-model="filter.status" style="width:100px" size="small" clearable @on-change="filterEv">
+                                        <Option value="pending">{{$t('learnActivity.mgtScEv.pending')}}</Option>
+                                        <Option value="going">{{$t('learnActivity.mgtScEv.going')}}</Option>
+                                        <Option value="finish">{{$t('learnActivity.mgtScEv.finish')}}</Option>
+                                    </Select>
+                                </div>
+                                <div class="filter-item">
+                                    <span>{{$t('learnActivity.mgtScEv.ftMode')}}</span>
+                                    <Select v-model="filter.mode" style="width:100px" size="small" clearable @on-change="filterEv">
+                                        <Option v-for="(item,index) in $GLOBAL.EV_MODE()" :value="item.value" :key="index">{{ item.label }}</Option>
+                                    </Select>
+                                </div>
+                                <div class="filter-item">
+                                    <span>{{$t('learnActivity.mgtScEv.ftType')}}</span>
+                                    <Select v-model="filter.type" style="width:100px" size="small" clearable @on-change="filterEv">
+                                        <Option v-for="(item,index) in $GLOBAL.EV_TYPE()" :value="item.value" :key="index">{{ item.label }}</Option>
+                                    </Select>
+                                </div>
+                            </div>
+                        </Poptip>
+                        <Icon type="md-search" class="to-create-icon" @click="isSearch = !isSearch" :title="$t('learnActivity.mgtScEv.search')" />
+                    </template>
+                    <div v-else style="float:right;width:calc(100% - 150px);padding-right:10px;" class="light-iview-input">
+                        <Input v-special-char icon="ios-close" v-model="keyword" :placeholder="$t('schoolBaseInfo.codeSearchHolder')" autofocus style="width:100%" @on-click="closeKeySearch" @on-change="filterByName" />
+                    </div>
                 </div>
                 <div class="evaluation-list-main">
                     <vuescroll>
@@ -45,11 +76,11 @@
                                 <span v-if="item.progress == 'going'" class="handle-end-tag ev-tag-common" @click="handleEnd(index)">
                                     {{$t('learnActivity.mgtScEv.stop')}}
                                 </span>
-                                <!-- 二维码分享 -->
-                                <span class="ev-tag-common ev-qr-tag" @click="openQrcode(index)">
-                                    <Icon size="20" custom="iconfont icon-qrcode" class="qr-code-icon" />
-                                </span>
                             </div>
+                            <!-- 二维码分享 -->
+                            <span class="ev-qr-tag" @click="openQrcode(index)" v-show="item.source != '1'">
+                                <Icon size="25" custom="iconfont icon-qr-code" class="qr-code-icon" />
+                            </span>
                         </div>
                         <EmptyData v-if="evaListShow.length == 0" style="margin-top:180px;" :textContent="$t('learnActivity.mgtScEv.nodata')"></EmptyData>
                     </vuescroll>
@@ -169,25 +200,61 @@ export default {
                 }
             ],
             scoreLoading: false,
-            answerLoading: false
+            answerLoading: false,
+            filter: {
+                status: '',
+                mode: '',
+                type: ''
+            },
+            isSearch: false,
+            keyword: ''
         }
     },
     methods: {
+        filterByName() {
+            // let curPdEv = this.evaluationList.filter(item => item.period.id === this.filterPeriod)
+            this.evaListShow = this.evaluationList.filter(item => {
+                return item.name.indexOf(this.keyword) > -1
+            })
+        },
+        closeKeySearch() {
+            this.isSearch = false
+            this.keyword = ''
+            this.filterByName()
+        },
+        //筛选评测
+        filterEv() {
+            // let curPdEv = this.evaluationList.filter(item => item.period.id === this.filterPeriod)
+            this.evaListShow = this.evaluationList.filter(item => {
+                let status = !this.filter.status || (this.filter.status == item.progress)
+                let type = !this.filter.type || (this.filter.type == item.type)
+                let mode = !this.filter.mode || (this.filter.mode == item.source)
+                return status && type && mode
+            })
+        },
         // 复制评测
         copyEv() {
-            this.$Modal.confirm({
-                title: this.$t('learnActivity.mgtScEv.copyTitle'),
-                content: this.$t('learnActivity.mgtScEv.copyContent'),
-                onOk: () => {
-                    console.log(this.evaListShow[this.curEvaIndex])
-                    this.$router.push({
-                        name: 'createPrivEva',
-                        params: {
-                            evaluationInfo: this.evaListShow[this.curEvaIndex]
-                        }
-                    })
-                }
-            })
+            // 课中评测不提供复制操作
+            if (this.evaListShow[this.curEvaIndex]?.source === '1') {
+                this.$Modal.info({
+                    title: this.$t('learnActivity.mgtScEv.copyTitle'),
+                    content: this.$t('learnActivity.mgtScEv.copyContent1')
+                })
+            } else if (this.evaListShow[this.curEvaIndex]) {
+                this.$Modal.confirm({
+                    title: this.$t('learnActivity.mgtScEv.copyTitle'),
+                    content: this.$t('learnActivity.mgtScEv.copyContent'),
+                    onOk: () => {
+                        console.log(this.evaListShow[this.curEvaIndex])
+                        this.$router.push({
+                            name: 'createPrivEva',
+                            params: {
+                                evaluationInfo: this.evaListShow[this.curEvaIndex]
+                            }
+                        })
+                    }
+                })
+            }
         },
         copyUrl() {
             let evName = this.evaListShow[this.curEvaIndex].name

+ 7 - 3
TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.less

@@ -264,9 +264,13 @@
     color: #2d8cf0;
 }
 .ev-qr-tag{
-    padding: 1px;
-    color: white;
-    background: #2d8cf0;
+    text-align: center;
+    padding: 1px 2px 1px 1px;
+    color: #2d8cf0;
+    position: absolute;
+    right: 15px;
+    top: 50%;
+    margin-top: -10px;
 }
 .qr-code-wrap {
     position: fixed;

+ 32 - 23
TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue

@@ -23,18 +23,18 @@
                                         <Option value="finish">{{$t('learnActivity.mgtScEv.finish')}}</Option>
                                     </Select>
                                 </div>
-                                <div class="filter-item">
-                                    <span>{{$t('learnActivity.mgtScEv.ftType')}}</span>
-                                    <Select v-model="filter.type" style="width:100px" size="small" clearable @on-change="filterEv">
-                                        <Option v-for="(item,index) in $GLOBAL.EV_TYPE()" :value="item.value" :key="index">{{ item.label }}</Option>
-                                    </Select>
-                                </div>
                                 <div class="filter-item">
                                     <span>{{$t('learnActivity.mgtScEv.ftMode')}}</span>
                                     <Select v-model="filter.mode" style="width:100px" size="small" clearable @on-change="filterEv">
                                         <Option v-for="(item,index) in $GLOBAL.EV_MODE()" :value="item.value" :key="index">{{ item.label }}</Option>
                                     </Select>
                                 </div>
+                                <div class="filter-item">
+                                    <span>{{$t('learnActivity.mgtScEv.ftType')}}</span>
+                                    <Select v-model="filter.type" style="width:100px" size="small" clearable @on-change="filterEv">
+                                        <Option v-for="(item,index) in $GLOBAL.EV_TYPE()" :value="item.value" :key="index">{{ item.label }}</Option>
+                                    </Select>
+                                </div>
                             </div>
                         </Poptip>
                         <Icon type="md-search" class="to-create-icon" @click="isSearch = !isSearch" :title="$t('learnActivity.mgtScEv.search')" />
@@ -77,11 +77,11 @@
                                 <span v-if="item.progress == 'going'" class="handle-end-tag ev-tag-common" @click="handleEnd(index)">
                                     {{$t('learnActivity.mgtScEv.stop')}}
                                 </span>
-                                <!-- 二维码分享 -->
-                                <span class="ev-tag-common ev-qr-tag" @click="openQrcode(index)">
-                                    <Icon size="20" custom="iconfont icon-qrcode" class="qr-code-icon" />
-                                </span>
                             </div>
+                            <!-- 二维码分享 -->
+                            <span class="ev-qr-tag" @click="openQrcode(index)" v-show="item.source != '1'">
+                                <Icon size="25" custom="iconfont icon-qr-code" class="qr-code-icon" />
+                            </span>
                         </div>
                         <EmptyData v-if="evaListShow.length == 0" style="margin-top:100px;" :textContent="`${scope == 'school' ? curPdInfo.name || '' : ''}${$t('learnActivity.mgtScEv.nodata')}`"></EmptyData>
                     </vuescroll>
@@ -225,19 +225,28 @@ export default {
     methods: {
         // 复制评测
         copyEv() {
-            this.$Modal.confirm({
-                title: this.$t('learnActivity.mgtScEv.copyTitle'),
-                content: this.$t('learnActivity.mgtScEv.copyContent'),
-                onOk: () => {
-                    console.log(this.evaListShow[this.curEvaIndex])
-                    this.$router.push({
-                        name: 'createSchoolEva',
-                        params: {
-                            evaluationInfo: this.evaListShow[this.curEvaIndex]
-                        }
-                    })
-                }
-            })
+            // 课中评测不提供复制操作
+            if (this.evaListShow[this.curEvaIndex]?.source === '1') {
+                this.$Modal.info({
+                    title: this.$t('learnActivity.mgtScEv.copyTitle'),
+                    content: this.$t('learnActivity.mgtScEv.copyContent1')
+                })
+            } else if (this.evaListShow[this.curEvaIndex]) {
+                this.$Modal.confirm({
+                    title: this.$t('learnActivity.mgtScEv.copyTitle'),
+                    content: this.$t('learnActivity.mgtScEv.copyContent'),
+                    onOk: () => {
+                        console.log(this.evaListShow[this.curEvaIndex])
+                        this.$router.push({
+                            name: 'createSchoolEva',
+                            params: {
+                                evaluationInfo: this.evaListShow[this.curEvaIndex]
+                            }
+                        })
+                    }
+                })
+            }
+
         },
         copyUrl() {
             let evName = this.evaListShow[this.curEvaIndex].name

+ 43 - 45
TEAMModelOS/ClientApp/src/view/login/Index.vue

@@ -395,7 +395,7 @@ export default {
         this.userOauth.identity = this.$route.query.identity // student 或 teacher
         if (this.userOauth.identity) {
             console.log('重新设置身份', this.userOauth.identity)
-            localStorage.setItem('identity', this.userOauth.identity)
+            sessionStorage.setItem('identity', this.userOauth.identity)
         } else {
             console.log('没有设置身份', this.$route.query)
         }
@@ -454,16 +454,12 @@ export default {
             this.$Spin.show(); //開啟加載畫面
             let redirect_uri = window.location.origin + '/login'
             this.$api.OauthLogin(this.userOauth.state, this.userOauth.code, redirect_uri).then(res => {
-
+                
                 //TODO 大陆站微信登陆需要验证是否启用
                 let tokenData = jwtDecode(res.id_token)
-                localStorage.setItem("access_token", res.access_token)
-                /**
-                 * 1、token解析出来为字符串,所以需要对比字符串‘false’
-                 * 2、目前只有大陆站检查账号绑定操作,所以这只就只判断isMobile
-                 * 3、这里只处理了三方登录的情况,如果使用账号密码登录不会做验证
-                 */
-                if (this.$store.state.config.srvAdr == 'China' && tokenData.isMobile === 'false') {
+                localStorage.setItem("access_token",res.access_token)
+                //token解析出来为字符串,所以需要对比字符串‘false’
+                if (tokenData.isActivate === 'false' && this.$store.state.config.srvAdr == 'China') {
                     //未启用,前往绑定手机号
                     this.$router.push({
                         path: '/bandphone',
@@ -495,46 +491,48 @@ export default {
         },
         loginProcess: async function (item, schoolCode) { // 登入用function
             let result;
-            let identity = localStorage.getItem('identity')
+            let identity = sessionStorage.getItem('identity')
             // 登录学生端
             if (identity === 'student') {
-                await this.$api.login.studLoginbyID(item).then(res => {
-                    result = res
-                })
-                //設定權限並登入 学生端默认权限
-                User.login({
-                    id: result.sub,
-                    roles: ['student'],
-                    permissions: []
-                }).then(res => {
-                    if (res) {
-                        this.$router.push({ path: '/studentWeb' })
-                    }
-                }).finally(() => {
-                    this.$Spin.hide(); //關閉加載畫面
-                })
+                this.$loginTools.stuLoginById(item)
+				// await this.$api.login.studLoginbyID(item).then(res => {
+                //     result = res
+                // })
+                // //設定權限並登入 学生端默认权限
+                // User.login({
+                //     id: result.sub,
+                //     roles: ['student'],
+                //     permissions: []
+                // }).then(res => {
+                //     if (res) {
+                //         this.$router.push({ path: '/studentWeb' })
+                //     }
+                // }).finally(()=>{
+                //     this.$Spin.hide(); //關閉加載畫面
+                // })
             }
             // 登录教师端
             else {
-                await this.$api.login.teacherLogin(item, schoolCode).then(res => {
-                    result = res
-                })
-                //設定權限並登入
-                User.login(result).then(res => {
-                    if (res && identity) {
-                        this.saveUserCodes({
-                            TEAMModelId: result.id,
-                            name: result.name,
-                            schoolCode: result.defaultschool
-                        })
-                        let homePath = this.$store.state.config.srvAdr == 'China' ? 'home' : 'myCourse'
-                        this.$router.push({ name: homePath })
-                    } else {
-                        this.identityFlag = true;
-                    }
-                }).finally(() => {
-                    this.$Spin.hide(); //關閉加載畫面
-                })
+				this.$loginTools.teacherLogin(item, schoolCode)
+                // await this.$api.login.teacherLogin(item, schoolCode).then(res => {
+                //     result = res
+                // })
+                // //設定權限並登入
+                // User.login(result).then(res => {
+                //     if (res && identity) {
+                //         this.saveUserCodes({
+                //             TEAMModelId: result.id,
+                //             name: result.name,
+                //             schoolCode: result.defaultschool
+                //         })
+                //         let homePath = this.$store.state.config.srvAdr == 'China' ? 'home' : 'myCourse'
+                //         this.$router.push({ name: homePath })
+                //     } else {
+                //         this.identityFlag = true;
+                //     }
+                // }).finally(()=>{
+                //     this.$Spin.hide(); //關閉加載畫面
+                // })
             }
         },
         saveUserCodes: function (res) {
@@ -549,7 +547,7 @@ export default {
             }
         },
         goWhere: function (identity) {
-            localStorage.setItem('identity', identity)
+            sessionStorage.setItem('identity', identity)
             let homePath = this.$store.state.config.srvAdr == 'China' ? 'home' : 'myCourse'
             let path = identity == 'student' ? 'studentWeb' : homePath
             this.$router.push({ name: path })

+ 2 - 2
TEAMModelOS/ClientApp/src/view/login/jinniu/Index.vue

@@ -415,7 +415,7 @@ export default {
         },
         loginProcess: async function (item, schoolCode) { // 登入用function
             let result;
-            let identity = localStorage.getItem('identity')
+            let identity = sessionStorage.getItem('identity')
             // 登录学生端
             if (identity === 'student') {
                 await this.$api.login.studLoginbyID(item).then(res => {
@@ -464,7 +464,7 @@ export default {
             }
         },
         goWhere: function (identity) {
-            localStorage.setItem('identity', identity)
+            sessionStorage.setItem('identity', identity)
             let path = identity == 'student' ? '/studentWeb' : '/home'
             this.$router.push({ path: path })
         },

+ 3 - 3
TEAMModelOS/ClientApp/src/view/login/jinniu/Student.vue

@@ -454,7 +454,7 @@ export default {
     },
     created() {
         // 此頁面為學生頁面
-        localStorage.setItem('identity', 'student')
+        sessionStorage.setItem('identity', 'student')
 
         // 建立學校LIST清單
         this.getSchools()
@@ -499,7 +499,7 @@ export default {
                                             permissions: []
                                         }).then(res => {
                                             if (res) {
-                                                localStorage.setItem('identity', 'student')
+                                                sessionStorage.setItem('identity', 'student')
                                                 this.$router.push({ path: '/studentWeb' })
                                             }
                                         })
@@ -526,7 +526,7 @@ export default {
                                 //設定權限並登入
                                 User.login(result).then(res => {
                                     if (res) {
-                                        localStorage.setItem('identity', 'student')
+                                        sessionStorage.setItem('identity', 'student')
                                         this.$router.push({ path: '/studentWeb' })
                                     }
                                 })

+ 1 - 1
TEAMModelOS/ClientApp/src/view/login/jinniu/Teacher.vue

@@ -342,7 +342,7 @@ export default {
     },
     created() {
         // 此頁面為老師頁面
-        localStorage.setItem('identity', 'teacher')
+        sessionStorage.setItem('identity', 'teacher')
 
         // 取得學校設定簡碼
         this.setDefSchool()

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 628 - 633
TEAMModelOS/ClientApp/src/view/login/page/Student.vue


+ 5 - 4
TEAMModelOS/ClientApp/src/view/login/page/Teacher.vue

@@ -206,7 +206,6 @@ import { EventSourcePolyfill } from 'event-source-polyfill';
 import QRCode from 'qrcodejs2'
 import { User } from '@/service/User'
 import { mapState, mapGetters } from 'vuex'
-
 export default {
     data() {
         const validateID = (rule, value, callback) => {
@@ -292,7 +291,7 @@ export default {
     },
     created() {
         // 此頁面為老師頁面
-        localStorage.setItem('identity', 'teacher')
+        sessionStorage.setItem('identity', 'teacher')
 
         // 取得學校設定簡碼
         this.setDefSchool()
@@ -343,7 +342,8 @@ export default {
                         //         }
                         //     })
                         // } else {
-                        this.loginProcess(result, this.defaultSchool.code)
+                        // this.loginProcess(result, this.defaultSchool.code)
+						this.$loginTools.teacherLogin(result)
                         // }
                     }
                 }
@@ -491,7 +491,8 @@ export default {
                 this.$Spin.hide(); // 關閉加載畫面
                 if (!res.error) {
                     // 登入大雲開始
-                    this.loginProcess(res, this.defaultSchool.code)
+					this.$loginTools.teacherLogin(res)
+                    // this.loginProcess(res, this.defaultSchool.code)
                 } else {
                     this.$Message.warning(this.$t('login.sse.error.text1'));
                 }

+ 35 - 26
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue

@@ -60,7 +60,7 @@
                                         <span class="attr-label">{{$t('cusMgt.stuCount')}}</span>
                                         <span class="class-name">{{item.allStu ? item.allStu.length : 0}}{{$t('unit.text7')}}</span>
                                     </p>
-                                    <Icon size="30" custom="iconfont icon-qr-code" class="qr-code-icon" @click="showQrCode(index)" v-if="listType == 'private'" :title="$t('cusMgt.qrCodeLabel')" />
+                                    <Icon size="25" custom="iconfont icon-qr-code" class="qr-code-icon" @click="showQrCode(index)" v-if="listType == 'private'" :title="$t('cusMgt.qrCodeLabel')" />
                                 </div>
                                 <EmptyData v-if="teaClassList.length == 0" :top="160" :textContent="$t('cusMgt.noClassList')"></EmptyData>
                             </vuescroll>
@@ -881,7 +881,7 @@ export default {
             this.renameBefore = this.teaClassList[this.curClassIndex].listName
             this.editClassStatus = true
         },
-        copyUrl() {
+        async copyUrl() {
             //邀请加入醍摩豆云平台IES教师个人课程
 
             // 课程名称:英语能力检测
@@ -905,17 +905,21 @@ export default {
                 return item.id == listId
             })
             let listNo = stulistInfo.no
+            try {
+                let shortUrl = await this.$api.getShortUrl(encodeURI(this.inviteUrl)) //暂不替换,等路由处理好了再替换
+                let shareText = `${this.$t('cusMgt.inviteInfo1')}\n\n${this.$t('cusMgt.inviteInfo2')}${cusName}\n${this.$t('cusMgt.inviteInfo3')}${listName}\n${this.$t('cusMgt.inviteInfo4')}${tName}\n\n${this.$t('cusMgt.inviteInfo5')}\n${shortUrl.result}\n\n${this.$t('cusMgt.inviteInfo6')}\nURL:https://${loginUrl}/login/student\n${this.$t('cusMgt.inviteInfo7')}${listNo}`
+                this.$copyText(shareText).then(
+                    ok => {
+                        this.$Message.success(this.$t("settings.copyModal1"))
+                    },
+                    fail => {
+                        this.$Message.error(this.$t("settings.copyModal2"))
+                    }
+                )
+            } catch (e) {
+                this.$Message.error(this.$t("settings.copyModal2"))
+            }
 
-            let shareText = `${this.$t('cusMgt.inviteInfo1')}\n\n${this.$t('cusMgt.inviteInfo2')}${cusName}\n${this.$t('cusMgt.inviteInfo3')}${listName}\n${this.$t('cusMgt.inviteInfo4')}${tName}\n\n${this.$t('cusMgt.inviteInfo5')}\n${encodeURI(this.inviteUrl)}\n\n${this.$t('cusMgt.inviteInfo6')}\nURL:https://${loginUrl}/login/student\n${this.$t('cusMgt.inviteInfo7')}${listNo}`
-
-            this.$copyText(shareText).then(
-                ok => {
-                    this.$Message.success(this.$t("settings.copyModal1"))
-                },
-                fail => {
-                    this.$Message.error(this.$t("settings.copyModal2"))
-                }
-            )
         },
         initData() {
             this.cusType = [
@@ -1411,21 +1415,26 @@ export default {
         createQRCode(url) {
             this.$nextTick(async () => {
                 // 此时已经渲染完成
-                let shortUrl = await this.$api.getShortUrl(encodeURI(url)) //暂不替换,等路由处理好了再替换
-                if (this.joinQRcode == undefined) {
-                    let qrcode = new QRCode('qrcode', {
-                        width: 280, // 设置宽度,单位像素
-                        height: 280, // 设置高度,单位像素
-                        text: encodeURI(url), // 编码处理
-                        correctLevel: QRCode.CorrectLevel.Q //解决编码后网址太长的问题
-                    })
-                    this.joinQRcode = qrcode
-                } else {
-                    this.joinQRcode.clear()
-                    this.joinQRcode.makeCode(encodeURI(url))
+                try {
+                    let shortUrl = await this.$api.getShortUrl(encodeURI(url)) //暂不替换,等路由处理好了再替换
+                    if (this.joinQRcode == undefined) {
+                        let qrcode = new QRCode('qrcode', {
+                            width: 280, // 设置宽度,单位像素
+                            height: 280, // 设置高度,单位像素
+                            // text: encodeURI(url), // 编码处理
+                            text: shortUrl.result, // 编码处理
+                            correctLevel: QRCode.CorrectLevel.Q //解决编码后网址太长的问题
+                        })
+                        this.joinQRcode = qrcode
+                    } else {
+                        this.joinQRcode.clear()
+                        this.joinQRcode.makeCode(shortUrl.result)
+                    }
+                    let dom = document.getElementById('qrcode')
+                    if (dom) dom.title = ''
+                } catch (e) {
+                    this.$Message.error(this.$t('cusMgt.qrcodeErr'))
                 }
-                let dom = document.getElementById('qrcode')
-                if (dom) dom.title = ''
             })
         },
         showQrCode(index) {

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

@@ -308,7 +308,7 @@ export default {
                         } else {
                             let result = res
 
-                            let identity = localStorage.getItem('identity')
+                            let identity = sessionStorage.getItem('identity')
 
                             //处理研修平台账号绑定问题(这部分统一调整手机绑定可以删掉)
                             // if (this.routerData && this.routerData.loginType && this.routerData.loginType === 'trainsso') {

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

@@ -127,7 +127,7 @@
                 isTyping: false,
                 curRole: '',
                 users: '',
-                identity: localStorage.getItem('identity'),
+                identity: sessionStorage.getItem('identity'),
                 userInfo: {},
                 isAddClass: false,
             };
@@ -163,7 +163,7 @@
         },
         created() {
             this.getUsers();
-            this.$store.dispatch('user/checkStudentProfile');// 檢查學生的詳細資訊,刷新后同步localStorage数据
+            this.$store.dispatch('user/checkStudentProfile');// 檢查學生的詳細資訊,刷新后同步localStorage数据
         },
         mounted() {
             this.getStudentData()
@@ -209,25 +209,25 @@
                 }
             },
             getUsers() {
-                this.users = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"));
-                let data = jwtDecode(localStorage.getItem('auth_token'))
+                this.users = JSON.parse(decodeURIComponent(sessionStorage.userInfo, "utf-8"));
+                let data = jwtDecode(localStorage.getItem('stu_auth_token'))
                 if (data.name !== "") {
                     this.$store.commit("setUserInfo", data)
                     this.$store.commit("setStuUserInfo", data)
-                    localStorage.setItem("userInfo", encodeURIComponent(JSON.stringify(data)))
+                    sessionStorage.setItem("userInfo", encodeURIComponent(JSON.stringify(data)))
                 }
                 if (this.users.roles.length) {
-                    this.curRole = localStorage.getItem('identity')
+                    this.curRole = sessionStorage.getItem('identity')
                 }
             },
             getStudentData() {
                 this.userInfo = this.$store.getters.getStuUserInfo
             },
             onRoleSelect(val) {
-                if (localStorage.getItem('identity') != val) {
+                if (sessionStorage.getItem('identity') != val) {
                     this.curRole = val
                     let path = val === 'student' ? '/studentWeb' : '/home'
-                    localStorage.setItem('identity', val)
+                    sessionStorage.setItem('identity', val)
                     this.$router.push({ path: path })
                 }
             },

+ 2 - 2
TEAMModelOS/ClientApp/src/view/user/UserCenter.vue

@@ -415,9 +415,9 @@ export default {
                                     setTimeout(() => {
                                         this.$set(this.userInfo, 'picture', p)
                                     })
-                                    let userInfo = JSON.parse(decodeURIComponent(localStorage.getItem('userInfo') || '{}', "utf-8"))
+                                    let userInfo = JSON.parse(decodeURIComponent(sessionStorage.getItem('userInfo') || '{}', "utf-8"))
                                     userInfo.picture = p
-                                    localStorage.setItem('userInfo', encodeURIComponent(JSON.stringify(userInfo)))
+                                    sessionStorage.setItem('userInfo', encodeURIComponent(JSON.stringify(userInfo)))
                                     this.$EventBus.$emit('freshUserInfo', {
                                         picture: p
                                     })

+ 1 - 1
TEAMModelOS/ClientApp/src/view/video/Video.vue

@@ -749,7 +749,7 @@
 				teachers: 'user/getSchoolUserJoined', // 取得已加入此學校的使用者
 			}),
 			curUserRoles() {
-				return JSON.parse(decodeURIComponent(localStorage.userAccess, "utf-8")).roles
+				return JSON.parse(decodeURIComponent(sessionStorage.userAccess, "utf-8")).roles
 			}
 		},
 	}

+ 1 - 1
TEAMModelOS/ClientApp/src/view/video/VideoReview.vue

@@ -575,7 +575,7 @@
 		},
 		computed: {
 			curUserRoles() {
-				return JSON.parse(decodeURIComponent(localStorage.userAccess, "utf-8")).roles
+				return JSON.parse(decodeURIComponent(sessionStorage.userAccess, "utf-8")).roles
 			}
 		},
 		watch: {

+ 1 - 1
TEAMModelOS/ClientApp/src/view/vote/ManageVote.vue

@@ -79,7 +79,7 @@
 									<span>{{ $t('vote.voteResult') }}</span>
 									<div class="hw-box-header-tools">
 										<div v-if="!isAreaVote">
-											<span class="hw-box-header-tools-tool" @click="changeTableView" v-if="!currentVote.secret">
+											<span class="hw-box-header-tools-tool" @click="changeTableView" v-if="!currentVote.secret && voteList.length">
 												<Icon type="md-podium" />
 												{{ isOptionView ? $t('vote.stuListView') : $t('vote.optionView') }}
 											</span>

+ 6 - 6
TEAMModelOS/Controllers/Analysis/ClassAnalysisController.cs

@@ -679,12 +679,12 @@ namespace TEAMModelOS.Controllers.Analysis
                     }
 
                 }
-                var sc_online = ps.Where(x => x.source.Equals("0") && x.scope.Equals("school")).ToList().Count;
-                var p_online = ps.Where(x => x.source.Equals("0") && x.scope.Equals("private")).ToList().Count;
-                var sc_class = ps.Where(x => x.source.Equals("1") && x.scope.Equals("school")).ToList().Count;
-                var p_class = ps.Where(x => x.source.Equals("1") && x.scope.Equals("private")).ToList().Count;
-                var sc_mark = ps.Where(x => x.source.Equals("2") && x.scope.Equals("school")).ToList().Count;
-                var p_mark = ps.Where(x => x.source.Equals("2") && x.scope.Equals("private")).ToList().Count;
+                var sc_online = ps.Where(x => x.source.Equals("0") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("school")).ToList().Count;
+                var p_online = ps.Where(x => x.source.Equals("0") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("private")).ToList().Count;
+                var sc_class = ps.Where(x => x.source.Equals("1") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("school")).ToList().Count;
+                var p_class = ps.Where(x => x.source.Equals("1") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("private")).ToList().Count;
+                var sc_mark = ps.Where(x => x.source.Equals("2") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("school")).ToList().Count;
+                var p_mark = ps.Where(x => x.source.Equals("2") && !string.IsNullOrEmpty(x.scope) && x.scope.Equals("private")).ToList().Count;
                 counts.Add(sc_online);
                 counts.Add(sc_class);
                 counts.Add(sc_mark);