Files
AI/middle.html

1026 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"">
<title>飒沓光伏智能体</title>
<meta property=" og:title" content="飒沓光伏智能体">
<meta property="og:description" content="SataBot Agent 是一款由人工智能驱动的光伏场景AI应用程序。">
<meta property="og:image" content="http://1.95.137.212:19000/mbzn/16%3A33%3A49123.png">
<!-- <script src=" https://unpkg.com/vconsole@latest/dist/vconsole.min.js"> -->
</script>
<link rel="prefetch" href="index.html">
<style>
:root {
--bg1: #eaf6ff;
--card-bg: rgba(255, 255, 255, 0.85);
--green: #1ac167;
--muted: #6b7280;
--shadow: 0 18px 50px rgba(16, 64, 92, 0.08);
font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft Yahei", Arial, sans-serif;
}
* {
box-sizing: border-box
}
html,
body {
height: 100%;
margin: 0
}
body {
display: flex;
align-items: center;
justify-content: center;
background: #fff;
padding: 28px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.fadeout {
opacity: 0;
transition: opacity .3s ease;
}
body {
opacity: 1;
transition: opacity .3s ease;
}
.wrap {
width: 100%;
max-width: 560px;
border-radius: 14px;
padding: 56px 48px;
text-align: center;
position: relative;
top: -15%;
}
.logo {
width: 92px;
height: 92px;
overflow: hidden;
margin: 0 auto 18px;
display: flex;
align-items: center;
justify-content: center;
}
.logo img {
width: 72px;
height: 72px;
object-fit: contain;
display: block
}
h1 {
margin: 6px 0 12px;
font-size: 36px;
font-weight: 600;
color: #333;
letter-spacing: 1px;
font-family: cursive;
}
.sloagan {
font-size: 14px;
font-weight: 500;
color: #999;
letter-spacing: 2px;
padding: 0px;
margin: 0px;
}
.agree {
display: flex;
align-items: center;
gap: 12px;
justify-content: flex-start;
margin: 22px auto 28px;
max-width: 420px;
color: var(--muted);
font-size: 14px
}
.agree input {
width: 18px;
height: 18px
}
.agree a {
color: #0b84b5;
text-decoration: none
}
.btn {
display: inline-block;
padding: 14px 48px;
border-radius: 40px;
background: linear-gradient(90deg, var(--green), #12b06c);
color: white;
font-weight: 700;
border: 0;
cursor: pointer;
font-size: 16px;
box-shadow: 0 12px 30px rgba(26, 193, 103, 0.18);
transition: transform .12s ease, opacity .12s ease;
}
.btn:active {
transform: translateY(1px)
}
.btn[disabled] {
opacity: 0.6;
cursor: not-allowed;
box-shadow: none
}
.subtle {
font-size: 13px;
color: var(--muted);
margin-top: 18px
}
.popbox {
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.4);
z-index: 999999;
}
.popbox .loading-box {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 999999999;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
opacity: 0.7;
}
.popbox .loading-box.none {
display: none;
}
.popbox .loading-box .loading {
border: solid #e2e8f0;
/* 浅灰色边框 */
border-top-color: #165DFF;
/* 蓝色顶部边框 */
border-radius: 50%;
animation: spin 1s linear infinite;
/* 旋转动画 */
display: inline-block;
margin-bottom: 20px;
width: 30px;
height: 30px;
}
#sms-form {
background-color: #fff;
border-radius: 8px;
padding: 10px;
position: relative;
}
.toast {
position: fixed;
top: 20%;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.8);
color: #fff;
padding: 10px 18px;
border-radius: 8px;
font-size: 15px;
opacity: 0;
transition: opacity 0.3s ease;
z-index: 9999999999;
}
.toast.show {
opacity: 1;
}
.toast.success {
background-color: #09db45;
}
@media (max-width:520px) {
.wrap {
padding: 36px 20px
}
.agree {
justify-content: center
}
}
.weixin-loading {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
position: fixed;
z-index: 99999;
background-color: #fff;
top: 0px;
left: 0px;
opacity: 0.7;
}
.weixin-loading.none {
display: none;
}
.weixin-loading .loading {
border: solid #e2e8f0;
/* 浅灰色边框 */
border-top-color: #165DFF;
/* 蓝色顶部边框 */
border-radius: 50%;
animation: spin 1s linear infinite;
/* 旋转动画 */
display: inline-block;
margin-bottom: 20px;
width: 30px;
height: 30px;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
</style>
<style>
* {
touch-action: manipulation;
/* 允许平移和捏合缩放,但禁用双击缩放和长按 */
-webkit-tap-highlight-color: transparent;
/* 移除点击时的默认高亮(可选,优化体验) */
}
body {
margin: 0;
font-family: "Segoe UI", "PingFang SC", Arial, sans-serif;
height: 100vh;
display: flex;
color: #333;
width: 100%;
}
.none {
display: none;
}
.stopBtn {
width: 36px;
height: 36px;
}
.none {
display: none;
}
.input-group {
display: flex;
align-items: center;
padding: 0px 5px;
border: 1px solid #ccc;
border-radius: 8px;
margin-bottom: 10px;
}
.area-select {
width: 130px;
font-size: 14px;
color: #333;
cursor: pointer;
}
input {
/* flex: 1; */
border: none;
outline: none;
font-size: 14px;
}
/* 获取验证码按钮 */
.code-btn {
border: none;
/* border: 1px solid #1890ff; */
background: white;
padding: 5px 12px;
border-radius: 6px;
color: #1890ff;
cursor: pointer;
font-size: 14px;
width: 135px;
}
/* 登录按钮 */
.login-btn {
margin-top: 25px;
width: 100%;
background: #1890ff;
color: white;
padding: 12px 0;
border-radius: 10px;
border: none;
font-size: 17px;
cursor: pointer;
}
/* 协议 */
.agreement {
margin-top: 15px;
font-size: 12px;
color: #777;
display: flex;
align-items: center;
gap: 6px;
}
/* 微信登录 */
.wechat-login {
text-align: center;
font-size: 14px;
color: #555;
cursor: pointer;
}
.wechat-login>div {
display: flex;
justify-content: center;
align-items: center;
gap: 2px;
}
.wechat-login img {
width: 38px;
display: block;
margin: 0 auto 5px;
}
/* 区号选择框 */
.mask {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
}
.area-box {
background: #fff;
position: absolute;
bottom: 0;
width: 100%;
max-height: 300px;
overflow-y: auto;
border-radius: 10px 10px 0 0;
}
.area-item {
padding: 15px;
border-bottom: 1px solid #eee;
font-size: 16px;
cursor: pointer;
}
.area-item:hover {
background: #f5f5f5;
}
.toggle-eye {
position: absolute;
right: 10px;
top: 10px;
}
.link {
color: #1677ff;
cursor: pointer;
}
.wechat-login {
display: flex;
justify-content: space-between;
font-size: 12px;
color: #666;
margin-bottom: 10px;
}
.wechat-login span:nth-child(1) {
margin-right: 8px;
}
.popbox {
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.4);
z-index: 999999;
}
.popbox .loading-box {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 999999999;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
opacity: 0.7;
}
.popbox .loading-box.none {
display: none;
}
.popbox .loading-box .loading {
border: solid #e2e8f0;
/* 浅灰色边框 */
border-top-color: #165DFF;
/* 蓝色顶部边框 */
border-radius: 50%;
animation: spin 1s linear infinite;
/* 旋转动画 */
display: inline-block;
margin-bottom: 20px;
width: 30px;
height: 30px;
}
#sms-form {
background-color: #fff;
border-radius: 8px;
padding: 10px;
position: relative;
}
</style>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
#sms-button {
padding: 12px;
}
.popup {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
width: 400px;
}
.popup h2 {
margin-top: 0;
font-size: 18px;
margin-bottom: 15px;
}
input,
select,
button {
width: 100%;
padding: 8px;
margin: 5px 0;
border-radius: 4px;
border: 1px solid #ccc;
}
input {
border: none;
}
#popupForm input {
border: 1px solid #ccc !important;
width: 94%;
}
.options {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin: 10px 0;
}
.option {
/* flex: 1 1 calc(50% - 5px); */
width: 28%;
text-align: center;
padding: 8px;
background: #f0f0f0;
border-radius: 4px;
cursor: pointer;
user-select: none;
}
.option.selected {
background: #007bff;
color: white;
}
button {
background: #007bff;
color: white;
border: none;
cursor: pointer;
}
@media (max-width: 768px) {
.popup {
position: absolute;
top: 50px;
width: 90%;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
}
</style>
</head>
<body>
<div class="wrap" role="main" aria-labelledby="title">
<div class="logo" aria-hidden>
<img src="./img/logo.png" alt="飒沓 logo">
</div>
<h1 id="title">飒沓智能</h1>
<p class="sloagan">沐光而立,顺风顺水</p>
<div style="height:8px"></div>
<div class="weixin-loading none">
<div class="loading">
</div>
</div>
<!-- <label class="agree" for="agreeChk">
<input type="checkbox" id="agreeChk" />
<div style="line-height:1.35">已阅读并同意
<a href="#" onclick="return false">服务协议</a>、
<a href="#" onclick="return false">隐私政策</a>
</div>
</label> -->
<!-- <div>
<button id="loginBtn" class="btn" onclick="handlelogin()">授权登录</button>
</div> -->
<!-- <div class="subtle">使用微信扫码或微信内授权登录。为保障账号安全,请勿在不信任的设备上授权。</div> -->
</div>
<script>
// 开启 vConsole 调试面板
// var vConsole = new VConsole();
// wx364b8ebf17fe45fe wx0eeb7556d60121db
// console.log("✅ vConsole 已经启动");
const params = new URLSearchParams(window.location.search);
const code = params.get("code");
let countTimer;
let userInfo = null;
let userId;
handleCode(code);
handlelogin();
// localStorage.removeItem("userInfo");
// localStorage.removeItem("userId");
function handlelogin() {
if (document.querySelector('.weixin-loading').classList.contains("none")) {
document.querySelector('.weixin-loading').classList.remove("none");
}
if (code) return;
// if (localStorage.getItem("userInfo") && localStorage.getItem("userId")) {
// const userId = localStorage.getItem("userId");
// const nickname = JSON.parse(localStorage.getItem("userInfo")).nickname;
// const imgurl = JSON.parse(localStorage.getItem("userInfo")).headimgurl;
// console.log(userId, nickname, imgurl);
// document.body.classList.add('fadeout');
// // return;
// window.location.replace(`https://ai.satabot.com?userId=${userId}&headingimg=${imgurl}&nickname=${nickname}&t=${Date.now()}`);
// return;
// }
const APP_ID = 'wxa957108dae7d9048';
const REDIRECT_URI = encodeURIComponent("https://ai.satabot.com/middle.html");
// const REDIRECT_URI = encodeURIComponent("https://ai.satabot.com/middle.html");
const STATE = Math.random().toString(36).substring(2, 12);
const SCOPE = 'snsapi_userinfo';
// const authUrl = `https://open.weixin.qq.com/connect/qrconnect?appid=${APP_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=${SCOPE}&state=${STATE}#wechat_redirect`;
// window.location.href = authUrl; // 跳转后页面刷新,后续代码不执行
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${APP_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=${SCOPE}&state=${STATE}&connect_redirect=1#wechat_redirect`
}
function handleCode(code) {
if (!code) return;
retryFetch(`https://servicestream.satabot.com/api/wechat/access_token?code=${code}`)
.then(res => {
userInfo = res;
console.log(res);
localStorage.setItem("userInfo", JSON.stringify(res));
// test(res.openid)
getUserByOpenId(res.openid)
}).catch(() => {
if (!document.querySelector('.weixin-loading').classList.contains("none")) {
document.querySelector('.weixin-loading').classList.add("none");
}
}).finally(() => {
})
}
function test(id) {
console.log(id);
const data = {
sourceType: 5,
openId: id,
phonenumber: '',
smsCode: '',
loginPlatForm: 2
}
retryFetch("https://serviceri.satabot.com/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(res => {
if (res.code == 300) {
// showpop(); // 弹出验证码
// const _token = "BEAR DHWJDBJDKWJDBDNJEWHBD"
// setCookie('token', _token);
// const encodedUserId = btoa(unescape(encodeURIComponent("138")));
// localStorage.setItem('userId', encodedUserId);
// const t = Date.now();
// document.body.classList.add('fadeout');
// window.location.replace(`https://ai.satabot.com?userId=${encodedUserId}&headingimg=${userInfo.headimgurl}&nickname=${userInfo.nickname}&localtoken=${_token}&t=${t}`)
} else if (res.code == 200) {
setCookie('token', res.token);
const encodedUserId = btoa(unescape(encodeURIComponent(res.userId)));
localStorage.setItem('userId', encodedUserId);
const t = Date.now();
document.body.classList.add('fadeout');
window.location.replace(`https://ai.satabot.com?userId=${encodedUserId}&headingimg=${userInfo.headimgurl}&nickname=${userInfo.nickname}&localtoken=${res.token}&t=${t}`)
}
})
.catch(err => {
console.error("登录请求失败(重试10次后):", err);
showToast("网络异常,请稍后再试");
})
.finally(() => {
console.log("登录请求结束");
// if (!document.querySelector('.weixin-loading').classList.contains("none")) {
// document.querySelector('.weixin-loading').classList.add("none");
// }
});
}
function getUserByOpenId(id) {
const data = {
sourceType: 5,
openId: id,
phonenumber: '',
smsCode: '',
loginPlatForm: 2
}
retryFetch("https://serviceri.satabot.com/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(res => {
if (res.code == 300) {
// showpop(); // 弹出验证码
// const _token = "BEAR DHWJDBJDKWJDBDNJEWHBD"
// setCookie('token', _token);
// const encodedUserId = btoa(unescape(encodeURIComponent("138")));
// localStorage.setItem('userId', encodedUserId);
// const t = Date.now();
// document.body.classList.add('fadeout');
// window.location.replace(`https://ai.satabot.com?userId=${encodedUserId}&headingimg=${userInfo.headimgurl}&nickname=${userInfo.nickname}&localtoken=${_token}&t=${t}`)
} else if (res.code == 200) {
setCookie('token', res.token);
const encodedUserId = btoa(unescape(encodeURIComponent(res.userId)));
localStorage.setItem('userId', encodedUserId);
const t = Date.now();
document.body.classList.add('fadeout');
window.location.replace(`https://ai.satabot.com?userId=${encodedUserId}&headingimg=${userInfo.headimgurl}&nickname=${userInfo.nickname}&localtoken=${res.token}&t=${t}`)
}
})
.catch(err => {
console.error("登录请求失败(重试10次后):", err);
showToast("网络异常,请稍后再试");
})
.finally(() => {
console.log("登录请求结束");
if (!document.querySelector('.weixin-loading').classList.contains("none")) {
document.querySelector('.weixin-loading').classList.add("none");
}
});
}
async function retryFetch(url, options, maxRetry = 10) {
let lastError;
for (let i = 0; i < maxRetry; i++) {
try {
console.log(`登录请求第 ${i + 1} 次尝试...`);
const response = await fetch(url, options);
return await response.json();
} catch (err) {
lastError = err;
console.warn(`第 ${i + 1} 次尝试失败:`, err);
// 最后一次重试失败 → 抛出错误
if (i === maxRetry - 1) throw err;
// 重试前延迟 300ms
await new Promise(res => setTimeout(res, 1000));
}
}
throw lastError;
}
function setCookie(name, value, days = 7) {
const d = new Date();
d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
const expires = "expires=" + d.toUTCString();
document.cookie = `${name}=${encodeURIComponent(value)}; ${expires}; path=/`;
}
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) return decodeURIComponent(match[2]);
return null;
}
function showpop() {
let html = `<div class='popbox'>
<div class="form sms-form" id="sms-form">
<div class="loading-box none">
<div class="loading"></div>
</div>
<h2 style='margin:0px'>欢迎使用光伏运维智能体</h2>
<p style='color:#666;margin:13px 0px;'>请先绑定手机号</p>
<div class="input-group">
<div class="area-select" onclick="showAreaSelect()">
<span id="areaText">中国大陆 +86</span>
</div>
<input id="sys-phone" type="text" placeholder="请输入手机号">
</div>
<!-- 验证码登录 -->
<div id="codeLogin" class="input-group">
<input id="code" type="text" placeholder="请输入验证码">
<button class="code-btn" id="send-code" onclick="getSms()">获取验证码</button>
</div>
<div class="form-group">
<button type="button" class="button button-primary" id="sms-button" onclick="bindToLogin()">
<!-- <i class="fas fa-user-plus mr-2"></i> -->
绑定
</button>
</div>
</div></div>`;
document.body.insertAdjacentHTML('beforeend', html);
}
function showToast(message, type = '') {
// 创建元素
const toast = document.createElement("div");
toast.className = `toast${type == "success" ? " success" : ""}`;
toast.innerText = message;
document.body.appendChild(toast);
// 显示
setTimeout(() => {
toast.classList.add("show");
}, 10);
// 2 秒后自动消失
setTimeout(() => {
toast.classList.remove("show");
setTimeout(() => toast.remove(), 300); // 动画结束后移除
}, 2000);
}
function getSms() {
document.getElementById('send-code').textContent = "60s";
let remainSeconds = 60;
countTimer = setInterval(() => {
if (remainSeconds > 0) {
remainSeconds--;
document.getElementById('send-code').textContent = `${remainSeconds}s`;
document.getElementById('send-code').disabled = true;
} else {
clearInterval(countTimer);
countTimer = null;
document.getElementById('send-code').textContent = "获取验证码";
document.getElementById('send-code').disabled = false;
}
}, 1000)
const phonenumber = document.getElementById('sys-phone').value;
const bindParams = {
phoneNumbers: phonenumber,
}
retryFetch("https://serviceri.satabot.com/external/sms/sendAliSmsCode", {
method: "POST", // 必选:指定请求方法为 POST
headers: {
"Content-Type": "application/json", // 声明请求体是 JSON 格式
// 可选:如果接口需要 Token 前置验证,可添加 Authorization 头
// "Authorization": "Bearer 你的前置 Token"
},
// 必选:请求体,将参数对象转为 JSON 字符串(不能直接传对象)
body: JSON.stringify(bindParams)
}).then(res => {
showToast("验证码发送成功");
if (res.code == 200) {
// showToast("验证码发送成功");
} else {
// showToast(res.msg + "yanzssahnegma");
// clearInterval(countTimer);
// countTimer = null;
// document.getElementById('send-code').textContent = "获取验证码";
// document.getElementById('send-code').disabled = false;
// return;
}
console.log(res);
}).catch(err => {
showToast(err + "验证码发送失败");
clearInterval(countTimer);
countTimer = null;
document.getElementById('send-code').textContent = "获取验证码";
document.getElementById('send-code').disabled = false;
return;
})
}
function unshowpop() {
if (countTimer) {
clearInterval(countTimer);
}
const popbox = document.querySelector('.popbox');
if (popbox) {
popbox.remove();
}
}
function bindToLogin() {
document.querySelector('.popbox .loading-box').classList.remove('none');
const data = {
sourceType: 5,
openId: userInfo.openid,
phonenumber: document.getElementById('sys-phone').value,
smsCode: document.getElementById('code').value,
loginPlatForm: 3
}
retryFetch("https://serviceri.satabot.com/login", {
// fetch("/api/remote/login", {
method: "POST", // 必选:指定请求方法为 POST
headers: {
"Content-Type": "application/json", // 声明请求体是 JSON 格式
// 可选:如果接口需要 Token 前置验证,可添加 Authorization 头
// "Authorization": "Bearer 你的前置 Token"
},
// 必选:请求体,将参数对象转为 JSON 字符串(不能直接传对象)
body: JSON.stringify(data)
}).then(res => {
console.log(res, "绑定信息")
if (res.code == 200) {
if (document.querySelector('.popbox .loading-box')) {
document.querySelector('.popbox .loading-box').classList.add('none');
}
userId = res.userId;
setCookie('token', res.token);
unshowpop();
const encodedUserId = btoa(unescape(encodeURIComponent(res.userId)));
localStorage.setItem("userId", encodedUserId)
const t = Date.now();
document.body.classList.add('fadeout');
window.location.replace(`https://ai.satabot.com?userId=${encodedUserId}&headingimg=${userInfo.headimgurl}&nickname=${userInfo.nickname}&localtoken=${res.token}&t=${t}`)
} else {
showToast(res.msg); // 给用户友好提示
}
}).catch(err => {
console.error("请求异常:", err);
showToast("登录失败,请重试" + err); // 给用户友好提示
})
.finally(() => {
unshowpop();
if (document.querySelector('.popbox .loading-box')) {
document.querySelector('.popbox .loading-box').classList.add('none');
}
});
}
</script>
<script>
</script>
</body>
</html>