Compare commits

...

15 Commits

  1. 2
      .gitignore
  2. 2
      dist-test/hcdbqb-download.html
  3. 2
      dist-test/hcdbqb-guide.html
  4. 118
      dist-test/hcdbqb-management.html
  5. 135
      dist-test/index.html
  6. 351
      dist-test/login-management.html
  7. 2
      dist-test/main.js
  8. 11
      dist-test/management.js
  9. 261
      hcdbqb-management.html
  10. 155
      index.html
  11. 351
      login-management.html
  12. 10
      node_modules/.vite/deps/_metadata.json
  13. 11
      node_modules/.vue-global-types/vue_3.5_0.d.ts
  14. 138
      node_modules/.vue-global-types/vue_99_0.d.ts
  15. 1
      vite.config.js

2
.gitignore

@ -0,0 +1,2 @@
/node_modules
/dist-test

2
dist-test/hcdbqb-download.html

@ -1622,7 +1622,7 @@
href="https://wa.me/+6588792879?text=夺宝奇兵下载我需要帮助"
target="_blank"
class="py-2 mt-2 rounded-full bg-gradient-to-r from-primary to-purple-600 text-white text-center"
>联系我们</a
>加入我们</a
>
</div>
</div>

2
dist-test/hcdbqb-guide.html

@ -2019,7 +2019,7 @@
href="https://wa.me/+6588792879?text=我要咨询"
target="_blank"
class="text-gray-400 hover:text-white transition-colors"
>联系我们</a
>加入我们</a
>
</li>
</ul>

118
dist-test/hcdbqb-management.html

@ -1,6 +1,7 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>管理后台</title>
@ -11,6 +12,7 @@
background: #f7f8fb;
color: #222;
}
.card {
background: #fff;
padding: 16px;
@ -18,11 +20,13 @@
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
margin: auto;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 12px;
}
th,
td {
padding: 10px 12px;
@ -30,16 +34,19 @@
text-align: left;
font-size: 14px;
}
th {
background: #fafafa;
font-weight: 600;
}
.controls {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.pagination {
display: flex;
gap: 6px;
@ -47,6 +54,7 @@
margin-left: auto;
flex-wrap: wrap;
}
.btn {
padding: 6px 10px;
border-radius: 6px;
@ -55,54 +63,71 @@
cursor: pointer;
user-select: none;
}
.btn:disabled {
opacity: 0.5;
cursor: default;
}
.btn.primary {
background: #007bff;
color: #fff;
border-color: #007bff;
}
.btn.whatsapp {
background: #25D366;
color: #fff;
border-color: #25D366;
}
.status-btn {
padding: 4px 8px;
border-radius: 6px;
border: 1px solid #ccc;
cursor: pointer;
}
.status-0 {
background: red;
color: #fff;
}
.status-1 {
background: #2f9e44;
color: #fff;
border-color: #2f9e44;
}
.btn.active {
background: #007bff;
color: #fff;
border-color: #007bff;
}
select,
input[type="number"] {
padding: 6px;
border-radius: 6px;
border: 1px solid #ddd;
}
.small {
font-size: 13px;
color: #666;
}
@media (max-width: 640px) {
.controls {
flex-direction: column;
align-items: flex-start;
}
.pagination {
margin-left: 0;
}
}
#noteModal {
display: none;
position: fixed;
@ -112,6 +137,7 @@
justify-content: center;
z-index: 9999;
}
#noteModal .dialog {
background: #fff;
padding: 16px;
@ -120,6 +146,7 @@
max-width: 520px;
box-sizing: border-box;
}
#noteModal textarea {
width: 100%;
min-width: 60%;
@ -131,6 +158,7 @@
border: 1px solid #ddd;
font-size: 14px;
}
.toast {
position: fixed;
top: -20px;
@ -147,32 +175,85 @@
z-index: 10000;
pointer-events: none;
}
.toast.show {
opacity: 1;
top: 20px;
}
table th,
table td {
text-align: center;
}
/* 登录验证样式 */
#loginCheckModal {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.7);
align-items: center;
justify-content: center;
z-index: 99999;
}
#loginCheckModal .dialog {
background: #fff;
padding: 30px;
border-radius: 12px;
width: 90%;
max-width: 400px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
#loginCheckModal h3 {
margin: 0 0 16px;
color: #e74c3c;
font-size: 20px;
}
#loginCheckModal p {
margin: 0 0 24px;
color: #666;
line-height: 1.5;
}
#loginCheckModal .btn {
padding: 10px 20px;
font-size: 16px;
}
</style>
<script type="module" crossorigin src="./management.js"></script>
<link rel="modulepreload" crossorigin href="./member.js">
</head>
<body>
</head>
<body>
<!-- 登录验证模态框 -->
<div id="loginCheckModal">
<div class="dialog">
<h3>访问被拒绝</h3>
<p>您尚未登录或登录已过期,请先登录系统。</p>
<button class="btn primary" id="goToLoginBtn">前往登录页面</button>
</div>
</div>
<div class="card">
<table aria-describedby="tableDesc">
<thead>
<tr>
<th style="width: 40px">#</th>
<th style="width: 100px">姓名</th>
<th style="width: 30px">#</th>
<th style="width: 60px">姓名</th>
<th style="width: 80px">WhatsApp</th>
<th style="width: 90px">国家/地区代码</th>
<th style="width: 120px">电话号码</th>
<th style="width: 120px">微信ID</th>
<th style="width: 150px">邮箱</th>
<th style="width: 160px">添加时间</th>
<th style="width: 100px">是否联系</th>
<th style="width: 160px">备注</th>
<th style="width: 110px">电话号码</th>
<th style="width: 110px">微信ID</th>
<th style="width: 110px">邮箱</th>
<th style="width: 70px">获客来源</th>
<th style="width: 130px">来源地址</th>
<th style="width: 150px">添加时间</th>
<th style="width: 90px">是否联系</th>
<th style="width: 90px">备注</th>
<th style="width: 100px">操作</th>
</tr>
</thead>
@ -198,19 +279,13 @@
<div id="noteModal">
<div class="dialog">
<h3 style="margin: 0 0 8px">编辑备注</h3>
<textarea
id="noteTextarea"
rows="6"
placeholder="输入备注..."
></textarea>
<div
style="
<textarea id="noteTextarea" rows="6" placeholder="输入备注..."></textarea>
<div style="
margin-top: 10px;
display: flex;
justify-content: flex-end;
gap: 8px;
"
>
">
<button class="btn" id="noteCancelBtn">取消</button>
<button class="btn primary" id="noteSaveBtn">保存</button>
</div>
@ -218,5 +293,6 @@
</div>
</div>
<div id="toast" class="toast"></div>
</body>
</body>
</html>

135
dist-test/index.html

@ -12,7 +12,7 @@
<link rel="bookmark" href="dbqb_favicon.ico" />
<meta http-equiv="keywords" content="夺宝奇兵,homilychart,homilylink">
<meta http-equiv="description" content="HomilyLink">
<title>夺宝奇兵 - AI炒股时代,机构界的黑科技</title>
<title>赢在美股——加入我们,开启赢家人生</title>
<script src="https://cdn.tailwindcss.com"></script>
<script type="text/javascript" src="https://hc.homilychart.com/hc/210802/js/jquery-1.9.1.min.js"></script>
@ -36,6 +36,24 @@
}
}
</script>
<style>
/* 在head中添加初始滚动样式 */
html,
body {
scroll-behavior: auto;
}
/* 隐藏页面内容,直到滚动完成 */
body {
opacity: 0;
transition: opacity 0.3s ease;
}
body.content-visible {
opacity: 1;
}
</style>
<script type="module" crossorigin src="./main.js"></script>
<link rel="modulepreload" crossorigin href="./member.js">
</head>
@ -51,11 +69,11 @@
<div class="container mx-auto px-4 py-3 flex justify-between items-center">
<a href="#" class="flex items-center space-x-2">
<div class="w-10 h-10 rounded-lg gradient-background flex items-center justify-center">
<img alt="夺宝奇兵" src="https://hc.homilychart.com/hc/250121/img/20230711171637.png"
<img alt="赢在美股" src="https://d31zlh4on95l9h.cloudfront.net/images/497d8b38ab9f738e9720d5d7bddf3beb.png"
style="width: 40px;height: 40px;">
</div>
<span class="text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-primary to-accent">
夺宝奇兵
赢在美股
</span>
</a>
@ -66,7 +84,7 @@
<!-- <a href="hcdbqb-guide.html" class="font-medium hover:text-primary transition-colors">操作指南</a> -->
<a href="https://api.whatsapp.com/send?phone=85255110485&text=我需要帮助" target="_blank"
class="px-5 py-2 rounded-full gradient-background text-white font-medium hover:shadow-lg transition-all">
联系我们
加入我们
</a>
</nav>
@ -83,9 +101,9 @@
<a href="#kc" class="font-medium py-2 hover:text-primary transition-colors">最新课程</a>
<!-- <a href="hcdbqb-guide.html" class="font-medium py-2 hover:text-primary transition-colors">操作指南</a> -->
<!-- <a href="#" class="font-medium py-2 hover:text-primary transition-colors">操作指南</a> -->
<a href="https://wa.me/+6588792879?text=夺宝奇兵指南我需要帮助" target="_blank"
<a href="https://api.whatsapp.com/send?phone=85255110485&text=我需要帮助" target="_blank"
class="py-2 rounded-full gradient-background text-white font-medium text-center hover:shadow-lg transition-all">
联系我们
加入我们
</a>
</div>
</div>
@ -102,7 +120,7 @@
</h1>
<p class="text-lg text-gray-600 mb-8 max-w-lg paragraph-text">
AI时代股票投资必备机构界的黑科技!<br />
现开放免费体验7天的活动,立刻注册报名吧!
加入「赢在美股」,即可参与夺宝奇兵免费体验 7 天的活动,立刻注册报名吧!
</p>
<div class="flex flex-col sm:flex-row gap-4">
<a href="#register"
@ -135,8 +153,8 @@
<section id="features" class="py-16 px-4 bg-white">
<div class="container mx-auto max-w-6xl">
<div class="text-center mb-16 animate-fade-in">
<h2 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold mb-4 heading-secondary">您可以免费体验什么?</h2>
<p class="text-gray-600 max-w-2xl mx-auto paragraph-text">您可以免费体验 超级云脑 AI预测大模型 夺宝利剑三个模块 7</p>
<h2 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold mb-4 heading-secondary">加入赢在美股,您可以免费体验什么?</h2>
<p class="text-gray-600 max-w-2xl mx-auto paragraph-text">您可以免费体验超级云脑 AI预测大模型 夺宝利剑三个模块 7 天,助力您赢在美股!</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
@ -192,19 +210,19 @@
<ul class="space-y-3 mb-8">
<li class="flex items-start list-item">
<i class="fa fa-check-circle text-secondary mt-1 mr-3"></i>
<span>云脑探秘</span>
<span>云脑探秘:深度解析股市底层数据</span>
</li>
<li class="flex items-start list-item">
<i class="fa fa-check-circle text-secondary mt-1 mr-3"></i>
<span>机构动向</span>
<span>机构动向:实时追踪机构资金动向</span>
</li>
<li class="flex items-start list-item">
<i class="fa fa-check-circle text-secondary mt-1 mr-3"></i>
<span>体检专家</span>
<span>体检专家:股票标的全方位健康检测</span>
</li>
</ul>
<a href="#register" class="inline-flex items-center text-primary font-medium hover:underline">
注册了解更多 <i class="fa fa-arrow-right ml-2"></i>
加入赢在美股,解锁更多资讯 <i class="fa fa-arrow-right ml-2"></i>
</a>
</div>
</div>
@ -239,7 +257,7 @@
</li>
</ul>
<a href="#register" class="inline-flex items-center text-primary font-medium hover:underline">
注册了解更多 <i class="fa fa-arrow-right ml-2"></i>
加入赢在美股,解锁更多资讯 <i class="fa fa-arrow-right ml-2"></i>
</a>
</div>
</div>
@ -274,7 +292,7 @@
</li>
</ul>
<a href="#register" class="inline-flex items-center text-primary font-medium hover:underline">
注册了解更多 <i class="fa fa-arrow-right ml-2"></i>
加入赢在美股,解锁更多资讯 <i class="fa fa-arrow-right ml-2"></i>
</a>
</div>
</div>
@ -288,7 +306,7 @@
<div class="md:w-1/2 p-8 md:p-12 flex flex-col justify-center">
<span
class="inline-block px-4 py-1 rounded-full bg-green-100 text-secondary text-base font-medium mb-4 breadcrumb-text">
HomilyLink > 消息 > John Lu谈股财富圈
HomilyLink > 消息 > 赢在美股班级群
</span>
<h3 class="text-2xl md:text-3xl font-bold mb-4 heading-tertiary">HomilyLink专题讲座</h3>
<p class="text-gray-600 mb-6 paragraph-text">
@ -297,34 +315,34 @@
<ul class="space-y-3 mb-8">
<li class="flex items-start list-item">
<i class="fa fa-check-circle text-secondary mt-1 mr-3"></i>
<span>新加坡时间</span>
<span>课程为香港时间</span>
</li>
<li class="flex items-start list-item">
<i class="fa fa-check-circle text-secondary mt-1 mr-3"></i>
<span>注意换算当地时间</span>
<span>体系化课程助力跟庄稳赢</span>
</li>
<li class="flex items-start list-item">
<i class="fa fa-check-circle text-secondary mt-1 mr-3"></i>
<span>HomilyLink班级群课程</span>
<span>HomilyLink赢在美股班级群专属课程(实时答疑+干货分享)</span>
</li>
</ul>
<a href="#register" class="inline-flex items-center text-primary font-medium hover:underline">
注册了解更多 <i class="fa fa-arrow-right ml-2"></i>
加入赢在美股,解锁更多资讯 <i class="fa fa-arrow-right ml-2"></i>
</a>
</div>
</div>
</div>
</section>
<!-- 注册表单区域 -->
<section id="register" class="py-20 px-4 bg-white">
<div class="container mx-auto max-w-6xl">
<div class="bg-gradient-to-br from-dark to-gray-800 rounded-3xl shadow-2xl overflow-hidden">
<div class="bg-gradient-to-br rounded-3xl shadow-2xl overflow-hidden">
<div class="grid grid-cols-1 md:grid-cols-2">
<div class="p-8 md:p-12 text-white flex flex-col justify-center">
<h2 class="text-2xl md:text-3xl font-bold mb-6 heading-secondary">立即注册,开启智能体验之旅!</h2>
<!-- 左侧区域 - 已替换背景 -->
<div class="p-8 md:p-12 text-white flex flex-col justify-center bg-image-overlay">
<h2 class="text-2xl md:text-3xl font-bold mb-6 heading-secondary">加入赢在美股,开启赢家人生!</h2>
<p class="text-gray-300 mb-10 leading-relaxed paragraph-text">
填写报名表,我们会尽快为您开启智能体验之旅
填写报名表,即可快速解锁专业投资AI工具,助力您把握投资机会
</p>
<div class="space-y-6">
<div class="flex items-start">
@ -359,6 +377,7 @@
</div>
</div>
<!-- 右侧表单区域 - 保持不变 -->
<div class="bg-white p-8 md:p-12">
<form id="registrationForm" class="space-y-6">
<input type="hidden" name="zbtype" id="zbType" value="6">
@ -450,19 +469,19 @@
</section>
<!-- 页脚区域 -->
<footer class="bg-dark text-white py-12 px-4">
<footer class="footer-bg text-white py-12 px-4">
<div class="container mx-auto max-w-6xl">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8">
<div>
<div class="flex items-center space-x-2 mb-6">
<div class="w-10 h-10 rounded-lg gradient-background flex items-center justify-center">
<img alt="夺宝奇兵" src="https://hc.homilychart.com/hc/250121/img/20230711171637.png"
<img alt="赢在美股" src="https://d31zlh4on95l9h.cloudfront.net/images/497d8b38ab9f738e9720d5d7bddf3beb.png"
style="width: 40px;height: 40px;">
</div>
<span class="text-xl font-bold">夺宝奇兵</span>
<span class="text-xl font-bold">赢在美股</span>
</div>
<p class="text-gray-400 mb-6 paragraph-text">
AI炒股时代 机构界的黑科技
加入赢在美股,开启赢家人生
</p>
<div class="flex space-x-4">
<a href="#"
@ -487,12 +506,12 @@
<div>
<h4 class="text-lg font-semibold mb-6 heading-tertiary">产品</h4>
<ul class="space-y-3">
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">弘历云版软件</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">HomilyChart</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">夺宝奇兵</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">弘历云版软件</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">HomilyChart</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">夺宝奇兵</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
class="text-gray-400 hover:text-white transition-colors">博股会员</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
@ -503,12 +522,12 @@
<div>
<h4 class="text-lg font-semibold mb-6 heading-tertiary">公司</h4>
<ul class="space-y-3">
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">关于我们</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">团队介绍</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">联系我们</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">关于我们</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">团队介绍</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">联系我们</a></li>
</ul>
</div>
@ -518,15 +537,16 @@
<li class="list-item">
<!-- <a href="hcdbqb-guide.html"
class="text-gray-400 hover:text-white transition-colors">帮助中心</a> -->
<a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" class="text-gray-400 hover:text-white transition-colors">帮助中心</a>
<a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
class="text-gray-400 hover:text-white transition-colors">帮助中心</a>
</li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">常见问题</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">常见问题</a></li>
</ul>
</div>
</div>
<div class="border-t border-gray-800 pt-8 flex flex-col md:flex-row justify-between items-center">
<div class=" border-gray-800 pt-8 flex flex-col md:flex-row justify-between items-center">
<p class="text-gray-500 text-sm mb-4 md:mb-0 paragraph-text">
&copy; Copyright 2025.Capitalmaster Pte Ltd All Rights Reserved.
</p>
@ -563,7 +583,6 @@
/* 全局字体大小调整 - 整体调小 */
html {
font-size: 16px;
scroll-behavior: smooth;
}
/* 文本样式类 */
@ -868,6 +887,30 @@
border-radius: 50%;
animation: spin 1s linear infinite;
}
.gradient-background {
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
}
.bg-image-overlay {
background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1)),
url('https://d31zlh4on95l9h.cloudfront.net/images/3b28e7abdfc4b495324cc3e6d9210b51.jpg');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.gradient-background {
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
}
.footer-bg {
background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)),
url('https://d31zlh4on95l9h.cloudfront.net/images/22576b3fe6f29e642f322d4d315ae426.jpg');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
</style>
</body>

351
dist-test/login-management.html

@ -0,0 +1,351 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>系统登录</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
}
body {
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.login-container {
background-color: white;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
width: 100%;
max-width: 420px;
padding: 40px 30px;
transition: transform 0.3s ease;
}
.login-container:hover {
transform: translateY(-5px);
}
.login-header {
text-align: center;
margin-bottom: 30px;
}
.login-header h1 {
color: #333;
font-size: 28px;
margin-bottom: 8px;
}
.login-header p {
color: #666;
font-size: 16px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: 500;
}
input {
width: 100%;
padding: 14px 16px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 16px;
transition: all 0.3s;
}
input:focus {
border-color: #4a90e2;
box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.2);
outline: none;
}
.error-message {
color: #e74c3c;
font-size: 14px;
margin-top: 5px;
display: none;
}
.login-button {
background: linear-gradient(to right, #6a11cb, #2575fc);
color: white;
border: none;
border-radius: 8px;
padding: 14px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
width: 100%;
transition: all 0.3s;
margin-top: 10px;
}
.login-button:hover {
background: linear-gradient(to right, #5a0db5, #1c68e8);
box-shadow: 0 5px 15px rgba(37, 117, 252, 0.4);
}
.login-button:active {
transform: scale(0.98);
}
.login-footer {
text-align: center;
margin-top: 25px;
color: #777;
font-size: 14px;
}
.alert {
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
display: none;
}
.alert-error {
background-color: #ffebee;
color: #c62828;
border: 1px solid #ffcdd2;
}
.alert-success {
background-color: #e8f5e9;
color: #2e7d32;
border: 1px solid #c8e6c9;
}
.password-requirements {
font-size: 12px;
color: #777;
margin-top: 5px;
}
.input-error {
border-color: #e74c3c;
box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.2);
}
</style>
</head>
<body>
<div class="login-container">
<div class="login-header">
<h1>系统登录</h1>
<p>请输入您的账号和密码</p>
</div>
<div id="usernameAlert" class="alert alert-error">
账号不存在,请检查后重试!
</div>
<div id="passwordAlert" class="alert alert-error">
密码错误,请检查后重试!
</div>
<form id="loginForm">
<div class="form-group">
<label for="username">账号</label>
<input type="text" id="username" name="username" placeholder="请输入账号" required>
<div class="error-message" id="usernameError">账号不能为空</div>
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" name="password" placeholder="请输入密码" required>
<div class="error-message" id="passwordError">密码不能为空</div>
<div class="password-requirements">密码必须为8位数字</div>
</div>
<button type="submit" class="login-button">登录</button>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const loginForm = document.getElementById('loginForm');
const usernameInput = document.getElementById('username');
const passwordInput = document.getElementById('password');
const usernameError = document.getElementById('usernameError');
const passwordError = document.getElementById('passwordError');
const usernameAlert = document.getElementById('usernameAlert');
const passwordAlert = document.getElementById('passwordAlert');
// 正确的账号和密码
const CORRECT_USERNAME = 'admin';
const CORRECT_PASSWORD = '20251107';
// 表单提交事件
loginForm.addEventListener('submit', function (e) {
e.preventDefault();
// 重置错误状态
resetErrors();
// 获取表单数据
const username = usernameInput.value.trim();
const password = passwordInput.value.trim();
// 表单验证
let isValid = true;
if (!username) {
showError(usernameError, '账号不能为空');
usernameInput.classList.add('input-error');
isValid = false;
}
if (!password) {
showError(passwordError, '密码不能为空');
passwordInput.classList.add('input-error');
isValid = false;
} else if (!/^\d{8}$/.test(password)) {
showError(passwordError, '密码必须为8位数字');
passwordInput.classList.add('input-error');
isValid = false;
}
// 如果验证通过,尝试登录
if (isValid) {
// 验证账号密码
if (username === CORRECT_USERNAME && password === CORRECT_PASSWORD) {
// 登录成功,保存登录状态
localStorage.setItem('isLoggedIn', 'true');
localStorage.setItem('loginTime', new Date().getTime());
// 显示成功消息(短暂显示后跳转)
showSuccessMessage();
// 延迟跳转,让用户看到成功消息
setTimeout(function () {
window.location.href = 'hcdbqb-management.html';
}, 1000);
} else {
// 登录失败,明确提示是账号还是密码错误
if (username !== CORRECT_USERNAME) {
usernameAlert.style.display = 'block';
usernameInput.classList.add('input-error');
usernameInput.focus();
} else {
passwordAlert.style.display = 'block';
passwordInput.classList.add('input-error');
passwordInput.value = '';
passwordInput.focus();
}
}
}
});
// 实时验证
usernameInput.addEventListener('blur', function () {
if (!this.value.trim()) {
showError(usernameError, '账号不能为空');
this.classList.add('input-error');
} else {
hideError(usernameError);
this.classList.remove('input-error');
}
});
passwordInput.addEventListener('blur', function () {
const password = this.value.trim();
if (!password) {
showError(passwordError, '密码不能为空');
this.classList.add('input-error');
} else if (!/^\d{8}$/.test(password)) {
showError(passwordError, '密码必须为8位数字');
this.classList.add('input-error');
} else {
hideError(passwordError);
this.classList.remove('input-error');
}
});
// 输入时隐藏错误提示
usernameInput.addEventListener('input', function () {
hideError(usernameError);
hideAlert(usernameAlert);
this.classList.remove('input-error');
});
passwordInput.addEventListener('input', function () {
hideError(passwordError);
hideAlert(passwordAlert);
this.classList.remove('input-error');
});
// 辅助函数
function showError(element, message) {
element.textContent = message;
element.style.display = 'block';
}
function hideError(element) {
element.style.display = 'none';
}
function hideAlert(alertElement) {
alertElement.style.display = 'none';
}
function resetErrors() {
hideError(usernameError);
hideError(passwordError);
hideAlert(usernameAlert);
hideAlert(passwordAlert);
usernameInput.classList.remove('input-error');
passwordInput.classList.remove('input-error');
}
function showSuccessMessage() {
// 临时创建一个成功提示
const successAlert = document.createElement('div');
successAlert.className = 'alert alert-success';
successAlert.textContent = '登录成功,正在跳转...';
usernameAlert.parentNode.insertBefore(successAlert, usernameAlert);
successAlert.style.display = 'block';
// 移除错误提示(如果有)
hideAlert(usernameAlert);
hideAlert(passwordAlert);
}
// 检查是否已经登录(如果已经登录,直接跳转)
if (localStorage.getItem('isLoggedIn') === 'true') {
// 检查登录时间,如果超过24小时需要重新登录
const loginTime = parseInt(localStorage.getItem('loginTime'));
const currentTime = new Date().getTime();
const hoursDiff = (currentTime - loginTime) / (1000 * 60 * 60);
if (hoursDiff < 24) {
window.location.href = 'hcdbqb-management.html';
} else {
// 超过24小时,清除登录状态
localStorage.removeItem('isLoggedIn');
localStorage.removeItem('loginTime');
}
}
});
</script>
</body>
</html>

2
dist-test/main.js

@ -1 +1 @@
import{g as E,r as h}from"./member.js";const I=50,L=100,B=20,u=document.getElementById("registrationForm"),l=document.getElementById("successModal"),p=document.getElementById("closeModal"),a=document.getElementById("submitBtn"),g=document.getElementById("loadingOverlay"),i=document.getElementById("lectureImage");let r=!1;async function v(){console.log("开始加载讲座图片...");try{const e={id:1};console.log("调用getImageApi,参数:",e);const t=await E(e);console.log("接口返回:",t),t.code===200&&t.data?(i.src=t.data,console.log("讲座图片加载成功:",t.data)):(console.warn("获取图片失败:",t.msg),i.src="https://hc.homilychart.com/hc/250121/img/kecheng.jpg")}catch(e){console.error("加载讲座图片失败:",e),i.src="https://hc.homilychart.com/hc/250121/img/kecheng.jpg"}}function w(){g.style.display="flex",a.disabled=!0,a.textContent="提交中...",r=!0}function M(){g.style.display="none",a.disabled=!1,a.textContent="提交注册",r=!1}function s(e){alert(e)}function b(e){const{name:t,tel:o,email:n}=e;return!t||t.length>I?(s("请输入有效的姓名(最多50个字符)"),document.getElementById("userNameInfo").focus(),!1):!o||o.length>B?(s("请输入有效的电话号码"),document.getElementById("userMobile").focus(),!1):!n||n.length>L?(s("请输入电子邮箱"),document.getElementById("userEmail").focus(),!1):/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(n)?!0:(s("请输入有效的电子邮箱地址"),document.getElementById("userEmail").focus(),!1)}async function A(e){if(e.preventDefault(),r)return;const t=document.getElementById("userNameInfo").value.trim(),o=document.getElementById("countryInfo").value,n=document.getElementById("userMobile").value.trim(),d=document.getElementById("userWechat").value.trim(),y=document.getElementById("userEmail").value.trim(),m={name:t,code:o,tel:n,wechat:d,email:y};if(b(m))try{w();const c=await h(m);c.code===200?(l.classList.remove("hidden"),u.reset()):s("注册失败: "+(c.msg||"未知错误"))}catch(c){console.error("请求失败:",c),s("网络错误,请稍后重试")}finally{M()}}function N(){document.getElementById("mobileMenu").classList.toggle("hidden");const t=document.getElementById("menuBtn").querySelector("i");t.classList.contains("fa-bars")?t.classList.replace("fa-bars","fa-times"):t.classList.replace("fa-times","fa-bars")}function H(){const e=document.querySelector("header");window.scrollY>50?(e.classList.add("py-2","shadow"),e.classList.remove("py-3")):(e.classList.add("py-3"),e.classList.remove("py-2","shadow"))}function f(){document.querySelectorAll(".animate-fade-in").forEach(t=>{const o=t.getBoundingClientRect().top,n=window.innerHeight;o<n-100&&(t.style.opacity="1",t.style.transform="translateY(0)")})}window.addEventListener("load",()=>{console.log("页面加载完成,开始调用loadLectureImage..."),v(),f(),document.getElementById("loadingOverlay").style.display="none"});u.addEventListener("submit",A);p.addEventListener("click",()=>{l.classList.add("hidden")});l.addEventListener("click",e=>{e.target===l&&l.classList.add("hidden")});document.getElementById("menuBtn").addEventListener("click",N);window.addEventListener("scroll",H);window.addEventListener("scroll",f);
import{g as I,r as L}from"./member.js";const w=50,p=100,B=20,u=document.getElementById("registrationForm"),c=document.getElementById("successModal"),v=document.getElementById("closeModal"),l=document.getElementById("submitBtn"),g=document.getElementById("loadingOverlay"),i=document.getElementById("lectureImage");let d=!1;function b(){document.documentElement.style.scrollBehavior="auto";const t=document.getElementById("register");if(t){const e=document.querySelector("header").offsetHeight,n=t.offsetTop-e-20;window.scrollTo(0,n)}setTimeout(()=>{document.documentElement.style.scrollBehavior="smooth"},100)}async function M(){console.log("开始加载讲座图片...");try{const t={id:1};console.log("调用getImageApi,参数:",t);const e=await I(t);console.log("接口返回:",e),e.code===200&&e.data?(i.src=e.data,console.log("讲座图片加载成功:",e.data)):(console.warn("获取图片失败:",e.msg),i.src="https://hc.homilychart.com/hc/250121/img/kecheng.jpg")}catch(t){console.error("加载讲座图片失败:",t),i.src="https://hc.homilychart.com/hc/250121/img/kecheng.jpg"}}function S(){g.style.display="flex",l.disabled=!0,l.textContent="提交中...",d=!0}function A(){g.style.display="none",l.disabled=!1,l.textContent="提交注册",d=!1}function s(t){alert(t)}function T(t){const{name:e,tel:n,email:o}=t;return!e||e.length>w?(s("请输入有效的姓名(最多50个字符)"),document.getElementById("userNameInfo").focus(),!1):!n||n.length>B?(s("请输入有效的电话号码"),document.getElementById("userMobile").focus(),!1):!o||o.length>p?(s("请输入电子邮箱"),document.getElementById("userEmail").focus(),!1):/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(o)?!0:(s("请输入有效的电子邮箱地址"),document.getElementById("userEmail").focus(),!1)}async function H(t){if(t.preventDefault(),d)return;const e=document.getElementById("userNameInfo").value.trim(),n=document.getElementById("countryInfo").value,o=document.getElementById("userMobile").value.trim(),m=document.getElementById("userWechat").value.trim(),y=document.getElementById("userEmail").value.trim(),h=await x(),E=await D(),a={name:e,code:n,tel:o,wechat:m,email:y,type:h,url:E};if(console.log("formData:",a),!!T(a))try{S();const r=await L(a);r.code===200?(c.classList.remove("hidden"),u.reset()):s("注册失败: "+(r.msg||"未知错误"))}catch(r){console.error("请求失败:",r),s("网络错误,请稍后重试")}finally{A()}}function P(){document.getElementById("mobileMenu").classList.toggle("hidden");const e=document.getElementById("menuBtn").querySelector("i");e.classList.contains("fa-bars")?e.classList.replace("fa-bars","fa-times"):e.classList.replace("fa-times","fa-bars")}function N(){const t=document.querySelector("header");window.scrollY>50?(t.classList.add("py-2","shadow"),t.classList.remove("py-3")):(t.classList.add("py-3"),t.classList.remove("py-2","shadow"))}function f(){document.querySelectorAll(".animate-fade-in").forEach(e=>{const n=e.getBoundingClientRect().top,o=window.innerHeight;n<o-100&&(e.style.opacity="1",e.style.transform="translateY(0)")})}document.addEventListener("DOMContentLoaded",function(){b(),setTimeout(()=>{document.body.classList.add("content-visible")},50)});window.addEventListener("load",()=>{console.log("页面加载完成,开始调用loadLectureImage..."),M(),f(),document.getElementById("loadingOverlay").style.display="none"});u.addEventListener("submit",H);v.addEventListener("click",()=>{c.classList.add("hidden")});c.addEventListener("click",t=>{t.target===c&&c.classList.add("hidden")});document.getElementById("menuBtn").addEventListener("click",P);window.addEventListener("scroll",N);window.addEventListener("scroll",f);function x(){const e=new URLSearchParams(window.location.search).get("type");return e==="video"?1:e==="live"?2:e==="article"?3:0}function D(){return new URLSearchParams(window.location.search).get("url")}

11
dist-test/management.js

@ -1,18 +1,23 @@
import{u as w,e as B,a as E}from"./member.js";let o={pageSize:20,currentPage:1,total:0,items:[]};const f=document.getElementById("tableBody"),h=document.getElementById("pagination"),P=document.getElementById("totalCount");document.getElementById("currentPage");document.getElementById("showingRange");const m=document.getElementById("pageSizeSelect"),v=document.getElementById("gotoInput"),y=document.getElementById("noteModal"),l=document.getElementById("noteTextarea"),x=document.getElementById("noteCancelBtn"),M=document.getElementById("noteSaveBtn"),g=document.getElementById("toast");let u=null;function b(a){g.textContent=a,g.classList.add("show"),setTimeout(()=>g.classList.remove("show"),1e3)}async function I(a,e){try{const t=await E({page:a,page_size:e});if(typeof t.code<"u"&&t.code!==200)throw new Error(t.msg||"接口返回错误");console.log(t);const n=t.data||{};o.items=n.list,o.total=n.total}catch{alert("获取数据失败"),o.total=0}}function S(){const a=(o.currentPage-1)*o.pageSize,e=o.items||[];f.innerHTML=e.map((t,n)=>{const s=a+n+1,c=t.isRelated?"status-1":"status-0",d=t.isRelated?"已联系":"未联系";return`
import{u as B,e as L,a as E}from"./member.js";function r(){const n=localStorage.getItem("isLoggedIn")==="true",e=parseInt(localStorage.getItem("loginTime")),a=(new Date().getTime()-e)/(1e3*60*60);return!n||a>=24?(localStorage.removeItem("isLoggedIn"),localStorage.removeItem("loginTime"),!1):!0}function d(){const n=document.getElementById("loginCheckModal");n.style.display="flex"}function $(){window.location.href="login-management.html"}r()||d();document.getElementById("goToLoginBtn").addEventListener("click",$);let o={pageSize:20,currentPage:1,total:0,items:[]};const y=document.getElementById("tableBody"),w=document.getElementById("pagination"),v=document.getElementById("totalCount");document.getElementById("currentPage");document.getElementById("showingRange");const h=document.getElementById("pageSizeSelect"),x=document.getElementById("gotoInput"),b=document.getElementById("noteModal"),u=document.getElementById("noteTextarea"),M=document.getElementById("noteCancelBtn"),P=document.getElementById("noteSaveBtn"),f=document.getElementById("toast");let p=null;function I(n){f.textContent=n,f.classList.add("show"),setTimeout(()=>f.classList.remove("show"),1e3)}async function C(n,e){if(!r()){d();return}try{const t=await E({page:n,page_size:e});if(typeof t.code<"u"&&t.code!==200)throw new Error(t.msg||"接口返回错误");console.log(t);const a=t.data||{};o.items=a.list,o.total=a.total}catch{alert("获取数据失败"),o.total=0}}function S(){const n=(o.currentPage-1)*o.pageSize,e=o.items||[];y.innerHTML=e.map((t,a)=>{const s=n+a+1,c=t.isRelated?"status-1":"status-0",l=t.isRelated?"已联系":"未联系";return(t.code||"").replace(/\+/g,"")+(t.telephone||""),`
<tr>
<td>${s}</td>
<td>${i(t.name||"")}</td>
<td>
<button class="btn whatsapp" data-action="whatsapp" data-id="${t.id}">WhatsApp</button>
</td>
<td>${i(t.code||"")}</td>
<td>${i(t.telephone||"")}</td>
<td>${i(t.wechat||"")}</td>
<td>${i(t.email||"")}</td>
<td>${i(t.type===0?"其它":t.type===1?"视频":t.type===2?"直播":t.type===3?"帖子":"其它")}</td>
<td>${i(t.url||"")}</td>
<td>${i(t.createdAt||"")}</td>
<td>
<button class="status-btn ${c}" data-action="toggle" data-id="${t.id}">${d}</button>
<button class="status-btn ${c}" data-action="toggle" data-id="${t.id}">${l}</button>
</td>
<td>${i(t.note||"")}</td>
<td>
<button class="btn" data-action="editNote" data-id="${t.id}">编辑备注</button>
</td>
</tr>
`}).join(""),P.textContent=o.total}f.addEventListener("click",async a=>{const e=a.target.closest('[data-action="toggle"]');if(e){const n=e.getAttribute("data-id");await $(n,e);return}const t=a.target.closest('[data-action="editNote"]');if(t){const n=t.getAttribute("data-id");L(n);return}});async function $(a,e){const t=o.items.find(c=>String(c.id)===String(a));if(!t)return;const n=t.isRelated,s=n?0:1;t.isRelated=s,e.textContent=s?"已联系":"未联系",e.classList.toggle("status-1",!!s),e.classList.toggle("status-0",!s);try{const c=await w({id:t.id,state:s});if(typeof c.code<"u"&&c.code!==200)throw new Error(c.msg||"更新失败");b("状态修改成功")}catch{t.isRelated=n,e.textContent=n?"已联系":"未联系",e.classList.toggle("status-1",!!n),e.classList.toggle("status-0",!n),alert("更新失败")}}function L(a){const e=o.items.find(t=>String(t.id)===String(a));e&&(u=a,l.value=e.note||"",y.style.display="flex",l.focus())}function r(){u=null,l.value="",y.style.display="none"}x.addEventListener("click",r);M.addEventListener("click",async()=>{if(!u)return r();const a=l.value.trim(),e=o.items.find(t=>String(t.id)===String(u));if(!e)return r();try{const t=await B({id:e.id,note:a});if(typeof t.code<"u"&&t.code!==200)throw new Error(t.msg||"保存失败");const n=e.note;e.note=a,S(),b("备注保存成功")}catch{alert("保存备注失败")}finally{r()}});function z(){const a=Math.max(1,Math.ceil(o.total/o.pageSize)),e=Math.min(Math.max(1,o.currentPage),a);o.currentPage=e;const t=N(e,a,2);let n="";n+=`<button class="btn" data-action="prev" ${e===1?"disabled":""}>上一页</button>`,t.forEach(s=>{s==="..."?n+='<span class="small" style="padding:6px 8px">...</span>':n+=`<button class="btn ${s===e?"active":""}" data-page="${s}">${s}</button>`}),n+=`<button class="btn" data-action="next" ${e===a?"disabled":""}></button>`,h.innerHTML=n}function N(a,e,t){const n=[],s=Math.max(1,a-t),c=Math.min(e,a+t);s>1&&(n.push(1),s>2&&n.push("..."));for(let d=s;d<=c;d++)n.push(d);return c<e&&(c<e-1&&n.push("..."),n.push(e)),n}h.addEventListener("click",a=>{const e=a.target.closest("button");if(!e)return;const t=e.getAttribute("data-action");if(t==="prev")o.currentPage>1&&o.currentPage--;else if(t==="next"){const n=Math.max(1,Math.ceil(o.total/o.pageSize));o.currentPage<n&&o.currentPage++}else{const n=Number(e.getAttribute("data-page"));isNaN(n)||(o.currentPage=n)}p()});m.addEventListener("change",()=>{const a=parseInt(m.value,10);o.pageSize=a,o.currentPage=1,p(),v.value=""});async function p(){const a=Math.max(1,o.currentPage);o.currentPage=a,await I(o.currentPage,o.pageSize),S(),z()}function i(a){return String(a).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}p();
`}).join(""),v.textContent=o.total}y.addEventListener("click",async n=>{if(!r()){d();return}const e=n.target.closest('[data-action="whatsapp"]');if(e){const s=e.getAttribute("data-id");T(s);return}const t=n.target.closest('[data-action="toggle"]');if(t){const s=t.getAttribute("data-id");await A(s,t);return}const a=n.target.closest('[data-action="editNote"]');if(a){const s=a.getAttribute("data-id");z(s);return}});function T(n){const e=o.items.find(c=>String(c.id)===String(n));if(!e)return;const a=(e.code||"").replace(/\+/g,"")+(e.telephone||""),s=`https://api.whatsapp.com/send?phone=${encodeURIComponent(a)}&text=${encodeURIComponent("hello欢迎来到赢在美股")}`;window.open(s,"_blank")}async function A(n,e){const t=o.items.find(c=>String(c.id)===String(n));if(!t)return;const a=t.isRelated,s=a?0:1;t.isRelated=s,e.textContent=s?"已联系":"未联系",e.classList.toggle("status-1",!!s),e.classList.toggle("status-0",!s);try{const c=await B({id:t.id,state:s});if(typeof c.code<"u"&&c.code!==200)throw new Error(c.msg||"更新失败");I("状态修改成功")}catch{t.isRelated=a,e.textContent=a?"已联系":"未联系",e.classList.toggle("status-1",!!a),e.classList.toggle("status-0",!a),alert("更新失败")}}function z(n){if(!r()){d();return}const e=o.items.find(t=>String(t.id)===String(n));e&&(p=n,u.value=e.note||"",b.style.display="flex",u.focus())}function g(){p=null,u.value="",b.style.display="none"}M.addEventListener("click",g);P.addEventListener("click",async()=>{if(!r()){d();return}if(!p)return g();const n=u.value.trim(),e=o.items.find(t=>String(t.id)===String(p));if(!e)return g();try{const t=await L({id:e.id,note:n});if(typeof t.code<"u"&&t.code!==200)throw new Error(t.msg||"保存失败");const a=e.note;e.note=n,S(),I("备注保存成功")}catch{alert("保存备注失败")}finally{g()}});function N(){const n=Math.max(1,Math.ceil(o.total/o.pageSize)),e=Math.min(Math.max(1,o.currentPage),n);o.currentPage=e;const t=k(e,n,2);let a="";a+=`<button class="btn" data-action="prev" ${e===1?"disabled":""}>上一页</button>`,t.forEach(s=>{s==="..."?a+='<span class="small" style="padding:6px 8px">...</span>':a+=`<button class="btn ${s===e?"active":""}" data-page="${s}">${s}</button>`}),a+=`<button class="btn" data-action="next" ${e===n?"disabled":""}>下一页</button>`,w.innerHTML=a}function k(n,e,t){const a=[],s=Math.max(1,n-t),c=Math.min(e,n+t);s>1&&(a.push(1),s>2&&a.push("..."));for(let l=s;l<=c;l++)a.push(l);return c<e&&(c<e-1&&a.push("..."),a.push(e)),a}w.addEventListener("click",n=>{if(!r()){d();return}const e=n.target.closest("button");if(!e)return;const t=e.getAttribute("data-action");if(t==="prev")o.currentPage>1&&o.currentPage--;else if(t==="next"){const a=Math.max(1,Math.ceil(o.total/o.pageSize));o.currentPage<a&&o.currentPage++}else{const a=Number(e.getAttribute("data-page"));isNaN(a)||(o.currentPage=a)}m()});h.addEventListener("change",()=>{if(!r()){d();return}const n=parseInt(h.value,10);o.pageSize=n,o.currentPage=1,m(),x.value=""});async function m(){if(!r()){d();return}const n=Math.max(1,o.currentPage);o.currentPage=n,await C(o.currentPage,o.pageSize),S(),N()}function i(n){return String(n).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}r()?m():d();

261
hcdbqb-management.html

@ -1,6 +1,7 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>管理后台</title>
@ -11,6 +12,7 @@
background: #f7f8fb;
color: #222;
}
.card {
background: #fff;
padding: 16px;
@ -18,11 +20,13 @@
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
margin: auto;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 12px;
}
th,
td {
padding: 10px 12px;
@ -30,16 +34,19 @@
text-align: left;
font-size: 14px;
}
th {
background: #fafafa;
font-weight: 600;
}
.controls {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.pagination {
display: flex;
gap: 6px;
@ -47,6 +54,7 @@
margin-left: auto;
flex-wrap: wrap;
}
.btn {
padding: 6px 10px;
border-radius: 6px;
@ -55,54 +63,71 @@
cursor: pointer;
user-select: none;
}
.btn:disabled {
opacity: 0.5;
cursor: default;
}
.btn.primary {
background: #007bff;
color: #fff;
border-color: #007bff;
}
.btn.whatsapp {
background: #25D366;
color: #fff;
border-color: #25D366;
}
.status-btn {
padding: 4px 8px;
border-radius: 6px;
border: 1px solid #ccc;
cursor: pointer;
}
.status-0 {
background: red;
color: #fff;
}
.status-1 {
background: #2f9e44;
color: #fff;
border-color: #2f9e44;
}
.btn.active {
background: #007bff;
color: #fff;
border-color: #007bff;
}
select,
input[type="number"] {
padding: 6px;
border-radius: 6px;
border: 1px solid #ddd;
}
.small {
font-size: 13px;
color: #666;
}
@media (max-width: 640px) {
.controls {
flex-direction: column;
align-items: flex-start;
}
.pagination {
margin-left: 0;
}
}
#noteModal {
display: none;
position: fixed;
@ -112,6 +137,7 @@
justify-content: center;
z-index: 9999;
}
#noteModal .dialog {
background: #fff;
padding: 16px;
@ -120,6 +146,7 @@
max-width: 520px;
box-sizing: border-box;
}
#noteModal textarea {
width: 100%;
min-width: 60%;
@ -131,6 +158,7 @@
border: 1px solid #ddd;
font-size: 14px;
}
.toast {
position: fixed;
top: -20px;
@ -147,30 +175,83 @@
z-index: 10000;
pointer-events: none;
}
.toast.show {
opacity: 1;
top: 20px;
}
table th,
table td {
text-align: center;
}
/* 登录验证样式 */
#loginCheckModal {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.7);
align-items: center;
justify-content: center;
z-index: 99999;
}
#loginCheckModal .dialog {
background: #fff;
padding: 30px;
border-radius: 12px;
width: 90%;
max-width: 400px;
text-align: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
#loginCheckModal h3 {
margin: 0 0 16px;
color: #e74c3c;
font-size: 20px;
}
#loginCheckModal p {
margin: 0 0 24px;
color: #666;
line-height: 1.5;
}
#loginCheckModal .btn {
padding: 10px 20px;
font-size: 16px;
}
</style>
</head>
<body>
</head>
<body>
<!-- 登录验证模态框 -->
<div id="loginCheckModal">
<div class="dialog">
<h3>访问被拒绝</h3>
<p>您尚未登录或登录已过期,请先登录系统。</p>
<button class="btn primary" id="goToLoginBtn">前往登录页面</button>
</div>
</div>
<div class="card">
<table aria-describedby="tableDesc">
<thead>
<tr>
<th style="width: 40px">#</th>
<th style="width: 100px">姓名</th>
<th style="width: 30px">#</th>
<th style="width: 60px">姓名</th>
<th style="width: 80px">WhatsApp</th>
<th style="width: 90px">国家/地区代码</th>
<th style="width: 120px">电话号码</th>
<th style="width: 120px">微信ID</th>
<th style="width: 150px">邮箱</th>
<th style="width: 160px">添加时间</th>
<th style="width: 100px">是否联系</th>
<th style="width: 160px">备注</th>
<th style="width: 110px">电话号码</th>
<th style="width: 110px">微信ID</th>
<th style="width: 110px">邮箱</th>
<th style="width: 70px">获客来源</th>
<th style="width: 130px">来源地址</th>
<th style="width: 150px">添加时间</th>
<th style="width: 90px">是否联系</th>
<th style="width: 90px">备注</th>
<th style="width: 100px">操作</th>
</tr>
</thead>
@ -196,19 +277,13 @@
<div id="noteModal">
<div class="dialog">
<h3 style="margin: 0 0 8px">编辑备注</h3>
<textarea
id="noteTextarea"
rows="6"
placeholder="输入备注..."
></textarea>
<div
style="
<textarea id="noteTextarea" rows="6" placeholder="输入备注..."></textarea>
<div style="
margin-top: 10px;
display: flex;
justify-content: flex-end;
gap: 8px;
"
>
">
<button class="btn" id="noteCancelBtn">取消</button>
<button class="btn primary" id="noteSaveBtn">保存</button>
</div>
@ -217,12 +292,55 @@
</div>
<div id="toast" class="toast"></div>
<script type="module">
import { getMemberListApi,updateMemberStateApi,editMemberNoteApi }from './src/api/member.js'
import { getMemberListApi, updateMemberStateApi, editMemberNoteApi } from './src/api/member.js'
// 登录验证函数
function checkLoginStatus() {
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
const loginTime = parseInt(localStorage.getItem('loginTime'));
const currentTime = new Date().getTime();
const hoursDiff = (currentTime - loginTime) / (1000 * 60 * 60);
// 检查是否登录且登录时间在24小时内
if (!isLoggedIn || hoursDiff >= 24) {
// 清除过期的登录状态
localStorage.removeItem('isLoggedIn');
localStorage.removeItem('loginTime');
return false;
}
return true;
}
// 显示登录验证模态框
function showLoginCheckModal() {
const modal = document.getElementById('loginCheckModal');
modal.style.display = 'flex';
}
// 隐藏登录验证模态框
function hideLoginCheckModal() {
const modal = document.getElementById('loginCheckModal');
modal.style.display = 'none';
}
// 跳转到登录页面
function redirectToLogin() {
window.location.href = 'login-management.html';
}
// 检查登录状态
if (!checkLoginStatus()) {
showLoginCheckModal();
}
// 绑定前往登录页面按钮事件
document.getElementById('goToLoginBtn').addEventListener('click', redirectToLogin);
let state = {
pageSize: 20,
currentPage: 1,
total: 0,
items:[]
items: []
};
// DOM
@ -247,6 +365,12 @@
setTimeout(() => toastEl.classList.remove("show"), 1000);
}
async function fetchPage(page, pageSize) {
// 每次请求数据前都检查登录状态
if (!checkLoginStatus()) {
showLoginCheckModal();
return;
}
try {
const res = await getMemberListApi({
page: page,
@ -274,24 +398,33 @@
const serial = startIndex + idx + 1;
const statusClass = item.isRelated ? "status-1" : "status-0";
const statusText = item.isRelated ? "已联系" : "未联系";
// 构建WhatsApp链接 - 移除国家代码中的+号
const cleanCode = (item.code || '').replace(/\+/g, '');
const whatsappPhone = cleanCode + (item.telephone || '');
const whatsappUrl = `https://api.whatsapp.com/send?phone=${encodeURIComponent(whatsappPhone)}&text=${encodeURIComponent('hello欢迎来到赢在美股')}`;
return `
<tr>
<td>${serial}</td>
<td>${escapeHtml(item.name || "")}</td>
<td>
<button class="btn whatsapp" data-action="whatsapp" data-id="${item.id}">WhatsApp</button>
</td>
<td>${escapeHtml(item.code || "")}</td>
<td>${escapeHtml(item.telephone || "")}</td>
<td>${escapeHtml(item.wechat || "")}</td>
<td>${escapeHtml(item.email || "")}</td>
<td>${escapeHtml(item.type === 0 ? "其它" : item.type === 1 ? "视频" : item.type === 2 ? "直播" : item.type === 3 ? "帖子" : "其它")}</td>
<td>${escapeHtml(item.url || "")}</td>
<td>${escapeHtml(item.createdAt || "")}</td>
<td>
<button class="status-btn ${statusClass}" data-action="toggle" data-id="${
item.id
<button class="status-btn ${statusClass}" data-action="toggle" data-id="${item.id
}">${statusText}</button>
</td>
<td>${escapeHtml(item.note || "")}</td>
<td>
<button class="btn" data-action="editNote" data-id="${
item.id
<button class="btn" data-action="editNote" data-id="${item.id
}">编辑备注</button>
</td>
</tr>
@ -302,6 +435,20 @@
}
tableBody.addEventListener("click", async (e) => {
// 每次操作前检查登录状态
if (!checkLoginStatus()) {
showLoginCheckModal();
return;
}
// WhatsApp跳转
const whatsappBtn = e.target.closest('[data-action="whatsapp"]');
if (whatsappBtn) {
const id = whatsappBtn.getAttribute("data-id");
handleWhatsApp(id);
return;
}
// 切换状态
const toggler = e.target.closest('[data-action="toggle"]');
if (toggler) {
@ -317,6 +464,20 @@
return;
}
});
// ---------- WhatsApp跳转 ----------
function handleWhatsApp(id) {
const item = state.items.find((it) => String(it.id) === String(id));
if (!item) return;
// 移除国家代码中的+号
const cleanCode = (item.code || '').replace(/\+/g, '');
const whatsappPhone = cleanCode + (item.telephone || '');
const whatsappUrl = `https://api.whatsapp.com/send?phone=${encodeURIComponent(whatsappPhone)}&text=${encodeURIComponent('hello欢迎来到赢在美股')}`;
window.open(whatsappUrl, '_blank');
}
// ---------- 切换联系状态 ----------
async function handleToggle(id, btnEl) {
const item = state.items.find((it) => String(it.id) === String(id));
@ -344,6 +505,12 @@
// ---------- 备注模态相关 ----------
function openNoteModal(id) {
// 打开模态框前检查登录状态
if (!checkLoginStatus()) {
showLoginCheckModal();
return;
}
const item = state.items.find((it) => String(it.id) === String(id));
if (!item) return;
editingRowId = id;
@ -360,6 +527,12 @@
noteCancelBtn.addEventListener("click", closeNoteModal);
noteSaveBtn.addEventListener("click", async () => {
// 保存前检查登录状态
if (!checkLoginStatus()) {
showLoginCheckModal();
return;
}
if (!editingRowId) return closeNoteModal();
const newNote = noteTextarea.value.trim();
const item = state.items.find((it) => String(it.id) === String(editingRowId));
@ -389,20 +562,17 @@
const pages = buildPageList(current, totalPages, 2);
let html = "";
html += `<button class="btn" data-action="prev" ${
current === 1 ? "disabled" : ""
html += `<button class="btn" data-action="prev" ${current === 1 ? "disabled" : ""
}>上一页</button>`;
pages.forEach((p) => {
if (p === "...") {
html += `<span class="small" style="padding:6px 8px">...</span>`;
} else {
html += `<button class="btn ${
p === current ? "active" : ""
html += `<button class="btn ${p === current ? "active" : ""
}" data-page="${p}">${p}</button>`;
}
});
html += `<button class="btn" data-action="next" ${
current === totalPages ? "disabled" : ""
html += `<button class="btn" data-action="next" ${current === totalPages ? "disabled" : ""
}>下一页</button>`;
paginationEl.innerHTML = html;
@ -429,6 +599,12 @@
}
paginationEl.addEventListener("click", (e) => {
// 分页操作前检查登录状态
if (!checkLoginStatus()) {
showLoginCheckModal();
return;
}
const btn = e.target.closest("button");
if (!btn) return;
const action = btn.getAttribute("data-action");
@ -449,6 +625,12 @@
// 每页条数变更
pageSizeSelect.addEventListener("change", () => {
// 操作前检查登录状态
if (!checkLoginStatus()) {
showLoginCheckModal();
return;
}
const newSize = parseInt(pageSizeSelect.value, 10);
state.pageSize = newSize;
state.currentPage = 1;
@ -457,6 +639,12 @@
});
async function update() {
// 更新数据前检查登录状态
if (!checkLoginStatus()) {
showLoginCheckModal();
return;
}
const p = Math.max(1, state.currentPage);
state.currentPage = p;
await fetchPage(state.currentPage, state.pageSize);
@ -474,8 +662,13 @@
.replace(/'/g, "&#39;");
}
// 首次渲染
// 首次渲染 - 检查登录状态
if (checkLoginStatus()) {
update();
} else {
showLoginCheckModal();
}
</script>
</body>
</body>
</html>

155
index.html

@ -36,6 +36,24 @@
}
}
</script>
<style>
/* 在head中添加初始滚动样式 */
html,
body {
scroll-behavior: auto;
}
/* 隐藏页面内容,直到滚动完成 */
body {
opacity: 0;
transition: opacity 0.3s ease;
}
body.content-visible {
opacity: 1;
}
</style>
</head>
<body class="font-sans bg-light text-dark body-text">
@ -49,7 +67,7 @@
<div class="container mx-auto px-4 py-3 flex justify-between items-center">
<a href="#" class="flex items-center space-x-2">
<div class="w-10 h-10 rounded-lg gradient-background flex items-center justify-center">
<img alt="赢在美股" src="https://hc.homilychart.com/hc/250121/img/20230711171637.png"
<img alt="赢在美股" src="https://d31zlh4on95l9h.cloudfront.net/images/497d8b38ab9f738e9720d5d7bddf3beb.png"
style="width: 40px;height: 40px;">
</div>
<span class="text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-primary to-accent">
@ -313,13 +331,13 @@
</div>
</div>
</section>
<!-- 注册表单区域 -->
<section id="register" class="py-20 px-4 bg-white">
<div class="container mx-auto max-w-6xl">
<div class="bg-gradient-to-br from-dark to-gray-800 rounded-3xl shadow-2xl overflow-hidden">
<div class="bg-gradient-to-br rounded-3xl shadow-2xl overflow-hidden">
<div class="grid grid-cols-1 md:grid-cols-2">
<div class="p-8 md:p-12 text-white flex flex-col justify-center">
<!-- 左侧区域 - 已替换背景 -->
<div class="p-8 md:p-12 text-white flex flex-col justify-center bg-image-overlay">
<h2 class="text-2xl md:text-3xl font-bold mb-6 heading-secondary">加入赢在美股,开启赢家人生!</h2>
<p class="text-gray-300 mb-10 leading-relaxed paragraph-text">
填写报名表,即可快速解锁专业投资AI工具,助力您把握投资机会!
@ -357,6 +375,7 @@
</div>
</div>
<!-- 右侧表单区域 - 保持不变 -->
<div class="bg-white p-8 md:p-12">
<form id="registrationForm" class="space-y-6">
<input type="hidden" name="zbtype" id="zbType" value="6">
@ -448,16 +467,16 @@
</section>
<!-- 页脚区域 -->
<footer class="bg-dark text-white py-12 px-4">
<footer class="footer-bg text-white py-12 px-4">
<div class="container mx-auto max-w-6xl">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8">
<div>
<div class="flex items-center space-x-2 mb-6">
<div class="w-10 h-10 rounded-lg gradient-background flex items-center justify-center">
<img alt="夺宝奇兵" src="https://hc.homilychart.com/hc/250121/img/20230711171637.png"
<img alt="赢在美股" src="https://d31zlh4on95l9h.cloudfront.net/images/497d8b38ab9f738e9720d5d7bddf3beb.png"
style="width: 40px;height: 40px;">
</div>
<span class="text-xl font-bold">夺宝奇兵</span>
<span class="text-xl font-bold">赢在美股</span>
</div>
<p class="text-gray-400 mb-6 paragraph-text">
加入赢在美股,开启赢家人生!
@ -485,12 +504,12 @@
<div>
<h4 class="text-lg font-semibold mb-6 heading-tertiary">产品</h4>
<ul class="space-y-3">
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">弘历云版软件</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">HomilyChart</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">夺宝奇兵</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">弘历云版软件</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">HomilyChart</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">夺宝奇兵</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
class="text-gray-400 hover:text-white transition-colors">博股会员</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
@ -501,12 +520,12 @@
<div>
<h4 class="text-lg font-semibold mb-6 heading-tertiary">公司</h4>
<ul class="space-y-3">
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">关于我们</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">团队介绍</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">联系我们</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">关于我们</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">团队介绍</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">联系我们</a></li>
</ul>
</div>
@ -516,15 +535,16 @@
<li class="list-item">
<!-- <a href="hcdbqb-guide.html"
class="text-gray-400 hover:text-white transition-colors">帮助中心</a> -->
<a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" class="text-gray-400 hover:text-white transition-colors">帮助中心</a>
<a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
class="text-gray-400 hover:text-white transition-colors">帮助中心</a>
</li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股" target="_blank"
class="text-gray-400 hover:text-white transition-colors">常见问题</a></li>
<li class="list-item"><a href="https://api.whatsapp.com/send?phone=85255110485&text=我想了解赢在美股"
target="_blank" class="text-gray-400 hover:text-white transition-colors">常见问题</a></li>
</ul>
</div>
</div>
<div class="border-t border-gray-800 pt-8 flex flex-col md:flex-row justify-between items-center">
<div class=" border-gray-800 pt-8 flex flex-col md:flex-row justify-between items-center">
<p class="text-gray-500 text-sm mb-4 md:mb-0 paragraph-text">
&copy; Copyright 2025.Capitalmaster Pte Ltd All Rights Reserved.
</p>
@ -580,6 +600,30 @@
let isSubmitting = false;
/**
* 立即滚动到注册表单(在页面加载前执行)
*/
function scrollToRegisterImmediately() {
// 禁用平滑滚动
document.documentElement.style.scrollBehavior = 'auto';
// 立即滚动到注册表单
const registerSection = document.getElementById('register');
if (registerSection) {
// 计算注册表单的位置(考虑固定导航栏的高度)
const headerHeight = document.querySelector('header').offsetHeight;
const registerPosition = registerSection.offsetTop - headerHeight - 20;
// 立即设置滚动位置
window.scrollTo(0, registerPosition);
}
// 恢复平滑滚动
setTimeout(() => {
document.documentElement.style.scrollBehavior = 'smooth';
}, 100);
}
/**
* 从后端获取讲座图片
*/
async function loadLectureImage() {
@ -694,14 +738,19 @@
const userMobile = document.getElementById("userMobile").value.trim();
const userWechat = document.getElementById("userWechat").value.trim();
const userEmail = document.getElementById("userEmail").value.trim();
const sourceType = await getSourceTypeFromUrl();
const url = await getFromUrl();
const formData = {
name: userNameInfo,
code: countryInfo,
tel: userMobile,
wechat: userWechat,
email: userEmail
email: userEmail,
type: sourceType,
url: url,
};
console.log('formData:', formData); // 调试信息
if (!validateFormData(formData)) {
return;
@ -772,6 +821,17 @@
});
}
// DOM加载完成后立即执行
document.addEventListener('DOMContentLoaded', function () {
// 立即滚动到注册表单
scrollToRegisterImmediately();
// 显示页面内容
setTimeout(() => {
document.body.classList.add('content-visible');
}, 50);
});
// 页面加载完成后执行
window.addEventListener('load', () => {
console.log('页面加载完成,开始调用loadLectureImage...');
@ -804,13 +864,34 @@
// 滚动时执行动画
window.addEventListener('scroll', executeScrollAnimation);
//识别所述的url
//0:是其它 1:是视频 2:是直播 3:是帖子
function getSourceTypeFromUrl() {
const urlParams = new URLSearchParams(window.location.search);
const source = urlParams.get("type");
if (source === "video") {
return 1;
}
if (source === "live") {
return 2;
}
if(source === "article"){
return 3;
}
return 0;
}
function getFromUrl(){
const urlParams = new URLSearchParams(window.location.search);
const url = urlParams.get("url");
return url;
}
</script>
<style>
/* 全局字体大小调整 - 整体调小 */
html {
font-size: 16px;
scroll-behavior: smooth;
}
/* 文本样式类 */
@ -1115,6 +1196,30 @@
border-radius: 50%;
animation: spin 1s linear infinite;
}
.gradient-background {
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
}
.bg-image-overlay {
background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1)),
url('https://d31zlh4on95l9h.cloudfront.net/images/3b28e7abdfc4b495324cc3e6d9210b51.jpg');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.gradient-background {
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
}
.footer-bg {
background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)),
url('https://d31zlh4on95l9h.cloudfront.net/images/22576b3fe6f29e642f322d4d315ae426.jpg');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
</style>
</body>

351
login-management.html

@ -0,0 +1,351 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>系统登录</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
}
body {
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.login-container {
background-color: white;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
width: 100%;
max-width: 420px;
padding: 40px 30px;
transition: transform 0.3s ease;
}
.login-container:hover {
transform: translateY(-5px);
}
.login-header {
text-align: center;
margin-bottom: 30px;
}
.login-header h1 {
color: #333;
font-size: 28px;
margin-bottom: 8px;
}
.login-header p {
color: #666;
font-size: 16px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #555;
font-weight: 500;
}
input {
width: 100%;
padding: 14px 16px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 16px;
transition: all 0.3s;
}
input:focus {
border-color: #4a90e2;
box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.2);
outline: none;
}
.error-message {
color: #e74c3c;
font-size: 14px;
margin-top: 5px;
display: none;
}
.login-button {
background: linear-gradient(to right, #6a11cb, #2575fc);
color: white;
border: none;
border-radius: 8px;
padding: 14px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
width: 100%;
transition: all 0.3s;
margin-top: 10px;
}
.login-button:hover {
background: linear-gradient(to right, #5a0db5, #1c68e8);
box-shadow: 0 5px 15px rgba(37, 117, 252, 0.4);
}
.login-button:active {
transform: scale(0.98);
}
.login-footer {
text-align: center;
margin-top: 25px;
color: #777;
font-size: 14px;
}
.alert {
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
display: none;
}
.alert-error {
background-color: #ffebee;
color: #c62828;
border: 1px solid #ffcdd2;
}
.alert-success {
background-color: #e8f5e9;
color: #2e7d32;
border: 1px solid #c8e6c9;
}
.password-requirements {
font-size: 12px;
color: #777;
margin-top: 5px;
}
.input-error {
border-color: #e74c3c;
box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.2);
}
</style>
</head>
<body>
<div class="login-container">
<div class="login-header">
<h1>系统登录</h1>
<p>请输入您的账号和密码</p>
</div>
<div id="usernameAlert" class="alert alert-error">
账号不存在,请检查后重试!
</div>
<div id="passwordAlert" class="alert alert-error">
密码错误,请检查后重试!
</div>
<form id="loginForm">
<div class="form-group">
<label for="username">账号</label>
<input type="text" id="username" name="username" placeholder="请输入账号" required>
<div class="error-message" id="usernameError">账号不能为空</div>
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" name="password" placeholder="请输入密码" required>
<div class="error-message" id="passwordError">密码不能为空</div>
<div class="password-requirements">密码必须为8位数字</div>
</div>
<button type="submit" class="login-button">登录</button>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const loginForm = document.getElementById('loginForm');
const usernameInput = document.getElementById('username');
const passwordInput = document.getElementById('password');
const usernameError = document.getElementById('usernameError');
const passwordError = document.getElementById('passwordError');
const usernameAlert = document.getElementById('usernameAlert');
const passwordAlert = document.getElementById('passwordAlert');
// 正确的账号和密码
const CORRECT_USERNAME = 'admin';
const CORRECT_PASSWORD = '20251107';
// 表单提交事件
loginForm.addEventListener('submit', function (e) {
e.preventDefault();
// 重置错误状态
resetErrors();
// 获取表单数据
const username = usernameInput.value.trim();
const password = passwordInput.value.trim();
// 表单验证
let isValid = true;
if (!username) {
showError(usernameError, '账号不能为空');
usernameInput.classList.add('input-error');
isValid = false;
}
if (!password) {
showError(passwordError, '密码不能为空');
passwordInput.classList.add('input-error');
isValid = false;
} else if (!/^\d{8}$/.test(password)) {
showError(passwordError, '密码必须为8位数字');
passwordInput.classList.add('input-error');
isValid = false;
}
// 如果验证通过,尝试登录
if (isValid) {
// 验证账号密码
if (username === CORRECT_USERNAME && password === CORRECT_PASSWORD) {
// 登录成功,保存登录状态
localStorage.setItem('isLoggedIn', 'true');
localStorage.setItem('loginTime', new Date().getTime());
// 显示成功消息(短暂显示后跳转)
showSuccessMessage();
// 延迟跳转,让用户看到成功消息
setTimeout(function () {
window.location.href = 'hcdbqb-management.html';
}, 1000);
} else {
// 登录失败,明确提示是账号还是密码错误
if (username !== CORRECT_USERNAME) {
usernameAlert.style.display = 'block';
usernameInput.classList.add('input-error');
usernameInput.focus();
} else {
passwordAlert.style.display = 'block';
passwordInput.classList.add('input-error');
passwordInput.value = '';
passwordInput.focus();
}
}
}
});
// 实时验证
usernameInput.addEventListener('blur', function () {
if (!this.value.trim()) {
showError(usernameError, '账号不能为空');
this.classList.add('input-error');
} else {
hideError(usernameError);
this.classList.remove('input-error');
}
});
passwordInput.addEventListener('blur', function () {
const password = this.value.trim();
if (!password) {
showError(passwordError, '密码不能为空');
this.classList.add('input-error');
} else if (!/^\d{8}$/.test(password)) {
showError(passwordError, '密码必须为8位数字');
this.classList.add('input-error');
} else {
hideError(passwordError);
this.classList.remove('input-error');
}
});
// 输入时隐藏错误提示
usernameInput.addEventListener('input', function () {
hideError(usernameError);
hideAlert(usernameAlert);
this.classList.remove('input-error');
});
passwordInput.addEventListener('input', function () {
hideError(passwordError);
hideAlert(passwordAlert);
this.classList.remove('input-error');
});
// 辅助函数
function showError(element, message) {
element.textContent = message;
element.style.display = 'block';
}
function hideError(element) {
element.style.display = 'none';
}
function hideAlert(alertElement) {
alertElement.style.display = 'none';
}
function resetErrors() {
hideError(usernameError);
hideError(passwordError);
hideAlert(usernameAlert);
hideAlert(passwordAlert);
usernameInput.classList.remove('input-error');
passwordInput.classList.remove('input-error');
}
function showSuccessMessage() {
// 临时创建一个成功提示
const successAlert = document.createElement('div');
successAlert.className = 'alert alert-success';
successAlert.textContent = '登录成功,正在跳转...';
usernameAlert.parentNode.insertBefore(successAlert, usernameAlert);
successAlert.style.display = 'block';
// 移除错误提示(如果有)
hideAlert(usernameAlert);
hideAlert(passwordAlert);
}
// 检查是否已经登录(如果已经登录,直接跳转)
if (localStorage.getItem('isLoggedIn') === 'true') {
// 检查登录时间,如果超过24小时需要重新登录
const loginTime = parseInt(localStorage.getItem('loginTime'));
const currentTime = new Date().getTime();
const hoursDiff = (currentTime - loginTime) / (1000 * 60 * 60);
if (hoursDiff < 24) {
window.location.href = 'hcdbqb-management.html';
} else {
// 超过24小时,清除登录状态
localStorage.removeItem('isLoggedIn');
localStorage.removeItem('loginTime');
}
}
});
</script>
</body>
</html>

10
node_modules/.vite/deps/_metadata.json

@ -1,19 +1,19 @@
{
"hash": "132e41bd",
"configHash": "66355eb0",
"hash": "7b5d0154",
"configHash": "b1454d85",
"lockfileHash": "f3cca4f5",
"browserHash": "6fca54e6",
"browserHash": "bb2def4f",
"optimized": {
"axios": {
"src": "../../axios/index.js",
"file": "axios.js",
"fileHash": "28c0a575",
"fileHash": "27afe6b0",
"needsInterop": false
},
"qs": {
"src": "../../qs/lib/index.js",
"file": "qs.js",
"fileHash": "7572a39a",
"fileHash": "7a1e0a7c",
"needsInterop": true
}
},

11
node_modules/.vue-global-types/vue_3.5_0.d.ts

@ -2,13 +2,14 @@
export {};
; declare global {
var __VLS_PROPS_FALLBACK: Record<string, unknown>;
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
const __VLS_unref: typeof import('vue').unref;
const __VLS_placeholder: any;
const __VLS_intrinsics: import('vue/jsx-runtime').JSX.IntrinsicElements;
type __VLS_NativeElements = __VLS_SpreadMerge<SVGElementTagNameMap, HTMLElementTagNameMap>;
type __VLS_IntrinsicElements = import('vue/jsx-runtime').JSX.IntrinsicElements;
type __VLS_Element = import('vue/jsx-runtime').JSX.Element;
type __VLS_Elements = __VLS_SpreadMerge<SVGElementTagNameMap, HTMLElementTagNameMap>;
type __VLS_GlobalComponents = import('vue').GlobalComponents;
type __VLS_GlobalDirectives = import('vue').GlobalDirectives;
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
@ -31,12 +32,12 @@ export {};
? K extends { __ctx?: { props?: infer P } } ? NonNullable<P> : never
: T extends (props: infer P, ...args: any) => any ? P
: {};
type __VLS_FunctionalComponent<T> = (props: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>, ctx?: any) => __VLS_Element & {
type __VLS_FunctionalComponent<T> = (props: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>, ctx?: any) => import('vue/jsx-runtime').JSX.Element & {
__ctx?: {
attrs?: any;
slots?: T extends { $slots: infer Slots } ? Slots : Record<string, any>;
emit?: T extends { $emit: infer Emit } ? Emit : {};
props?: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>;
props?: typeof props;
expose?: (exposed: T) => void;
};
};

138
node_modules/.vue-global-types/vue_99_0.d.ts

@ -0,0 +1,138 @@
// @ts-nocheck
export {};
; declare global {
var __VLS_PROPS_FALLBACK: Record<string, unknown>;
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
const __VLS_unref: typeof import('vue').unref;
const __VLS_placeholder: any;
const __VLS_intrinsics: import('vue/jsx-runtime').JSX.IntrinsicElements;
type __VLS_Elements = __VLS_SpreadMerge<SVGElementTagNameMap, HTMLElementTagNameMap>;
type __VLS_GlobalComponents = import('vue').GlobalComponents;
type __VLS_GlobalDirectives = import('vue').GlobalDirectives;
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
type __VLS_SpreadMerge<A, B> = Omit<A, keyof B> & B;
type __VLS_WithComponent<N0 extends string, LocalComponents, Self, N1 extends string, N2 extends string, N3 extends string> =
N1 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N1] } :
N2 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N2] } :
N3 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N3] } :
Self extends object ? { [K in N0]: Self } :
N1 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N1] } :
N2 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N2] } :
N3 extends keyof __VLS_GlobalComponents ? { [K in N0]: __VLS_GlobalComponents[N3] } :
{};
type __VLS_FunctionalComponentCtx<T, K> = __VLS_PickNotAny<'__ctx' extends keyof __VLS_PickNotAny<K, {}>
? K extends { __ctx?: infer Ctx } ? NonNullable<Ctx> : never : any
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
>;
type __VLS_FunctionalComponentProps<T, K> = '__ctx' extends keyof __VLS_PickNotAny<K, {}>
? K extends { __ctx?: { props?: infer P } } ? NonNullable<P> : never
: T extends (props: infer P, ...args: any) => any ? P
: {};
type __VLS_FunctionalComponent<T> = (props: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>, ctx?: any) => import('vue/jsx-runtime').JSX.Element & {
__ctx?: {
attrs?: any;
slots?: T extends { $slots: infer Slots } ? Slots : Record<string, any>;
emit?: T extends { $emit: infer Emit } ? Emit : {};
props?: typeof props;
expose?: (exposed: T) => void;
};
};
type __VLS_IsFunction<T, K> = K extends keyof T
? __VLS_IsAny<T[K]> extends false
? unknown extends T[K]
? false
: true
: false
: false;
type __VLS_NormalizeComponentEvent<
Props,
Emits,
onEvent extends keyof Props,
Event extends keyof Emits,
CamelizedEvent extends keyof Emits,
> = __VLS_IsFunction<Props, onEvent> extends true
? Props
: __VLS_IsFunction<Emits, Event> extends true
? { [K in onEvent]?: Emits[Event] }
: __VLS_IsFunction<Emits, CamelizedEvent> extends true
? { [K in onEvent]?: Emits[CamelizedEvent] }
: Props;
// fix https://github.com/vuejs/language-tools/issues/926
type __VLS_UnionToIntersection<U> = (U extends unknown ? (arg: U) => unknown : never) extends ((arg: infer P) => unknown) ? P : never;
type __VLS_OverloadUnionInner<T, U = unknown> = U & T extends (...args: infer A) => infer R
? U extends T
? never
: __VLS_OverloadUnionInner<T, Pick<T, keyof T> & U & ((...args: A) => R)> | ((...args: A) => R)
: never;
type __VLS_OverloadUnion<T> = Exclude<
__VLS_OverloadUnionInner<(() => never) & T>,
T extends () => never ? never : () => never
>;
type __VLS_ConstructorOverloads<T> = __VLS_OverloadUnion<T> extends infer F
? F extends (event: infer E, ...args: infer A) => any
? { [K in E & string]: (...args: A) => void; }
: never
: never;
type __VLS_NormalizeEmits<T> = __VLS_PrettifyGlobal<
__VLS_UnionToIntersection<
__VLS_ConstructorOverloads<T> & {
[K in keyof T]: T[K] extends any[] ? { (...args: T[K]): void } : never
}
>
>;
type __VLS_EmitsToProps<T> = __VLS_PrettifyGlobal<{
[K in string & keyof T as `on${Capitalize<K>}`]?:
(...args: T[K] extends (...args: infer P) => any ? P : T[K] extends null ? any[] : never) => any;
}>;
type __VLS_ResolveEmits<
Comp,
Emits,
TypeEmits = Comp extends { __typeEmits?: infer T } ? unknown extends T ? {} : import('vue').ShortEmitsToObject<T> : {},
NormalizedEmits = __VLS_NormalizeEmits<Emits> extends infer E ? string extends keyof E ? {} : E : never,
> = __VLS_SpreadMerge<NormalizedEmits, TypeEmits>;
type __VLS_ResolveDirectives<T> = {
[K in keyof T & string as `v${Capitalize<K>}`]: T[K];
};
type __VLS_PrettifyGlobal<T> = { [K in keyof T as K]: T[K]; } & {};
type __VLS_WithDefaultsGlobal<P, D> = {
[K in keyof P as K extends keyof D ? K : never]-?: P[K];
} & {
[K in keyof P as K extends keyof D ? never : K]: P[K];
};
type __VLS_UseTemplateRef<T> = Readonly<import('vue').ShallowRef<T | null>>;
type __VLS_ProxyRefs<T> = import('vue').ShallowUnwrapRef<T>;
function __VLS_getVForSourceType<T extends number | string | any[] | Iterable<any>>(source: T): [
item: T extends number ? number
: T extends string ? string
: T extends any[] ? T[number]
: T extends Iterable<infer T1> ? T1
: any,
index: number,
][];
function __VLS_getVForSourceType<T>(source: T): [
item: T[keyof T],
key: keyof T,
index: number,
][];
function __VLS_getSlotParameters<S, D extends S>(slot: S, decl?: D):
D extends (...args: infer P) => any ? P : any[];
function __VLS_asFunctionalDirective<T>(dir: T): T extends import('vue').ObjectDirective
? NonNullable<T['created' | 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated' | 'beforeUnmount' | 'unmounted']>
: T extends (...args: any) => any
? T
: (arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown) => void;
function __VLS_asFunctionalComponent<T, K = T extends new (...args: any) => any ? InstanceType<T> : unknown>(t: T, instance?: K):
T extends new (...args: any) => any ? __VLS_FunctionalComponent<K>
: T extends () => any ? (props: {}, ctx?: any) => ReturnType<T>
: T extends (...args: any) => any ? T
: __VLS_FunctionalComponent<{}>;
function __VLS_functionalComponentArgsRest<T extends (...args: any) => any>(t: T): 2 extends Parameters<T>['length'] ? [any] : [];
function __VLS_asFunctionalElement<T>(tag: T, endTag?: T): (attrs: T & Record<string, unknown>) => void;
function __VLS_asFunctionalSlot<S>(slot: S): S extends () => infer R ? (props: {}) => R : NonNullable<S>;
function __VLS_tryAsConstant<const T>(t: T): T;
}

1
vite.config.js

@ -32,6 +32,7 @@ export default defineConfig(({ mode, command }) => {
main: './index.html',
download: './hcdbqb-download.html',
guide: './hcdbqb-guide.html',
loginManagement: './login-management.html',
management: './hcdbqb-management.html'
},
output: {

Loading…
Cancel
Save