chore(ccgo): 以 Vue3 做题站替换 TempLate/CCGO 原生页面并清理 www 残留
CCGO 构建产物部署至 TempLate/CCGO(旧文件移至 backup/ccgo);GVSite 已迁移残留的 Invite/Errors 旧页移至 backup/www;.gitignore 排除新工程
This commit is contained in:
1 parent
5549b28a08
commit
14902a404d
47 files changed
+6
-1255
No files matched your search
+6
-1
@@ -29,4 +29,9 @@ __pycache__/
|
||||
/GVSite/node_modules/
|
||||
|
||||
# GVSite 生产部署产物(TempLate/GVSite,由 deploy.ps1 同步)
|
||||
/TempLate/GVSite/
|
||||
/TempLate/GVSite/
|
||||
|
||||
# CCGO 做题站前端工程(独立 git 仓库)
|
||||
/CCGO/
|
||||
# CCGO 的编译文件
|
||||
/TempLate/CCGO/
|
||||
@@ -1,70 +0,0 @@
|
||||
<!-- 二维码浮动层(透明度优化) -->
|
||||
<div class="fixed bottom-6 right-6 z-50 bg-white p-3 rounded-lg shadow-xl transition-all duration-300 hover:shadow-blue-300/30 border border-gray-100">
|
||||
<div class="img-card-container">
|
||||
<div class="img-card">
|
||||
<img src="https://volunteer.cdn-go.cn/404/latest/img/dream4schoolQR.png"
|
||||
alt="志愿者活动二维码"
|
||||
class="w-32 h-32 object-contain" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 404页面主体内容(透明度调低版) -->
|
||||
<div class="page-header counter-area header-filter min-h-screen flex items-center justify-center relative bg-gradient-to-br from-blue-50 to-indigo-100 overflow-hidden" id="img">
|
||||
<div class="absolute inset-0 bg-[url('https://bing.img.run/uhd.php')] bg-cover bg-center opacity-1"></div>
|
||||
<div class="absolute inset-0 bg-white/70"></div>
|
||||
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10 text-center mt-8">
|
||||
<div class="content-center brand">
|
||||
<!-- 404标题 -->
|
||||
<h1 class="h1-seo shaded-text text-[clamp(5rem,15vw,10rem)] font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-blue-500 to-indigo-600 mb-4 tracking-tighter">
|
||||
404
|
||||
</h1>
|
||||
<h2 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-gray-800 mb-6">NOT FOUND</h2>
|
||||
|
||||
<!-- 工作室名称 -->
|
||||
<h3 class="shaded-text text-[clamp(1rem,2vw,1.5rem)] text-blue-700 mb-8">
|
||||
Galactic Vorpal Software Development Studio
|
||||
</h3>
|
||||
|
||||
<!-- 描述信息 -->
|
||||
<h4 class="description shaded-text text-gray-600 text-lg md:text-xl mb-10 max-w-2xl mx-auto leading-relaxed">
|
||||
您访问的页面走丢在追寻梦想的路上,请稍后再试或<a style="color: #2563eb; font-weight: 500;" href="mailto://support@gvsds.com?subject=我在使用银河锋锐软件开发工作室官方网站%20www.gvsds.com%20时遇到%20404%20错误&body=错误:{{ e }}%0D%0A路径:{{ path }}%0D%0A时间:{{ time }}%0D%0A恳请您能够尽快修复此页面的问题。">向网站反馈此问题</a><br>不过您还可以和志愿者一起
|
||||
</h4>
|
||||
|
||||
<!-- 行动号召 -->
|
||||
<h3 class="text-blue-800 text-2xl md:text-3xl font-semibold mb-8 animate-pulse">
|
||||
为孩子们点亮一个梦想
|
||||
</h3>
|
||||
|
||||
<!-- 错误信息展示 -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-3xl mx-auto">
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200 hover:border-blue-300 transition-all shadow-sm hover:shadow-md">
|
||||
<p class="category d-inline shaded-text text-gray-800">
|
||||
<span class="block text-blue-600 mb-1 font-medium">Error:</span>
|
||||
{{ e }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200 hover:border-blue-300 transition-all shadow-sm hover:shadow-md">
|
||||
<p class="category d-inline shaded-text text-gray-800">
|
||||
<span class="block text-blue-600 mb-1 font-medium">Path:</span>
|
||||
{{ path }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200 hover:border-blue-300 transition-all shadow-sm hover:shadow-md">
|
||||
<p class="category d-inline shaded-text text-gray-800">
|
||||
<span class="block text-blue-600 mb-1 font-medium">Time:</span>
|
||||
{{ time }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 返回按钮 -->
|
||||
<div class="mt-12 mb-16 sm:mb-12">
|
||||
<button class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-3 px-8 rounded-full transition-all transform hover:scale-105 shadow-md hover:shadow-blue-200" onclick="window.location='/';">
|
||||
返回首页
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,70 +0,0 @@
|
||||
<!-- 二维码浮动层(透明度优化) -->
|
||||
<div class="fixed bottom-6 right-6 z-50 bg-white p-3 rounded-lg shadow-xl transition-all duration-300 hover:shadow-blue-300/30 border border-gray-100">
|
||||
<div class="img-card-container">
|
||||
<div class="img-card">
|
||||
<img src="https://volunteer.cdn-go.cn/500/latest/img/dream4schoolQR.png"
|
||||
alt="志愿者活动二维码"
|
||||
class="w-32 h-32 object-contain" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 500页面主体内容(透明度调低版) -->
|
||||
<div class="page-header counter-area header-filter min-h-screen flex items-center justify-center relative bg-gradient-to-br from-blue-50 to-indigo-100 overflow-hidden" id="img">
|
||||
<div class="absolute inset-0 bg-[url('https://bing.img.run/uhd.php')] bg-cover bg-center opacity-1"></div>
|
||||
<div class="absolute inset-0 bg-white/70"></div>
|
||||
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10 text-center mt-8">
|
||||
<div class="content-center brand">
|
||||
<!-- 500标题 -->
|
||||
<h1 class="h1-seo shaded-text text-[clamp(5rem,15vw,10rem)] font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-blue-500 to-indigo-600 mb-4 tracking-tighter">
|
||||
500
|
||||
</h1>
|
||||
<h2 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-gray-800 mb-6">NOT FOUND</h2>
|
||||
|
||||
<!-- 工作室名称 -->
|
||||
<h3 class="shaded-text text-[clamp(1rem,2vw,1.5rem)] text-blue-700 mb-8">
|
||||
Galaxy Vantone Software Development Studio
|
||||
</h3>
|
||||
|
||||
<!-- 描述信息 -->
|
||||
<h4 class="description shaded-text text-gray-600 text-lg md:text-xl mb-10 max-w-2xl mx-auto leading-relaxed">
|
||||
您访问的页面出现了一些故障,请稍后再试或<a style="color: #2563eb; font-weight: 500;" href="mailto://support@gvsds.com?subject=我在使用银河锋锐软件开发工作室官方网站%20www.gvsds.com%20时遇到%20500%20错误&body=错误:{{ e }}%0D%0A路径:{{ path }}%0D%0A时间:{{ time }}%0D%0A恳请您能够尽快修复此页面的问题。">向网站反馈此问题</a><br>不过您还可以和志愿者一起
|
||||
</h4>
|
||||
|
||||
<!-- 行动号召 -->
|
||||
<h3 class="text-blue-800 text-2xl md:text-3xl font-semibold mb-8 animate-pulse">
|
||||
为孩子们点亮一个梦想
|
||||
</h3>
|
||||
|
||||
<!-- 错误信息展示 -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-3xl mx-auto">
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200 hover:border-blue-300 transition-all shadow-sm hover:shadow-md">
|
||||
<p class="category d-inline shaded-text text-gray-800">
|
||||
<span class="block text-blue-600 mb-1 font-medium">Error:</span>
|
||||
{{ e }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200 hover:border-blue-300 transition-all shadow-sm hover:shadow-md">
|
||||
<p class="category d-inline shaded-text text-gray-800">
|
||||
<span class="block text-blue-600 mb-1 font-medium">Path:</span>
|
||||
{{ path }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200 hover:border-blue-300 transition-all shadow-sm hover:shadow-md">
|
||||
<p class="category d-inline shaded-text text-gray-800">
|
||||
<span class="block text-blue-600 mb-1 font-medium">Time:</span>
|
||||
{{ time }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 返回按钮 -->
|
||||
<div class="mt-12 mb-16 sm:mb-12">
|
||||
<button class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-3 px-8 rounded-full transition-all transform hover:scale-105 shadow-md hover:shadow-blue-200" onclick="window.location='/';">
|
||||
返回首页
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,70 +0,0 @@
|
||||
<!-- 二维码浮动层(透明度优化) -->
|
||||
<div class="fixed bottom-6 right-6 z-50 bg-white p-3 rounded-lg shadow-xl transition-all duration-300 hover:shadow-blue-300/30 border border-gray-100">
|
||||
<div class="img-card-container">
|
||||
<div class="img-card">
|
||||
<img src="https://volunteer.cdn-go.cn/503/latest/img/dream4schoolQR.png"
|
||||
alt="志愿者活动二维码"
|
||||
class="w-32 h-32 object-contain" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 503页面主体内容(透明度调低版) -->
|
||||
<div class="page-header counter-area header-filter min-h-screen flex items-center justify-center relative bg-gradient-to-br from-blue-50 to-indigo-100 overflow-hidden" id="img">
|
||||
<div class="absolute inset-0 bg-[url('https://bing.img.run/uhd.php')] bg-cover bg-center opacity-1"></div>
|
||||
<div class="absolute inset-0 bg-white/70"></div>
|
||||
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 relative z-10 text-center mt-8">
|
||||
<div class="content-center brand">
|
||||
<!-- 503标题 -->
|
||||
<h1 class="h1-seo shaded-text text-[clamp(5rem,15vw,10rem)] font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-blue-503 to-indigo-600 mb-4 tracking-tighter">
|
||||
503
|
||||
</h1>
|
||||
<h2 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-gray-800 mb-6">NOT FOUND</h2>
|
||||
|
||||
<!-- 工作室名称 -->
|
||||
<h3 class="shaded-text text-[clamp(1rem,2vw,1.5rem)] text-blue-700 mb-8">
|
||||
Galaxy Vantone Software Development Studio
|
||||
</h3>
|
||||
|
||||
<!-- 描述信息 -->
|
||||
<h4 class="description shaded-text text-gray-600 text-lg md:text-xl mb-10 max-w-2xl mx-auto leading-relaxed">
|
||||
您无权访问此页面,请稍后再试或<a style="color: #2563eb; font-weight: 503;" href="mailto://support@gvsds.com?subject=我在使用银河锋锐软件开发工作室官方网站%20www.gvsds.com%20时遇到%20503%20错误&body=错误:{{ e }}%0D%0A路径:{{ path }}%0D%0A时间:{{ time }}%0D%0A恳请您能够尽快修复此页面的问题。">向网站反馈此问题</a><br>不过您还可以和志愿者一起
|
||||
</h4>
|
||||
|
||||
<!-- 行动号召 -->
|
||||
<h3 class="text-blue-800 text-2xl md:text-3xl font-semibold mb-8 animate-pulse">
|
||||
为孩子们点亮一个梦想
|
||||
</h3>
|
||||
|
||||
<!-- 错误信息展示 -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-3xl mx-auto">
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200 hover:border-blue-300 transition-all shadow-sm hover:shadow-md">
|
||||
<p class="category d-inline shaded-text text-gray-800">
|
||||
<span class="block text-blue-600 mb-1 font-medium">Error:</span>
|
||||
{{ e }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200 hover:border-blue-300 transition-all shadow-sm hover:shadow-md">
|
||||
<p class="category d-inline shaded-text text-gray-800">
|
||||
<span class="block text-blue-600 mb-1 font-medium">Path:</span>
|
||||
{{ path }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="bg-white rounded-lg p-4 border border-gray-200 hover:border-blue-300 transition-all shadow-sm hover:shadow-md">
|
||||
<p class="category d-inline shaded-text text-gray-800">
|
||||
<span class="block text-blue-600 mb-1 font-medium">Time:</span>
|
||||
{{ time }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 返回按钮 -->
|
||||
<div class="mt-12 mb-16 sm:mb-12">
|
||||
<button class="bg-blue-503 hover:bg-blue-600 text-white font-medium py-3 px-8 rounded-full transition-all transform hover:scale-105 shadow-md hover:shadow-blue-200" onclick="window.location='/';">
|
||||
返回首页
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,360 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>403 Forbidden</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Microsoft YaHei', sans-serif;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f9f9f9;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 50px auto;
|
||||
padding: 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #e74c3c;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
border-bottom: 2px solid #f1c40f;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.notice {
|
||||
background-color: #f8f9fa;
|
||||
border-left: 4px solid #3498db;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: #fffcf2;
|
||||
padding: 15px;
|
||||
border-left: 4px solid #ffc107;
|
||||
margin-bottom: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: #f2dede;
|
||||
padding: 15px;
|
||||
border-left: 4px solid #c73c3a;
|
||||
margin-bottom: 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.theme-content {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.theme-content h2 {
|
||||
color: #2c3e50;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.theme-content p {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #eee;
|
||||
color: #7f8c8d;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: #fffde7;
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div style="text-align: center;">
|
||||
<h1>⛔ 403 Forbidden</h1>
|
||||
</div>
|
||||
<div class="error">
|
||||
<p>
|
||||
服务器已拒绝您对当前 URL 的访问请求。<br>
|
||||
您应当通过我们的官方域名
|
||||
<span class="highlight">www.gvsds.com</span>
|
||||
访问网站,而非当前使用的
|
||||
<span class="highlight" id="current-host"> [HostName] </span>
|
||||
<br>
|
||||
出于安全考虑,我们已启用host白名单策略。
|
||||
</p>
|
||||
</div>
|
||||
<div class="warning">
|
||||
<p>
|
||||
错误代码:
|
||||
<span class="highlight" id="violated-rule"></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="notice">
|
||||
<div class="request-section">
|
||||
<h4>请求基本信息</h4>
|
||||
<table class="request-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="request-key">请求URL</td>
|
||||
<td class="request-value" id="request-url">[正在加载...]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="request-key">请求方法</td>
|
||||
<td class="request-value" id="request-method">[正在加载...]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="request-key">协议版本</td>
|
||||
<td class="request-value" id="request-protocol">[正在加载...]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="request-key">请求时间</td>
|
||||
<td class="request-value" id="request-time">[正在加载...]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="request-section">
|
||||
<h4>请求头 (Headers)</h4>
|
||||
<table class="request-table" id="request-headers-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Header名称</th>
|
||||
<th>值</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="request-section">
|
||||
<h4>查询参数 (Query Args)</h4>
|
||||
<table class="request-table" id="request-args-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>参数名</th>
|
||||
<th>值</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="request-section">
|
||||
<h4>客户端信息</h4>
|
||||
<table class="request-table" id="client-info-table">
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="request-section">
|
||||
<h4>服务器信息</h4>
|
||||
<table class="request-table" id="server-info-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="request-key">服务器名称</td>
|
||||
<td class="request-value">GVSDS Web Server</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="request-key">安全策略</td>
|
||||
<td class="request-value">Host白名单验证</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="request-key">拒绝原因</td>
|
||||
<td class="request-value" id="reject-reason">[正在加载...]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>银河锋锐软件开发工作室 © 2025 | 实际网站: <a href="https://www.gvsds.com">https://www.gvsds.com</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// Automatically display the current hostname and detect rule violation
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
// Display current hostname
|
||||
const currentHostElement = document.getElementById('current-host');
|
||||
currentHostElement.textContent = window.location.hostname;
|
||||
|
||||
// Detect likely rule violation (simplified example)
|
||||
const violatedRuleElement = document.getElementById('violated-rule');
|
||||
const officialDomain = 'www.gvsds.com';
|
||||
let rejectReason = '';
|
||||
|
||||
if (window.location.hostname !== officialDomain) {
|
||||
violatedRuleElement.textContent = '1';
|
||||
violatedRuleElement.title = '域名白名单规则';
|
||||
rejectReason = '访问域名不在白名单中';
|
||||
} else if (window.location.protocol !== 'https:') {
|
||||
violatedRuleElement.textContent = '3';
|
||||
violatedRuleElement.title = 'HTTPS强制规则';
|
||||
rejectReason = '非HTTPS安全连接';
|
||||
} else {
|
||||
violatedRuleElement.textContent = '2';
|
||||
violatedRuleElement.title = 'IP4检查'
|
||||
rejectReason = '您的IP处于黑名单中';
|
||||
}
|
||||
|
||||
document.getElementById('reject-reason').textContent = rejectReason;
|
||||
|
||||
// Additional security logging (example)
|
||||
console.warn('Security Alert: Unauthorized domain access attempt from', window.location.hostname);
|
||||
|
||||
// 填充高级信息表格
|
||||
fillAdvancedTables();
|
||||
});
|
||||
|
||||
// 可折叠面板功能
|
||||
const coll = document.getElementsByClassName("collapsible");
|
||||
for (let i = 0; i < coll.length; i++) {
|
||||
coll[i].addEventListener("click", function () {
|
||||
this.classList.toggle("active");
|
||||
const content = this.nextElementSibling;
|
||||
if (content.style.maxHeight) {
|
||||
content.style.maxHeight = null;
|
||||
} else {
|
||||
content.style.maxHeight = content.scrollHeight + "px";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 填充高级信息表格
|
||||
function fillAdvancedTables() {
|
||||
// 请求基本信息
|
||||
document.getElementById('request-url').textContent = window.location.href;
|
||||
document.getElementById('request-method').textContent = 'GET';
|
||||
document.getElementById('request-protocol').textContent = 'HTTP/1.1';
|
||||
document.getElementById('request-time').textContent = new Date().toLocaleString();
|
||||
|
||||
// 请求头表格
|
||||
const headersTable = document.getElementById('request-headers-table').getElementsByTagName('tbody')[0];
|
||||
const headers = {
|
||||
'Host': window.location.hostname,
|
||||
'User-Agent': navigator.userAgent,
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
|
||||
'Accept-Language': navigator.language,
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Connection': 'keep-alive',
|
||||
'Cache-Control': 'max-age=0',
|
||||
'Referer': document.referrer || '(无)'
|
||||
};
|
||||
|
||||
for (const [key, value] of Object.entries(headers)) {
|
||||
const row = headersTable.insertRow();
|
||||
row.insertCell(0).textContent = key;
|
||||
row.insertCell(1).textContent = value;
|
||||
}
|
||||
|
||||
// 查询参数表格
|
||||
const argsTable = document.getElementById('request-args-table').getElementsByTagName('tbody')[0];
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
if (urlParams.toString()) {
|
||||
for (const [key, value] of urlParams.entries()) {
|
||||
const row = argsTable.insertRow();
|
||||
row.insertCell(0).textContent = key;
|
||||
row.insertCell(1).textContent = value;
|
||||
}
|
||||
} else {
|
||||
const row = argsTable.insertRow();
|
||||
const cell = row.insertCell(0);
|
||||
cell.textContent = '无查询参数';
|
||||
cell.colSpan = 2;
|
||||
}
|
||||
|
||||
const getUserIP = (onNewIP) => {
|
||||
const RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
|
||||
if (!RTCPeerConnection) return;
|
||||
|
||||
const pc = new RTCPeerConnection({ iceServers: [] });
|
||||
const localIPs = {};
|
||||
const ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g;
|
||||
|
||||
const iterateIP = (ip) => {
|
||||
if (!localIPs[ip]) onNewIP(ip);
|
||||
localIPs[ip] = true;
|
||||
};
|
||||
|
||||
pc.createDataChannel('');
|
||||
pc.createOffer().then((sdp) => {
|
||||
sdp.sdp.split('\n').forEach((line) => {
|
||||
if (line.indexOf('candidate') < 0) return;
|
||||
line.match(ipRegex)?.forEach(iterateIP);
|
||||
});
|
||||
pc.setLocalDescription(sdp);
|
||||
}).catch(() => { });
|
||||
|
||||
pc.onicecandidate = (event) => {
|
||||
if (event.candidate) {
|
||||
event.candidate.candidate.match(ipRegex)?.forEach(iterateIP);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
getUserIP((ip) => {
|
||||
window.ip = ip;
|
||||
});
|
||||
|
||||
|
||||
// 客户端信息表格
|
||||
const clientTable = document.getElementById('client-info-table').getElementsByTagName('tbody')[0];
|
||||
const clientInfo = [
|
||||
['IP Address', window.ip],
|
||||
['User Agent', navigator.userAgent],
|
||||
['Platform', navigator.platform],
|
||||
['Screen Resolution', `${window.screen.width}x${window.screen.height}`],
|
||||
['Color Depth', `${window.screen.colorDepth}位`],
|
||||
['Language', navigator.language],
|
||||
['Cookies Enabled', navigator.cookieEnabled ? '是' : '否'],
|
||||
['Online Status', navigator.onLine ? '在线' : '离线'],
|
||||
['Browser', getBrowserName()],
|
||||
['Timezone', Intl.DateTimeFormat().resolvedOptions().timeZone],
|
||||
['Local Time', new Date().toString()]
|
||||
];
|
||||
|
||||
for (const [key, value] of clientInfo) {
|
||||
const row = clientTable.insertRow();
|
||||
row.insertCell(0).textContent = key;
|
||||
row.insertCell(1).textContent = value;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取浏览器名称
|
||||
function getBrowserName() {
|
||||
const userAgent = navigator.userAgent;
|
||||
if (userAgent.includes("Firefox")) return "Mozilla Firefox";
|
||||
if (userAgent.includes("SamsungBrowser")) return "Samsung Internet";
|
||||
if (userAgent.includes("Opera") || userAgent.includes("OPR")) return "Opera";
|
||||
if (userAgent.includes("Trident")) return "Internet Explorer";
|
||||
if (userAgent.includes("Edge")) return "Microsoft Edge";
|
||||
if (userAgent.includes("Chrome")) return "Google Chrome";
|
||||
if (userAgent.includes("Safari")) return "Apple Safari";
|
||||
return "未知浏览器";
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,277 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="ID1"><button onclick="showSection('ID2');">转到 ID2</button>这是 ID1 部分
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
</div>
|
||||
<div id="ID2"><button onclick="showSection('ID3');">转到 ID3</button>这是 ID2 部分
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
</div>
|
||||
<div id="ID3"><button onclick="showSection('ID4');">转到 ID4</button>这是 ID3 部分 1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
</div>
|
||||
<div id="ID4"><button onclick="showSection('ID5');">转到 ID5</button>这是 ID4 部分 1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
</div>
|
||||
<div id="ID5">这是 ID5 部分 1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
1231<br>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
const sections = document.querySelectorAll('div');
|
||||
sections.forEach(section => {
|
||||
if (section.id!== 'ID1') {
|
||||
section.style.display = 'none';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function showSection(id) {
|
||||
const sections = document.querySelectorAll('div');
|
||||
sections.forEach(section => {
|
||||
section.style.display = 'none';
|
||||
});
|
||||
document.getElementById(id).style.display = 'block';
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
@@ -1,49 +0,0 @@
|
||||
<div class="bg-gradient-to-br from-indigo-50 to-purple-50 min-h-screen flex flex-col">
|
||||
<main class="flex-grow flex flex-col items-center justify-center px-6 py-12 relative overflow-hidden">
|
||||
<div class="hidden lg:block absolute left-0 top-1/8 -translate-y-1/2 w-1/3 max-w-md animate-float c-furry" style="animation-delay: 0s;"><img src="https://www.gvsds.com/assets/img/Background/ChiSha_Left.png" alt="左侧插画"
|
||||
class="w-full h-auto object-contain transform hover:scale-105 transition-transform duration-300"></div>
|
||||
<div class="text-center max-w-3xl z-10">
|
||||
<h1 class="text-[clamp(2rem,5vw,4rem)] font-bold text-gray-800 leading-tight mb-6"> 加入我们,<br class="md:hidden"><span class="text-primary">创造未来</span></h1>
|
||||
<p class="text-[clamp(1rem,2vw,1.25rem)] text-gray-600 mb-10 max-w-2xl mx-auto"> 我们正在寻找充满激情、创意和才华的你。 加入我们,与我们一同创作。 </p>
|
||||
<button id="Apply" class="bg-primary hover:bg-primary/90 text-white font-bold py-4 px-10 rounded-full text-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-300 animate-pulse-slow">
|
||||
提交简历 <i class="fa fa-arrow-right ml-2"></i>
|
||||
</button>
|
||||
<div class="mt-12 grid grid-cols-2 md:grid-cols-4 gap-6">
|
||||
<div class="bg-white/70 backdrop-blur-sm p-4 rounded-xl shadow-sm"><i class="fa fa-users text-primary text-2xl mb-2"></i>
|
||||
<p class="text-gray-700 font-medium">多元团队</p>
|
||||
</div>
|
||||
<div class="bg-white/70 backdrop-blur-sm p-4 rounded-xl shadow-sm"><i class="fa fa-lightbulb text-primary text-2xl mb-2"></i>
|
||||
<p class="text-gray-700 font-medium">创新文化</p>
|
||||
</div>
|
||||
<div class="bg-white/70 backdrop-blur-sm p-4 rounded-xl shadow-sm"><i class="fa fa-graduation-cap text-primary text-2xl mb-2"></i>
|
||||
<p class="text-gray-700 font-medium">成长机会</p>
|
||||
</div>
|
||||
<div class="bg-white/70 backdrop-blur-sm p-4 rounded-xl shadow-sm"><i class="fa fa-coffee text-primary text-2xl mb-2"></i>
|
||||
<p class="text-gray-700 font-medium">舒适环境</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden lg:block absolute right-0 top-1/8 -translate-y-1/2 w-1/3 max-w-md animate-float c-furry" style="animation-delay: 1s;"><img src="https://www.gvsds.com/assets/img/Background/Ying_Right.png" alt="右侧插画"
|
||||
class="w-full h-auto object-contain transform hover:scale-105 transition-transform duration-300"></div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById("Apply").addEventListener("click", function () {
|
||||
this.classList.add("scale-95");
|
||||
setTimeout(() => {
|
||||
this.classList.remove("scale-95");
|
||||
window.open("/Apply/");
|
||||
}, 200);
|
||||
});
|
||||
window.addEventListener("scroll", function () {
|
||||
const nav = document.querySelector("nav");
|
||||
if (window.scrollY > 50) {
|
||||
nav.classList.add("shadow-md");
|
||||
nav.classList.remove("shadow-sm");
|
||||
} else {
|
||||
nav.classList.remove("shadow-md");
|
||||
nav.classList.add("shadow-sm");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,358 +0,0 @@
|
||||
<div class="bg-gray-50">
|
||||
<div class="max-w-3xl mx-auto p-4 md:p-6">
|
||||
<h1 class="text-2xl md:text-3xl font-bold text-text-primary mb-6">AI-HR 审核对话</h1>
|
||||
<div id="chat-container" class="border border-gray-200 rounded-lg h-[60vh] overflow-y-auto p-4 mb-4 bg-gray-50"></div>
|
||||
<div class="flex border border-gray-200 rounded-lg overflow-hidden">
|
||||
<textarea
|
||||
id="message-input"
|
||||
placeholder="请输入内容...(回车发送,Shift+回车换行)"
|
||||
class="flex-1 p-3 focus:outline-none focus:ring-1 focus:ring-primary resize-none"
|
||||
rows="3"
|
||||
disabled
|
||||
></textarea>
|
||||
<button
|
||||
id="send-btn"
|
||||
class="bg-primary text-white px-6 py-3 hover:bg-primary/90 transition-colors disabled:bg-gray-300 disabled:cursor-not-allowed"
|
||||
disabled
|
||||
>
|
||||
发送
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 统计信息显示区域 -->
|
||||
<div class="flex justify-between text-sm text-text-secondary mt-2">
|
||||
<div id="word-count">当前输入:0 字(最多 2048 字)</div>
|
||||
<div id="message-count">对话数量:0/50</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const chatContainer = document.getElementById('chat-container');
|
||||
const messageInput = document.getElementById('message-input');
|
||||
const sendBtn = document.getElementById('send-btn');
|
||||
const wordCountEl = document.getElementById('word-count');
|
||||
const messageCountEl = document.getElementById('message-count');
|
||||
let isAiResponding = false;
|
||||
let InviteID = '';
|
||||
let currentMessageCount = 0;
|
||||
let isConversationFinal = false; // 标记对话是否终态
|
||||
|
||||
// 生成12位邀请码
|
||||
function generateInviteID() {
|
||||
return Math.floor(Math.random() * 1000000000000).toString().padStart(12, '0');
|
||||
}
|
||||
|
||||
// 初始化邀请码(从URL获取或生成)
|
||||
function initInviteID() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
InviteID = urlParams.get('InviteID');
|
||||
|
||||
if (!InviteID || InviteID.length !== 12) {
|
||||
InviteID = generateInviteID();
|
||||
const newUrl = `${window.location.pathname}?InviteID=${InviteID}`;
|
||||
window.history.replaceState({}, document.title, newUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新字数统计
|
||||
function updateWordCount() {
|
||||
const text = messageInput.value;
|
||||
const count = text.length;
|
||||
// 超过限制时标红
|
||||
wordCountEl.className = count > 2048 ? 'text-red-500' : 'text-sm text-text-secondary';
|
||||
wordCountEl.textContent = `当前输入:${count} 字(最多 2048 字)`;
|
||||
|
||||
// 控制发送按钮状态
|
||||
if (count > 2048 || isAiResponding || isConversationFinal) {
|
||||
sendBtn.disabled = true;
|
||||
} else {
|
||||
sendBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新对话数量统计
|
||||
function updateMessageCount() {
|
||||
// 超过限制时标红
|
||||
messageCountEl.className = currentMessageCount >= 50 ? 'text-red-500' : 'text-sm text-text-secondary';
|
||||
messageCountEl.textContent = `对话数量:${currentMessageCount}/50`;
|
||||
|
||||
// 达到最大对话数时禁用输入
|
||||
if (currentMessageCount >= 50) {
|
||||
messageInput.disabled = true;
|
||||
sendBtn.disabled = true;
|
||||
messageInput.placeholder = '对话已达到最大条数,无法继续输入';
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染终态结果(高亮样式)
|
||||
function renderFinalResult(status, result, reason = '', mood = '') {
|
||||
const finalDiv = document.createElement('div');
|
||||
finalDiv.className = 'mt-6 p-4 rounded-lg bg-gray-100 border border-gray-300';
|
||||
|
||||
// 终态标题
|
||||
const title = document.createElement('h3');
|
||||
title.className = `text-lg font-bold mb-2 ${status === 0 ? 'text-green-600' : 'text-red-600'}`;
|
||||
title.textContent = status === 0
|
||||
? '面试结果:通过 ✅'
|
||||
: status === 1
|
||||
? '面试结果:未通过 ❌'
|
||||
: '无法回答该问题 🚫';
|
||||
finalDiv.appendChild(title);
|
||||
|
||||
// 结果内容(确保不为空)
|
||||
const resultEl = document.createElement('div');
|
||||
resultEl.className = 'mb-2 text-gray-800';
|
||||
resultEl.textContent = result.because;
|
||||
finalDiv.appendChild(resultEl);
|
||||
|
||||
// 拒绝原因(仅拒绝回答时显示)
|
||||
if (reason) {
|
||||
const reasonEl = document.createElement('div');
|
||||
reasonEl.className = 'text-sm text-gray-600 mb-1';
|
||||
reasonEl.textContent = `原因:${reason}`;
|
||||
finalDiv.appendChild(reasonEl);
|
||||
}
|
||||
|
||||
// AI心情(仅拒绝回答时显示)
|
||||
if (mood) {
|
||||
const moodEl = document.createElement('div');
|
||||
moodEl.className = 'text-sm text-gray-500 italic';
|
||||
moodEl.textContent = `AI心情:${mood}`;
|
||||
finalDiv.appendChild(moodEl);
|
||||
}
|
||||
|
||||
// 终态提示
|
||||
const tipEl = document.createElement('div');
|
||||
tipEl.className = 'mt-3 text-xs text-gray-400';
|
||||
tipEl.textContent = '对话已结束,无法继续发送消息';
|
||||
finalDiv.appendChild(tipEl);
|
||||
|
||||
chatContainer.appendChild(finalDiv);
|
||||
chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||
}
|
||||
|
||||
// 添加普通消息到聊天容器
|
||||
function addMessage(sender, text) {
|
||||
if (sender === 'ai') {
|
||||
try {
|
||||
const json = JSON.parse(text);
|
||||
text = json.because || text;
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
const messageDiv = document.createElement('div');
|
||||
messageDiv.className = `mb-4 ${sender === 'user' ? 'flex justify-end' : 'flex justify-start'}`;
|
||||
|
||||
const messageBubble = document.createElement('div');
|
||||
messageBubble.className = `${
|
||||
sender === 'user'
|
||||
? 'bg-primary text-white rounded-lg rounded-tl-lg px-4 py-2 max-w-[80%]'
|
||||
: 'bg-white border border-gray-200 rounded-lg rounded-tr-lg px-4 py-2 max-w-[80%] shadow-sm'
|
||||
}`;
|
||||
|
||||
const senderLabel = document.createElement('div');
|
||||
senderLabel.className = `text-xs mb-1 ${sender === 'user' ? 'text-white/80' : 'text-text-secondary'}`;
|
||||
senderLabel.textContent = sender === 'user' ? '您' : 'AI-HR';
|
||||
messageBubble.appendChild(senderLabel);
|
||||
|
||||
const messageContent = document.createElement('div');
|
||||
messageContent.className = 'whitespace-pre-wrap';
|
||||
messageContent.textContent = text;
|
||||
messageBubble.appendChild(messageContent);
|
||||
|
||||
messageDiv.appendChild(messageBubble);
|
||||
chatContainer.appendChild(messageDiv);
|
||||
chatContainer.scrollTop = chatContainer.scrollHeight;
|
||||
}
|
||||
|
||||
// 锁死对话(禁用输入和发送)
|
||||
function lockConversation() {
|
||||
messageInput.disabled = true;
|
||||
sendBtn.disabled = true;
|
||||
messageInput.placeholder = '对话已结束,无法继续输入';
|
||||
}
|
||||
|
||||
// 启用输入和发送
|
||||
function enableInput() {
|
||||
if (!isConversationFinal && currentMessageCount < 50) {
|
||||
messageInput.disabled = false;
|
||||
sendBtn.disabled = false;
|
||||
messageInput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
async function sendMessage() {
|
||||
if (isConversationFinal) {
|
||||
alert('对话已结束,无法继续发送消息');
|
||||
return;
|
||||
}
|
||||
|
||||
const text = messageInput.value.trim();
|
||||
if (text.length > 2048) {
|
||||
alert('消息长度不能超过2048字,请精简内容');
|
||||
return;
|
||||
}
|
||||
if (currentMessageCount >= 50) {
|
||||
alert('已达到最大对话数量(50条),无法继续发送');
|
||||
return;
|
||||
}
|
||||
if (!text || !InviteID) return;
|
||||
|
||||
// 添加用户消息到界面
|
||||
addMessage('user', text);
|
||||
messageInput.value = '';
|
||||
currentMessageCount++;
|
||||
updateMessageCount();
|
||||
updateWordCount();
|
||||
|
||||
// 禁用输入防止重复发送
|
||||
disableInput();
|
||||
isAiResponding = true;
|
||||
|
||||
try {
|
||||
const response = await fetch(`/API/SendConversation?InviteID=${InviteID}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: `Content=${encodeURIComponent(text)}`
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
if (result.Success) {
|
||||
// 显示AI回复
|
||||
addMessage('ai', result.Data.AiMessage.Content);
|
||||
currentMessageCount++;
|
||||
updateMessageCount();
|
||||
|
||||
// 检查是否为终态,若是则渲染终态结果并锁死对话
|
||||
if (result.Data.IsFinal) {
|
||||
isConversationFinal = true;
|
||||
renderFinalResult(
|
||||
result.Data.FinalStatus,
|
||||
result.Data.AiMessage.Content,
|
||||
result.Data.FinalReason,
|
||||
result.Data.FinalMood
|
||||
);
|
||||
lockConversation();
|
||||
}
|
||||
} else {
|
||||
// 显示错误消息
|
||||
addMessage('ai', `错误:${result.Message}`);
|
||||
currentMessageCount++;
|
||||
updateMessageCount();
|
||||
|
||||
// 若错误是终态导致的,直接锁死
|
||||
if (result.IsFinal) {
|
||||
isConversationFinal = true;
|
||||
lockConversation();
|
||||
}
|
||||
|
||||
// 处理对话过期/不存在的情况
|
||||
if (result.Message.includes('已过期') || result.Message.includes('不存在')) {
|
||||
InviteID = generateInviteID();
|
||||
window.history.replaceState({}, document.title, `${window.location.pathname}?InviteID=${InviteID}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
addMessage('ai', '发送消息失败,请重试');
|
||||
currentMessageCount++;
|
||||
updateMessageCount();
|
||||
console.error('发送失败:', error);
|
||||
} finally {
|
||||
// 非终态且未达最大条数时,重新启用输入
|
||||
if (!isConversationFinal && currentMessageCount < 50) {
|
||||
enableInput();
|
||||
}
|
||||
isAiResponding = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 禁用输入和发送
|
||||
function disableInput() {
|
||||
messageInput.disabled = true;
|
||||
sendBtn.disabled = true;
|
||||
}
|
||||
|
||||
// 初始化聊天(加载历史或创建新对话)
|
||||
async function initChat() {
|
||||
initInviteID();
|
||||
try {
|
||||
const response = await fetch(`/API/ConversationHistory?InviteID=${InviteID}`);
|
||||
const result = await response.json();
|
||||
|
||||
if (result.Success) {
|
||||
// 渲染历史消息
|
||||
result.Data.Messages.forEach(msg => {
|
||||
addMessage(msg.Role === 'User' ? 'user' : 'ai', msg.Content);
|
||||
});
|
||||
currentMessageCount = result.Data.MessageCount;
|
||||
updateMessageCount();
|
||||
|
||||
// 【关键修复】只有 FinalStatus 存在且为有效数值(0/1)时,才判定为终态
|
||||
// 避免因 FinalStatus 为 undefined 或 null 误触发终态渲染
|
||||
if (result.Data.FinalStatus !== undefined && result.Data.FinalStatus !== null) {
|
||||
isConversationFinal = true;
|
||||
renderFinalResult(
|
||||
result.Data.FinalStatus,
|
||||
result.Data.FinalResult || result.Data.Messages[result.Data.Messages.length - 1]?.Content || '无结果信息',
|
||||
result.Data.FinalReason,
|
||||
result.Data.FinalMood
|
||||
);
|
||||
lockConversation();
|
||||
} else {
|
||||
// 非终态则启用输入
|
||||
enableInput();
|
||||
}
|
||||
} else {
|
||||
// 历史对话获取失败,创建新对话
|
||||
const initResponse = await fetch(`/API/InitConversation?InviteID=${InviteID}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
const initResult = await initResponse.json();
|
||||
if (initResult.Success) {
|
||||
addMessage('ai', initResult.Data.AiMessage.Content);
|
||||
currentMessageCount = 1;
|
||||
updateMessageCount();
|
||||
enableInput();
|
||||
} else {
|
||||
addMessage('ai', `初始化失败:${initResult.Message}`);
|
||||
currentMessageCount = 1;
|
||||
updateMessageCount();
|
||||
}
|
||||
}
|
||||
updateWordCount(); // 初始化字数统计
|
||||
} catch (error) {
|
||||
addMessage('ai', '初始化对话失败,请刷新页面重试');
|
||||
console.error('初始化失败:', error);
|
||||
currentMessageCount = 1;
|
||||
updateMessageCount();
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定事件监听
|
||||
messageInput.addEventListener('input', updateWordCount);
|
||||
|
||||
// 回车发送,Shift+回车换行
|
||||
messageInput.addEventListener('keydown', (e) => {
|
||||
if (isConversationFinal) return;
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
if (!isAiResponding) {
|
||||
sendMessage();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 发送按钮点击事件
|
||||
sendBtn.addEventListener('click', () => {
|
||||
if (!isConversationFinal && !isAiResponding) {
|
||||
sendMessage();
|
||||
}
|
||||
});
|
||||
|
||||
// 启动聊天初始化
|
||||
initChat();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user