<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: 10000,
						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>