htc 2 dienas atpakaļ
vecāks
revīzija
503876d1d7

+ 1 - 0
components/CusTabbar/index.vue

@@ -44,6 +44,7 @@
 		methods: {
 			changeTabbar(e) {
 				this.tabbarValue = e;
+				if(e===1&&!this.isLogin()) return
 				uni.reLaunch({
 					url: this.list[e].path
 				})

+ 9 - 9
components/CusTeamInfo/index.vue

@@ -6,40 +6,40 @@
 			<view class="dialog-box-form">
 				<view class="dialog-box-form-item adfacjb">
 					<view class="dialog-box-form-item-left">团队名称</view>
-					<view class="dialog-box-form-item-right">{{teamInfo.aaa||'暂无'}}</view>
+					<view class="dialog-box-form-item-right">{{teamInfo.teamName||'暂无'}}</view>
 				</view>
 				<view class="dialog-box-form-item adfacjb">
 					<view class="dialog-box-form-item-left">所在公司</view>
-					<view class="dialog-box-form-item-right">{{teamInfo.bbb||'暂无'}}</view>
+					<view class="dialog-box-form-item-right">{{teamInfo.enterpriseName||'暂无'}}</view>
 				</view>
 				<view class="dialog-box-form-item adfacjb">
 					<view class="dialog-box-form-item-left">所属地区</view>
-					<view class="dialog-box-form-item-right">{{teamInfo.ccc||'暂无'}}</view>
+					<view class="dialog-box-form-item-right">{{teamInfo.address||'暂无'}}</view>
 				</view>
 				<view class="dialog-box-form-item adfacjb">
 					<view class="dialog-box-form-item-left">所属行业</view>
-					<view class="dialog-box-form-item-right">{{teamInfo.ddd||'暂无'}}</view>
+					<view class="dialog-box-form-item-right">{{teamInfo.industryName||'暂无'}}</view>
 				</view>
 				<view class="dialog-box-form-item adfacjb">
 					<view class="dialog-box-form-item-left">团队职能类型</view>
-					<view class="dialog-box-form-item-right">{{teamInfo.eee||'暂无'}}</view>
+					<view class="dialog-box-form-item-right">{{teamInfo.functionsName||'暂无'}}</view>
 				</view>
 				<view class="dialog-box-form-item adfacjb">
 					<view class="dialog-box-form-item-left">团队架构类型</view>
-					<view class="dialog-box-form-item-right">{{teamInfo.fff||'暂无'}}</view>
+					<view class="dialog-box-form-item-right">{{teamInfo.organizationsName||'暂无'}}</view>
 				</view>
 				<view class="dialog-box-form-item adfacjb">
 					<view class="dialog-box-form-item-left">团队规模</view>
-					<view class="dialog-box-form-item-right">{{teamInfo.ggg||'暂无'}}</view>
+					<view class="dialog-box-form-item-right">{{teamInfo.scaleName||'暂无'}}</view>
 				</view>
 				<view class="dialog-box-form-item adfacjb">
 					<view class="dialog-box-form-item-left">团队层级</view>
-					<view class="dialog-box-form-item-right">{{teamInfo.hhh||'暂无'}}</view>
+					<view class="dialog-box-form-item-right">{{teamInfo.hierarchyName||'暂无'}}</view>
 				</view>
 			</view>
 			<view class="dialog-box-intro">
 				<view class="dialog-box-intro-title">团队简介</view>
-				<view class="dialog-box-intro-content">{{teamInfo.iii||'暂无'}}</view>
+				<view class="dialog-box-intro-content">{{teamInfo.brief||'暂无'}}</view>
 			</view>
 		</view>
 	</view>

+ 1 - 0
components/QuestionItem/index3.vue

@@ -65,6 +65,7 @@
 
 <style scoped lang="less">
 	.li_box{
+		margin-top: 20rpx;
 		.lb_title{
 			font-family: PingFang-SC, PingFang-SC;
 			font-weight: bold;

+ 1 - 1
pages/home.vue

@@ -153,7 +153,7 @@
 		methods:{
 			toTurn(url){
 				if(!url) return 
-				// if(url!=='/pages/dialog'&&!this.isLogin()) return
+				if(url!=='/pages/dialog'&&!this.isLogin()) return
 				uni.navigateTo({
 					url
 				})

+ 10 - 6
pages/publish.vue

@@ -35,9 +35,9 @@
 		components:{ Tabbar, Notice },
 		data(){
 			return {
-				questionnaireId:'',
 				list:[],
 				type:1,
+				questionnaireId:'',
 				typeDict:{
 					1:'基础版',
 					2:'专业版',
@@ -64,11 +64,15 @@
 				})
 			},
 			handleTurnPage(item){
-				if(item.type==3) return this.$showToast('敬请期待专家版~')
-				this.questionnaireId = item.id;
 				this.type = item.type;
-				// this.buyShow = true;
-				this.noticeShow = true;
+				if(item.type==3) return this.$showToast('敬请期待专家版~')
+				this.$api.get(`/que/order/getUseFrequency/${JSON.parse(uni.getStorageSync('userInfo')).id}/${item.type}`).then(({data:res})=>{
+					if(res.code!==0) return this.$showToast(res.msg)
+					if(res.data>0){
+						this.questionnaireId = item.id;
+						this.noticeShow = true;
+					}else this.buyShow = true;
+				})
 			},
 			handleBuy(){
 				uni.navigateTo({
@@ -78,7 +82,7 @@
 			handleKnow(){
 				this.noticeShow = false;
 				uni.navigateTo({
-					url:'/pagesPublish/fillTeamInfo?questionnaireId='+this.questionnaireId
+					url:'/pagesPublish/fillTeamInfo?type='+this.type+'&questionnaireId='+this.questionnaireId+'&next=true'
 				})
 			}
 		}

+ 2 - 1
pages/registerInfo.vue

@@ -68,7 +68,8 @@
 					uni.setStorageSync('userInfo',JSON.stringify({
 						id:this.user.id,
 						gender:this.user.gender,
-						realName:this.user.realName,
+						realName:this.dto.realName,
+						email:this.dto.email,
 						mobile:this.user.mobile,
 						headUrl:this.user.headUrl,
 						teamId:this.user.teamId,

+ 1 - 1
pagesHome/components/createList.vue

@@ -233,7 +233,7 @@
 			},
 			handleAnswer(item){
 				uni.navigateTo({
-					url:'/pagesPublish/questionnaireFill?questionnaireId='+item.questionnaireId
+					url:'/pagesPublish/questionnaireFill?teamQuestionnaireId='+item.teamQuestionnaireId+'&teamId='+item.teamId+'&type='+item.type
 				})
 			},
 			createReport(item){

+ 1 - 1
pagesHome/components/receiveList.vue

@@ -311,7 +311,7 @@ The following statements in the assessment describe the ideal state of a team. P
 						font-family: PingFangSC, PingFang SC;
 						font-weight: 400;
 						font-size: 24rpx;
-						color: #FFFFFF;
+						color: #193D59;
 						line-height: 24rpx;
 						margin-left: 12rpx;
 					}

+ 8 - 5
pagesPublish/fillTeamInfo.vue

@@ -12,18 +12,21 @@
 		data(){
 			return {
 				type:'',
+				next:'',
 				questionnaireId:'',
 				confirmText:'下一步'
 			}
 		},
 		onLoad(options) {
-			this.type = options.type||''
-			this.questionnaireId = options.questionnaireId||''
-			this.confirmText = options.type?'确定':'下一步'
+			this.type = options.type;
+			this.questionnaireId = options.questionnaireId||'';
+			this.confirmText = options.type?'确定':'下一步';
+			this.next = options.next;
+			if(this.next) this.confirmText = '下一步';
 		},
 		methods:{
 			handleConfirm(team){
-				if(!this.type){
+				if(this.next){
 					team.questionnaireId = this.questionnaireId;
 					team.coachId = JSON.parse(uni.getStorageSync('userInfo')).id;
 					this.$api.post('/core/user/team',team).then(({data:res})=>{
@@ -32,7 +35,7 @@
 						setTimeout(()=>{
 							uni.removeStorageSync('newUser')
 							uni.navigateTo({
-								url:'/pagesPublish/questionnaireFill?questionnaireId='+this.questionnaireId
+								url:'/pagesPublish/questionnaireFill?teamQuestionnaireId='+res.data.teamQueId+'&teamId='+res.data.teamId+'&type='+this.type
 							})	
 						},1500)
 					})			

+ 267 - 59
pagesPublish/questionnaireFill.vue

@@ -6,25 +6,42 @@
 			<view class="top-progress adfac">
 				<view class="top-progress-text">测评进度</view>
 				<view class="top-progress-box">
-					<view class="top-progress-box-current" :style="{'width':(2/36*100)+'%'}"></view>
+					<view class="top-progress-box-current" :style="{'width':(answerNum/list.length*100)+'%'}"></view>
 				</view>
-				<view class="top-progress-num"><span>{{2}}</span>/{{36}}</view>
+				<view class="top-progress-num"><span>{{answerNum}}</span>/{{list.length}}</view>
 			</view>
 		</view>
 		<view class="memo adfac" v-if="type==='questionnaire'" @click="noticeShow=true">
 			<text>问卷答题说明</text>
 			<image :src="imgBase+'icon_memo.png'"></image>
 		</view>
-		<view class="list">
-			<question-item v-for="(item,index) in list" :key="index" :item="item"></question-item>
-		</view>
+		<scroll-view class="list" scroll-y="true" :scroll-top="scrollTop" :style="{ height: h - 203 - mt + 'px' }">
+			<div v-if="isLoading" class="loading-container adfacjc">
+				<div class="adfac">
+					<u-loading-icon size="42"></u-loading-icon>
+					<text style="margin-left: 10rpx; font-size: 34rpx; color: #666666">问卷加载中...</text>
+				</div>
+			</div>
+			<template v-else>
+				<view>
+					<div class="l_item" v-for="(item, index) in list" :key="item.id" :id="'question-' + index">
+						<question-item :item="item" :index="index" @change="handleAnswerChange"></question-item>
+					</div>
+				</view>
+			</template>
+		</scroll-view>
+		<!-- <view class="list">
+			<div class="l_item" v-for="(item, index) in list" :key="item.id" :id="'question-' + index">
+				<question-item :item="item" :index="index" @change="handleAnswerChange"></<question-item>
+			</div>
+		</view> -->
 		<view class="bottom adfacjb">
-			<view class="bottom-left adffcac" @click="teamShow=true" v-if="!type">
+			<view class="bottom-left adffcac" @click="showTeamInfo" v-if="type==1">
 				<image :src="imgBase+'questionnaire_info.png'"></image>
 				<text>团队信息</text>
 			</view>
 			<view class="bottom-left adfac" v-else-if="type==='questionnaire'">
-				<view class="bottom-left-pre adffcac" @click="teamShow=true">
+				<view class="bottom-left-pre adffcac" @click="showTeamInfo">
 					<image :src="imgBase+'questionnaire_info.png'"></image>
 					<text>团队信息</text>
 				</view>
@@ -57,68 +74,257 @@
 				noticeContent:`问卷答题说明<br/><br/>问卷答题说明<br/><br/>问卷答题说明<br/><br/>问卷答题说明`,
 				teamShow:false,
 				userShow:false,
-				teamUserList:[],
-				list:[
-					{
-						question:'我们的团队成员可以清晰阐述团队的共享目的 We can collectively and clearly articulate our shared purpose',
-						userAnswer:[
-							{
-								assessmentMethod:1,
-								answer:'',
-								questionOption:[
-									{ questionOption:'1-强烈不同意(Strongly disagree)' },
-									{ questionOption:'2-不同意(Disagree)' },
-									{ questionOption:'3-中立(Neutral)' },
-									{ questionOption:'4-同意(Agree)' },
-									{ questionOption:'5-完全同意(Totally agree)' }
-								]
-							},
-							{
-								assessmentMethod:2,
-								answer:'',
-								questionOption:[
-									{ questionOption:'1-强烈不同意(Strongly disagree)' },
-									{ questionOption:'2-不同意(Disagree)' },
-									{ questionOption:'3-中立(Neutral)' },
-									{ questionOption:'4-同意(Agree)' },
-									{ questionOption:'5-完全同意(Totally agree)' }
-								]
-							},
-						]
-					}
-				],
-				teamInfo:{
-					aaa:'',
-					bbb:'',
-					ccc:'',
-					ddd:'',
-					eee:'',
-					fff:'',
-					ggg:'',
-					hhh:'',
-					iii:'',
-				}
+				teamUserList:[],
+				teamQuestionnaireId: '',
+				list: [],
+				questionnaire: null,
+				isLoading: true,
+				isSubmitting: false,
+				scrollTop: 0, // scroll-view 的滚动位置
+				oldScrollTop: 0, // 辅助值,确保即使滚动到相同位置也能触发
+				userAnswerTemp: [],
+				teamId:'',
+				teamInfo:{},
+				teamScaleData:[],
+				teamLevelData:[],
 			}
 		},
 		onLoad(options) {
-			this.type = options.type;
-			this.questionnaireId = options.questionnaireId;
+			this.type = options.type;
+			this.teamQuestionnaireId = options.teamQuestionnaireId;
+			this.teamId = options.teamId;
+			this.getList();
+		},
+		computed: {
+			answerNum() {
+				return this.list.filter(l => l?.answer.filter(a => a?.value).length == this.userAnswerTemp.length).length || 0;
+			}
 		},
-		methods:{
-			confirmSubmit(){
-				let url = '/pagesPublish/questionnaireResult'
-				if(this.type === 'questionnaire') url = '/pagesPublish/submitResult'
-				uni.navigateTo({ url })
+		methods:{
+			handleAnswerChange(e) {
+				const item = this.list[e.index];
+				if (item) {
+					let answer = JSON.parse(JSON.stringify(item.answer));
+					answer.forEach(a=>{
+						a.value = a.assessmentMethod==e.assessmentMethod?e.value:a.value
+					})
+					this.$set(item, 'answer', answer);
+					if (item.warn) {
+						this.$set(item, 'warn', false);
+					}
+				}
+				this.setQuestionnaireCache();
+			},
+			getList() {
+				let questionnaire = null;
+				try {
+					const cacheStr = uni.getStorageSync('questionnaire');
+					if (cacheStr) {
+						questionnaire = JSON.parse(cacheStr);
+					}
+				} catch (e) {
+					console.error('解析问卷缓存失败:', e);
+					uni.removeStorageSync('questionnaire');
+				}
+			
+				this.isLoading = true;
+				this.$api
+					.get('/core/team/member/answer/listByUser/' + this.teamQuestionnaireId)
+					.then((res) => {
+						if (res.data.code !== 0) return this.$showToast(res.data.msg);
+						const answerMap = new Map();
+						if (questionnaire && this.teamQuestionnaireId == questionnaire.key) {
+							questionnaire.list.forEach((q) => answerMap.set(q.id, q.answer));
+						}
+						
+						this.userAnswerTemp = res.data.data[0].userAnswer.map(u=>{
+							return {
+								assessmentMethod:u.assessmentMethod,
+								value:''
+							}
+						}) 
+						let uaTemp = JSON.parse(JSON.stringify(this.userAnswerTemp))
+						this.list = res.data.data.map(item => {
+							let _a = answerMap.get(item.id);
+							return {
+								...item,
+								answer:_a?uaTemp.map(u=>{
+									return {
+										assessmentMethod:u.assessmentMethod,
+										value:_a.find(a=>a.assessmentMethod==u.assessmentMethod)?.value||''
+									}
+								}):this.userAnswerTemp,
+								warn: false
+							}
+						});
+						this.list.forEach(l=>{
+							let _a = answerMap.get(l.id);
+							l.userAnswer.forEach(u=>{
+								u.answer = _a?(_a.find(a=>a.assessmentMethod==u.assessmentMethod)?.value||''):''
+							})
+						})
+					})
+					.catch(() => {
+						this.isLoading = false;
+						this.$showToast('网络异常,请稍后重试');
+					})
+					.finally(() => {
+						this.isLoading = false;
+					});
+			},
+			scrollToQuestion(index) {
+				const query = uni.createSelectorQuery().in(this);
+				const targetId = `#question-${index}`;
+				query.select(targetId).boundingClientRect();
+				query.select('.list').scrollOffset(); // 获取 scroll-view 的滚动信息
+				query.select('.list').boundingClientRect(); // 获取 scroll-view 自身的位置信息
+				query.exec((res) => {
+					// 增加安全校验
+					if (!res || !res[0] || !res[1] || !res[2]) {
+						return;
+					}
+			
+					// res[0]: 目标元素 (#question-N) 的位置信息
+					const itemRect = res[0];
+					// res[1]: 滚动容器 (.list) 的滚动信息
+					const scrollViewScroll = res[1];
+					// res[2]: 滚动容器 (.list) 自身的位置信息
+					const scrollViewRect = res[2];
+			
+					// 计算目标滚动位置 = 当前滚动距离 + (目标元素顶部 - 滚动容器顶部) - 预留间距
+					const targetPosition = scrollViewScroll.scrollTop + itemRect.top - scrollViewRect.top - 10; // 减10px作为顶部留白
+			
+					// 通过先设置为旧值,再在 nextTick 中设置为新值的方式,确保滚动能够触发
+					this.scrollTop = this.oldScrollTop;
+					this.$nextTick(() => {
+						this.scrollTop = targetPosition;
+						this.oldScrollTop = targetPosition;
+					});
+				});
+			},
+			confirmSubmit() {
+				if (this.isSubmitting) return;
+			
+				let firstUnansweredIndex = -1;
+				this.list.forEach((l, i) => {
+					const isAnswered = l.answer.filter(a => a?.value).length==this.userAnswerTemp.length?true:false;
+					this.$set(l, 'warn', !isAnswered);
+					if (!isAnswered && firstUnansweredIndex === -1) {
+						firstUnansweredIndex = i;
+					}
+				});
+			
+				if (firstUnansweredIndex > -1) {
+					uni.showModal({
+						title: '提示',
+						content: `第 ${firstUnansweredIndex + 1} 项未选择答案,请选择。`,
+						showCancel: false,
+						success: (res) => {
+							if (res.confirm) {
+								// 调用新的滚动方法
+								this.scrollToQuestion(firstUnansweredIndex);
+							}
+						}
+					});
+					return; // 终止提交
+				}
+			
+				const submitList = this.list.map((l) => {
+					let {answer,userAnswer,warn,...other} = JSON.parse(JSON.stringify(l));
+					userAnswer.forEach(u=>{
+						u.questionOption.forEach(q=>{
+							q.userAnswer=answer.find(a=>a.assessmentMethod==u.assessmentMethod)?.value==q.questionOption;
+						})
+					})
+					return {
+						...other,
+						isAnswer: '1',
+						userAnswer
+					};
+				});
+				
+				this.isSubmitting = true;
+				this.$api
+					.post('/core/team/member/answer/submit', submitList)
+					.then((res) => {
+						if (res.data.code !== 0) {
+							this.isSubmitting = false;
+							return this.$showToast(res.data.msg);
+						}
+						uni.removeStorageSync('questionnaire');
+						let url = '/pagesPublish/questionnaireResult'
+						if(this.type == 2) url = '/pagesPublish/submitResult'
+						uni.navigateTo({ url })
+					})
+					.catch((err) => {
+						this.$showToast('网络异常,请稍后重试');
+					})
+					.finally(() => {
+						this.isSubmitting = false;
+					});
+			},
+			setQuestionnaireCache() {
+				const answeredList = this.list.filter((l) => l.answer.filter(a => a?.value).length>0).map((l) => ({ id: l.id, answer: l.answer }));
+				if (answeredList.length === 0) {
+					uni.removeStorageSync('questionnaire');
+					return;
+				}
+			
+				const qinfo = {
+					key: this.teamQuestionnaireId,
+					list: answeredList
+				};
+				uni.setStorageSync('questionnaire', JSON.stringify(qinfo));
+			},
+			async getTeamScaleData(){
+				return new Promise((resolve,reject)=>{
+					this.$api.get('/getListByType/team_scale').then(({data:res})=>{
+						if(res.code!==0) return this.$showToast(res.msg)
+						this.teamScaleData = res.data.map(d=>({name:d.dictLabel,id:d.dictValue}))
+						resolve()
+					})
+				})	
+			},
+			async getTeamHierarchyData(){
+				return new Promise((resolve,reject)=>{
+					this.$api.get('/getListByType/team_hierarchy').then(({data:res})=>{
+						if(res.code!==0) return this.$showToast(res.msg)
+						this.teamLevelData = res.data.map(d=>({name:d.dictLabel,id:d.dictValue}))
+						resolve()
+					})
+				})	
+			},
+			async showTeamInfo(){
+				await this.getTeamScaleData()
+				await this.getTeamHierarchyData()
+				this.$api.get(`/core/user/team/${this.teamId}`).then(({data:res})=>{
+					if(res.code!==0) return this.$showToast(res.msg)
+					this.teamInfo = res.data;
+					this.teamInfo.functionsName = res.data.functions.map(f=>f.functionName).join('、');
+					this.teamInfo.organizationsName = res.data.organizations.map(f=>f.orgName).join('、');
+					this.teamInfo.address = res.data.provinceName+res.data.cityName;
+					this.teamInfo.scaleName = this.teamScaleData.find(d=>d.id==res.data.scale).name;
+					this.teamInfo.hierarchyName = this.teamLevelData.find(d=>d.id==res.data.hierarchy).name;
+					this.teamShow = true;
+				})
 			}
 		}
 	}
 </script>
 
 <style scoped lang="scss">
+	.loading-container {
+		width: 100%;
+		height: 100%;
+	}
 	.default_page{
 		padding: 0 0 192rpx;
 		background: #FFFFFF;
-		box-sizing: border-box;
+		box-sizing: border-box;
+		height: 100vh;
+		overflow: hidden;
+		display: flex;
+		flex-direction: column;
 		
 		.top{
 			padding: 40rpx 24rpx 50rpx;
@@ -186,10 +392,12 @@
 			}
 		}
 	
-		.list{
-			flex: 1;
+		.list{
+			width: 100%;
 			padding: 0 24rpx;
-			overflow-y: auto;
+			box-sizing: border-box;
+			// flex: 1;
+			// overflow-y: auto;
 		}
 	
 		.bottom{