1219 lines
38 KiB
HTML
Executable File
1219 lines
38 KiB
HTML
Executable File
<!DOCTYPE html>
|
||
<html lang="zh">
|
||
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>新能源运维智能体</title>
|
||
<style>
|
||
body {
|
||
margin: 0;
|
||
font-family: "Segoe UI", "PingFang SC", Arial, sans-serif;
|
||
height: 100vh;
|
||
display: flex;
|
||
background: #f0f6fb;
|
||
color: #333;
|
||
|
||
}
|
||
|
||
/* 侧边栏 */
|
||
.sidebar {
|
||
width: 240px;
|
||
background: #ffffff;
|
||
border-right: 1px solid #e3eaf2;
|
||
display: flex;
|
||
flex-direction: column;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.04);
|
||
z-index: 10;
|
||
}
|
||
|
||
.sidebar.collapsed {
|
||
width: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.sidebar-header {
|
||
padding: 16px;
|
||
padding-left: 20px;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #0057ff;
|
||
border-bottom: 1px solid #f0f4f8;
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
}
|
||
|
||
.sidebar-header img {
|
||
width: 24px;
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.sidebar-actions {
|
||
padding: 12px;
|
||
border-bottom: 1px solid #f0f4f8;
|
||
}
|
||
|
||
.sidebar-actions button {
|
||
width: 100%;
|
||
padding: 10px;
|
||
border: none;
|
||
border-radius: 8px;
|
||
background: #0057ff;
|
||
color: #fff;
|
||
font-size: 14px;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.sidebar-actions button:hover {
|
||
background: #0046cc;
|
||
}
|
||
|
||
.chat-list {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.chat-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 12px 16px;
|
||
border-bottom: 1px solid #f7f9fb;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
text-align: center;
|
||
}
|
||
|
||
.chat-item:hover {
|
||
background: #f2f8fd;
|
||
}
|
||
|
||
.chat-item.active {
|
||
background: #e6f0ff;
|
||
font-weight: bold;
|
||
color: #0057ff;
|
||
}
|
||
|
||
.chat-title {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.delete-btn {
|
||
margin-left: 8px;
|
||
color: #aaa;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.delete-btn:hover {
|
||
color: #e74c3c;
|
||
}
|
||
|
||
/* 收起按钮(独立漂浮在左边) */
|
||
.toggle-btn {
|
||
position: absolute;
|
||
top: 10px;
|
||
left: 190px;
|
||
background: #0057ff;
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 50%;
|
||
width: 40px;
|
||
height: 40px;
|
||
font-size: 18px;
|
||
cursor: pointer;
|
||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
||
z-index: 20;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.toggle-btn:hover {
|
||
background: #0046cc;
|
||
}
|
||
|
||
/* 右侧聊天区域 */
|
||
.chat-container {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: #f9fcff;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.chat-container .content {
|
||
height: 70%;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.chat-header {
|
||
height: 50px;
|
||
padding: 1px 20px;
|
||
padding-left: 22px;
|
||
background: #fff;
|
||
border-bottom: 1px solid #e3eaf2;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #0057ff;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
}
|
||
|
||
.chat-header .back {
|
||
display: none;
|
||
}
|
||
|
||
.chat-messages {
|
||
flex: 1;
|
||
padding: 20px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.message {
|
||
|
||
|
||
max-width: 70%;
|
||
margin-bottom: 16px;
|
||
padding: 12px 16px;
|
||
border-radius: 14px;
|
||
font-size: 16px;
|
||
line-height: 1.5;
|
||
/* white-space: pre-wrap;*/
|
||
white-space: normal;
|
||
word-wrap: break-word;
|
||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||
animation: fadeIn 0.3s ease;
|
||
}
|
||
|
||
.message.user {
|
||
display: block;
|
||
background: #d4e5ff;
|
||
color: #000;
|
||
align-self: flex-end;
|
||
border-bottom-right-radius: 4px;
|
||
|
||
display: block;
|
||
width: fit-content;
|
||
}
|
||
|
||
.message.assistant {
|
||
max-width: 100%;
|
||
background: #fff;
|
||
color: #333;
|
||
align-self: flex-start;
|
||
border: 1px solid #e6eaf0;
|
||
border-bottom-left-radius: 4px;
|
||
}
|
||
|
||
.message img {
|
||
max-width: 200px;
|
||
border-radius: 8px;
|
||
margin-top: 8px;
|
||
}
|
||
|
||
.chat-input {
|
||
padding: 12px;
|
||
background: #fff;
|
||
border-top: 1px solid #e3eaf2;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
.message.thinking {
|
||
width: auto;
|
||
/* 宽度自适应内容 */
|
||
max-width: 40%;
|
||
/* 限制最大宽度 */
|
||
}
|
||
|
||
.input-row {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
}
|
||
|
||
.none {
|
||
display: none;
|
||
}
|
||
|
||
.input-row .img-row {
|
||
width: 100%;
|
||
min-width: 0px;
|
||
min-height: 0px;
|
||
box-sizing: border-box;
|
||
padding: 10px;
|
||
|
||
}
|
||
|
||
.input-row .img-box .delete-btn {
|
||
position: absolute;
|
||
right: -5px;
|
||
top: -5px;
|
||
|
||
}
|
||
|
||
.input-row .img-box {
|
||
width: 40px;
|
||
position: relative
|
||
}
|
||
|
||
|
||
|
||
.input-row img {
|
||
width: 40px;
|
||
height: 40px;
|
||
border-radius: 5px;
|
||
|
||
}
|
||
|
||
|
||
.chat-input textarea {
|
||
flex: 1;
|
||
resize: none;
|
||
padding: 10px;
|
||
border-radius: 8px;
|
||
border: 1px solid #d9e4f0;
|
||
font-size: 14px;
|
||
outline: none;
|
||
background: #f9fcff;
|
||
transition: border 0.2s;
|
||
width: 100%;
|
||
}
|
||
|
||
.chat-input textarea:focus {
|
||
/* border-color: #0057ff; */
|
||
}
|
||
|
||
.chat-input button {
|
||
padding: 10px 16px;
|
||
border: none;
|
||
border-radius: 8px;
|
||
background: #0057ff;
|
||
color: #fff;
|
||
font-size: 14px;
|
||
cursor: pointer;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.chat-input button:hover {
|
||
background: #0046cc;
|
||
}
|
||
|
||
.options-row {
|
||
display: flex;
|
||
gap: 10px;
|
||
align-items: center;
|
||
font-size: 13px;
|
||
}
|
||
|
||
select,
|
||
input[type="file"] {
|
||
font-size: 13px;
|
||
padding: 4px 6px;
|
||
border: 1px solid #d9e4f0;
|
||
border-radius: 6px;
|
||
background: #fff;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(5px);
|
||
}
|
||
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
|
||
/* 修改后的输入框样式 - 豆包/腾讯元宝风格 */
|
||
.chat-input {
|
||
padding: 16px;
|
||
background: #fff;
|
||
border-top: 1px solid #e8e8e8;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
.input-row {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
justify-content: flex-end;
|
||
/* 底部对齐 */
|
||
gap: 8px;
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.input-row .button-row {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: flex-end;
|
||
justify-content: space-between;
|
||
gap: 12px;
|
||
width: 100%;
|
||
margin-right: 10px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.input-row .button-row>div {
|
||
cursor: pointer;
|
||
width: 40px;
|
||
height: 40px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
margin-left: 12px;
|
||
}
|
||
|
||
.chat-input textarea {
|
||
flex: 1;
|
||
resize: none;
|
||
padding: 12px 16px;
|
||
|
||
|
||
font-size: 14px;
|
||
outline: none;
|
||
background: #fff;
|
||
transition: all 0.2s;
|
||
min-height: 44px;
|
||
max-height: 200px;
|
||
box-shadow: none;
|
||
border: none !important;
|
||
box-sizing: border-box
|
||
}
|
||
|
||
.chat-input textarea:focus {
|
||
/* border-color: #0057ff; */
|
||
/* box-shadow: 0 0 0 2px rgba(0, 87, 255, 0.1); */
|
||
}
|
||
|
||
.chat-input button {
|
||
padding: 10px 16px;
|
||
height: 44px;
|
||
border: none;
|
||
border-radius: 8px;
|
||
background: #0057ff;
|
||
color: #fff;
|
||
font-size: 14px;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.chat-input button:hover {
|
||
background: #0046cc;
|
||
}
|
||
|
||
/* 文件选择和模型选择样式调整 */
|
||
.options-row {
|
||
display: flex;
|
||
gap: 8px;
|
||
align-items: center;
|
||
font-size: 13px;
|
||
}
|
||
|
||
select,
|
||
input[type="file"] {
|
||
font-size: 13px;
|
||
padding: 6px 8px;
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: 6px;
|
||
background: #fff;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
select:focus,
|
||
input[type="file"]:focus {
|
||
border-color: #0057ff;
|
||
outline: none;
|
||
}
|
||
|
||
#fileInput {
|
||
display: none;
|
||
}
|
||
|
||
.mobilelogo {
|
||
display: none;
|
||
}
|
||
|
||
|
||
/* 手机端适配 */
|
||
@media (max-width: 768px) {
|
||
.mobilelogo {
|
||
|
||
display: flex;
|
||
width: 28px;
|
||
height: 28px;
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.sidebar {
|
||
display: none;
|
||
}
|
||
|
||
.chat-container {
|
||
width: 100%;
|
||
height: 100vh;
|
||
}
|
||
|
||
|
||
.chat-input {
|
||
/* position: fixed; */
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 100;
|
||
}
|
||
|
||
.chat-messages {
|
||
padding-bottom: 125px;
|
||
/* 留出输入框空间 */
|
||
}
|
||
|
||
.chat-header .back {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
margin-right: 20px;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
.fourquestion {
|
||
display: flex;
|
||
flex-direction: row;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-bottom: 20px;
|
||
|
||
}
|
||
|
||
.fourquestion>div {
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 10px;
|
||
|
||
}
|
||
|
||
.fourquestion .question {
|
||
width: 350px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 21px;
|
||
color: #999;
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: 10px;
|
||
padding: 24px 10px;
|
||
cursor: pointer;
|
||
|
||
|
||
|
||
}
|
||
|
||
.fourquestion .question:hover {
|
||
background-color: #e5e5e5;
|
||
color: #0057ff;
|
||
|
||
|
||
|
||
}
|
||
|
||
.fourquestion .question img {
|
||
width: 35px;
|
||
height: 35px;
|
||
margin-right: 5px;
|
||
|
||
|
||
}
|
||
|
||
.sidequestion {
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex-wrap: wrap;
|
||
width: 100%;
|
||
display: none;
|
||
|
||
}
|
||
|
||
.sidequestion>div {
|
||
width: 100%;
|
||
|
||
}
|
||
|
||
.sidequestion>div .question {
|
||
width: 80%;
|
||
height: 2px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 16px;
|
||
color: #999;
|
||
border: 1px solid #e5e5e5;
|
||
border-radius: 10px;
|
||
padding: 15px -16px !important;
|
||
cursor: pointer;
|
||
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<!-- 左侧侧边栏 -->
|
||
<div class="sidebar" id="sidebar">
|
||
<button class="toggle-btn" id="toggleBtn" onclick="toggleSidebar()">☰</button>
|
||
<div class="sidebar-header"><img src="./img/logo.png">会话列表</div>
|
||
<div class="sidebar-actions">
|
||
<button onclick="newChat()">+ 新建会话</button>
|
||
</div>
|
||
<div class="chat-list" id="chatList"></div>
|
||
<div class="fourquestion sidequestion">
|
||
<div>
|
||
<div class='question' data-value='分析这个场站' data-pre-value="详细分析这个光伏场站,根据图片给出详细的运维方案"><img src="./img/1.png"
|
||
alt="">分析这个场站</div>
|
||
<div class='question' data-value='详细的清洗计划' data-pre-value="如果这个光伏场站需要用无人机清洗怎么做,给出一份详细的计划"><img
|
||
src="./img/4.png" alt="">详细的清洗计划</div>
|
||
</div>
|
||
<div>
|
||
<div class='question' data-value='详细的巡检计划' data-pre-value="如果这个光伏场站需要巡检怎么做,给出一份详细的计划"><img src="./img/2.png"
|
||
alt="">详细的巡检计划</div>
|
||
<div class='question' data-value='详细的割草计划' data-pre-value="如果这个光伏场站需要割草怎么做,给出一份详细的计划"><img src="./img/3.png"
|
||
alt="">详细的割草计划</div>
|
||
</div>
|
||
|
||
|
||
|
||
</div>
|
||
|
||
|
||
</div>
|
||
|
||
<!-- 收起按钮 -->
|
||
|
||
|
||
<!-- 右侧聊天区 -->
|
||
<div class="chat-container">
|
||
<div class="chat-header">
|
||
<!-- <div class='back' onclick="handleBack()">
|
||
<svg t="1748925372585" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||
p-id="4688" width="16" height="16">
|
||
<path
|
||
d="M395.21518 513.604544l323.135538-312.373427c19.052938-18.416442 19.052938-48.273447 0-66.660212-19.053961-18.416442-49.910737-18.416442-68.964698 0L291.75176 480.290811c-19.052938 18.416442-19.052938 48.273447 0 66.660212l357.633237 345.688183c9.525957 9.207709 22.01234 13.796214 34.497699 13.796214 12.485359 0 24.971741-4.588505 34.466999-13.82896 19.052938-18.416442 19.052938-48.242747 0-66.660212L395.21518 513.604544z"
|
||
fill="#999" p-id="4689"></path>
|
||
</svg>
|
||
</div> -->
|
||
<div style="
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
align-items: center;
|
||
width: 100%;
|
||
">
|
||
<img src="./img/logo.png" class="mobilelogo" alt="">
|
||
新能源运维智能体<span style="font-size:14px">(MBAgent)</span>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="content">
|
||
<div id="chatMessages" class="chat-messages"></div>
|
||
<div class="fourquestion fourquestionmain">
|
||
<div>
|
||
<div class='question mainauestion' data-value='分析这个场站' data-pre-value="详细分析这个光伏场站,根据图片给出详细的运维方案"><img
|
||
src="./img/1.png" alt="">分析这个场站</div>
|
||
<div class='question mainauestion' data-value='详细的清洗计划' data-pre-value="如果这个光伏场站需要用无人机清洗怎么做,给出一份详细的计划"><img
|
||
src="./img/4.png" alt="">详细的清洗计划</div>
|
||
</div>
|
||
<div>
|
||
<div class='question mainauestion' data-value='详细的巡检计划' data-pre-value="如果这个光伏场站需要巡检怎么做,给出一份详细的计划"><img
|
||
src="./img/2.png" alt="">详细的巡检计划</div>
|
||
<div class='question mainauestion' data-value='详细的割草计划' data-pre-value="如果这个光伏场站需要割草怎么做,给出一份详细的计划"><img
|
||
src="./img/3.png" alt="">详细的割草计划</div>
|
||
</div>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="chat-input">
|
||
<!-- <div class="options-row">
|
||
|
||
<select id="mmModel">
|
||
<option value="hunyuan-vision">hunyuan-vision</option>
|
||
</select>
|
||
<select id="llModel">
|
||
<option value="hunyuan-api">hunyuan-api</option>
|
||
</select>
|
||
</div> -->
|
||
<div class="input-row">
|
||
<div class="img-row none">
|
||
<div class="img-box">
|
||
<img src="" alt="">
|
||
<span class="delete-btn" onclick="deleteImg()"><svg t="1757836617046" class="icon" viewBox="0 0 1024 1024"
|
||
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16945" width="16" height="16">
|
||
<path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#EF4631" p-id="16946">
|
||
</path>
|
||
<path
|
||
d="M733.6 733.6c-16.7 16.7-43.7 16.6-60.2 0.1l-151-151-151 151c-16.6 16.6-43.4 16.6-60.2-0.1-16.7-16.7-16.6-43.7-0.1-60.2l151-151-151-151c-16.6-16.6-16.6-43.4 0.1-60.2 16.7-16.7 43.7-16.6 60.2-0.1l151 151 151-151c16.6-16.6 43.4-16.6 60.2 0.1 16.7 16.7 16.6 43.7 0.1 60.2l-151 151 151 151c16.6 16.6 16.7 43.4-0.1 60.2z"
|
||
fill="#FFFFFF" p-id="16947"></path>
|
||
</svg></span>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
<textarea id="chatInput" rows="1" placeholder="询问任何问题..."></textarea>
|
||
<div class="button-row">
|
||
<!-- <div id="sendFileBtn">
|
||
<input type="file" id="fileInput" /><svg t="1757833755414" class="icon" viewBox="0 0 1024 1024"
|
||
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14318" width="24" height="24">
|
||
<path
|
||
d="M576 928H192c-52.992 0-96-43.093333-96-96V192c0-52.992 43.093333-96 96-96h640c52.992 0 96 43.093333 96 96v384.064c0 17.706667-14.293333 32-32 32s-32-14.293333-32-32V192.021333c0-17.706667-14.4-32-32-32H192c-17.706667 0-32 14.378667-32 32v639.957334c0 17.706667 14.4 32 32 32h384c17.706667 0 32 14.314667 32 32 0 17.706667-14.293333 32.021333-32 32.021333zM128 693.312a32.064 32.064 0 0 1-22.613333-54.698667l159.402666-159.338666a95.786667 95.786667 0 0 1 110.72-17.984l173.589334 86.805333c12.309333 6.186667 27.093333 3.797333 36.8-5.994667l287.402666-287.445333a32.042667 32.042667 0 0 1 45.290667 45.312L631.210667 587.392a95.786667 95.786667 0 0 1-110.72 18.005333l-173.589334-86.826666a31.616 31.616 0 0 0-36.8 6.016l-159.509333 159.317333c-6.186667 6.314667-14.4 9.386667-22.592 9.386667z m320-277.376c-52.906667 0-96-43.093333-96-96s43.093333-96.021333 96-96.021333 96 43.093333 96 96-43.093333 96.021333-96 96.021333z m0-128c-17.6 0-32 14.378667-32 32 0 17.6 14.4 32 32 32s32-14.4 32-32c0-17.621333-14.4-32-32-32zM768 928c-17.706667 0-32-14.293333-32-32v-192.021333c0-17.706667 14.293333-32 32-32s32 14.293333 32 32v192c0 17.706667-14.293333 32.021333-32 32.021333z m128-128c-7.893333 0-15.701333-2.922667-21.909333-8.725333L768 691.669333l-106.090667 99.712a31.936 31.936 0 0 1-45.226666-1.408 31.957333 31.957333 0 0 1 1.408-45.205333l112.213333-105.386667A48.554667 48.554667 0 0 1 768 621.44c14.72 0 28.501333 6.613333 37.696 17.92l112.213333 105.386667A31.957333 31.957333 0 0 1 896 800z"
|
||
fill="#666666" p-id="14319"></path>
|
||
</svg>
|
||
</div> -->
|
||
<div id="sendFileBtn" style="position: relative; width: 40px; height: 40px; cursor: pointer;">
|
||
<input type="file" id="fileInput" style="position: absolute;
|
||
left: 0; top: 0; width: 100%; height: 100%;
|
||
opacity: 0; cursor: pointer;" capture="camera" />
|
||
<img src="./img/link.jpg" alt="" style="width:24px;height:24px">
|
||
<path
|
||
d="M576 928H192c-52.992 0-96-43.093333-96-96V192c0-52.992 43.093333-96 96-96h640c52.992 0 96 43.093333 96 96v384.064c0 17.706667-14.293333 32-32 32s-32-14.293333-32-32V192.021333c0-17.706667-14.4-32-32-32H192c-17.706667 0-32 14.378667-32 32v639.957334c0 17.706667 14.4 32 32 32h384c17.706667 0 32 14.314667 32 32 0 17.706667-14.293333 32.021333-32 32.021333zM128 693.312a32.064 32.064 0 0 1-22.613333-54.698667l159.402666-159.338666a95.786667 95.786667 0 0 1 110.72-17.984l173.589334 86.805333c12.309333 6.186667 27.093333 3.797333 36.8-5.994667l287.402666-287.445333a32.042667 32.042667 0 0 1 45.290667 45.312L631.210667 587.392a95.786667 95.786667 0 0 1-110.72 18.005333l-173.589334-86.826666a31.616 31.616 0 0 0-36.8 6.016l-159.509333 159.317333c-6.186667 6.314667-14.4 9.386667-22.592 9.386667z m320-277.376c-52.906667 0-96-43.093333-96-96s43.093333-96.021333 96-96.021333 96 43.093333 96 96-43.093333 96.021333-96 96.021333z m0-128c-17.6 0-32 14.378667-32 32 0 17.6 14.4 32 32 32s32-14.4 32-32c0-17.621333-14.4-32-32-32zM768 928c-17.706667 0-32-14.293333-32-32v-192.021333c0-17.706667 14.293333-32 32-32s32 14.293333 32 32v192c0 17.706667-14.293333 32.021333-32 32.021333z m128-128c-7.893333 0-15.701333-2.922667-21.909333-8.725333L768 691.669333l-106.090667 99.712a31.936 31.936 0 0 1-45.226666-1.408 31.957333 31.957333 0 0 1 1.408-45.205333l112.213333-105.386667A48.554667 48.554667 0 0 1 768 621.44c14.72 0 28.501333 6.613333 37.696 17.92l112.213333 105.386667A31.957333 31.957333 0 0 1 896 800z"
|
||
fill="#666666" p-id="14319"></path>
|
||
</svg>
|
||
</div>
|
||
<div id="sendBtn">
|
||
<img src="./img/upload.png" alt="" style="width:36px;height:36px">
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
<script src="./marked.min.js"></script>
|
||
|
||
|
||
|
||
|
||
<script>
|
||
const sidebar = document.getElementById("sidebar");
|
||
const chatMessages = document.getElementById("chatMessages");
|
||
const chatInput = document.getElementById("chatInput");
|
||
const fileInput = document.getElementById("fileInput");
|
||
const chatList = document.getElementById("chatList");
|
||
let sessIdList = [];
|
||
let isUpload = {};
|
||
let isPre = false;//是否点击了预设问题
|
||
// let sessIdList = JSON.parse(localStorage.getItem("sessId")) || [];
|
||
let sessId;
|
||
let activeChatId = '';
|
||
const params = new URLSearchParams(window.location.search);
|
||
console.log(params.get("userId"), 644);
|
||
const encodedUserId = params.get("userId");
|
||
|
||
// ✅ 先 URL 解码,再 Base64 解码,再 UTF-8 解码
|
||
const userId = decodeURIComponent(Number(escape(atob(encodedUserId))));
|
||
// const userId = encodedUserId;
|
||
let sendParam = {
|
||
imageBase64: '',
|
||
userId: userId,
|
||
sessionId: '',
|
||
userPrompt: ''
|
||
}
|
||
const questions = document.querySelectorAll(".question");
|
||
|
||
questions.forEach(q => {
|
||
|
||
q.addEventListener("click", () => {
|
||
if (q.classList.contains("mainauestion")) {
|
||
// q.style.display = 'none';
|
||
if (!isMobile()) {
|
||
document.querySelector('.fourquestionmain').style.display = 'none';
|
||
document.querySelector('.sidequestion').style.display = 'flex';
|
||
}
|
||
|
||
}
|
||
isPre = true;
|
||
console.log(isUpload, 88)
|
||
if (!sendParam.imageBase64 && !fileInput.files.length) {
|
||
if (!isUpload[activeChatId]) {
|
||
alert("请先上传图片");
|
||
return;
|
||
}
|
||
|
||
}
|
||
const value = q.getAttribute("data-value");
|
||
const preValue = q.getAttribute("data-pre-value");
|
||
sendParam.userPrompt = preValue;
|
||
chatInput.value = value; // ✅ 把预设问题填入输入框
|
||
chatInput.focus(); // 可选:让光标聚焦输入框
|
||
sendMessage(true);
|
||
});
|
||
});
|
||
function isMobile() {
|
||
return /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||
}
|
||
|
||
// getHistory();
|
||
function getCookie(name) {
|
||
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
|
||
if (match) return decodeURIComponent(match[2]);
|
||
return null;
|
||
}
|
||
function handleBack() {
|
||
RPJavaFragmentInterface.navigateTo("StatusFragment");
|
||
|
||
}
|
||
|
||
function generateUniqueId16() {
|
||
// 当前时间戳(毫秒,取后几位)
|
||
const timestamp = Date.now().toString().slice(-10);
|
||
// 生成 6 位随机数
|
||
const random = Math.floor(Math.random() * 1e6).toString().padStart(6, "0");
|
||
return timestamp + random; // 一共 16 位
|
||
}
|
||
|
||
function createSession(userId, sessionId) {
|
||
try {
|
||
fetch("http://1.95.137.212:30009/session", {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify({
|
||
userId,
|
||
sessionId,
|
||
|
||
})
|
||
}).then(res => res.json()).then(data => {
|
||
if (data.code === 0) {
|
||
console.log("会话创建成功:", data.message);
|
||
} else {
|
||
console.error("创建失败:", data.error);
|
||
}
|
||
})
|
||
|
||
|
||
|
||
} catch (err) {
|
||
console.error("请求异常:", err);
|
||
}
|
||
}
|
||
|
||
|
||
function toggleSidebar() {
|
||
sidebar.classList.toggle("collapsed");
|
||
}
|
||
|
||
function renderChatList(isNew) {
|
||
console.log(sessIdList);
|
||
chatList.innerHTML = "";
|
||
|
||
if (!sessIdList || sessIdList.length == 0) {
|
||
chatMessages.innerHTML = "";
|
||
return;
|
||
}
|
||
// if (isNew == "new") {
|
||
activeChatId = sessIdList[sessIdList.length - 1];
|
||
// } else {
|
||
// activeChatId = sessIdList[0];
|
||
// }
|
||
sendParam.sessionId = activeChatId;
|
||
getHistory();
|
||
sessIdList.forEach((item, index) => {
|
||
console.log(item, activeChatId);
|
||
|
||
const item1 = document.createElement("div");
|
||
item1.setAttribute("data-sessionid", item);
|
||
item1.className = "chat-item" + (activeChatId == item ? " active" : "");
|
||
const title = document.createElement("div");
|
||
title.className = "chat-title";
|
||
title.textContent = `新对话${index + 1}`;
|
||
item1.onclick = () => switchChat(item);
|
||
|
||
const del = document.createElement("span");
|
||
del.className = "delete-btn";
|
||
del.textContent = "✕";
|
||
del.onclick = (e) => {
|
||
e.stopPropagation();
|
||
deleteChat(item);
|
||
};
|
||
item1.appendChild(title);
|
||
item1.appendChild(del);
|
||
chatList.appendChild(item1);
|
||
})
|
||
|
||
}
|
||
// bool 是否新创建的
|
||
function renderMessages(data, bool) {
|
||
|
||
|
||
chatMessages.innerHTML = "";
|
||
if (bool || !data || !data.length) {
|
||
|
||
return;
|
||
}
|
||
data.forEach(msg => {
|
||
addMessage(msg.content, msg.role, msg.image_base64, msg.created_at);
|
||
});
|
||
}
|
||
// 内容 角色 图片 创造时间
|
||
function addMessage(content = '', role = "assistant", imgUrl = null, time = null) {
|
||
const msg = document.createElement("div");
|
||
msg.className = `message ${role}`;
|
||
if (time) {
|
||
const timeNode = document.createElement("div");
|
||
timeNode.textContent = time;
|
||
timeNode.style.fontSize = "12px";
|
||
timeNode.style.color = "#999";
|
||
timeNode.style.marginTop = "4px";
|
||
msg.appendChild(timeNode);
|
||
}
|
||
// 如果有文字内容,先创建文字节点
|
||
if (content) {
|
||
const textNode = document.createElement("div");
|
||
textNode.innerHTML = marked.parse(content);
|
||
msg.appendChild(textNode);
|
||
}
|
||
|
||
// 如果有图片,创建图片节点
|
||
if (imgUrl) {
|
||
const img = document.createElement("img");
|
||
img.src = imgUrl;
|
||
img.style.marginTop = content ? "8px" : "0"; // 如果有文字,图片加一点间距
|
||
msg.appendChild(img);
|
||
}
|
||
|
||
// 如果有时间,可以显示
|
||
|
||
chatMessages.appendChild(msg);
|
||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||
}
|
||
|
||
|
||
function sendMessage(isPre) {
|
||
console.log("发送消息");
|
||
if (!activeChatId) {
|
||
|
||
newChat();
|
||
|
||
}
|
||
// if (sessIdList.length == 0) {
|
||
// return;
|
||
// }
|
||
|
||
ifSessionId = true;
|
||
const text = chatInput.value.trim();
|
||
if (!text && !fileInput.files.length && !sendParam.imageBase64) return;
|
||
|
||
if (text) addMessage(text, "user");
|
||
let imgUrl = '';
|
||
if (sendParam.imageBase64) {
|
||
imgUrl = sendParam.imageBase64;
|
||
if (fileInput.files[0]) {
|
||
const file = fileInput.files[0];
|
||
const url = URL.createObjectURL(file);
|
||
addMessage('', "user", url);
|
||
} else {
|
||
addMessage('', "user", sendParam.imageBase64);
|
||
sendParam.imageBase64 = '';
|
||
}
|
||
|
||
fileInput.value = "";
|
||
}
|
||
if (!isPre) {
|
||
sendParam.userPrompt = text;
|
||
} else {
|
||
|
||
}
|
||
|
||
chatInput.value = "";
|
||
getAiResponse(imgUrl);
|
||
}
|
||
|
||
const getAiResponse = async (img) => {
|
||
deleteImg();
|
||
const aiMsg = { role: "assistant", content: "", isImage: false };
|
||
const msgDiv = document.createElement("div");
|
||
msgDiv.className = "message assistant";
|
||
msgDiv.textContent = '思考中';
|
||
let dots = 0;
|
||
const interval = setInterval(() => {
|
||
dots = (dots + 1) % 4; // 0,1,2,3
|
||
msgDiv.textContent = '思考中' + '.'.repeat(dots);
|
||
}, 500);
|
||
|
||
msgDiv.className = "message assistant thinking ";
|
||
chatMessages.appendChild(msgDiv);
|
||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||
sessId = sendParam.sessionId;
|
||
sendParam.imageBase64 = img;
|
||
// sendParam.userId= encodedUserId;
|
||
sendParam.userId = decodeURIComponent(Number(escape(atob(encodedUserId))));
|
||
const res = await fetch("http://1.95.137.212:30009/analyze", {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(sendParam),
|
||
});
|
||
|
||
sendParam.imageBase64 = '';
|
||
|
||
const reader = res.body.getReader();
|
||
const decoder = new TextDecoder("utf-8");
|
||
let buffer = "";
|
||
msgDiv.classList.remove("thinking");
|
||
clearInterval(interval);
|
||
|
||
while (true) {
|
||
const { done, value } = await reader.read();
|
||
if (done) break;
|
||
buffer += decoder.decode(value, { stream: true });
|
||
|
||
let lines = buffer.split("\n");
|
||
buffer = lines.pop();
|
||
|
||
for (let line of lines) {
|
||
line = line.trim();
|
||
if (!line.startsWith("data:")) continue;
|
||
|
||
const data = line.slice(5).trim();
|
||
if (data === "[DONE]") {
|
||
// 更新聊天滚动条
|
||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const obj = JSON.parse(data);
|
||
if (obj.content) {
|
||
// 每次追加内容到 AI 消息
|
||
aiMsg.content += obj.content;
|
||
msgDiv.innerHTML = marked.parse(aiMsg.content);
|
||
// msgDiv.textContent = aiMsg.content;
|
||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||
}
|
||
} catch (err) {
|
||
console.error("JSON parse error", data);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
|
||
function newChat() {
|
||
const id = generateUniqueId16();
|
||
sessIdList.push(id);
|
||
createSession(userId, id)
|
||
const chat = [{
|
||
id,
|
||
title: "新对话 " + (sessIdList.length),
|
||
messages: { role: "assistant", content: "👋 新会话已创建,请输入问题。", }
|
||
}];
|
||
activeChatId = id;
|
||
ifSessionId = true;
|
||
sessId = id;
|
||
sendParam.sessionId = sessId;
|
||
renderMessages([chat[0].messages], true);
|
||
renderChatList('new');
|
||
}
|
||
|
||
function switchChat(id) {
|
||
activeChatId = id;
|
||
sendParam.sessionId = id;
|
||
const items = document.querySelectorAll(".chat-item");
|
||
items.forEach(item => {
|
||
if (item.dataset.sessionid === id) {
|
||
item.classList.add("active");
|
||
} else {
|
||
item.classList.remove("active");
|
||
}
|
||
});
|
||
|
||
getHistory();
|
||
// renderChatList();
|
||
|
||
}
|
||
const deleteSession = (sessionId, userId) => {
|
||
try {
|
||
fetch(`http://1.95.137.212:30009/session?sessionId=${sessionId}&userId=${userId}`, {
|
||
method: "DELETE"
|
||
}).then(res => res.json()).then(data => {
|
||
if (data.code === 0) {
|
||
getSessionList();
|
||
// renderChatList();
|
||
|
||
console.log("删除成功:", data.message);
|
||
} else {
|
||
console.error("删除失败:", data.error);
|
||
}
|
||
})
|
||
|
||
|
||
} catch (err) {
|
||
console.error("请求异常:", err);
|
||
}
|
||
}
|
||
|
||
|
||
function deleteChat(id) {
|
||
// sessIdList = sessIdList.filter(item => item !== id);
|
||
// localStorage.setItem("sessId", JSON.stringify(sessIdList));
|
||
deleteSession(id, sendParam.userId)
|
||
|
||
}
|
||
|
||
// 初始化
|
||
// if (chats.length === 0) {
|
||
// newChat();
|
||
// } else {
|
||
// if (!activeChatId || !chats.find(c => c.id === activeChatId)) {
|
||
// activeChatId = chats[0].id;
|
||
// }
|
||
// renderChatList();
|
||
// renderMessages();
|
||
// }
|
||
|
||
function handleSendFile() {
|
||
console.log("选择文件");
|
||
// 触发隐藏的 input 点击
|
||
document.getElementById("fileInput").click();
|
||
}
|
||
|
||
// 监听文件选择
|
||
document.getElementById("fileInput").addEventListener("change", function (e) {
|
||
const file = e.target.files[0];
|
||
if (file) {
|
||
console.log("选择的文件:", file.name);
|
||
// 这里可以直接上传
|
||
uploadFile(file);
|
||
}
|
||
});
|
||
|
||
// 示例上传函数(fetch 到后端接口)
|
||
function uploadFile(file) {
|
||
|
||
if (file) {
|
||
console.log("上传文件:", file.name, URL.createObjectURL(file));
|
||
const reader = new FileReader();
|
||
reader.readAsDataURL(file);
|
||
|
||
reader.onload = async function () {
|
||
console.log(reader.result)
|
||
sendParam.imageBase64 = reader.result;
|
||
document.querySelector(".img-row").classList.remove("none");
|
||
document.querySelector(".img-row img").src = sendParam.imageBase64;
|
||
isUpload[activeChatId] = true;
|
||
}
|
||
// document.getElementById("rawImg").src = URL.createObjectURL(file);
|
||
}
|
||
}
|
||
function deleteImg() {
|
||
document.querySelector(".img-row").classList.add("none");
|
||
sendParam.imageBase64 = '';
|
||
document.querySelector(".img-row img").src = '';
|
||
}
|
||
|
||
chatInput.addEventListener("keydown", function (e) {
|
||
if (e.key === "Enter" && !e.shiftKey) { // 按下回车且未按Shift
|
||
e.preventDefault(); // 阻止换行
|
||
sendMessage(); // 调用发送函数
|
||
}
|
||
});
|
||
document.getElementById("sendBtn").addEventListener("click", function () {
|
||
sendMessage();
|
||
});
|
||
document.getElementById("sendFileBtn").addEventListener("click", function () {
|
||
handleSendFile()
|
||
});
|
||
// getHistory();
|
||
// renderChatList("new");
|
||
|
||
// sendParam.sessionId = "7906661519458367";
|
||
// 调用获取历史记录的接口
|
||
function getHistory() {
|
||
// sendParam.userId = encodedUserId;
|
||
fetch(`http://1.95.137.212:30009/history?sessionId=${sendParam.sessionId}`, {
|
||
// fetch(`http://1.95.137.212:30008/history?sessionId=${sendParam.sessionId}`, {
|
||
method: "GET",
|
||
// headers: { "Content-Type": "application/json" },
|
||
// credentials: 'include', // 发送 cookie
|
||
// body: JSON.stringify(sendParam),
|
||
}).then(res => res.json()).then(data => {
|
||
// chats = data.messages;
|
||
// renderChatList();
|
||
renderMessages(data.messages)
|
||
|
||
})
|
||
}
|
||
function getCookie(name) {
|
||
console.log(document.cookie, 8777222)
|
||
const value = `; ${document.cookie}`;
|
||
const parts = value.split(`; ${name}=`);
|
||
if (parts.length === 2) return parts.pop().split(';').shift();
|
||
return null;
|
||
}
|
||
|
||
getSessionList();
|
||
function getSessionList() {
|
||
|
||
sendParam.userId = userId;
|
||
fetch(`http://1.95.137.212:30009/sessions?userId=${sendParam.userId}`, {
|
||
// fetch(`http://1.95.137.212:30008/history?sessionId=${sendParam.sessionId}`, {
|
||
method: "GET",
|
||
// headers: { "Content-Type": "application/json" },
|
||
// credentials: 'include', // 发送 cookie
|
||
// body: JSON.stringify(sendParam),
|
||
}).then(res => res.json()).then(data => {
|
||
console.log(data, 8777)
|
||
if (data.code == 300) {
|
||
// window.location.href='http://localhost/#/login?goRemote=1 '
|
||
window.location.href = data.error;
|
||
return;
|
||
}
|
||
sessIdList = data.sessions;
|
||
renderChatList();
|
||
console.log(data, 8777)
|
||
// chats = data.messages;
|
||
// renderChatList();
|
||
// renderMessages(data.messages)
|
||
|
||
})
|
||
}
|
||
function toggleSidebar() {
|
||
sidebar.classList.toggle("collapsed");
|
||
const toggleBtn = document.getElementById("toggleBtn");
|
||
if (sidebar.classList.contains("collapsed")) {
|
||
toggleBtn.style.left = "10px"; // 收起后
|
||
} else {
|
||
toggleBtn.style.left = "190px"; // 展开后
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
|
||
</html> |