Pārlūkot izejas kodu

按照最新设计图进行改版;问卷保留作答进度(当前问卷)

htc 12 stundas atpakaļ
vecāks
revīzija
c996766f89

+ 1 - 1
App.vue

@@ -14,7 +14,7 @@
 		onShow: function() {
 			if(uni.getStorageSync('userInfo')){
 				uni.reLaunch({
-					url:'/pages/dialog'
+					url:'/pages/home'
 				})
 			}else{
 				uni.reLaunch({

+ 1 - 1
components/CusHeader/index.vue

@@ -61,7 +61,7 @@
 				if(this.backAlert){
 					uni.showModal({
 						title:'温馨提示',
-						content:'您当前正在填写问卷,返回会清空作答进度,是否确认返回?',
+						content:'您正在填写问卷中,系统仅保留当前问卷的作答进度,是否确认返回?',
 						success: (res) => {
 							if(res.confirm){
 								this.dealBack(url)

+ 5 - 11
components/CusTabbar/index.vue

@@ -17,16 +17,10 @@
 				tabbarValue: 0,
 				list: [
 					{
-						inactiveImg: require('@/static/tab_qa.png'),
-						activeImg: require('@/static/tab_qa_active.png'),
-						text: '问答',
-						path: '/pages/dialog'
-					},
-					{
-						inactiveImg: require('@/static/tab_wj.png'),
-						activeImg: require('@/static/tab_wj_active.png'),
-						text: '问卷',
-						path: '/pages/questionnaire'
+						inactiveImg: require('@/static/tab_home.png'),
+						activeImg: require('@/static/tab_home_active.png'),
+						text: '首页',
+						path: '/pages/home'
 					},
 					{
 						inactiveImg: require('@/static/tab_my.png'),
@@ -67,7 +61,7 @@
 		box-shadow: 0rpx -2rpx 8rpx 0rpx rgba(0,0,0,0.06);
 
 		&>view {
-			width: calc(100% / 3);
+			width: calc(100% / 2);
 			height: 100%;
 			display: flex;
 			flex-direction: column;

+ 2 - 2
http/baseApi.js

@@ -1,5 +1,5 @@
-const BaseApi = 'https://transcend.ringzle.com/chuangheng-app/app' //线上
-// const BaseApi = 'http://192.168.2.19:9023/chuangheng-app/app' //李勇
+// const BaseApi = 'https://transcend.ringzle.com/chuangheng-app/app' //线上
+const BaseApi = 'http://192.168.2.19:9023/chuangheng-app/app' //李勇
 
 export {
 	BaseApi

+ 12 - 0
pages.json

@@ -6,6 +6,12 @@
 				"navigationStyle": "custom"
 			}
 		},
+		{
+			"path": "pages/home",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
 		{
 			"path": "pages/dialog",
 			"style": {
@@ -30,6 +36,12 @@
 				"navigationStyle": "custom"
 			}
 		},
+		{
+			"path": "pages/report",
+			"style": {
+				"navigationStyle": "custom"
+			}
+		},
 		{
 			"path": "pages/my",
 			"style": {

+ 413 - 0
pages/dialog - 副本.vue

@@ -0,0 +1,413 @@
+<template>
+	<view class="tabPage" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<u-navbar title="创衡正念企业教练" bgColor="#FFFFFF" :titleStyle="{'font-size':'32rpx','font-weight':'bold'}">
+			<view class="u-nav-slot" slot="left" style="display: flex;background-color: transparent;">
+				<image src="@/static/history_dialog.png" style="width: 42rpx;height: 42rpx;" @tap="reviewHistory"></image>
+				<image src="@/static/new_dialog.png" style="width: 42rpx;height: 42rpx;margin-left: 40rpx;" @tap="startNewDialog"></image>
+			</view>
+		</u-navbar>
+		<div class="dialogs container" ref="messageContainer">
+			<div class="d_answer init">
+				<div class="da_top adfac">
+					<image src="@/static/logo.png"></image>
+					<text>创衡正念企业教练</text>
+				</div>
+				<div class="da_content">
+					Hi,我是企业教练,很高兴遇见你!我随时可以回答您的问题!
+				</div>
+			</div>
+			<div v-for="(item,index) in dialogList" :key="index">
+				<div class="d_question">
+					<div class="dq_text">{{ item.question }}</div>
+				</div>
+				<div class="d_answer">
+					<div class="da_top adfac">
+						<image src="@/static/logo.png"></image>
+						<text>创衡正念企业教练</text>
+					</div>
+					<div class="da_content">
+						<u-parse :content="item.answer"></u-parse>
+						<div class="dc_btns adfacjb" v-if="item.answer">
+							<div class="db_l">
+								<image :src="item.copy?require('@/static/copy_active.png'):require('@/static/copy.png')" @tap="toCopy(item,index)"></image>
+								<image :src="item.upvote?require('@/static/upvote_active.png'):require('@/static/upvote.png')" @tap="toUpvote(item,index)"></image>
+								<image :src="item.comment?require('@/static/comment_active.png'):require('@/static/comment.png')" @tap="toComment(item,index)"></image>
+							</div>
+							<div class="db_r">
+								<image :src="item.share?require('@/static/share_active.png'):require('@/static/share.png')" @tap="toShare(item,index)"></image>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div class="ask adfacjb">
+			<div class="a_l">
+				<input type="text" v-model="question" placeholder="请输入您的问题" @confirm="sendQuestion" ref="questionInp">
+			</div>
+			<image class="a_r" src="@/static/send.png" @tap="sendQuestion"></image>
+		</div>
+		<u-modal :show="commentShow" title="评论" @confirm="commentConfirm" @cancel="commentCancel" @close="commentCancel" :showCancelButton="true">
+			<u-textarea v-model="content" placeholder="对于我们的回答您是否不满意,您有更好的答案建议吗?"></u-textarea>
+		</u-modal>
+		<u-popup :show="historyShow" mode="left"  @close="historyClose">
+			<view class="history" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+				<u-navbar title="历史回答" bgColor="#FFFFFF" :titleStyle="{'font-size':'32rpx','font-weight':'bold'}" style="width: 672rpx;">
+					<view class="u-nav-slot" slot="left" style="display: flex;background-color: transparent;">
+						<image src="@/static/arrow_left_hei.png" style="width: 40rpx;height: 40rpx;" @tap="historyClose"></image>
+					</view>
+				</u-navbar>
+				<div class="h_list">
+					<div class="hl_item" v-for="(item,index) in historyList" :key="index">
+						<div class="hi_date">{{item.date}}</div>
+						<div class="hl_pre" v-for="(pre,idx) in item.list" :key="idx">
+							{{pre.name}}
+						</div>
+					</div>
+				</div>
+			</view>
+		</u-popup>
+		<Tabbar :tabbarIndex="0"></Tabbar>
+	</view>
+</template>
+
+<script>
+	var timer = null;
+	let requestTask = null;
+	import { BaseApi } from '../http/baseApi.js'
+	import Tabbar from '@/components/CusTabbar/index.vue'
+	import * as TextEncoding from "text-encoding-shim";
+	export default {
+		components:{ Tabbar },
+		data(){
+			return {
+				retryCount: 3, // 最大重试次数
+				currentRetry: 0, // 当前重试次数
+				isRequesting: false, // 请求状态锁
+				question:'',
+				streamingResponse:'',
+				receivedData:'',
+				dialogList:[],
+				windex:0,
+				commentShow:false,
+				content:'',
+				cindex:'',
+				historyShow:false,
+				historyList:[
+					{
+						date:'今天',
+						list:[
+							{name:'教练的标准是什么'},
+							{name:'教练的标准是什么?'},
+						]
+					},
+					{
+						date:'2025-05-12',
+						list:[
+							{name:'小众水果网名创意分享'},
+							{name:'教练的标准是什么?'},
+						]
+					},
+				]
+			}
+		},
+		methods:{
+			reviewHistory(){
+				this.historyShow = true;
+			},
+			startNewDialog(){
+				clearInterval(timer)
+				this.dialogList = [];
+				this.question = '';
+				this.streamingResponse = '';
+			},
+			historyClose(){
+				this.historyShow = false;
+			},
+			// 封装带重试机制的请求方法
+			async sendRequestWithRetry() {
+				if (this.isRequesting) return;
+				this.isRequesting = true;
+				this.currentRetry = 0;
+				try {
+					await this._executeRequest();
+				} catch (error) {
+					  console.error('最终请求失败:', error);
+					  this.$showToast('请求失败,请稍后重试')
+				} finally {
+					this.isRequesting = false;
+				}
+			},
+			// 实际执行请求的方法
+			_executeRequest() {
+			    return new Promise((resolve, reject) => {
+					requestTask = uni.request({
+						url: `${BaseApi}/core/chat/streamingMessage`,
+						method: 'POST',
+						timeout: 100000,
+						data:{ 
+							query: this.question,
+							timestamp:Date.now()
+						},
+						header: {
+						  'Content-Type': 'application/json',
+						  'token': uni.getStorageSync('token') || ''
+						},
+						enableChunked: true, // 启用流式接收
+						responseType:'text',
+						success: (res) => {
+							if (res.statusCode === 200) {
+								this._handleSuccess(res.data);
+								resolve();
+							} else {
+								this._handleError(`状态码异常: ${res.statusCode}`, resolve, reject);
+							}
+						},
+						fail: (err) => {
+							this._handleError(err.errMsg, resolve, reject);
+						},
+						complete: (com) => {
+							console.log('请求完成',com)
+						}
+					});
+					
+					requestTask.onChunkReceived(async (res) => {
+							console.log('res',res)
+						const uint8Array = new Uint8Array(res.data);
+						// const decoder = new TextDecoder("utf-8");
+						const decoder = new TextEncoding.TextDecoder("utf-8");
+						const decodedString = decoder.decode(uint8Array);
+						let newtext = decodedString.replaceAll('data:','')
+						newtext = newtext.replace(/\s+/g,'');
+						if(newtext){
+							let answer = this.dialogList[this.dialogList.length-1].answer+newtext;
+							this.$set(this.dialogList[this.dialogList.length-1],'answer',answer);
+							uni.pageScrollTo({ scrollTop: 99999, duration: 300});
+						}
+					});
+			    });
+			},
+			// 成功处理
+			_handleSuccess(data) {
+			    if (data) {
+			      this.streamingResponse += data;
+				  console.log(this.streamingResponse,'streamingResponse');
+			    }
+			    this.currentRetry = 0; // 重置重试计数器
+			},
+			// 错误处理
+			_handleError(errorMsg, resolve, reject) {
+			    console.error(`请求失败 (${this.currentRetry}/${this.retryCount}):`, errorMsg);
+			    if (this._shouldRetry(errorMsg)) {
+					this.currentRetry++;
+					setTimeout(() => {
+						this._executeRequest().then(resolve).catch(reject);
+					}, this._getRetryDelay());
+			    } else {
+					reject(errorMsg);
+			    }
+			},
+			// 判断是否需要重试
+			_shouldRetry(errorMsg) {
+			    const retryableErrors = [
+					'timeout', 
+					'request:fail', 
+					'Network Error'
+			    ];
+			    return this.currentRetry < this.retryCount && retryableErrors.some(e => errorMsg.includes(e));
+			},
+			// 获取指数退避延迟时间
+			_getRetryDelay() {
+			    return Math.min(1000 * Math.pow(2, this.currentRetry), 10000);
+			},
+			sendQuestion(){
+				if(!this.question) return this.$showToast('请输入问题');
+				let qa = {
+					question:JSON.parse(JSON.stringify(this.question)),
+					answer:'',
+					copy:false,
+					upvote:false,
+					comment:'',
+					share:false,
+				}
+				this.dialogList = [...this.dialogList,...[qa]];
+				this.$nextTick(()=>{
+					uni.pageScrollTo({ scrollTop: 99999, duration: 300});
+					this.sendRequestWithRetry();
+					this.question = '';
+				})
+			},
+			toCopy(item,index){
+				this.$set(this.dialogList[index],'copy',!this.dialogList[index].copy);
+			},
+			toUpvote(item,index){
+				this.$set(this.dialogList[index],'upvote',!this.dialogList[index].upvote);
+			},
+			toComment(item,index){
+				this.cindex = index;
+				this.commentShow = true;
+			},
+			toShare(item,index){
+				this.$set(this.dialogList[index],'share',!this.dialogList[index].share);
+			},
+			commentConfirm(){
+				this.$set(this.dialogList[this.cindex],'comment',this.content);
+				this.commentShow = false;
+			},
+			commentCancel(){
+				this.content = '';
+				this.commentShow = false;
+			},
+		}
+	}
+</script>
+
+<style>
+	.history .u-navbar .u-status-bar,.history .u-navbar .u-navbar__content{
+		width: 672rpx !important;
+	}
+</style>
+<style scoped lang="scss">
+	.tabPage{
+		position: relative;
+		background: #F7F2F6;
+		display: flex;
+		flex-direction: column;
+		
+		.history{
+			width: 672rpx;
+			height: 100vh;
+			background: #FFFFFF;
+			box-sizing: border-box;
+			display: flex;
+			flex-direction: column;
+			.h_list{
+				flex: 1;
+				width: 100%;
+				padding: 0 64rpx;
+				box-sizing: border-box;
+				margin-top: 20rpx;
+				overflow-y: auto;
+				.hl_item{
+					margin-top: 64rpx;
+					&:first-child{
+						margin-top: 0;
+					}
+					.hi_date{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 30rpx;
+						color: #A4A4A4;
+						line-height: 42rpx;
+					}
+					.hl_pre{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 30rpx;
+						color: #000000;
+						line-height: 42rpx;
+						margin-top: 48rpx;
+					}
+				}
+			}
+		}
+		
+		.dialogs{
+			width: 100%;
+			padding: 34rpx 36rpx 164rpx;
+			flex: 1;
+			box-sizing: border-box;
+			overflow-y: auto;
+			.d_answer{
+				margin-top: 40rpx;
+				&.init{
+					margin-top: 0;
+				}
+				.da_top{
+					image{
+						width: 48rpx;
+						height: 48rpx;
+					}
+					text{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #505050;
+						line-height: 42rpx;
+						margin-left: 20rpx;
+					}
+				}
+				.da_content{
+					padding: 30rpx 32rpx;
+					margin-top: 20rpx;
+					background: #FFFFFF;
+					border-radius: 4rpx 24rpx 24rpx 24rpx;
+					.dc_btns{
+						margin-top: 44rpx;
+						image{
+							width: 48rpx;
+							height: 48rpx;
+						}
+						.db_l{
+							image{
+								margin-right: 40rpx;
+							}
+						}
+					}
+				}
+			}
+			.d_question{
+				margin-top: 40rpx;
+				display: flex;
+				justify-content: flex-end;
+				.dq_text{
+					background: #833478;
+					border-radius: 24rpx 4rpx 24rpx 24rpx;
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 30rpx;
+					color: #FFFFFF;
+					line-height: 42rpx;
+					text-align: right;
+					padding: 26rpx 30rpx;
+				}
+			}
+		}
+		
+		.ask{
+			width: 100%;
+			height: 130rpx;
+			background: #FFFFFF;
+			padding: 21rpx 30rpx;
+			box-sizing: border-box;
+			position: fixed;
+			left: 0;
+			bottom: 172rpx;
+			z-index: 2;
+			.a_l{
+				width: calc(100% - 102rpx);
+				height: 88rpx;
+				padding: 20rpx 30rpx;
+				box-sizing: border-box;
+				border-radius: 44rpx;
+				border: 2rpx solid rgba(131,52,120,0.74);
+				input{
+					border: none;
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #252525;
+					line-height: 48rpx;
+					&::placeholder{
+						color: #808080;
+					}
+				}
+			}
+			.a_r{
+				width: 72rpx;
+				height: 72rpx;
+				border-radius: 36rpx;
+			}
+		}
+	}
+</style>

+ 188 - 180
pages/dialog.vue

@@ -1,73 +1,77 @@
 <template>
-	<view class="tabPage" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
-		<u-navbar title="创衡正念企业教练" bgColor="#FFFFFF" :titleStyle="{'font-size':'32rpx','font-weight':'bold'}">
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<u-navbar title="创衡正念企业教练" bgColor="transparent" :titleStyle="{'font-size':'32rpx','font-weight':'bold'}">
 			<view class="u-nav-slot" slot="left" style="display: flex;background-color: transparent;">
-				<image src="@/static/history_dialog.png" style="width: 42rpx;height: 42rpx;" @tap="reviewHistory"></image>
-				<image src="@/static/new_dialog.png" style="width: 42rpx;height: 42rpx;margin-left: 40rpx;" @tap="startNewDialog"></image>
+				<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/ef50e3e8-d0f9-41dd-a4ec-546b157a1de9.png" style="width: 45rpx;height: 45rpx;" @tap="toBack"></image>
+				<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/e536bf8e-3b33-4ea8-b60b-7154c6353bec.png" style="width: 42rpx;height: 42rpx;margin-left: 40rpx;" @tap="startNewDialog"></image>
 			</view>
 		</u-navbar>
-		<div class="dialogs container" ref="messageContainer">
-			<div class="d_answer init">
-				<div class="da_top adfac">
-					<image src="@/static/logo.png"></image>
-					<text>创衡正念企业教练</text>
-				</div>
-				<div class="da_content">
-					Hi,我是企业教练,很高兴遇见你!我随时可以回答您的问题!
-				</div>
+		<template v-if="dialogList.length===0">
+			<div class="welcome">
+				<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/5292af4c-977b-4620-a4e4-4aadcd5ad092.png"></image>
+				<p>Hi,我是你的AI团队教练助手~</p>
+				<p class="tip">任何关于团队、分析报告、教练的问题,你都可以向我提问。我正在快速学习和进化中,有新功能时,我一定第一时间告诉你~ </p>
 			</div>
-			<div v-for="(item,index) in dialogList" :key="index">
-				<div class="d_question">
-					<div class="dq_text">{{ item.question }}</div>
-				</div>
-				<div class="d_answer">
+		</template>
+		<template v-else>
+			<div class="dialogs container" ref="messageContainer">
+				<div class="d_answer init">
 					<div class="da_top adfac">
 						<image src="@/static/logo.png"></image>
 						<text>创衡正念企业教练</text>
 					</div>
-					<div class="da_content">
-						<u-parse :content="item.answer"></u-parse>
-						<div class="dc_btns adfacjb" v-if="item.answer">
-							<div class="db_l">
-								<image :src="item.copy?require('@/static/copy_active.png'):require('@/static/copy.png')" @tap="toCopy(item,index)"></image>
-								<image :src="item.upvote?require('@/static/upvote_active.png'):require('@/static/upvote.png')" @tap="toUpvote(item,index)"></image>
-								<image :src="item.comment?require('@/static/comment_active.png'):require('@/static/comment.png')" @tap="toComment(item,index)"></image>
-							</div>
-							<div class="db_r">
-								<image :src="item.share?require('@/static/share_active.png'):require('@/static/share.png')" @tap="toShare(item,index)"></image>
+					<div class="da_content">Hi,任何关于团队、分析报告、教练的问题,你都可以向我提问~</div>
+				</div>
+				<div v-for="(item,index) in dialogList" :key="index">
+					<div class="d_question">
+						<div class="dq_text">{{ item.question }}</div>
+					</div>
+					<div class="d_answer">
+						<div class="da_top adfac">
+							<image src="@/static/logo.png"></image>
+							<text>创衡正念企业教练</text>
+						</div>
+						<div class="da_content">
+							<u-parse :content="item.answer"></u-parse>
+							<div class="dc_btns adfacjb" v-if="item.answer">
+								<div class="db_l">
+									<image :src="item.copy?require('@/static/copy_active.png'):require('@/static/copy.png')" @tap="toCopy(item,index)"></image>
+									<image :src="item.upvote?require('@/static/upvote_active.png'):require('@/static/upvote.png')" @tap="toUpvote(item,index)"></image>
+									<image :src="item.comment?require('@/static/comment_active.png'):require('@/static/comment.png')" @tap="toComment(item,index)"></image>
+								</div>
+								<div class="db_r">
+									<image :src="item.share?require('@/static/share_active.png'):require('@/static/share.png')" @tap="toShare(item,index)"></image>
+								</div>
 							</div>
 						</div>
 					</div>
 				</div>
 			</div>
-		</div>
-		<div class="ask adfacjb">
-			<div class="a_l">
-				<input type="text" v-model="question" placeholder="请输入您的问题" @confirm="sendQuestion" ref="questionInp">
+		</template>
+		<div class="ask">
+			<div class="a_inp">
+				<u-textarea v-model="question" placeholder="请输入您的问题" autoHeight @confirm="sendQuestion"></u-textarea>
+			</div>
+			<div class="a_btn adfacjb">
+				<div class="ab_l adfac">
+					<div class="al_pre adfacjc">
+						<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/451ac13c-5fdc-4d15-8f35-9f4d238e87c1.png"></image>
+						<text>创衡增强</text>
+					</div>
+					<div class="al_pre adfacjc">
+						<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/d4668dcc-1d28-47ff-8bae-84dc6475794b.png"></image>
+						<text>联网搜索</text>
+					</div>
+				</div>
+				<div class="ab_r">
+					<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/caf6075c-0967-4c99-a269-ea453537075c.png"></image>
+					<image @tap="sendQuestion" src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/2429556b-54b7-4878-97c0-6b440b546ee4.png"></image>
+				</div>
 			</div>
-			<image class="a_r" src="@/static/send.png" @tap="sendQuestion"></image>
 		</div>
 		<u-modal :show="commentShow" title="评论" @confirm="commentConfirm" @cancel="commentCancel" @close="commentCancel" :showCancelButton="true">
-			<u-textarea v-model="content" placeholder="对于我们的回答您是否不满意,您有更好的答案建议吗?"></u-textarea>
+			<u-textarea v-model="content" placeholder="对于我们的回答您是否不满意,您有更好的答案建议吗?请在此输入."></u-textarea>
 		</u-modal>
-		<u-popup :show="historyShow" mode="left"  @close="historyClose">
-			<view class="history" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
-				<u-navbar title="历史回答" bgColor="#FFFFFF" :titleStyle="{'font-size':'32rpx','font-weight':'bold'}" style="width: 672rpx;">
-					<view class="u-nav-slot" slot="left" style="display: flex;background-color: transparent;">
-						<image src="@/static/arrow_left_hei.png" style="width: 40rpx;height: 40rpx;" @tap="historyClose"></image>
-					</view>
-				</u-navbar>
-				<div class="h_list">
-					<div class="hl_item" v-for="(item,index) in historyList" :key="index">
-						<div class="hi_date">{{item.date}}</div>
-						<div class="hl_pre" v-for="(pre,idx) in item.list" :key="idx">
-							{{pre.name}}
-						</div>
-					</div>
-				</div>
-			</view>
-		</u-popup>
-		<Tabbar :tabbarIndex="0"></Tabbar>
 	</view>
 </template>
 
@@ -75,12 +79,11 @@
 	var timer = null;
 	let requestTask = null;
 	import { BaseApi } from '../http/baseApi.js'
-	import Tabbar from '@/components/CusTabbar/index.vue'
 	import * as TextEncoding from "text-encoding-shim";
 	export default {
-		components:{ Tabbar },
 		data(){
 			return {
+				isDialog:false,
 				retryCount: 3, // 最大重试次数
 				currentRetry: 0, // 当前重试次数
 				isRequesting: false, // 请求状态锁
@@ -92,28 +95,13 @@
 				commentShow:false,
 				content:'',
 				cindex:'',
-				historyShow:false,
-				historyList:[
-					{
-						date:'今天',
-						list:[
-							{name:'教练的标准是什么'},
-							{name:'教练的标准是什么?'},
-						]
-					},
-					{
-						date:'2025-05-12',
-						list:[
-							{name:'小众水果网名创意分享'},
-							{name:'教练的标准是什么?'},
-						]
-					},
-				]
 			}
 		},
 		methods:{
-			reviewHistory(){
-				this.historyShow = true;
+			toBack(){
+				uni.reLaunch({
+					url:'/pages/home'
+				})
 			},
 			startNewDialog(){
 				clearInterval(timer)
@@ -121,9 +109,6 @@
 				this.question = '';
 				this.streamingResponse = '';
 			},
-			historyClose(){
-				this.historyShow = false;
-			},
 			// 封装带重试机制的请求方法
 			async sendRequestWithRetry() {
 				if (this.isRequesting) return;
@@ -132,7 +117,6 @@
 				try {
 					await this._executeRequest();
 				} catch (error) {
-					  console.error('最终请求失败:', error);
 					  this.$showToast('请求失败,请稍后重试')
 				} finally {
 					this.isRequesting = false;
@@ -140,7 +124,7 @@
 			},
 			// 实际执行请求的方法
 			_executeRequest() {
-			    return new Promise((resolve, reject) => {
+				return new Promise((resolve, reject) => {
 					requestTask = uni.request({
 						url: `${BaseApi}/core/chat/streamingMessage`,
 						method: 'POST',
@@ -172,56 +156,66 @@
 					});
 					
 					requestTask.onChunkReceived(async (res) => {
-							console.log('res',res)
 						const uint8Array = new Uint8Array(res.data);
-						// const decoder = new TextDecoder("utf-8");
 						const decoder = new TextEncoding.TextDecoder("utf-8");
 						const decodedString = decoder.decode(uint8Array);
-						let newtext = decodedString.replaceAll('data:','')
-						newtext = newtext.replace(/\s+/g,'');
-						if(newtext){
-							let answer = this.dialogList[this.dialogList.length-1].answer+newtext;
-							this.$set(this.dialogList[this.dialogList.length-1],'answer',answer);
-							uni.pageScrollTo({ scrollTop: 99999, duration: 300});
+						try {
+							let newtext = decodedString.replaceAll('data:','')
+							let ntArr = newtext.split(/\s+/);
+							if(ntArr.length){
+								ntArr.forEach(n=>{
+									if(!n.trim()) return
+									let nj = JSON.parse(n);
+									if(nj.event=='agent_message'){
+										let answer = this.dialogList[this.dialogList.length-1].answer+nj.answer;
+										this.$set(this.dialogList[this.dialogList.length-1],'answer',answer);
+										this.$set(this.dialogList[this.dialogList.length-1],'id',nj.id);
+										this.$set(this.dialogList[this.dialogList.length-1],'task_id',nj.task_id);
+										this.$set(this.dialogList[this.dialogList.length-1],'message_id',nj.message_id);
+										this.$set(this.dialogList[this.dialogList.length-1],'conversation_id',nj.conversation_id);
+										uni.pageScrollTo({ scrollTop: 99999, duration: 300});
+									}
+								})
+							}
+						} catch (e) {
+							console.error('解析失败', e, '原始数据:', decodedString);
 						}
 					});
-			    });
+				});
 			},
 			// 成功处理
 			_handleSuccess(data) {
-			    if (data) {
-			      this.streamingResponse += data;
-				  console.log(this.streamingResponse,'streamingResponse');
-			    }
-			    this.currentRetry = 0; // 重置重试计数器
+				if (data) {
+				  this.streamingResponse += data;
+				}
+				this.currentRetry = 0; // 重置重试计数器
 			},
 			// 错误处理
 			_handleError(errorMsg, resolve, reject) {
-			    console.error(`请求失败 (${this.currentRetry}/${this.retryCount}):`, errorMsg);
-			    if (this._shouldRetry(errorMsg)) {
+				if (this._shouldRetry(errorMsg)) {
 					this.currentRetry++;
 					setTimeout(() => {
 						this._executeRequest().then(resolve).catch(reject);
 					}, this._getRetryDelay());
-			    } else {
+				} else {
 					reject(errorMsg);
-			    }
+				}
 			},
 			// 判断是否需要重试
 			_shouldRetry(errorMsg) {
-			    const retryableErrors = [
+				const retryableErrors = [
 					'timeout', 
 					'request:fail', 
 					'Network Error'
-			    ];
-			    return this.currentRetry < this.retryCount && retryableErrors.some(e => errorMsg.includes(e));
+				];
+				return this.currentRetry < this.retryCount && retryableErrors.some(e => errorMsg.includes(e));
 			},
 			// 获取指数退避延迟时间
 			_getRetryDelay() {
-			    return Math.min(1000 * Math.pow(2, this.currentRetry), 10000);
+				return Math.min(1000 * Math.pow(2, this.currentRetry), 10000);
 			},
 			sendQuestion(){
-				if(!this.question) return this.$showToast('请输入问题');
+				if(!this.question) return this.$showToast('请输入您的问题');
 				let qa = {
 					question:JSON.parse(JSON.stringify(this.question)),
 					answer:'',
@@ -238,7 +232,15 @@
 				})
 			},
 			toCopy(item,index){
-				this.$set(this.dialogList[index],'copy',!this.dialogList[index].copy);
+				uni.setClipboardData({
+					data:item.answer,
+					success: (res) => {
+						this.$showToast('复制成功');
+					},
+					fail: (err) => {
+						this.$showToast('复制失败');
+					}
+				})
 			},
 			toUpvote(item,index){
 				this.$set(this.dialogList[index],'upvote',!this.dialogList[index].upvote);
@@ -262,60 +264,50 @@
 	}
 </script>
 
-<style>
-	.history .u-navbar .u-status-bar,.history .u-navbar .u-navbar__content{
-		width: 672rpx !important;
-	}
-</style>
 <style scoped lang="scss">
-	.tabPage{
-		position: relative;
-		background: #F7F2F6;
-		display: flex;
-		flex-direction: column;
+	::v-deep .u-textarea{
+		border: none !important;
+		padding: 0 !important;
+	}
+	::v-deep .u-textarea textarea{
+		min-height: 96rpx !important;
+	}
+	
+	.page{
+		background: linear-gradient( 227deg, #EEEFF8 0%, #F6ECF4 100%, #F6ECF4 100%);
+		padding: 0 30rpx 302rpx;
+		box-sizing: border-box;
 		
-		.history{
-			width: 672rpx;
-			height: 100vh;
-			background: #FFFFFF;
-			box-sizing: border-box;
-			display: flex;
-			flex-direction: column;
-			.h_list{
-				flex: 1;
-				width: 100%;
-				padding: 0 64rpx;
-				box-sizing: border-box;
-				margin-top: 20rpx;
-				overflow-y: auto;
-				.hl_item{
-					margin-top: 64rpx;
-					&:first-child{
-						margin-top: 0;
-					}
-					.hi_date{
-						font-family: PingFangSC, PingFang SC;
-						font-weight: 400;
-						font-size: 30rpx;
-						color: #A4A4A4;
-						line-height: 42rpx;
-					}
-					.hl_pre{
-						font-family: PingFangSC, PingFang SC;
-						font-weight: 400;
-						font-size: 30rpx;
-						color: #000000;
-						line-height: 42rpx;
-						margin-top: 48rpx;
-					}
+		.welcome{
+			margin-top: 259rpx;
+			padding: 0 34rpx;
+			image{
+				width: 88rpx;
+				height: 87rpx;
+				margin-left: 20rpx;
+			}
+			p{
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 36rpx;
+				color: #252525;
+				line-height: 36rpx;
+				margin-top: 36rpx;
+				&.tip{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #646464;
+					line-height: 40rpx;
+					margin-top: 20rpx;
 				}
 			}
 		}
-		
+	
 		.dialogs{
 			width: 100%;
-			padding: 34rpx 36rpx 164rpx;
-			flex: 1;
+			height: calc(100vh - 282rpx);
+			padding-top: 34rpx;
 			box-sizing: border-box;
 			overflow-y: auto;
 			.d_answer{
@@ -333,7 +325,7 @@
 						font-weight: bold;
 						font-size: 30rpx;
 						color: #505050;
-						line-height: 42rpx;
+						line-height: 48rpx;
 						margin-left: 20rpx;
 					}
 				}
@@ -367,46 +359,62 @@
 					font-weight: 400;
 					font-size: 30rpx;
 					color: #FFFFFF;
-					line-height: 42rpx;
+					line-height: 48rpx;
 					text-align: right;
 					padding: 26rpx 30rpx;
 				}
 			}
 		}
-		
+	
 		.ask{
-			width: 100%;
-			height: 130rpx;
+			width: calc(100% - 60rpx);
+			height: 210rpx;
 			background: #FFFFFF;
-			padding: 21rpx 30rpx;
-			box-sizing: border-box;
+			border-radius: 24rpx;
+			border: 2rpx solid #F0F2F8;
 			position: fixed;
-			left: 0;
-			bottom: 172rpx;
-			z-index: 2;
-			.a_l{
-				width: calc(100% - 102rpx);
-				height: 88rpx;
-				padding: 20rpx 30rpx;
-				box-sizing: border-box;
-				border-radius: 44rpx;
-				border: 2rpx solid rgba(131,52,120,0.74);
-				input{
-					border: none;
-					font-family: PingFangSC, PingFang SC;
-					font-weight: 400;
-					font-size: 28rpx;
-					color: #252525;
-					line-height: 48rpx;
-					&::placeholder{
-						color: #808080;
+			left: 30rpx;
+			bottom: 72rpx;
+			display: flex;
+			flex-direction: column;
+			padding: 24rpx;
+			box-sizing: border-box;
+			.a_inp{
+				flex: 1;
+				overflow-y: auto;
+			}
+			.a_btn{
+				padding-top: 20rpx;
+				height: 54rpx;
+				.ab_l{
+					.al_pre{
+						width: 162rpx;
+						height: 54rpx;
+						background: #FFFFFF;
+						border-radius: 27rpx;
+						border: 1rpx solid #E0E0E0;
+						margin-right: 24rpx;
+						image{
+							width: 24rpx;
+							height: 24rpx;
+						}
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 22rpx;
+							color: #393939;
+							line-height: 22rpx;
+							margin-left: 10rpx;
+						}
+					}
+				}
+				.ab_r{
+					image{
+						width: 48rpx;
+						height: 48rpx;
+						margin-left: 30rpx;
 					}
 				}
-			}
-			.a_r{
-				width: 72rpx;
-				height: 72rpx;
-				border-radius: 36rpx;
 			}
 		}
 	}

+ 269 - 0
pages/home.vue

@@ -0,0 +1,269 @@
+<template>
+	<view class="tabPage" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='创衡正念企业教练' bgColor="transparent" :showback="false"></cus-header>
+		<image class="topbg" src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/dbb693be-c302-4848-8e2e-a4eb263aa60c.png"></image>
+		<div class="home_top">
+			<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/12c326b4-7328-4282-9175-a87903adbf12.png"></image>
+			<p>Hi,我是AI团队教练助手</p>
+			<p class="tip">可以为你提供全方位多角度的PREILL团队分析</p>
+		</div>
+		<div class="order">
+			<div class="pre">
+				<div class="top">
+					<div class="left">
+						<p>我的问卷</p>
+						<p>{{wjDwc}}/{{wjYwc}}</p>
+					</div>
+					<div class="right">
+						<p>待完成:<span>{{wjDwc}}</span></p>
+						<p>已完成:<span>{{wjYwc}}</span></p>
+					</div>
+				</div>
+				<div class="bottom">
+					<div class="jd" :style="{'width':(wjDwc/(wjDwc+wjYwc)*100)+'%'}"></div>
+				</div>
+			</div>
+			<div class="pre">
+				<div class="top">
+					<div class="left">
+						<p>我的报告</p>
+						<p>{{bgGr}}/{{bgTd}}</p>
+					</div>
+					<div class="right">
+						<p class="gr">个人:<span>{{bgGr}}</span></p>
+						<p>团队:<span>{{bgTd}}</span></p>
+					</div>
+				</div>
+				<div class="bottom">
+					<div class="jd green" :style="{'width':(bgGr/(bgGr+bgTd)*100)+'%'}"></div>
+				</div>
+			</div>
+		</div>
+		<div class="title">快速访问</div>
+		<div class="menus adfacjb">
+			<div class="m_pre adffcacjc" @tap="toTurn('/pages/dialog')">
+				<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/b86ddd7a-6111-48d8-a9db-54a62a3446c4.png"></image>
+				<p>智能问答</p>
+			</div>
+			<div class="m_pre adffcacjc" @tap="toTurn('/pages/report')">
+				<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/35023203-f2d3-4c09-bd13-31047ec68d9e.png"></image>
+				<p>我的报告</p>
+			</div>
+			<div class="m_pre adffcacjc" @tap="toTurn('/pages/questionnaire')">
+				<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/79bf1765-b520-43c7-9ed0-ab1d1a84fe64.png"></image>
+				<p>我的问卷</p>
+			</div>
+		</div>
+		<Tabbar :tabbarIndex="0"></Tabbar>
+	</view>
+</template>
+
+<script>
+	import Tabbar from '@/components/CusTabbar/index.vue'
+	export default {
+		components:{ Tabbar },
+		data(){
+			return {
+				wjDwc:0,
+				wjYwc:0,
+				bgGr:0,
+				bgTd:0
+			}
+		},
+		onLoad() {
+			this.getWjList();
+			this.getReportList();
+		},
+		methods:{
+			toTurn(url){
+				if(!url) return 
+				uni.navigateTo({
+					url
+				})
+			},
+			getWjList(){
+				this.$api.get('/core/teammember/que/listByUser').then(res=>{
+					if(res.data.code!==0) return this.$showToast(res.data.msg)
+					this.wjDwc = res.data.data.filter(d=>d.status===0).length;
+					this.wjYwc = res.data.data.filter(d=>d.status===1).length;
+				})
+			},
+			getReportList(){
+				this.$api.get('/core/report/member/personalReportList/'+'1').then(res=>{
+					if(res.data.code!==0) return this.$showToast(res.data.msg)
+					this.bgGr = res.data.data.filter(d=>d.type===2).length;
+					this.bgTd = res.data.data.filter(d=>d.type===1).length;
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.tabPage{
+		background: #FFFFFF;
+		padding: 0 30rpx 192rpx;
+		box-sizing: border-box;
+		
+		.topbg{
+			width: 100%;
+			height: 720rpx;
+			position: fixed;
+			top: 0;
+			left: 0;
+		}
+	
+		.home_top{
+			width: 100%;
+			height: 288rpx;
+			position: relative;
+			background:url(https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/537756e6-f473-479e-ab0a-1a56cce38cd2.png) no-repeat;
+			background-size: 100% 100%;
+			padding-left: 275rpx;
+			box-sizing: border-box;
+			padding-top: 71rpx;
+			margin-top: 52rpx;
+			&>image{
+				width: 184rpx;
+				height: 312rpx;
+				position: absolute;
+				left: 31rpx;
+				bottom: 19rpx;
+			}
+			&>p{
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 34rpx;
+				color: #252525;
+				line-height: 48rpx;
+				&.tip{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #6B7280;
+					line-height: 40rpx;
+					margin-top: 11rpx;
+				}
+			}
+		}
+	
+		.order{
+			display: flex;
+			justify-content: space-between;
+			position: relative;
+			margin-top: 20rpx;
+			position: relative;
+			.pre{
+				width: calc(50% - 9rpx);
+				background: linear-gradient( 180deg, #FFFFFF 0%, #FFFFFF 100%);
+				box-shadow: 0rpx 4rpx 16rpx 0rpx rgba(131,52,120,0.08);
+				border-radius: 12rpx;
+				padding: 40rpx 24rpx;
+				box-sizing: border-box;
+				.top{
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.left{
+						p{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 28rpx;
+							color: #252525;
+							line-height: 28rpx;
+							&:last-child{
+								font-family: DINAlternate, DINAlternate;
+								font-weight: bold;
+								font-size: 40rpx;
+								color: #333333;
+								line-height: 40rpx;
+								margin-top: 30rpx;
+							}
+						}
+					}
+					.right{
+						p{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #657588;
+							position: relative;
+							padding-left: 16rpx;
+							&::before{
+								content: '';
+								width: 10rpx;
+								height: 10rpx;
+								background: #FEA400;
+								border-radius: 50%;
+								position: absolute;
+								left: 0;
+								top: 50%;
+								margin-top: -5rpx;
+							}
+							&.gr::before{
+								background: #31D1D6;
+							}
+							&:last-child{
+								margin-top: 44rpx;
+								&::before{
+									background: #DDE0E6;
+								}
+							}
+							span{
+								color: #1D2129;
+							}
+						}
+					}
+				}
+				.bottom{
+					width: 100%;
+					height: 10rpx;
+					background: #DFE5EE;
+					border-radius: 3rpx;
+					margin-top: 30rpx;
+					position: relative;
+					.jd{
+						height: 10rpx;
+						background: #FEA400;
+						border-radius: 3rpx;
+						position: absolute;
+						left: 0;
+						top: 0;
+						&.green{
+							background: #31D1D6;
+						}
+					}
+				}
+			}
+		}
+	
+		&>.title{
+			font-family: PingFang-SC, PingFang-SC;
+			font-weight: bold;
+			font-size: 34rpx;
+			color: #111111;
+			line-height: 48rpx;
+			margin-top: 44rpx;
+		}
+		
+		.menus{
+			margin-top: 64rpx;
+			.m_pre{
+				width: calc(100% / 3);
+				image{
+					width: 110rpx;
+					height: 110rpx;
+				}
+				p{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #252525;
+					line-height: 37rpx;
+					text-align: center;
+					margin-top: 24rpx;
+				}
+			}
+		}
+	}
+</style>

+ 2 - 2
pages/login.vue

@@ -36,7 +36,7 @@
 			decryptPhoneNumber(e){
 				if(uni.getStorageSync('token')){
 					uni.reLaunch({
-						url:'/pages/dialog'
+						url:'/pages/home'
 					})
 					return
 				}
@@ -66,7 +66,7 @@
 								uni.hideLoading();
 								that.$showToast('登录成功');
 								setTimeout(()=>{
-									uni.reLaunch({ url:'/pages/dialog' })
+									uni.reLaunch({ url:'/pages/home' })
 								},1500)
 							}else that.$showToast(res.data.msg)
 						})

+ 97 - 149
pages/my.vue

@@ -1,197 +1,145 @@
 <template>
-	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+	<view class="tabPage" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
 		<cus-header title='我的' bgColor="transparent" :showback="false"></cus-header>
-		<div class="info adffcacjc">
-			<div class="i_avatar">
-				<image src="@/static/avatar.png"></image>
+		<div class="info">
+			<div class="i_top adfac">
+				<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/0bdaa978-db1a-4edb-8a41-fc45b096380f.png"></image>
+				<div class="it_texts">
+					<p>{{userName||''}}</p>
+					<p>{{mobile||''}}</p>
+				</div>
+			</div>
+			<div class="i_tips">
+				<p>所属公司:{{'甜梦巧克力公司甜梦巧克力公司'}}</p>
+				<p>所属团队:{{'甜梦巧克力团队'}}</p>
 			</div>
-			<div class="i_name">{{userName}}</div>
-			<div class="i_phone">手机号:{{mobile}}</div>
 		</div>
 		<div class="box">
-			<div class="tabs adf">
-				<div class="pre" :class="{'active':tidx===1}" @tap="changeTab(1)">收藏</div>
-				<div class="pre" :class="{'active':tidx===2}" @tap="changeTab(2)">评论</div>
-				<div class="pre" :class="{'active':tidx===3}" @tap="changeTab(3)">报告</div>
+			<div class="b_pre adfacjb">
+				<div class="bp_l adfac">
+					<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/ecb80887-6d86-420c-b797-7f12c5916871.png"></image>
+					<text>版本</text>
+				</div>
+				<div class="bp_r">1.0.0</div>
 			</div>
-			<div class="list" :style="{'height':'calc(100vh - '+(356+mt)+'px)'}">
-				<block v-if="tidx===1">
-					<u-list @scrolltolower="stCollect" v-if="collectList.length">
-						<u-list-item v-for="(item, index) in collectList" :key="index">
-							<div class="l_item adfacjb">
-								<div class="li_l">
-									<div class="title">{{'撰写企业管理方案'}}</div>
-									<div class="intro">{{'帮我写一篇关于企业管理的方案'}}</div>
-									<div class="date">{{'4/25'}}</div>
-								</div>
-								<div class="li_r"></div>
-							</div>
-						</u-list-item>
-					</u-list>
-					<template v-else>
-						<page-empty :height="'calc(100vh - '+(356+mt)+'px)'"></page-empty>
-					</template>
-				</block>
-				<block v-else-if="tidx===2">
-					<u-list @scrolltolower="stComment" v-if="commentList.length"></u-list>
-					<template v-else>
-						<page-empty :height="'calc(100vh - '+(356+mt)+'px)'"></page-empty>
-					</template>
-				</block>
-				<block v-else-if="tidx===3">
-					<u-list @scrolltolower="stReport" v-if="reportList.length"></u-list>
-					<template v-else>
-						<page-empty :height="'calc(100vh - '+(356+mt)+'px)'"></page-empty>
-					</template>
-				</block>
+			<div class="b_pre adfacjb" @tap="exitLogin">
+				<div class="bp_l adfac">
+					<image src="https://transcend.ringzle.com/xiaozhi-app/profile/2025/06/16/4d10c9ef-8a13-4502-adfd-d388628446ab.png"></image>
+					<text>退出登录</text>
+				</div>
+				<div class="bp_r">
+					<u-icon name="arrow-right" color="#D3D2D2" size="32"></u-icon>
+				</div>
 			</div>
 		</div>
-		<Tabbar :tabbarIndex="2"></Tabbar>
+		<Tabbar :tabbarIndex="1"></Tabbar>
 	</view>
 </template>
 
 <script>
 	import Tabbar from '@/components/CusTabbar/index.vue'
-	import pageEmpty from '@/components/pageEmpty/index.vue'
 	export default {
-		components:{ Tabbar, pageEmpty },
+		components:{ Tabbar },
 		data(){
 			return {
 				userName:'',
 				mobile:'',
-				tidx:1,
-				collectList:[],
-				commentList:[],
-				reportList:[],
 			}
 		},
 		onLoad() {
 			if(uni.getStorageSync('userInfo')){
 				this.userName = JSON.parse(uni.getStorageSync('userInfo')).realName||'';
 				this.mobile = JSON.parse(uni.getStorageSync('userInfo')).mobile||'';
+				if(this.mobile) this.mobile = this.mobile.replace(this.mobile.substr(3,4),' **** ')
 			}
 		},
 		methods:{
-			changeTab(index){
-				this.tidx = index;
+			exitLogin(){
+				uni.clearStorageSync();
+				uni.reLaunch({
+					url:'/pages/login'
+				})
 			}
 		}
 	}
 </script>
 
 <style scoped lang="less">
-	.page{
-		box-sizing: border-box;
+	.tabPage{
 		background: linear-gradient( 270deg, #EEEFF8 0%, #F6ECF4 100%, #F6ECF4 100%);
+		padding: 0 0 172rpx;
+		box-sizing: border-box;
+		display: flex;
+		flex-direction: column;
 		.info{
-			width: 100%;
-			height: 410rpx;
-			box-sizing: border-box;
-			padding-bottom: 64rpx;
-			.i_avatar{
-				width: 188rpx;
-				height: 188rpx;
-				border-radius: 50%;
-				background: #FFFFFF;
-				margin-top: 30rpx;
+			padding: 54rpx 40rpx;
+			.i_top{
 				image{
-					width: 100%;
-					height: 100%;
-					border-radius: 50%;
+					width: 188rpx;
+					height: 188rpx;
+				}
+				.it_texts{
+					padding-left: 30rpx;
+					p{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 40rpx;
+						color: #252525;
+						line-height: 40rpx;
+						&:last-child{
+							font-family: PingFang-SC, PingFang-SC;
+							font-weight: bold;
+							font-size: 32rpx;
+							color: #646464;
+							line-height: 32rpx;
+							margin-top: 36rpx;
+						}
+					}
 				}
 			}
-			.i_name{
-				font-family: PingFang-SC, PingFang-SC;
-				font-weight: bold;
-				font-size: 40rpx;
-				color: #252525;
-				line-height: 40rpx;
-				margin-top: 40rpx;
-			}
-			.i_phone{
-				font-family: PingFangSC, PingFang SC;
-				font-weight: 400;
-				font-size: 28rpx;
-				color: #6B7280;
-				line-height: 28rpx;
-				margin-top: 20rpx;
+			.i_tips{
+				margin-top: 48rpx;
+				overflow: hidden;
+				p{
+					margin-top: 40rpx;
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #6B7280;
+					line-height: 28rpx;
+				}
 			}
 		}
-	
 		.box{
-			width: 100%;
-			border-radius: 32rpx 32rpx 0 0;
+			padding: 30rpx;
 			background: #FFFFFF;
-			.tabs{
-				padding: 38rpx calc((100% - 510rpx) / 2) 40rpx;
-				border-bottom: 1rpx solid #E5E7EB;
-				.pre{
-					width: 170rpx;
+			flex: 1;
+			.b_pre{
+				background: #FFFFFF;
+				box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+				border-radius: 16rpx 16rpx 0rpx 0rpx;
+				padding: 39rpx 0;
+				.bp_l{
+					image{
+						width: 36rpx;
+						height: 36rpx;
+					}
+					text{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 30rpx;
+						color: #111111;
+						line-height: 32rpx;
+						margin-left: 30rpx;
+					}
+				}
+				.bp_r{
 					font-family: PingFang-SC, PingFang-SC;
 					font-weight: bold;
-					font-size: 32rpx;
-					color: #252525;
+					font-size: 30rpx;
+					color: #111111;
 					line-height: 32rpx;
-					text-align: center;
-					position: relative;
-					&.active{
-						color: #761E6A;
-						&::after{
-							content:'';
-							width: 120rpx;
-							height: 4rpx;
-							background: #833478;
-							border-radius: 2rpx;
-							position: absolute;
-							left: 50%;
-							margin-left: -60rpx;
-							bottom: -40rpx;
-						}
-					}
-				}
-			}
-		
-			.list{
-				overflow-y: auto;
-				.l_item{
-					padding: 30rpx 36rpx;
-					border-bottom: 1rpx solid #E5E7EB;
-					.li_l{
-						width: calc(100% - 186rpx);
-						.title{
-							font-family: PingFang-SC, PingFang-SC;
-							font-weight: bold;
-							font-size: 32rpx;
-							color: #252525;
-							line-height: 32rpx;
-							overflow: hidden;
-							white-space: nowrap;
-							text-overflow: ellipsis;
-						}
-						.intro{
-							font-family: PingFangSC, PingFang SC;
-							font-weight: 400;
-							font-size: 28rpx;
-							color: #252525;
-							line-height: 32rpx;
-							margin-top: 20rpx;
-							overflow: hidden;
-							white-space: nowrap;
-							text-overflow: ellipsis;
-						}
-						.date{
-							font-family: PingFangSC, PingFang SC;
-							font-weight: 400;
-							font-size: 26rpx;
-							color: #999999;
-							line-height: 32rpx;
-							margin-top: 28rpx;
-						}
-					}
-					.li_r{
-						width: 166rpx;
-						height: 166rpx;
-					}
+					text-align: right;
 				}
 			}
 		}

+ 30 - 23
pages/questionnaire.vue

@@ -1,28 +1,32 @@
 <template>
-	<view class="tabPage" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
-		<cus-header title='问卷' :showback="false"></cus-header>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='我的问卷'></cus-header>
 		<div class="tabs adf">
-			<div class="t_pre" :class="{'active':tidx===1}" @tap="changeTab(1)">待参与</div>
-			<div class="t_pre" :class="{'active':tidx===2}" @tap="changeTab(2)">已参与</div>
+			<div class="t_pre" :class="{'active':tidx===1}" @tap="changeTab(1)">待完成</div>
+			<div class="t_pre" :class="{'active':tidx===2}" @tap="changeTab(2)">已完成</div>
 		</div>
 		<template v-if="list.length">
 			<div class="list">
 				<div class="l_item" v-for="(item,index) in list" :key="index">
 					<div class="li_top adfacjb">
-						<div class="lt_l">{{item.title}}</div>
-						<div class="lt_r" :class="{'dcy':item.status===0,'ycy':item.status===1}">{{item.status===0?'待参与':item.status===1?'已参与':''}}</div>
+						<div class="lt_l">{{item.title||''}}</div>
+						<div class="lt_r" :class="{'dcy':item.status===0,'ycy':item.status===1}">{{item.status===0?'待完成':item.status===1?'已完成':''}}</div>
 					</div>
 					<div class="li_text">
-						所属项目:<span>{{item.enterpriseName}}</span>
+						所属项目:<span>{{item.enterpriseName||''}}</span>
 					</div>
 					<div class="li_text">
-						所属团队:<span>{{item.teamName}}</span>
+						所属团队:<span>{{item.teamName||''}}</span>
 					</div>
 					<div class="li_bottom adfacjb">
-						<div class="lb_l">截止时间:{{ item.endTime}}</div>
+						<div class="lb_l adfac">
+							<u-icon name="clock" color="#FD4F66" size="32"></u-icon>
+							<span v-if="item.status===0">截止时间:{{ item.endTime||''}}</span>
+							<span v-else-if="item.status===1">完成时间:{{ item.submitTime||''}}</span>
+						</div>
 						<div class="lb_r">
-							<div class="lr_btn" @tap="" v-if="item.status===0" @tap="toFill(item)">立即作答</div>
-							<div class="lr_btn" @tap="" v-if="item.status===1" @tap="toRepoer">查看报告</div>
+							<div class="lr_btn" v-if="item.status===0" @tap="toFill(item)">立即作答</div>
+							<div class="lr_btn" v-if="item.status===1" @tap="toRepoer(item)">查看报告</div>
 						</div>
 					</div>
 				</div>
@@ -31,15 +35,13 @@
 		<template v-else>
 			<page-empty :height="'calc(100vh - 200px)'"></page-empty>
 		</template>
-		<Tabbar :tabbarIndex="1"></Tabbar>
 	</view>
 </template>
 
 <script>
-	import Tabbar from '@/components/CusTabbar/index.vue'
 	import pageEmpty from '@/components/pageEmpty/index.vue'
 	export default {
-		components:{ Tabbar, pageEmpty },
+		components:{ pageEmpty },
 		data(){
 			return {
 				tidx:1,
@@ -66,7 +68,7 @@
 					url:`/pages/questionnaireFill?teamQuestionnaireId=${item.teamQuestionnaireId}&title=${item.title}`
 				})
 			},
-			toRepoer(){
+			toRepoer(item){
 				
 			},
 		}
@@ -74,9 +76,9 @@
 </script>
 
 <style scoped lang="less">
-	.tabPage{
+	.page{
 		background: #F7F7F7;
-		padding-bottom: 20rpx;
+		padding-bottom: 40rpx;
 		box-sizing: border-box;
 		.tabs{
 			width: 100%;
@@ -153,12 +155,17 @@
 					padding-top: 29rpx;
 					border-top: 1rpx solid #F0F2F8;
 					.lb_l{
-						width: calc(100% - 142rpx);
-						font-family: PingFangSC, PingFang SC;
-						font-weight: 400;
-						font-size: 26rpx;
-						color: #252525;
-						line-height: 51rpx;
+						background: rgba(253, 79, 102, 0.06);
+						border-radius: 16rpx;
+						padding: 3rpx 16rpx;
+						span{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #FD4F66;
+							line-height: 51rpx;
+							margin-left: 6rpx;
+						}
 					}
 					.lb_r{
 						.lr_btn{

+ 37 - 2
pages/questionnaireFill.vue

@@ -3,7 +3,7 @@
 		<cus-header title='问卷填写' :backAlert="true"></cus-header>
 		<div class="top adffcacjc">
 			<p>{{title}}</p>
-			<p class="tip">共 <span>{{list.length}}</span> 题,请耐心选择!</p>
+			<p class="tip">共 <span>{{list.length}}</span> 题,已作答 <span style="font-weight: bold;">{{answerNum}}</span> 题,请耐心选择!</p>
 		</div>
 		<div class="list" :style="{'height':(h-180-mt)+'px'}">
 			<div class="l_item" v-for="(item,index) in list" :key="index">
@@ -34,7 +34,9 @@
 			return {
 				title:'',
 				teamQuestionnaireId:'',
-				list:[]
+				list:[],
+				answerNum:0,
+				questionnaire:null
 			}
 		},
 		onLoad(option) {
@@ -42,14 +44,27 @@
 			this.teamQuestionnaireId = option.teamQuestionnaireId;
 			this.getList();
 		},
+		watch:{
+			list:{
+				handler(newval){
+					this.answerNum = this.list.filter(l=>l.answer!='')?.length||0;
+				},
+				deep:true
+			}
+		},
 		methods:{
 			getList(){
+				if(uni.getStorageSync('questionnaire')) this.questionnaire = JSON.parse(uni.getStorageSync('questionnaire'))
 				this.$api.get('/core/team/member/answer/listByUser/'+this.teamQuestionnaireId).then(res=>{
 					if(res.data.code!==0) return this.$showToast(res.data.msg)
 					this.list = res.data.data;
 					this.list.forEach((l,i)=>{
 						this.$set(this.list[i],'warn',false);
 						this.$set(this.list[i],'answer','');
+						if(this.questionnaire&&this.teamQuestionnaireId==this.questionnaire.key){
+							let t = this.questionnaire.list.find(q=>q.id==l.id)
+							this.$set(this.list[i],'answer',t?t.answer:'');
+						}
 					})
 				})
 			},
@@ -69,11 +84,31 @@
 				})
 				this.$api.post('/core/team/member/answer/submit',newList).then(res=>{
 					if(res.data.code!==0) return this.$showToast(res.data.msg)
+					uni.removeStorageSync('questionnaire')
 					uni.navigateTo({
 						url:'/pages/questionnaireResult'
 					})
 				})
+			},
+			setQuestionnaireCache(){
+				if(uni.getStorageSync('questionnaire')) uni.removeStorageSync('questionnaire')
+				let list = [];
+				this.list.forEach(l=>{
+					if(l.answer) list.push({id:l.id,answer:l.answer})
+				})
+				let qinfo = {
+					key:this.teamQuestionnaireId,
+					list
+				}
+				if(list.length===0) return
+				uni.setStorageSync('questionnaire',JSON.stringify(qinfo));
 			}
+		},
+		onUnload() {
+			this.setQuestionnaireCache();
+		},
+		onBackPress() {
+			this.setQuestionnaireCache();
 		}
 	}
 </script>

+ 2 - 2
pages/questionnaireResult.vue

@@ -1,6 +1,6 @@
 <template>
 	<view class="page adffcacjc" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
-		<cus-header title='问卷结果'></cus-header>
+		<cus-header title='问卷结果' backUrl="/pages/questionnaire"></cus-header>
 		<div class="top adffcacjc">
 			<image src="@/static/result.png"></image>
 			<div class="text">您的问卷已经提交,感谢您的参与<br>报告将在问卷完成后<br>由教练统一发送,请耐心等待!</div>
@@ -21,7 +21,7 @@
 		},
 		methods:{
 			toBack(){
-				uni.reLaunch({
+				uni.redirectTo({
 					url:'/pages/questionnaire'
 				})
 			},

+ 177 - 0
pages/report.vue

@@ -0,0 +1,177 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='我的报告'></cus-header>
+		<div class="tabs adf">
+			<div class="t_pre" :class="{'active':tidx===2}" @tap="changeTab(2)">个人报告</div>
+			<div class="t_pre" :class="{'active':tidx===1}" @tap="changeTab(1)">团队报告</div>
+		</div>
+		<template v-if="list.length">
+			<div class="list">
+				<div class="l_item" v-for="(item,index) in list" :key="index">
+					<div class="li_title">{{item.reportName||''}}</div>
+					<div class="li_pre">报告时间:<span>{{item.createDate||''}}</span></div>
+					<div class="li_pre" v-if="item.type==1">作答人数:<span>{{item.answerNum||0}}/{{item.finishNum||0}}</span></div>
+					<div class="li_pre">团队名称:<span>{{item.teamName||''}}</span></div>
+					<div class="li_jd adfacjb" v-if="item.type==1">
+						<div class="lj_l">
+							<div class="ljl_box" :style="{'width':((item.answerNum||0)/(item.finishNum||0)*100)+'%'}"></div>
+						</div>
+						<div class="lj_r">进度<span>{{item.answerNum||0}}/{{item.finishNum||0}}</span></div>
+					</div>
+					<div class="li_view">查看</div>
+				</div>
+			</div>
+		</template>
+		<template v-else>
+			<page-empty :height="'calc(100vh - 200px)'"></page-empty>
+		</template>
+	</view>
+</template>
+
+<script>
+	import pageEmpty from '@/components/pageEmpty/index.vue'
+	export default {
+		components:{ pageEmpty },
+		data(){
+			return {
+				tidx:2,
+				list:[]
+			}
+		},
+		onLoad() {
+			this.getReportList();
+		},
+		methods:{
+			changeTab(idx){
+				this.tidx = idx;
+				this.getReportList();
+			},
+			getReportList(){
+				this.$api.get('/core/report/member/personalReportList/'+this.tidx).then(res=>{
+					if(res.data.code!==0) return this.$showToast(res.data.msg)
+					this.list = res.data.data;
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		background: #F7F7F7;
+		padding-bottom: 40rpx;
+		box-sizing: border-box;
+		
+		.tabs{
+			width: 100%;
+			height: 90rpx;
+			background: #FFFFFF;
+			.t_pre{
+				width: 50%;
+				height: 90rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #666666;
+				line-height: 90rpx;
+				text-align: center;
+				position: relative;
+				&.active{
+					color: #761E6A;
+					&::after{
+						content: '';
+						width: 148rpx;
+						height: 6rpx;
+						background: #761E6A;
+						border-radius: 9rpx;
+						position: absolute;
+						left: 50%;
+						margin-left: -74rpx;
+						bottom: 0;
+					}
+				}
+			}
+		}
+	
+		.list{
+			padding: 0 24rpx;
+			overflow: hidden;
+			.l_item{
+				margin-top: 20rpx;
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				padding: 40rpx 24rpx;
+				position: relative;
+				.li_title{
+					width: calc(100% - 100rpx);
+					font-family: PingFang-SC, PingFang-SC;
+					font-weight: bold;
+					font-size: 30rpx;
+					color: #252525;
+					line-height: 30rpx;
+					overflow: hidden;
+					text-overflow: ellipsis;
+					white-space: nowrap;
+				}
+				.li_pre{
+					margin-top: 40rpx;
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #86909C;
+					line-height: 26rpx;
+					overflow: hidden;
+					text-overflow: ellipsis;
+					white-space: nowrap;
+					span{
+						color: #1D2129;
+					}
+				}
+				.li_jd{
+					margin-top: 27rpx;
+					.lj_l{
+						width: calc(100% - 181rpx);
+						height: 10rpx;
+						background: #EFEFEF;
+						border-radius: 5rpx;
+						position: relative;
+						.ljl_box{
+							height: 100%;
+							background: #FFD750;
+							border-radius: 5rpx;
+							position: absolute;
+							left: 0;
+							top: 0;
+						}
+					}
+					.lj_r{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #A6A6A6;
+						line-height: 24rpx;
+						span{
+							color: #1D2129;
+							margin-left: 8rpx;
+						}
+					}
+				}
+				.li_view{
+					width: 88rpx;
+					height: 54rpx;
+					background: #833478;
+					border-radius: 24rpx;
+					font-family: PingFang-SC, PingFang-SC;
+					font-weight: bold;
+					font-size: 24rpx;
+					color: #FFFFFF;
+					line-height: 54rpx;
+					text-align: center;
+					position: absolute;
+					top: 40rpx;
+					right: 24rpx;
+				}
+			}
+		}
+	}
+</style>

BIN
static/tab_home.png


BIN
static/tab_home_active.png


BIN
static/tab_my.png


BIN
static/tab_my_active.png


BIN
static/tab_qa.png


BIN
static/tab_qa_active.png


BIN
static/tab_wj.png


BIN
static/tab_wj_active.png