You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
654 lines
16 KiB
654 lines
16 KiB
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
<title>管理后台</title>
|
|
<style>
|
|
.tab-container {
|
|
max-width: 1200px;
|
|
margin: 0 0 12px 0;
|
|
padding: 0 16px;
|
|
}
|
|
|
|
.tabs {
|
|
display: flex;
|
|
gap: 50px;
|
|
padding: 4px;
|
|
border-radius: 8px;
|
|
width: fit-content;
|
|
}
|
|
|
|
.tab {
|
|
padding: 10px 20px;
|
|
border-radius: 6px;
|
|
border: none;
|
|
background: transparent;
|
|
color: #131212;
|
|
font-weight: 700;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
font-size: 16px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.tab:hover {
|
|
background: rgba(46, 125, 50, 0.1);
|
|
color: #25D366;
|
|
}
|
|
|
|
.tab.active {
|
|
background: #BAF7D0;
|
|
color: #0E4322;
|
|
box-shadow: 0 2px 4px rgba(46, 125, 50, 0.3);
|
|
}
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
padding: 24px;
|
|
background: #f7f8fb;
|
|
color: #222;
|
|
}
|
|
|
|
.card {
|
|
background: #fff;
|
|
padding: 16px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
margin: auto;
|
|
min-height: 700px;
|
|
border: 5px solid #D9D9D9;
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: relative;
|
|
}
|
|
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 12px;
|
|
}
|
|
|
|
th,
|
|
td {
|
|
padding: 10px 12px;
|
|
border-bottom: 1px solid #eee;
|
|
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;
|
|
align-items: center;
|
|
margin-left: auto;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.btn {
|
|
padding: 6px 10px;
|
|
border-radius: 6px;
|
|
border: 1px solid #ddd;
|
|
background: #fff;
|
|
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) {
|
|
.tabs {
|
|
flex-wrap: wrap;
|
|
width: 100%;
|
|
}
|
|
|
|
.tab {
|
|
flex: 1;
|
|
min-width: 120px;
|
|
text-align: center;
|
|
}
|
|
.controls {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.pagination {
|
|
margin-left: 0;
|
|
}
|
|
}
|
|
|
|
#noteModal {
|
|
display: none;
|
|
position: fixed;
|
|
inset: 0;
|
|
background: rgba(0, 0, 0, 0.45);
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 9999;
|
|
}
|
|
|
|
#noteModal .dialog {
|
|
background: #fff;
|
|
padding: 16px;
|
|
border-radius: 8px;
|
|
width: 90%;
|
|
max-width: 520px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
#noteModal textarea {
|
|
width: 100%;
|
|
min-width: 60%;
|
|
max-width: 100%;
|
|
min-height: 150px;
|
|
box-sizing: border-box;
|
|
padding: 8px;
|
|
border-radius: 6px;
|
|
border: 1px solid #ddd;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.toast {
|
|
position: fixed;
|
|
top: -20px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
background: #4caf50;
|
|
color: #fff;
|
|
padding: 10px 16px;
|
|
border-radius: 6px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
font-size: 16px;
|
|
opacity: 0;
|
|
transition: all 0.3s ease;
|
|
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;
|
|
}
|
|
|
|
/* 图片上传组件样式 */
|
|
.config-section {
|
|
display: flex;
|
|
align-items: center; /* 垂直居中 */
|
|
gap: 30px;
|
|
margin-bottom: 40px;
|
|
padding: 20px 40px;
|
|
}
|
|
.section-label {
|
|
font-weight: bold;
|
|
min-width: 60px;
|
|
font-size: 20px;
|
|
color: #333;
|
|
}
|
|
.image-uploader {
|
|
position: relative;
|
|
/* 图片尺寸需要修改确认几比几 */
|
|
width: 240px;
|
|
height: 160px;
|
|
border: 1px dashed #d9d9d9;
|
|
border-radius: 6px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
background: #fff;
|
|
transition: all 0.3s;
|
|
cursor: pointer;
|
|
}
|
|
.image-uploader:hover {
|
|
border-color: #BAF7D0;
|
|
}
|
|
.upload-btn {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
font-size: 36px;
|
|
color: #bfbfbf; /* 更淡的灰色 */
|
|
font-weight: lighter;
|
|
}
|
|
.preview-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: relative;
|
|
}
|
|
.preview-container img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
.delete-overlay {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0,0,0,0.5);
|
|
display: none;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transition: all 0.3s;
|
|
}
|
|
.preview-container:hover .delete-overlay {
|
|
display: flex;
|
|
}
|
|
.delete-btn {
|
|
background: transparent;
|
|
color: white;
|
|
border: 1px solid white;
|
|
padding: 6px 16px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
transition: all 0.3s;
|
|
}
|
|
.delete-btn:hover {
|
|
background: rgba(255,255,255,0.2);
|
|
}
|
|
.action-bar {
|
|
display: flex;
|
|
justify-content: center;
|
|
margin-top: auto; /* 关键:推到底部 */
|
|
padding-bottom: 40px; /* 留出底部间距 */
|
|
}
|
|
#saveConfigBtn {
|
|
width: 130px;
|
|
height: 60px;
|
|
font-size: 30px;
|
|
background: #BAF7D0;
|
|
color: #0D4221;
|
|
border: none;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
border-radius: 6px;
|
|
letter-spacing: 2px;
|
|
}
|
|
#saveConfigBtn:hover {
|
|
background: #a5e6bc;
|
|
box-shadow: 0 4px 12px rgba(186, 247, 208, 0.4);
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<!-- 登录验证模态框 -->
|
|
<div id="loginCheckModal">
|
|
<div class="dialog">
|
|
<h3>访问被拒绝</h3>
|
|
<p>您尚未登录或登录已过期,请先登录系统。</p>
|
|
<button class="btn primary" id="goToLoginBtn">前往登录页面</button>
|
|
</div>
|
|
</div>
|
|
<div class="tab-container">
|
|
<div class="tabs">
|
|
<button class="tab" data-tab="win-us-stock">赢在美股导流</button>
|
|
<button class="tab" data-tab="deepchart">DeepChart导流</button>
|
|
<button class="tab active" data-tab="content-config">内容配置</button>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<div class="config-section">
|
|
<div class="section-label">课程图</div>
|
|
<div class="image-uploader" id="imageUploader">
|
|
<div class="upload-btn" id="uploadBtn">
|
|
<span>+</span>
|
|
<input type="file" id="fileInput" accept="image/*" hidden>
|
|
</div>
|
|
<div class="preview-container" id="previewContainer" style="display: none;">
|
|
<img id="previewImage" src="" alt="Preview">
|
|
<div class="delete-overlay">
|
|
<button class="delete-btn" id="deleteBtn">删除</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="action-bar">
|
|
<button id="saveConfigBtn">保存</button>
|
|
</div>
|
|
</div>
|
|
<div id="toast" class="toast"></div>
|
|
<script type="module">
|
|
import { saveContentConfigApi, getImage1Api, uploadFileApi } 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);
|
|
|
|
// 初始化Tab切换
|
|
initTabs();
|
|
|
|
// Tab切换功能
|
|
function initTabs() {
|
|
const tabs = document.querySelectorAll('.tab');
|
|
tabs.forEach(tab => {
|
|
tab.addEventListener('click', function() {
|
|
tabs.forEach(t => t.classList.remove('active'));
|
|
this.classList.add('active');
|
|
|
|
const tabId = this.getAttribute('data-tab');
|
|
switch(tabId) {
|
|
case 'win-us-stock':
|
|
// 当前页面,不需要跳转
|
|
console.log('切换到赢在美股导流页面');
|
|
window.location.href = 'hcdbqb-management.html';
|
|
break;
|
|
case 'deepchart':
|
|
// 跳转到DeepChart导流页面
|
|
console.log('切换到DeepChart导流页面');
|
|
window.location.href = 'deepchart-management.html';
|
|
break;
|
|
case 'content-config':
|
|
// 跳转到内容配置页面
|
|
console.log('切换到内容配置页面');
|
|
// window.location.href = 'content-config.html';
|
|
break;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// --- 新增图片上传逻辑 ---
|
|
|
|
const uploadBtn = document.getElementById('uploadBtn');
|
|
const fileInput = document.getElementById('fileInput');
|
|
const previewContainer = document.getElementById('previewContainer');
|
|
const previewImage = document.getElementById('previewImage');
|
|
const deleteBtn = document.getElementById('deleteBtn');
|
|
const saveConfigBtn = document.getElementById('saveConfigBtn');
|
|
const toastEl = document.getElementById('toast');
|
|
|
|
let currentFile = null;
|
|
let currentImageUrl = '';
|
|
let currentVideoUrl = '';
|
|
|
|
function showToast(msg) {
|
|
toastEl.textContent = msg;
|
|
toastEl.classList.add("show");
|
|
setTimeout(() => toastEl.classList.remove("show"), 1000);
|
|
}
|
|
|
|
// 页面加载时获取当前配置
|
|
if (checkLoginStatus()) {
|
|
loadCurrentConfig();
|
|
}
|
|
|
|
async function loadCurrentConfig() {
|
|
// 每次请求数据前都检查登录状态
|
|
if (!checkLoginStatus()) {
|
|
showLoginCheckModal();
|
|
return;
|
|
}
|
|
try {
|
|
const res = await getImage1Api({
|
|
id:1
|
|
});
|
|
if (res && res.code === 200 && res.data && res.data.img_url) {
|
|
currentImageUrl = res.data.img_url;
|
|
currentVideoUrl = res.data.video;
|
|
showPreview(currentImageUrl);
|
|
}
|
|
} catch (e) {
|
|
console.error('加载配置失败', e);
|
|
}
|
|
}
|
|
|
|
function showPreview(src) {
|
|
previewImage.src = src;
|
|
previewContainer.style.display = 'block';
|
|
uploadBtn.style.display = 'none';
|
|
}
|
|
|
|
function resetUpload() {
|
|
fileInput.value = '';
|
|
currentFile = null;
|
|
currentImageUrl = '';
|
|
previewImage.src = '';
|
|
previewContainer.style.display = 'none';
|
|
uploadBtn.style.display = 'flex';
|
|
}
|
|
|
|
uploadBtn.addEventListener('click', () => {
|
|
if (!checkLoginStatus()) {
|
|
showLoginCheckModal();
|
|
return;
|
|
}
|
|
fileInput.click();
|
|
});
|
|
|
|
fileInput.addEventListener('change', async (e) => {
|
|
if (!checkLoginStatus()) {
|
|
showLoginCheckModal();
|
|
return;
|
|
}
|
|
const file = e.target.files[0];
|
|
if (file) {
|
|
// 1. 立即显示本地预览
|
|
const reader = new FileReader();
|
|
reader.onload = (e) => {
|
|
showPreview(e.target.result);
|
|
};
|
|
reader.readAsDataURL(file);
|
|
|
|
// 2. 立即上传文件获取URL
|
|
try {
|
|
showToast('正在上传图片...');
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
formData.append('app_from', 'en');
|
|
formData.append('type', 'image');
|
|
//尺寸不确定
|
|
formData.append('imgWidth', '600');
|
|
formData.append('imgHeight', '400');
|
|
const res = await uploadFileApi(formData);
|
|
|
|
if (res && res.code === 200 && res.data) {
|
|
const uploadedUrl = typeof res.data === 'string' ? res.data : res.data.url;
|
|
|
|
if (uploadedUrl) {
|
|
currentImageUrl = uploadedUrl;
|
|
currentFile = null;
|
|
showToast('图片上传成功');
|
|
} else {
|
|
throw new Error('未获取到有效的图片地址');
|
|
}
|
|
} else {
|
|
throw new Error(res.msg || '上传接口返回错误');
|
|
}
|
|
} catch (error) {
|
|
console.error('上传失败', error);
|
|
showToast('图片上传失败: ' + (error.message || '未知错误'));
|
|
resetUpload()
|
|
}
|
|
}
|
|
});
|
|
|
|
deleteBtn.addEventListener('click', (e) => {
|
|
if (!checkLoginStatus()) {
|
|
showLoginCheckModal();
|
|
return;
|
|
}
|
|
e.stopPropagation();
|
|
resetUpload();
|
|
});
|
|
|
|
saveConfigBtn.addEventListener('click', async () => {
|
|
if (!checkLoginStatus()) {
|
|
showLoginCheckModal();
|
|
return;
|
|
}
|
|
|
|
if (!currentImageUrl) {
|
|
showToast('请先上传图片');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const formData = new FormData();
|
|
formData.append('id', 1);
|
|
formData.append('url', currentImageUrl);
|
|
formData.append('video', currentVideoUrl);
|
|
const res = await saveContentConfigApi(formData);
|
|
if (res && res.code === 200) {
|
|
showToast('保存配置成功');
|
|
} else {
|
|
throw new Error(res.msg || '保存失败');
|
|
}
|
|
} catch (e) {
|
|
showToast(e.message || '保存失败');
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|