瀏覽代碼

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

Li 3 年之前
父節點
當前提交
268aa8910a

+ 1 - 1
TEAMModelOS.SDK/TEAMModelOS.SDK.csproj

@@ -12,7 +12,7 @@
 
   <ItemGroup>
     <PackageReference Include="CHTCHSConv" Version="1.0.0" />
-    <PackageReference Include="HTEXLib" Version="5.2111.41" />
+    <PackageReference Include="HTEXLib" Version="5.2202.222" />
     <PackageReference Include="AspectCore.Extensions.Reflection" Version="2.2.0" />
     <PackageReference Include="Azure.Cosmos" Version="4.0.0-preview3" />
     <PackageReference Include="Azure.Identity" Version="1.5.0" />

+ 6 - 2
TEAMModelOS/ClientApp/src/api/service.js

@@ -1,9 +1,13 @@
 import { fetch, post } from '@/api/http'
 export default {
 	/* 获取端外通知 */
-    getNotification: function (data) {
-        return post('https://api2.teammodel.net/service/getnotification', data)
+    getNotification: function (host,data) {
+        return post(`${host}/service/getnotification`, data)
     },
+	/* 删除通知 */
+	delNotification: function (host,data) {
+	    return post(`${host}/service/DelNotification`, data)
+	},
     /* 获取id详细信息 */
     getIdProfile: function (host,data) {
         return post(`${host}/oauth2/profile`, data)

+ 72 - 30
TEAMModelOS/ClientApp/src/common/BaseNotification.vue

@@ -6,7 +6,8 @@
 			</Badge>
 			<div slot="title" style="display: flex;justify-content: space-between;align-items: center;">
 				<span>{{ $t('utils.newNotice') }}</span>
-				<span style="font-size: 12px;cursor: pointer;" v-if="msgArr.length" @click="clearAllMsgs">{{ $t('utils.clearAllMsgs') }}</span>
+				<span style="font-size: 12px;cursor: pointer;" v-if="msgArr.length"
+					@click="clearAllMsgs">{{ $t('utils.clearAllMsgs') }}</span>
 			</div>
 			<div slot="content" class="notice-wrap">
 				<div v-if="!msgArr.length" class="notice-empty">
@@ -45,20 +46,28 @@
 					'coedit_syllabus': vm.$t('notice.type4'), // 邀请课纲共编的通知
 					'share_syllabus': vm.$t('notice.type4'), // 个人课纲分享的通知
 					'transfer-admin_school': vm.$t('notice.type5'), // 管理员转移的通知
-					'scoring-arb_school':vm.$t('notice.type6'), // 仲裁卷阅卷任务分配通知
-					'scoring-err_school':vm.$t('notice.type6'), // 异常卷阅卷任务分配通知
-					'scoring-mark_school':vm.$t('notice.type6'), // 普通阅卷任务分配通知
+					'scoring-arb_school': vm.$t('notice.type6'), // 仲裁卷阅卷任务分配通知
+					'scoring-err_school': vm.$t('notice.type6'), // 异常卷阅卷任务分配通知
+					'scoring-mark_school': vm.$t('notice.type6'), // 普通阅卷任务分配通知
 				}
 			}
 		},
 		methods: {
 			/* 清空所有消息 */
-			clearAllMsgs(){
+			clearAllMsgs() {
 				this.$Modal.confirm({
 					title: this.$t('settings.modalTip4'),
 					content: this.$t('utils.clearAllTip'),
 					onOk: () => {
-						this.msgArr = []
+						if(this.msgArr.length < 2){
+							this.msgArr = []
+						}else{
+							let groups = this._.groupBy(this.msgArr, 'from')
+							Object.keys(groups).forEach(from => {
+								this.delMsgs(from,groups[from].map(i => i.indexNum))
+							})
+							this.msgArr = []
+						}
 						localStorage.removeItem('msgs')
 					}
 				})
@@ -69,7 +78,6 @@
 			},
 			/* 获取消息通知时间 */
 			getMsgTime(msg) {
-				console.log(msg);
 				return this.$tools.getDateDiff(msg.body.time)
 			},
 			/* 获取消息通知内容 */
@@ -109,7 +117,7 @@
 						break;
 					case 'scoring-mark_school':
 						return `${body.schoolname}-${body.tmdname} ${this.$t('notice.tip10')}【${body.examname}】 `
-						break;	
+						break;
 					default:
 						break;
 				}
@@ -118,27 +126,42 @@
 			doClickMsg(msg, index) {
 				let body = msg.body
 				let routerInfo = null
+				console.log(msg);
 				switch (msg.label) {
 					case 'request_school':
-						routerInfo = { name: "teachermgmt"	}
+						routerInfo = {
+							name: "teachermgmt"
+						}
 						break;
 					case 'invite-join_school':
-						routerInfo = { name: "teachermgmt"	}
+						routerInfo = {
+							name: "teachermgmt"
+						}
 						break;
 					case 'invite_school':
-						routerInfo = { name: "settings"	}
+						routerInfo = {
+							name: "settings"
+						}
 						break;
 					case 'coedit_syllabus':
-						routerInfo = { name: "syllabus"	}
+						routerInfo = {
+							name: "syllabus"
+						}
 						break;
 					case 'scoring-arb_school':
-						routerInfo = { name: "taskList"	}
+						routerInfo = {
+							name: "taskList"
+						}
 						break;
 					case 'scoring-err_school':
-						routerInfo = { name: "taskList"	}
+						routerInfo = {
+							name: "taskList"
+						}
 						break;
 					case 'scoring-mark_school':
-						routerInfo = { name: "taskList"	}
+						routerInfo = {
+							name: "taskList"
+						}
 						break;
 					case 'share_syllabus':
 						routerInfo = {
@@ -149,22 +172,26 @@
 					default:
 						break;
 				}
-				this.changeSchool(body.schoolcode,routerInfo)
+				this.changeSchool(body.schoolcode, routerInfo)
 				this.msgArr.splice(index, 1)
-				localStorage.setItem('msgs',JSON.stringify(this.msgArr))
+				// localStorage.setItem('msgs',JSON.stringify(this.msgArr))
+				this.delMsgs(msg.from, [msg.indexNum])
 			},
 			/* 点击通知判断是否切换学校 */
-			changeSchool(schoolCode,routerInfo) {
-				return new Promise((r,j) => {
-					if(!routerInfo) return
+			changeSchool(schoolCode, routerInfo) {
+				return new Promise((r, j) => {
+					if (!routerInfo) return
 					// 如果是同一学校则不做处理
-					if (schoolCode === this.$store.state.userInfo.schoolCode || !schoolCode || routerInfo.name === 'settings') {
+					if (schoolCode === this.$store.state.userInfo.schoolCode || !schoolCode || routerInfo.name ===
+						'settings') {
 						this.$router.push(routerInfo)
 						return
 					}
 					// 需要切换学校
-					let user = this.$store.state.user.userProfile || JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"));
-					let joinSchools = user.schools && user.schools.length ? user.schools.filter(i => i.status === 'join') : null
+					let user = this.$store.state.user.userProfile || JSON.parse(decodeURIComponent(localStorage
+						.user_profile, "utf-8"));
+					let joinSchools = user.schools && user.schools.length ? user.schools.filter(i => i.status ===
+						'join') : null
 					if (joinSchools && joinSchools.length) {
 						joinSchools.forEach(i => {
 							if (!i.area) {
@@ -174,7 +201,7 @@
 							}
 						})
 						let areaName = joinSchools.find(i => i.schoolId === schoolCode).area.name
-						if(areaName !== sessionStorage.getItem('areaName')){
+						if (areaName !== sessionStorage.getItem('areaName')) {
 							this.$Modal.confirm({
 								title: this.$t('settings.modalTip4'),
 								content: this.$t('settings.modalTip9'),
@@ -182,7 +209,7 @@
 									this.$EventBus.$emit('resetAreaIndex', {
 										areaName: areaName,
 										schoolCode: schoolCode,
-										routerInfo:routerInfo
+										routerInfo: routerInfo
 									})
 									r(200)
 								},
@@ -190,27 +217,42 @@
 									r(500)
 								}
 							})
-						}else{
+						} else {
 							this.$EventBus.$emit('resetAreaIndex', {
 								areaName: areaName,
 								schoolCode: schoolCode,
-								routerInfo:routerInfo
+								routerInfo: routerInfo
 							})
 							r(200)
 						}
-					}else{
+					} else {
 						r(500)
 					}
 				})
+			},
+			/* API删除通知 */
+			async delMsgs(from, idArr) {
+				try {
+					let srvAdr = this.$store.state.config.srvAdr
+					let host = srvAdr == 'Global' ? this.$store.state.config.Global.coreAPIUrl : this.$store.state.config.China.coreAPIUrl
+					await this.$api.service.delNotification(host,{
+						"from": from,
+						"receiver": this.$store.state.userInfo.TEAMModelId,
+						"indexNums": idArr
+					})
+				} catch (e) {
+					this.$Message.error('remove fail')
+				}
+
 			}
 		},
 		watch: {
 			msgs: {
 				handler(n, o) {
 					let localMsgs = JSON.parse(localStorage.getItem('msgs'))
-					if(!localMsgs || !localMsgs.length){
+					if (!localMsgs || !localMsgs.length) {
 						this.msgArr = []
-					}else{
+					} else {
 						// 只查询当前站点的消息通知
 						let curLocation = localStorage.getItem('location')
 						this.msgArr = localMsgs.filter(i => {

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

@@ -425,7 +425,7 @@
                     file: []
                 }
                 for (let item of data) {
-                    if (item.type == 'normal' || item.type === 'video') {
+                    if (item.type === 'normal' || item.type === 'video') {
                         source.normal.push(item)
                     } else if (item.blobUrl) {
                         let code = item.blobUrl.split('/')

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

@@ -398,6 +398,7 @@ import { mapGetters, mapState } from 'vuex';
                             .scrollHeight,
                         behavior: "smooth",
                     });
+                    this.sentSelectedEventTitle(this.eventShow[0])
                 } else this.isListNoItem = true; //清單空值樣式配置
             },
             // 下拉数据筛选

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

@@ -1,4 +1,5 @@
 export default {
+	noFilePaste:'Pasting files is not supported',
 	saving:'The exam file is being saved...',
 	choosePageItems:'Select all questions in this page',
 	completeTip:'Please complete the subject, grade and semester data for the current school system first!',

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

@@ -1,4 +1,5 @@
 export default {
+	noFilePaste:'暂不支持粘贴文件',
 	saving:'试卷保存中...',
 	choosePageItems:'选择本页所有题目',
 	completeTip:'请先完善当前学段的科目、年级及学期数据!',

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

@@ -1,4 +1,5 @@
 export default {
+	noFilePaste:'暫不支持粘貼文件',
 	saving:'試卷保存中...',
 	choosePageItems:'選擇本頁所有題目',
 	completeTip:'請先完善當前學段的科目、年級及學期數據!',

+ 4 - 1
TEAMModelOS/ClientApp/src/utils/editorTools.js

@@ -79,6 +79,9 @@ export default {
 	},
 	/* 粘贴事件监听 */
 	pasteEvent(e, editor) {
+		if(e.target.nodeName === 'INPUT'){
+			return
+		}
 		let that = this
 		e.stopPropagation()
 		let pasteItems = e.clipboardData.items
@@ -86,7 +89,7 @@ export default {
 			let item = pasteItems[i];
 			/* 如果监听到粘贴的是file类型 */
 			if (item.kind === "file" && pasteItems.length === 1 && !item.type.includes('image/')) {
-				Message.warning('暂不支持粘贴文件!')
+				Message.warning(app.$t('evaluation.noFilePaste'))
 			} else if (item.kind === "string" && pasteItems.length === 1) {
 				/* 如果监听到粘贴的是单纯文本 */
 				item.getAsString(str => {

+ 7 - 8
TEAMModelOS/ClientApp/src/view/Home.vue

@@ -150,12 +150,7 @@ export default {
                     i.body = JSON.parse(this.getBodyJson(i.body))
                 })
             }
-            let localMsgs = JSON.parse(localStorage.getItem('msgs'))
-            if (localMsgs) {
-                localStorage.setItem('msgs', JSON.stringify([...this.msgs, ...localMsgs]))
-            } else {
-                localStorage.setItem('msgs', JSON.stringify(this.msgs))
-            }
+			localStorage.setItem('msgs', JSON.stringify(this.msgs))
             console.log('端外通知', this.msgs)
         },
         getBodyJson(str) {
@@ -167,7 +162,9 @@ export default {
         getSchoolNotice(user_profile, userId) {
             return new Promise((r, j) => {
                 if (this.hasSchool) {
-                    this.$api.service.getNotification({
+					let srvAdr = this.$store.state.config.srvAdr
+					let host = srvAdr == 'Global' ? this.$store.state.config.Global.coreAPIUrl : this.$store.state.config.China.coreAPIUrl
+                    this.$api.service.getNotification(host,{
                         "from": "ies5:" + this.location + ':' + (user_profile.defaultschool || user_profile.schools[0].schoolId),
                         "receiver": userId
                     }).then(res => {
@@ -180,7 +177,9 @@ export default {
         },
         getPrivateNotice(userId) {
             return new Promise((r, j) => {
-                this.$api.service.getNotification({
+				let srvAdr = this.$store.state.config.srvAdr
+				let host = srvAdr == 'Global' ? this.$store.state.config.Global.coreAPIUrl : this.$store.state.config.China.coreAPIUrl
+                this.$api.service.getNotification(host,{
                     "from": "ies5:" + this.location + ":private",
                     "receiver": userId
                 }).then(res => {

+ 6 - 2
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaBase.vue

@@ -100,7 +100,9 @@ export default {
         getSchoolNotice(user_profile, userId) {
             return new Promise((r, j) => {
                 if (this.hasSchool) {
-                    this.$api.service.getNotification({
+					let srvAdr = this.$store.state.config.srvAdr
+					let host = srvAdr == 'Global' ? this.$store.state.config.Global.coreAPIUrl : this.$store.state.config.China.coreAPIUrl
+                    this.$api.service.getNotification(host,{
                         "from": "ies5:" + (user_profile.defaultschool || user_profile.schools[0].schoolId),
                         "receiver": userId
                     }).then(res => {
@@ -113,7 +115,9 @@ export default {
         },
         getPrivateNotice(userId) {
             return new Promise((r, j) => {
-                this.$api.service.getNotification({
+				let srvAdr = this.$store.state.config.srvAdr
+				let host = srvAdr == 'Global' ? this.$store.state.config.Global.coreAPIUrl : this.$store.state.config.China.coreAPIUrl
+                this.$api.service.getNotification(host,{
                     "from": "ies5:private",
                     "receiver": userId
                 }).then(res => {

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

@@ -93,7 +93,7 @@
 									style="font-weight: bold;color: #0086E6;">{{ item.score }}</span>
 								{{$t('evaluation.paperList.score')}}</span>
 						</template>
-						<Icon @click.stop="onQuestionToggle(exerciseList.indexOf(item),item.id,$event,typeItem.list)" :type="collapseList.indexOf(index) > -1 ? 'ios-arrow-dropup' : 'ios-arrow-dropdown'"
+						<Icon @click.stop="onQuestionToggle(exerciseList.indexOf(item),item.id,$event,typeItem.list)" :type="collapseList.indexOf(exerciseList.indexOf(item)) > -1 ? 'ios-arrow-dropup' : 'ios-arrow-dropdown'"
 							v-if="item.type !== 'compose'" />
 					</div>
 

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

@@ -271,6 +271,7 @@
 				let { list,fileName } = importRes
 				if(fileName){
 					this.evaluationInfo.name = fileName
+					sessionStorage.setItem('paper_name',this.evaluationInfo.name)
 				}
 				this.errorList = []
 				this.$refs.testPaper.$refs.exList.errorList = []

+ 1 - 0
TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.less

@@ -182,6 +182,7 @@
 					}
 
 					.status-coedit{
+						min-width: 54px;
 						background-color: var(--assist-color-light);
 					}
 					

+ 3 - 3
TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.vue

@@ -231,7 +231,7 @@
 								:placeholder="$t('syllabus.place3')"></Input>
 						</FormItem>
 						<FormItem :label="$t('syllabus.authors')" v-if="isSchool">
-							<Select v-model="addVolumeForm.auth" multiple filterable>
+							<Select v-model="addVolumeForm.auth" multiple filterable :max-tag-count="10">
 								<Option v-for="(item,index) in teacherList" :value="item.id" :label="item.name" :key="index">
 									<span style="margin-right: 10px;">{{item.name}}</span>
 									<span class="tch-group-tag" v-for="(group,groupIndex) in item.groups" :key="groupIndex">{{ group.name }}</span>
@@ -2583,7 +2583,7 @@
 		}
 
 		.ivu-input {
-			height: 35px;
+			min-height: 35px;
 			color: var(--primary-text-color);
 
 			&::-webkit-input-placeholder {
@@ -2593,7 +2593,7 @@
 
 		.ivu-select-selection {
 			color: var(--primary-text-color);
-			height: 35px;
+			min-height: 35px;
 		}
 
 		.ivu-select-arrow {

+ 196 - 171
TEAMModelOS/ClientApp/src/view/train/PhoneSign.vue

@@ -1,14 +1,16 @@
 <template>
-    <div class="join-wrap">
-        <div class="join-main-box" v-show="!isSign && isOpen">
-            <p class="join-title">
-                <span>
-                    {{$t('train.detail.qrCodeText')}}
-                </span>
-            </p>
-            <p class="course-name">{{topic || $t('cusMgt.join.errorInfo')}}</p>
-            <div style="width:fit-content;margin: auto;">
-                <!-- <p class="info-item">
+	<div class="join-wrap">
+		<div class="join-main-box" v-show="!isSign && isOpen">
+			<p class="join-title">
+				<span>
+					{{$t('train.detail.qrCodeText')}}
+				</span>
+			</p>
+			<p class="course-name">{{topic || $t('cusMgt.join.errorInfo')}}</p>
+			<Input v-model="phoneNum" prefix="ios-phone-portrait" type="tel" placeholder="输入手机号"
+				style="width: 300px;margin-top: 20px;height: 40px;" />
+			<div style="width:fit-content;margin: auto;">
+				<!-- <p class="info-item">
                     <span class="info-lable">
                         {{$t('train.detail.presenter')}}
                     </span>
@@ -16,7 +18,7 @@
                         {{presenter}}
                     </span>
                 </p> -->
-                <!-- <p class="info-item">
+				<!-- <p class="info-item">
                     <span class="info-lable">
                         {{$t('train.detail.address')}}
                     </span>
@@ -32,168 +34,191 @@
                         {{time}}
                     </span>
                 </p> -->
-            </div>
-            <div class="join-btn" @click="signIn()">
-                {{$t('train.detail.signNow')}}
-            </div>
-        </div>
-        <div v-show="isSign" class="join-main-box">
-            <p class="join-title">
-                <span>
-                    {{$t('train.detail.qrCodeText')}}
-                </span>
-            </p>
-            <Icon type="md-checkmark-circle-outline" color="#19be6b" size="120" />
-            <p class="success-tips" style="font-size:24px;color:#19be6b">{{$t('train.detail.signOk')}}</p>
-        </div>
-        <div v-show="!isOpen" class="join-main-box">
-            <p class="join-title">
-                <span>
-                    {{$t('train.detail.qrCodeText')}}
-                </span>
-            </p>
-            <Icon type="md-close-circle" color="#ed4014" size="120" />
-            <p class="success-tips" style="font-size:24px;color:#ed4014">{{$t('train.detail.unStart')}}</p>
-        </div>
-    </div>
+			</div>
+			<div class="join-btn" @click="signIn()">
+				{{$t('train.detail.signNow')}}
+			</div>
+		</div>
+		<div v-show="isSign" class="join-main-box">
+			<p class="join-title">
+				<span>
+					{{$t('train.detail.qrCodeText')}}
+				</span>
+			</p>
+			<Icon type="md-checkmark-circle-outline" color="#19be6b" size="120" />
+			<p class="success-tips" style="font-size:24px;color:#19be6b">{{$t('train.detail.signOk')}}</p>
+		</div>
+		<div v-show="!isOpen" class="join-main-box">
+			<p class="join-title">
+				<span>
+					{{$t('train.detail.qrCodeText')}}
+				</span>
+			</p>
+			<Icon type="md-close-circle" color="#ed4014" size="120" />
+			<p class="success-tips" style="font-size:24px;color:#ed4014">{{$t('train.detail.unStart')}}</p>
+		</div>
+	</div>
 </template>
 <script>
-import jwtDecode from 'jwt-decode'
-export default {
-    data() {
-        return {
-            isOpen: false,
-            isSign: false,
-            id: '',
-            school: '',
-            presenter: '',
-            address: '',
-            time: '',
-            topic: '',
-            code: '',
-            userId: '',
-            p: {}
-        }
-    },
-    methods: {
-        signIn() {
-            let params = {
-                id: this.id,
-                code: this.school,
-                tId: this.userId
-            }
-            this.p = params
-            this.$api.train.signIn(params).then(
-                res => {
-                    this.$Message.success('签到成功')
-                    this.isSign = true
-                },
-                err => {
-                    this.$Message.error('签到失败')
-                }
-            )
-        }
-    },
-    created() {
-        this.id = this.$route.query.id //活动id
-        this.code = this.$route.query.code  //登录成功返回的code
-        this.school = this.$route.query.school
-        // this.presenter = this.$route.query.presenter
-        // this.address = this.$route.query.address
-        // this.time = this.$route.query.time
-        this.topic = this.$route.query.topic
-        this.isOpen = this.$route.query.isOpen == 'true'
+	import jwtDecode from 'jwt-decode'
+	export default {
+		data() {
+			return {
+				phoneNum: '',
+				isOpen: false,
+				isSign: false,
+				id: '',
+				school: '',
+				presenter: '',
+				address: '',
+				time: '',
+				topic: '',
+				code: '',
+				userId: '',
+				p: {}
+			}
+		},
+		methods: {
+			signIn() {
+				if (!this.phoneNum.trim() || !this.isTel(this.phoneNum)) {
+					this.$Message.warning('请输入正确手机号!')
+					return
+				}
+				let params = {
+					id: this.id,
+					code: this.school,
+					mobile: this.phoneNum
+				}
+				this.p = params
+				this.$api.train.signIn(params).then(
+					res => {
+						if(res.code === 404){
+							this.$Message.warning('未查询到对应账号!请检查后重试!')
+						}else{
+							this.$Message.success('签到成功')
+							this.isSign = true
+						}
+					},
+					err => {
+						this.$Message.error('签到失败')
+					}
+				)
+			},
+			isTel(tel) {
+				var re = /^1\d{10}$/
+				return re.test(tel)
+			}
+		},
+		created() {
+			this.id = this.$route.query.id //活动id
+			this.code = this.$route.query.code //登录成功返回的code
+			this.school = this.$route.query.school
+			// this.presenter = this.$route.query.presenter
+			// this.address = this.$route.query.address
+			// this.time = this.$route.query.time
+			this.topic = this.$route.query.topic
+			this.isOpen = this.$route.query.isOpen == 'true'
 
-        //获取登录信息
-        let srvAdr = this.$store.state.config.srvAdr
-        let host = srvAdr == 'Global' ? this.$store.state.config.Global.coreAPIUrl : this.$store.state.config.China.coreAPIUrl
-        let clientId = srvAdr == 'Global' ? this.$store.state.config.Gloabl.clientID : this.$store.state.config.China.clientID
-        this.$api.service.getToken(host, {
-            grant_type: "authorization_code",
-            client_id: clientId,
-            code: this.code
-        }).then(
-            res => {
-                if (!res.error) {
-                    let tokenData = jwtDecode(res.id_token)
-                    if (tokenData) {
-                        this.userId = tokenData.sub
-                        console.log(this.userId)
-                    } else {
-                        this.$Message.error(this.$t('cusMgt.join.parseErr'))
-                    }
-                } else {
-                    this.$Message.error(this.$t('cusMgt.join.getErr'))
-                }
-            },
-            err => {
-                this.$Message.error(this.$t('cusMgt.join.getErr'))
-            }
-        )
-    }
-}
+			//获取登录信息
+			let srvAdr = this.$store.state.config.srvAdr
+			let host = srvAdr == 'Global' ? this.$store.state.config.Global.coreAPIUrl : this.$store.state.config.China
+				.coreAPIUrl
+			let clientId = srvAdr == 'Global' ? this.$store.state.config.Gloabl.clientID : this.$store.state.config.China
+				.clientID
+			// this.$api.service.getToken(host, {
+			// 	grant_type: "authorization_code",
+			// 	client_id: clientId,
+			// 	code: this.code
+			// }).then(
+			// 	res => {
+			// 		if (!res.error) {
+			// 			let tokenData = jwtDecode(res.id_token)
+			// 			if (tokenData) {
+			// 				this.userId = tokenData.sub
+			// 				console.log(this.userId)
+			// 			} else {
+			// 				this.$Message.error(this.$t('cusMgt.join.parseErr'))
+			// 			}
+			// 		} else {
+			// 			this.$Message.error(this.$t('cusMgt.join.getErr'))
+			// 		}
+			// 	},
+			// 	err => {
+			// 		this.$Message.error(this.$t('cusMgt.join.getErr'))
+			// 	}
+			// )
+		}
+	}
 </script>
 <style scoped lang="less">
-.success-tips {
-    color: white;
-    font-size: 16px;
-    margin-top: 20px;
-}
-.join-wrap {
-    display: flex;
-    flex-direction: column;
-    justify-content: space-evenly;
-    align-items: center;
-    width: 100%;
-    height: 100%;
-    background-image: url("../../assets/image/bak_light.jpg");
-}
-.join-btn {
-    cursor: pointer;
-    width: 100%;
-    margin: auto;
-    margin-top: 60px;
-    text-align: center;
-    border: 1px solid rgba(25, 190, 107, 0.5);
-    // color: rgba(25, 190, 107, 1);
-    color: white;
-    padding: 4px 30px;
-    border-radius: 5px;
-    font-size: 16px;
-    letter-spacing: 2px;
-    font-weight: 400;
-    user-select: none;
-    background: rgba(25, 190, 107, 0.5);
-}
-.course-name {
-    color: white;
-    margin-bottom: 15px;
-    font-size: 30px;
-    // font-family: cursive;
-}
-.join-main-box {
-    max-width: 90%;
-    width: fit-content;
-    text-align: center;
-    .info-item {
-        margin-top: 20px;
-        font-size: 15px;
-        width: fit-content;
-    }
-    .info-lable {
-        color: #a5a5a5;
-    }
-    .info-value {
-        color: #eeeeee;
-    }
-}
-.join-title {
-    position: absolute;
-    top: 15px;
-    text-align: center;
-    width: 100%;
-    left: 0px;
-    border-bottom: 1px dashed;
-    padding-bottom: 8px;
-}
-</style>
+	.success-tips {
+		color: white;
+		font-size: 16px;
+		margin-top: 20px;
+	}
+
+	.join-wrap {
+		display: flex;
+		flex-direction: column;
+		justify-content: space-evenly;
+		align-items: center;
+		width: 100%;
+		height: 100%;
+		background-image: url("../../assets/image/bak_light.jpg");
+	}
+
+	.join-btn {
+		cursor: pointer;
+		width: 100%;
+		margin: auto;
+		margin-top: 60px;
+		text-align: center;
+		border: 1px solid rgba(25, 190, 107, 0.5);
+		// color: rgba(25, 190, 107, 1);
+		color: white;
+		padding: 4px 30px;
+		border-radius: 5px;
+		font-size: 16px;
+		letter-spacing: 2px;
+		font-weight: 400;
+		user-select: none;
+		background: rgba(25, 190, 107, 0.5);
+	}
+
+	.course-name {
+		color: white;
+		margin-bottom: 15px;
+		font-size: 30px;
+		// font-family: cursive;
+	}
+
+	.join-main-box {
+		max-width: 90%;
+		width: fit-content;
+		text-align: center;
+
+		.info-item {
+			margin-top: 20px;
+			font-size: 15px;
+			width: fit-content;
+		}
+
+		.info-lable {
+			color: #a5a5a5;
+		}
+
+		.info-value {
+			color: #eeeeee;
+		}
+	}
+
+	.join-title {
+		position: absolute;
+		top: 15px;
+		text-align: center;
+		width: 100%;
+		left: 0px;
+		border-bottom: 1px dashed;
+		padding-bottom: 8px;
+	}
+</style>

+ 5 - 4
TEAMModelOS/ClientApp/src/view/train/TrainDetail.vue

@@ -1340,11 +1340,12 @@ export default {
             else {
                 clientId = this.$store.state.config.China.clientID
             }
-            url = encodeURIComponent(url)
+            // url = encodeURIComponent(url)
             // let accUrl = process.env.NODE_ENV == 'development' ? 'https://account-rc.teammodel.cn' : 'https://account.teammodel.cn'
-            let accUrl = 'https://account.teammodel.cn'
-            let loginUrl = `${accUrl}?response_type=code&client_id=${clientId}&state=${state}&nonce=${nonce}&redirect_uri=${url}`
-            return loginUrl
+            // let accUrl = 'https://account.teammodel.cn'
+            // let loginUrl = `${accUrl}?response_type=code&client_id=${clientId}&state=${state}&nonce=${nonce}&redirect_uri=${url}`
+			window.open(url)
+            return url
         },
         fullQRcode() {
             this.$nextTick(() => {

+ 28 - 8
TEAMModelOS/Controllers/Common/StudyController.cs

@@ -16,6 +16,7 @@ using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Service;
 
 namespace TEAMModelOS.Controllers.Common
 {
@@ -34,9 +35,11 @@ namespace TEAMModelOS.Controllers.Common
         private readonly AzureStorageFactory _azureStorage;
         private readonly AzureRedisFactory _azureRedis;
         public IConfiguration _configuration { get; set; }
-        public StudyController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        public StudyController(CoreAPIHttpService  coreAPIHttpService,AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
            IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, IConfiguration configuration)
         {
+            _coreAPIHttpService = coreAPIHttpService;
             _azureCosmos = azureCosmos;
             _serviceBus = serviceBus;
             _snowflakeId = snowflakeId;
@@ -130,8 +133,8 @@ namespace TEAMModelOS.Controllers.Common
         /// <param name="request"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
-        [Authorize(Roles = "IES")]
-        [AuthToken(Roles = "teacher,admin")]
+        //[Authorize(Roles = "IES")]
+        //[AuthToken(Roles = "teacher,admin")]
         [HttpPost("sign-in")]
         public async Task<IActionResult> Sign(JsonElement request)
         {
@@ -140,10 +143,28 @@ namespace TEAMModelOS.Controllers.Common
             {
                 if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
                 if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
-                if (!request.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
+                request.TryGetProperty("tId", out JsonElement tId);
+                request.TryGetProperty("mobile", out JsonElement mobile);
+                string tmdid = "";
+                if (!string.IsNullOrWhiteSpace($"{mobile}"))
+                {
+                    var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{mobile}" } }, _option.Location, _configuration);
+                    if (coreUser != null)
+                    {
+                        tmdid = coreUser.id;
+                    }
+                }
+                else {
+                    if (!string.IsNullOrWhiteSpace($"{tId}") && string.IsNullOrWhiteSpace(tmdid) ) {
+                        tmdid = $"{tId}";
+                    }
+                }
+                if (string.IsNullOrWhiteSpace(tmdid)) {
+                    return Ok(new { code = HttpStatusCode.NotFound ,msg="账号不存在!"});
+                }
                 var client = _azureCosmos.GetCosmosClient();
                 long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-                var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(id.ToString(), new PartitionKey($"StudyRecord-{tId}"));
+                var response = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(id.ToString(), new PartitionKey($"StudyRecord-{tmdid}"));
                 var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Study-{code}"));
                 if (sresponse.Status == (int)HttpStatusCode.OK)
                 {
@@ -159,12 +180,11 @@ namespace TEAMModelOS.Controllers.Common
                     }
                     else
                     {
-
                         StudyRecord setting = new();
                         setting.id = id.GetString();
-                        setting.tId = tId.GetString();
+                        setting.tId = tmdid;
                         setting.signTime = now;
-                        setting.code = "StudyRecord-" + tId.GetString();
+                        setting.code = "StudyRecord-" + tmdid;
                         setting.sign = study.startTime < now ? "2" : "1";
                         await client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(setting, new PartitionKey($"{setting.code}"));
                     }

+ 2 - 1
TEAMModelOS/Controllers/XTest/TestController.cs

@@ -652,8 +652,9 @@ namespace TEAMModelOS.Controllers
         [HttpPost("get-ip")]
         public async Task<IActionResult> GetIp(JsonElement request)
         {
+            var token = await CoreTokenExtensions.CreateAccessToken("c7317f88-7cea-4e48-ac57-a16071f7b884", "kguxh:V.PLmxBdaI@jnrTrDSth]A3346", "China");
             string ip = await _searcher.SearchIpAsync($"{request.GetProperty("ip")}");
-            return Ok(ip);
+            return Ok(new { ip, token.AccessToken,token.TokenType,token.IdToken });
         }
     }
 

+ 3 - 3
TEAMModelOS/TEAMModelOS.csproj

@@ -31,9 +31,9 @@
     <SpaRoot>ClientApp\</SpaRoot>
     <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
     <UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-    <Version>5.2202.18</Version>
-    <AssemblyVersion>5.2202.18.1</AssemblyVersion>
-    <FileVersion>5.2202.18.1</FileVersion>
+    <Version>5.2202.21</Version>
+    <AssemblyVersion>5.2202.21.1</AssemblyVersion>
+    <FileVersion>5.2202.21.1</FileVersion>
     <Description>TEAMModelOS(IES5)版本更新。</Description>
     <PackageReleaseNotes>6.0版本说明</PackageReleaseNotes>
   </PropertyGroup>