<template>
	<view class="content" ref="scrollView">
		<view class="chat">
			<view class="conversation" v-for="item in sparkResult">
				<view class="question">
					<view class="text">{{item.question}}</view>
					<u-avatar class="avatar" bg-color="#2b7" size="25" icon="account-fill" fontSize="20"></u-avatar>
				</view>
				<view class="answer">
					<view class="avatar">
						<image class="img" src="../../static/logo.png" mode=""></image>
					</view>
					<view class="text">{{item.answer}}</view>
				</view>
			</view>
		</view>
		<view class="btn">
			<u-input v-model="TEXT" placeholder="问我任何问题...">
				<template slot="suffix">
					<u-button @click="sendToSpark()" type="success" size="mini" icon="checkmark"
					shape="circle"></u-button>
				</template>
			</u-input>
		</view>
	</view>
</template>

<script>
	import CryptoJS from 'crypto-js';
	import setting from '@/setting.js';
	const base64 = require('js-base64').Base64
	export default {
		data() {
			return {
				TEXT: '',
				// V1.1-V3.5动态获取，高于以上版本手动指定
				modelDomain:'',
				wsLiveFlag: false,
				sparkResult: [],
				historyTextList: [], // 历史会话信息，由于最大token12000,可以结合实际使用，进行移出
				tempRes: '' // 临时答复保存
			}
		},
		methods: {
			async sendToSpark() {
				if(this.TEXT==""){
					uni.showToast({
						title:"输入框不能为空",
						icon:"none"
					})
					return
				}
				let myUrl = await this.getWebSocketUrl();
				this.tempRes = "";
	
				this.socketTask = uni.connectSocket({
					url: myUrl,
					method: 'GET',
					success: res => {
						console.log(res, "ws成功连接...", myUrl)
						this.wsLiveFlag = true;
					}
				})
				this.socketTask.onError((res) => {
					console.log("连接发生错误，请检查appid是否填写", res)
				})
				this.socketTask.onOpen((res) => {
					this.historyTextList.push({
						"role": "user",
						"content": this.TEXT
					})
					// 第一帧..........................................
					let params = {
						"header": {
							"app_id": setting.APPID,
							"uid": "aef9f963-7"
						},
						"parameter": {
							"chat": {
								"domain": this.modelDomain,
								"temperature": 0.5,
								"max_tokens": 1024
							}
						},
						"payload": {
							"message": {
								"text": this.historyTextList
							}
						}
					};
					this.sparkResult.push({
						question:this.TEXT,
						answer:"思考中..."
					})
					this.socketTask.send({ // 发送消息，，都用uni的官方版本
						data: JSON.stringify(params),
						success:()=>{
							this.TEXT = ""
							console.log('第一帧发送成功')
						}
					});
				});
		
				// 接受到消息时
				this.socketTask.onMessage((res) => {
					let obj = JSON.parse(res.data)
					let dataArray = obj.payload.choices.text;
					if(this.sparkResult[this.sparkResult.length-1].answer=='思考中...'){
						this.sparkResult[this.sparkResult.length-1].answer=""
					}
					for (let i = 0; i < dataArray.length; i++) {
						this.sparkResult[this.sparkResult.length-1].answer += dataArray[i].content//动态拼接并显示回复的消息
						this.tempRes = this.tempRes + dataArray[i].content
					}
					uni.pageScrollTo({
						scrollTop: 999999999,
						duration: 300
					});
					let temp = JSON.parse(res.data)
					
					if (temp.header.code !== 0) {
						this.socketTask.close({
							success(res) {
								console.log('关闭成功', res)
								this.wsLiveFlag = false;
							},
							fail(err) {
								console.log('关闭失败', err)
							}
						})
					} else {
						if (res.data && temp.header.status === 2) {
							this.historyTextList.push({
								"role": "assistant",
								"content": this.tempRes
							})
							setTimeout(() => {
								this.socketTask.close({
									success(res) {
										console.log('关闭成功', res)
									},
									fail(err) {
										console.log('关闭失败', err)
									}
								})
							}, 1000)
						}
					}
				})
			},
			// 鉴权
			getWebSocketUrl() {
				var httpUrlHost = (setting.httpUrl).substring(8, 28);
				var httpUrlPath = (setting.httpUrl).substring(28);
		
				switch (httpUrlPath) {
					case "/v1.1/chat":
						this.modelDomain = "general";
						break;
					case "/v2.1/chat":
						this.modelDomain = "generalv2";
						break;
					case "/v3.1/chat":
						this.modelDomain = "generalv3";
						break;
					case "/v3.5/chat":
						this.modelDomain = "generalv3.5";
						break;
				}
		
				return new Promise((resolve, reject) => {
					// https://spark-api.xf-yun.com/v1.1/chat  V1.5 domain general
					// https://spark-api.xf-yun.com/v2.1/chat  V2.0 domain generalv2
					var url = "wss://"+httpUrlHost+httpUrlPath;
					var host = "spark-api.xf-yun.com";
					var apiKeyName = "api_key";
					var date = new Date().toGMTString();
					var algorithm = "hmac-sha256";
					var headers = "host date request-line";
					var signatureOrigin = `host: ${host}\ndate: ${date}\nGET ${httpUrlPath} HTTP/1.1`;
					var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, setting.APISecret);
					var signature = CryptoJS.enc.Base64.stringify(signatureSha);
					var authorizationOrigin =
						`${apiKeyName}="${setting.APIKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
					var authorization = base64.encode(authorizationOrigin);
					url = `${url}?authorization=${authorization}&date=${encodeURI(date)}&host=${host}`;
		
					resolve(url); // 主要是返回地址
				});
			},
		}
	}
</script>

<style lang="scss" scoped>
	// page{
	// 	background: #fff;
	// }
	.content{
		padding: 20rpx 20rpx 100rpx 20rpx;
		.chat{
			.conversation{
				.question{
					display: flex;
					align-items: center;
					justify-content: flex-end;
					margin-bottom: 20rpx;
					.avatar{
						align-self:  normal;
					}
					.text{
						max-width: 80%;
						margin-right: 10rpx;
						background: #fff;
						padding: 20rpx;
						box-sizing: border-box;
						border-radius: 20rpx;
					}
				}
				.answer{
					display: flex;
					align-items: center;
					margin-bottom: 20rpx;
					.avatar{
						width: 50rpx;
						height: 50rpx;
						display: flex;
						align-items: center;
						justify-content: center;
						background: #fff;
						border: 1px solid #eee;
						border-radius: 25rpx;
						margin-right: 10rpx;
						align-self:  normal ;
						.img{
							width: 40rpx;
							height: 40rpx;
						}
					}
				}
				.text{
					max-width: 80%;
					word-break: break-word;
					background: #fff;
					padding: 20rpx;
					box-sizing: border-box;
					border-radius: 20rpx;
				}
			}
		}
		.btn{
			position: fixed;
			border-radius: 20rpx;
			width: 100%;
			bottom: var(--window-bottom);
			left: 0;
			background: #fff;
		}
	}

</style>
