UI微调
This commit is contained in:
@@ -12,7 +12,7 @@
|
|||||||
.container { max-width: 360px; margin: 12vh auto; padding: 24px; background: #fff; border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
.container { max-width: 360px; margin: 12vh auto; padding: 24px; background: #fff; border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
||||||
h1 { font-size: 20px; margin: 0 0 16px; }
|
h1 { font-size: 20px; margin: 0 0 16px; }
|
||||||
label { display: block; margin: 12px 0 6px; color: #333; }
|
label { display: block; margin: 12px 0 6px; color: #333; }
|
||||||
input { width: 100%; padding: 10px 12px; border: 1px solid #dcdde1; border-radius: 6px; }
|
input { width: 100%; padding: 10px 0px; border: 1px solid #dcdde1; border-radius: 6px; }
|
||||||
button { width: 100%; margin-top: 16px; padding: 10px 12px; background: #2d8cf0; color: #fff; border: none; border-radius: 6px; cursor: pointer; }
|
button { width: 100%; margin-top: 16px; padding: 10px 12px; background: #2d8cf0; color: #fff; border: none; border-radius: 6px; cursor: pointer; }
|
||||||
button:disabled { background: #9bbcf0; cursor: not-allowed; }
|
button:disabled { background: #9bbcf0; cursor: not-allowed; }
|
||||||
.error { color: #d93025; margin-top: 10px; min-height: 20px; }
|
.error { color: #d93025; margin-top: 10px; min-height: 20px; }
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
.container { max-width: 400px; margin: 10vh auto; padding: 24px; background: #fff; border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
.container { max-width: 400px; margin: 10vh auto; padding: 24px; background: #fff; border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
||||||
h1 { font-size: 20px; margin: 0 0 16px; }
|
h1 { font-size: 20px; margin: 0 0 16px; }
|
||||||
label { display:block; margin: 12px 0 6px; color:#333; }
|
label { display:block; margin: 12px 0 6px; color:#333; }
|
||||||
input { width:100%; padding:10px 12px; border:1px solid #dcdde1; border-radius:6px; }
|
input { width:100%; padding:10px 0px; border:1px solid #dcdde1; border-radius:6px; }
|
||||||
button { width:100%; margin-top:16px; padding:10px 12px; background:#2d8cf0; color:#fff; border:none; border-radius:6px; cursor:pointer; }
|
button { width:100%; margin-top:16px; padding:10px 12px; background:#2d8cf0; color:#fff; border:none; border-radius:6px; cursor:pointer; }
|
||||||
button:disabled { background:#9bbcf0; cursor:not-allowed; }
|
button:disabled { background:#9bbcf0; cursor:not-allowed; }
|
||||||
.error { color:#d93025; margin-top:10px; min-height:20px; }
|
.error { color:#d93025; margin-top:10px; min-height:20px; }
|
||||||
|
|||||||
@@ -4,70 +4,18 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>数据管理</title>
|
<title>数据管理</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {margin: 0;font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;background: #fafafa;}
|
||||||
margin: 0;
|
|
||||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导航栏样式 */
|
/* 导航栏样式 */
|
||||||
.sidebar {
|
.sidebar {position: fixed;top: 0;left: 0;width: 180px;height: 100vh;background: #1e1e2e;color: white;padding: 20px;box-shadow: 2px 0 5px rgba(0,0,0,0.1);z-index: 1000;display: flex;
|
||||||
position: fixed;
|
flex-direction: column;align-items: center;}
|
||||||
top: 0;
|
.user-id {text-align: center;margin-bottom: 0px;}
|
||||||
left: 0;
|
.sidebar h3 {margin-top: 0;font-size: 18px;color: #add8e6;text-align: center; margin-bottom: 20px;}
|
||||||
width: 180px;
|
.navigation-links {width: 100%;margin-top: 60px;}
|
||||||
height: 100vh;
|
|
||||||
background: #1e1e2e;
|
|
||||||
color: white;
|
|
||||||
padding: 20px;
|
|
||||||
box-shadow: 2px 0 5px rgba(0,0,0,0.1);
|
|
||||||
z-index: 1000;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-id {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
color: #add8e6;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-links {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a,
|
.sidebar a,
|
||||||
.sidebar button {
|
.sidebar button {display: block;color: #8be9fd;text-decoration: none;margin: 10px 0;font-size: 16px;padding: 15px;border-radius: 4px;background: transparent;
|
||||||
display: block;
|
border: none;cursor: pointer; width: calc(100% - 40px);text-align: left;transition: all 0.2s ease;}
|
||||||
color: #8be9fd;
|
|
||||||
text-decoration: none;
|
|
||||||
margin: 10px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
width: calc(100% - 40px);
|
|
||||||
text-align: left;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a:hover,
|
.sidebar a:hover,
|
||||||
.sidebar button:hover {
|
.sidebar button:hover {color: #ff79c6;background-color: rgba(139, 233, 253, 0.2);}
|
||||||
color: #ff79c6;
|
|
||||||
background-color: rgba(139, 233, 253, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 主内容区 */
|
/* 主内容区 */
|
||||||
.main-content {
|
.main-content {
|
||||||
margin-left: 200px;
|
margin-left: 200px;
|
||||||
@@ -278,11 +226,11 @@
|
|||||||
<!-- 左侧固定栏目 -->
|
<!-- 左侧固定栏目 -->
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<div class="user-id">
|
<div class="user-id">
|
||||||
<h3>用户ID:{{ user_id }}</h3>
|
<h3>你好,{{ username|default:"访客" }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="navigation-links">
|
<div class="navigation-links">
|
||||||
<a href="{% url 'main:home' %}">主页</a>
|
<a href="{% url 'main:home' %}">返回主页</a>
|
||||||
<button id="logoutBtn">退出登录</button>
|
<a id="logoutBtn">退出登录</a>
|
||||||
<div id="logoutMsg"></div>
|
<div id="logoutMsg"></div>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<style>
|
<style>
|
||||||
body { margin:0; font-family: system-ui,-apple-system, Segoe UI, Roboto, sans-serif; background:#fafafa; }
|
body { margin:0; font-family: system-ui,-apple-system, Segoe UI, Roboto, sans-serif; background:#fafafa; }
|
||||||
.sidebar { position:fixed; top:0; left:0; width:180px; height:100vh; background:#1e1e2e; color:#fff; padding:20px; box-shadow:2px 0 5px rgba(0,0,0,0.1); z-index:1000; display:flex; flex-direction:column; align-items:center; }
|
.sidebar { position:fixed; top:0; left:0; width:180px; height:100vh; background:#1e1e2e; color:#fff; padding:20px; box-shadow:2px 0 5px rgba(0,0,0,0.1); z-index:1000; display:flex; flex-direction:column; align-items:center; }
|
||||||
.sidebar h3 { margin:0; font-size:18px; color:#add8e6; text-align:center; }
|
.sidebar h3 { margin:0; font-size:18px; color:#add8e6; text-align:center; margin-bottom: 20px; }
|
||||||
.navigation-links { width:100%; margin-top:60px; }
|
.navigation-links { width:100%; margin-top:60px; }
|
||||||
.sidebar a, .sidebar button { display:block; color:#8be9fd; text-decoration:none; margin:10px 0; font-size:16px; padding:15px; border-radius:4px; background:transparent; border:none; cursor:pointer; width:calc(100% - 40px); text-align:left; transition:all .2s ease; }
|
.sidebar a, .sidebar button { display:block; color:#8be9fd; text-decoration:none; margin:10px 0; font-size:16px; padding:15px; border-radius:4px; background:transparent; border:none; cursor:pointer; width:calc(100% - 40px); text-align:left; transition:all .2s ease; }
|
||||||
.sidebar a:hover, .sidebar button:hover { color:#ff79c6; background-color:rgba(139,233,253,.2); }
|
.sidebar a:hover, .sidebar button:hover { color:#ff79c6; background-color:rgba(139,233,253,.2); }
|
||||||
@@ -70,9 +70,12 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<h3>用户ID:{{ user_id }}</h3>
|
<h3>你好,{{ username|default:"访客" }}</h3>
|
||||||
<div class="navigation-links">
|
<div class="navigation-links">
|
||||||
<a href="{% url 'main:home' %}">主页</a>
|
<a href="{% url 'main:home' %}">返回主页</a>
|
||||||
|
<a id="logoutBtn">退出登录</a>
|
||||||
|
<div id="logoutMsg"></div>
|
||||||
|
{% csrf_token %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
@@ -115,5 +118,167 @@
|
|||||||
<div class="code-box" id="codeOut"></div>
|
<div class="code-box" id="codeOut"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
|
// 获取CSRF令牌的函数
|
||||||
|
function getCookie(name) {
|
||||||
|
const value = `; ${document.cookie}`;
|
||||||
|
const parts = value.split(`; ${name}=`);
|
||||||
|
if (parts.length === 2) return parts.pop().split(';').shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导航点击处理函数,提供备用URL
|
||||||
|
function handleNavClick(element, fallbackUrl) {
|
||||||
|
// 尝试使用Django模板生成的URL,如果失败则使用备用URL
|
||||||
|
try {
|
||||||
|
// 如果模板渲染正常,直接返回true让默认行为处理
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
// 如果模板渲染有问题,使用备用URL
|
||||||
|
window.location.href = fallbackUrl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修复用户管理链接跳转问题
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// 为用户管理链接添加事件监听器,确保正确跳转
|
||||||
|
const userManagementLink = document.querySelector('a[href*="get_users"]');
|
||||||
|
if (userManagementLink) {
|
||||||
|
userManagementLink.addEventListener('click', function(e) {
|
||||||
|
// 阻止默认行为
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// 获取备用URL
|
||||||
|
const fallbackUrl = this.getAttribute('onclick').match(/'([^']+)'/g)[1].replace(/'/g, '');
|
||||||
|
|
||||||
|
// 直接跳转到用户管理页面
|
||||||
|
window.location.href = fallbackUrl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 登出功能
|
||||||
|
document.getElementById('logoutBtn').addEventListener('click', async () => {
|
||||||
|
const msg = document.getElementById('logoutMsg');
|
||||||
|
msg.textContent = '';
|
||||||
|
const csrftoken = getCookie('csrftoken');
|
||||||
|
try {
|
||||||
|
const resp = await fetch('/accounts/logout/', {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRFToken': csrftoken || ''
|
||||||
|
},
|
||||||
|
body: JSON.stringify({})
|
||||||
|
});
|
||||||
|
const data = await resp.json();
|
||||||
|
if (!resp.ok || !data.ok) {
|
||||||
|
throw new Error('登出失败');
|
||||||
|
}
|
||||||
|
document.cookie = 'sessionid=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
|
||||||
|
document.cookie = 'csrftoken=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
|
||||||
|
window.location.href = data.redirect_url;
|
||||||
|
} catch (e) {
|
||||||
|
msg.textContent = e.message || '发生错误';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function fetchJSON(url){ return fetch(url, {credentials:'same-origin'}).then(r=>r.json()); }
|
||||||
|
function qs(params){ const u = new URLSearchParams(params); return u.toString(); }
|
||||||
|
|
||||||
|
const trendChart = echarts.init(document.getElementById('chartTrend'));
|
||||||
|
const typesChart = echarts.init(document.getElementById('chartTypes'));
|
||||||
|
const typesTrendChart = echarts.init(document.getElementById('chartTypesTrend'));
|
||||||
|
|
||||||
|
async function loadTrend(){
|
||||||
|
const url = '/elastic/analytics/trend/?' + qs({ from:'now-90d', to:'now', interval:'day' });
|
||||||
|
const res = await fetchJSON(url);
|
||||||
|
if(res.status!=='success') return;
|
||||||
|
const buckets = res.data || [];
|
||||||
|
const x = buckets.map(b=>b.key_as_string||'');
|
||||||
|
const y = buckets.map(b=>b.doc_count||0);
|
||||||
|
trendChart.setOption({
|
||||||
|
tooltip:{trigger:'axis'},
|
||||||
|
xAxis:{type:'category', data:x},
|
||||||
|
yAxis:{type:'value'},
|
||||||
|
series:[{ type:'line', areaStyle:{}, data:y, smooth:true, color:'#4f46e5' }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadTypes(){
|
||||||
|
const url = '/elastic/analytics/types/?' + qs({ from:'now-30d', to:'now', size:10 });
|
||||||
|
const res = await fetchJSON(url);
|
||||||
|
if(res.status!=='success') return;
|
||||||
|
const buckets = res.data || [];
|
||||||
|
const data = buckets.map(b=>({ name: String(b.key||'未知'), value: b.doc_count||0 }));
|
||||||
|
typesChart.setOption({
|
||||||
|
tooltip:{trigger:'item'},
|
||||||
|
legend:{type:'scroll'},
|
||||||
|
series:[{ type:'pie', radius:['40%','70%'], data }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadTypesTrend(){
|
||||||
|
const url = '/elastic/analytics/types_trend/?' + qs({ from:'now-180d', to:'now', interval:'week', size:6 });
|
||||||
|
const res = await fetchJSON(url);
|
||||||
|
if(res.status!=='success') return;
|
||||||
|
const rows = res.data || [];
|
||||||
|
const x = rows.map(r=>r.key_as_string||'');
|
||||||
|
const typeSet = new Set();
|
||||||
|
rows.forEach(r=> (r.types||[]).forEach(t=> typeSet.add(String(t.key||'未知'))));
|
||||||
|
const types = Array.from(typeSet);
|
||||||
|
const series = types.map(tp=>({
|
||||||
|
name: tp,
|
||||||
|
type:'line',
|
||||||
|
smooth:true,
|
||||||
|
data: rows.map(r=>{
|
||||||
|
const b = (r.types||[]).find(x=>String(x.key||'')===tp);
|
||||||
|
return b? b.doc_count||0 : 0;
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
typesTrendChart.setOption({
|
||||||
|
tooltip:{trigger:'axis'},
|
||||||
|
legend:{type:'scroll'},
|
||||||
|
xAxis:{type:'category', data:x},
|
||||||
|
yAxis:{type:'value'},
|
||||||
|
series
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTime(t){
|
||||||
|
try{
|
||||||
|
const d = new Date(t);
|
||||||
|
if(String(d) !== 'Invalid Date'){
|
||||||
|
const pad = n=> String(n).padStart(2,'0');
|
||||||
|
return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||||||
|
}
|
||||||
|
}catch(e){}
|
||||||
|
return t||'';
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadRecent(){
|
||||||
|
const listEl = document.getElementById('recentList');
|
||||||
|
const url = '/elastic/analytics/recent/?' + qs({ from:'now-7d', to:'now', limit:10 });
|
||||||
|
const res = await fetchJSON(url);
|
||||||
|
if(res.status!=='success') return;
|
||||||
|
const items = res.data || [];
|
||||||
|
listEl.innerHTML = '';
|
||||||
|
items.forEach(it=>{
|
||||||
|
const li = document.createElement('li');
|
||||||
|
const t = formatTime(it.time);
|
||||||
|
const u = it.username || '';
|
||||||
|
const ty = it.type || '未知';
|
||||||
|
li.textContent = `${t},${u},${ty}`;
|
||||||
|
listEl.appendChild(li);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTrend();
|
||||||
|
loadTypes();
|
||||||
|
loadTypesTrend();
|
||||||
|
loadRecent();
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -4,282 +4,67 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>图片上传与识别</title>
|
<title>图片上传与识别</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {margin: 0;font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;background: #fafafa;}
|
||||||
margin: 0;
|
/* 导航栏样式 */
|
||||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
.sidebar {position: fixed;top: 0;left: 0;width: 180px;height: 100vh;background: #1e1e2e;color: white;padding: 20px;box-shadow: 2px 0 5px rgba(0,0,0,0.1);z-index: 1000;display: flex;
|
||||||
background: #fafafa;
|
flex-direction: column;align-items: center;}
|
||||||
}
|
.user-id {text-align: center;margin-bottom: 0px;}
|
||||||
|
.sidebar h3 {margin-top: 0;font-size: 18px;color: #add8e6;text-align: center; margin-bottom: 20px;}
|
||||||
/* 导航栏样式 - 保持原有样式 */
|
.navigation-links {width: 100%;margin-top: 60px;}
|
||||||
.sidebar {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 180px;
|
|
||||||
height: 100vh;
|
|
||||||
background: #1e1e2e;
|
|
||||||
color: white;
|
|
||||||
padding: 20px;
|
|
||||||
box-shadow: 2px 0 5px rgba(0,0,0,0.1);
|
|
||||||
z-index: 1000;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-id {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
color: #add8e6;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-links {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a,
|
.sidebar a,
|
||||||
.sidebar button {
|
.sidebar button {display: block;color: #8be9fd;text-decoration: none;margin: 10px 0;font-size: 16px;padding: 15px;border-radius: 4px;background: transparent;
|
||||||
display: block;
|
border: none;cursor: pointer; width: calc(100% - 40px);text-align: left;transition: all 0.2s ease;}
|
||||||
color: #8be9fd;
|
|
||||||
text-decoration: none;
|
|
||||||
margin: 10px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
width: calc(100% - 40px);
|
|
||||||
text-align: left;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a:hover,
|
.sidebar a:hover,
|
||||||
.sidebar button:hover {
|
.sidebar button:hover {color: #ff79c6;background-color: rgba(139, 233, 253, 0.2);}
|
||||||
color: #ff79c6;
|
|
||||||
background-color: rgba(139, 233, 253, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 主内容区 - 改进后的样式 */
|
/* 主内容区 - 改进后的样式 */
|
||||||
.main-content {
|
.main-content {margin-left: 200px;padding: 20px;color: #333;}
|
||||||
margin-left: 200px;
|
.container { max-width: 1200px;margin: 0 auto;background: #fff;border-radius: 14px;box-shadow: 0 10px 24px rgba(31,35,40,0.08);
|
||||||
padding: 20px;
|
padding: 24px;}
|
||||||
color: #333;
|
.header {display: flex;align-items: center;justify-content: space-between;margin-bottom: 12px;}
|
||||||
}
|
.header h2 {margin: 0; color: #1e293b;}
|
||||||
|
.header p {margin: 5px 0 0 0;color: #64748b;font-size: 14px;}
|
||||||
.container {
|
.upload-section { background: #f8fafc; border: 2px dashed #cbd5e1; border-radius: 12px;padding: 32px; text-align: center;transition: all 0.3s ease;
|
||||||
max-width: 1200px;
|
margin-bottom: 24px;}
|
||||||
margin: 0 auto;
|
.upload-section:hover {border-color: #4f46e5; background: #f1f5f9; }
|
||||||
background: #fff;
|
.upload-section.drag-over {border-color: #4f46e5; background: #e0e7ff; }
|
||||||
border-radius: 14px;
|
.upload-section input[type="file"] {margin: 15px 0;}
|
||||||
box-shadow: 0 10px 24px rgba(31,35,40,0.08);
|
.btn {padding: 10px 16px;border: none;border-radius: 8px;cursor: pointer;margin: 0 4px;font-size: 14px;transition: all 0.2s ease; }
|
||||||
padding: 24px;
|
.btn-primary { background: #4f46e5; color: #fff; }
|
||||||
}
|
.btn-primary:hover { background: #4338ca;}
|
||||||
|
.btn-secondary {background: #e2e8f0;color: #334155; }
|
||||||
.header {
|
.btn-secondary:hover { background: #cbd5e1;}
|
||||||
display: flex;
|
.btn-danger { background: #ef4444;color: #fff;}
|
||||||
align-items: center;
|
.btn-danger:hover { background: #dc2626;}
|
||||||
justify-content: space-between;
|
.preview-container {display: flex; gap: 24px; margin: 24px 0;}
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header h2 {
|
|
||||||
margin: 0;
|
|
||||||
color: #1e293b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header p {
|
|
||||||
margin: 5px 0 0 0;
|
|
||||||
color: #64748b;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-section {
|
|
||||||
background: #f8fafc;
|
|
||||||
border: 2px dashed #cbd5e1;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 32px;
|
|
||||||
text-align: center;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-section:hover {
|
|
||||||
border-color: #4f46e5;
|
|
||||||
background: #f1f5f9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-section.drag-over {
|
|
||||||
border-color: #4f46e5;
|
|
||||||
background: #e0e7ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-section input[type="file"] {
|
|
||||||
margin: 15px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
padding: 10px 16px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
margin: 0 4px;
|
|
||||||
font-size: 14px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background: #4f46e5;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background: #4338ca;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-secondary {
|
|
||||||
background: #e2e8f0;
|
|
||||||
color: #334155;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-secondary:hover {
|
|
||||||
background: #cbd5e1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-danger {
|
|
||||||
background: #ef4444;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-danger:hover {
|
|
||||||
background: #dc2626;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-container {
|
|
||||||
display: flex;
|
|
||||||
gap: 24px;
|
|
||||||
margin: 24px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.preview-container {
|
.preview-container {flex-direction: column;}
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-box {
|
|
||||||
flex: 1;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-box h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
color: #334155;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-box img {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 300px;
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
border-radius: 8px;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result-box {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result-box h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
color: #334155;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-controls {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
#kvForm {
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 12px;
|
|
||||||
max-height: 300px;
|
|
||||||
overflow: auto;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr auto;
|
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-row input {
|
|
||||||
padding: 8px;
|
|
||||||
border: 1px solid #cbd5e1;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#resultBox {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 200px;
|
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 12px;
|
|
||||||
border: 1px solid #e2e8f0;
|
|
||||||
border-radius: 8px;
|
|
||||||
resize: vertical;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-message {
|
|
||||||
padding: 10px;
|
|
||||||
margin: 10px 0;
|
|
||||||
border-radius: 6px;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-message.success {
|
|
||||||
background-color: #d4edda;
|
|
||||||
color: #155724;
|
|
||||||
border: 1px solid #c3e6cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-message.error {
|
|
||||||
background-color: #f8d7da;
|
|
||||||
color: #721c24;
|
|
||||||
border: 1px solid #f5c6cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons {
|
|
||||||
margin-top: 16px;
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
}
|
||||||
|
.preview-box {flex: 1; text-align: center; }
|
||||||
|
.preview-box h3 {margin-top: 0;color: #334155; }
|
||||||
|
.preview-box img { max-width: 100%;max-height: 300px;border: 1px solid #e2e8f0;border-radius: 8px;object-fit: contain;}
|
||||||
|
.result-box {flex: 1;}
|
||||||
|
.result-box h3 { margin-top: 0; color: #334155;}
|
||||||
|
.form-controls { display: flex;gap: 8px;margin-bottom: 12px;flex-wrap: wrap;}
|
||||||
|
#kvForm {border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px; max-height: 300px; overflow: auto;margin-bottom: 12px;background: white;}
|
||||||
|
.form-row {display: grid;grid-template-columns: 1fr 1fr auto;gap: 8px; margin-bottom: 6px; }
|
||||||
|
.form-row input {padding: 8px;border: 1px solid #cbd5e1;border-radius: 4px;}
|
||||||
|
#resultBox { width: 100%;min-height: 200px;font-family: ui-monospace, SFMono-Regular, Menlo, monospace;font-size: 14px; padding: 12px; border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 8px; resize: vertical;box-sizing: border-box; }
|
||||||
|
.status-message { padding: 10px; margin: 10px 0; border-radius: 6px; display: none; }
|
||||||
|
.status-message.success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
|
||||||
|
.status-message.error { background-color: #f8d7da;color: #721c24; border: 1px solid #f5c6cb; }
|
||||||
|
.action-buttons { margin-top: 16px; display: flex; gap: 8px; flex-wrap: wrap; }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- 左侧固定栏目 -->
|
<!-- 左侧固定栏目 -->
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<div class="user-id">
|
<div class="user-id">
|
||||||
<h3>用户ID:{{ user_id }}</h3>
|
<h3>你好,{{ username|default:"访客" }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="navigation-links">
|
<div class="navigation-links">
|
||||||
<a href="{% url 'main:home' %}">主页</a>
|
<a href="{% url 'main:home' %}">返回主页</a>
|
||||||
<button id="logoutBtn">退出登录</button>
|
<a id="logoutBtn">退出登录</a>
|
||||||
<div id="logoutMsg"></div>
|
<div id="logoutMsg"></div>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,70 +4,18 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>用户管理</title>
|
<title>用户管理</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {margin: 0;font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;background: #fafafa;}
|
||||||
margin: 0;
|
|
||||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导航栏样式 */
|
/* 导航栏样式 */
|
||||||
.sidebar {
|
.sidebar {position: fixed;top: 0;left: 0;width: 180px;height: 100vh;background: #1e1e2e;color: white;padding: 20px;box-shadow: 2px 0 5px rgba(0,0,0,0.1);z-index: 1000;display: flex;
|
||||||
position: fixed;
|
flex-direction: column;align-items: center;}
|
||||||
top: 0;
|
.user-id {text-align: center;margin-bottom: 0px;}
|
||||||
left: 0;
|
.sidebar h3 {margin-top: 0;font-size: 18px;color: #add8e6;text-align: center; margin-bottom: 20px;}
|
||||||
width: 180px;
|
.navigation-links {width: 100%;margin-top: 60px;}
|
||||||
height: 100vh;
|
|
||||||
background: #1e1e2e;
|
|
||||||
color: white;
|
|
||||||
padding: 20px;
|
|
||||||
box-shadow: 2px 0 5px rgba(0,0,0,0.1);
|
|
||||||
z-index: 1000;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-id {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
color: #add8e6;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-links {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a,
|
.sidebar a,
|
||||||
.sidebar button {
|
.sidebar button {display: block;color: #8be9fd;text-decoration: none;margin: 10px 0;font-size: 16px;padding: 15px;border-radius: 4px;background: transparent;
|
||||||
display: block;
|
border: none;cursor: pointer; width: calc(100% - 40px);text-align: left;transition: all 0.2s ease;}
|
||||||
color: #8be9fd;
|
|
||||||
text-decoration: none;
|
|
||||||
margin: 10px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
width: calc(100% - 40px);
|
|
||||||
text-align: left;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a:hover,
|
.sidebar a:hover,
|
||||||
.sidebar button:hover {
|
.sidebar button:hover {color: #ff79c6;background-color: rgba(139, 233, 253, 0.2);}
|
||||||
color: #ff79c6;
|
|
||||||
background-color: rgba(139, 233, 253, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 主内容区 */
|
/* 主内容区 */
|
||||||
.main-content {
|
.main-content {
|
||||||
margin-left: 200px;
|
margin-left: 200px;
|
||||||
@@ -258,11 +206,11 @@
|
|||||||
<!-- 左侧固定栏目 -->
|
<!-- 左侧固定栏目 -->
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<div class="user-id">
|
<div class="user-id">
|
||||||
<h3>用户ID:{{ user_id }}</h3>
|
<h3>你好,{{ username|default:"访客" }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="navigation-links">
|
<div class="navigation-links">
|
||||||
<a href="{% url 'main:home' %}" onclick="return handleNavClick(this, '/');">主页</a>
|
<a href="{% url 'main:home' %}" onclick="return handleNavClick(this, '/');">返回主页</a>
|
||||||
<button id="logoutBtn">退出登录</button>
|
<a id="logoutBtn">退出登录</a>
|
||||||
<div id="logoutMsg"></div>
|
<div id="logoutMsg"></div>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,138 +6,37 @@
|
|||||||
<title>数据管理系统</title>
|
<title>数据管理系统</title>
|
||||||
<script src="{% static 'vendor/echarts.min.js' %}"></script>
|
<script src="{% static 'vendor/echarts.min.js' %}"></script>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {margin: 0;font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;background: #fafafa;}
|
||||||
margin: 0;
|
|
||||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导航栏样式 */
|
/* 导航栏样式 */
|
||||||
.sidebar {
|
.sidebar {position: fixed;top: 0;left: 0;width: 180px;height: 100vh;background: #1e1e2e;color: white;padding: 20px;box-shadow: 2px 0 5px rgba(0,0,0,0.1);z-index: 1000;display: flex;
|
||||||
position: fixed;
|
flex-direction: column;align-items: center;}
|
||||||
top: 0;
|
.user-id {text-align: center;margin-bottom: 0px;}
|
||||||
left: 0;
|
.sidebar h3 {margin-top: 0;font-size: 18px;color: #add8e6;text-align: center; margin-bottom: 20px;}
|
||||||
width: 180px;
|
.navigation-links {width: 100%;margin-top: 60px;}
|
||||||
height: 100vh;
|
|
||||||
background: #1e1e2e;
|
|
||||||
color: white;
|
|
||||||
padding: 20px;
|
|
||||||
box-shadow: 2px 0 5px rgba(0,0,0,0.1);
|
|
||||||
z-index: 1000;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-id {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
color: #add8e6;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navigation-links {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a,
|
.sidebar a,
|
||||||
.sidebar button {
|
.sidebar button {display: block;color: #8be9fd;text-decoration: none;margin: 10px 0;font-size: 16px;padding: 15px;border-radius: 4px;background: transparent;
|
||||||
display: block;
|
border: none;cursor: pointer; width: calc(100% - 40px);text-align: left;transition: all 0.2s ease;}
|
||||||
color: #8be9fd;
|
|
||||||
text-decoration: none;
|
|
||||||
margin: 10px 0;
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
width: calc(100% - 40px);
|
|
||||||
text-align: left;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar a:hover,
|
.sidebar a:hover,
|
||||||
.sidebar button:hover {
|
.sidebar button:hover {color: #ff79c6;background-color: rgba(139, 233, 253, 0.2);}
|
||||||
color: #ff79c6;
|
|
||||||
background-color: rgba(139, 233, 253, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 主内容区 */
|
/* 主内容区 */
|
||||||
.main-content {
|
.main-content {margin-left: 200px;padding: 20px;color: #333;}
|
||||||
margin-left: 200px;
|
.card {background: #fff;border-radius: 14px;box-shadow: 0 10px 24px rgba(31,35,40,0.08);padding: 20px;}
|
||||||
padding: 20px;
|
.grid {display: grid;grid-template-columns: repeat(2, 1fr);gap: 16px;}
|
||||||
color: #333;
|
.grid-3 {display: grid;grid-template-columns: repeat(3, 1fr);gap: 16px; }
|
||||||
}
|
.header {display: flex;align-items: center; justify-content: space-between; margin-bottom: 12px; }
|
||||||
|
.badge { background: #eef2ff; color: #3730a3; border-radius: 999px; padding: 4px 10px; font-size: 12px; }
|
||||||
.card {
|
.legend {display: flex;gap: 12px;align-items: center;}
|
||||||
background: #fff;
|
.legend .dot { width: 8px;height: 8px;border-radius: 50%;display: inline-block; }
|
||||||
border-radius: 14px;
|
.muted {color: #6b7280;font-size: 12px;}
|
||||||
box-shadow: 0 10px 24px rgba(31,35,40,0.08);
|
.btn {padding: 8px 12px;border: none; border-radius: 8px;cursor: pointer; }
|
||||||
padding: 20px;
|
.btn-primary {background: #4f46e5;color: #fff;}
|
||||||
}
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
.grid-3 {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
.badge {
|
|
||||||
background: #eef2ff;
|
|
||||||
color: #3730a3;
|
|
||||||
border-radius: 999px;
|
|
||||||
padding: 4px 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.legend {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.legend .dot {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
.muted {
|
|
||||||
color: #6b7280;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.btn {
|
|
||||||
padding: 8px 12px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.btn-primary {
|
|
||||||
background: #4f46e5;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- 左侧固定栏目 -->
|
<!-- 左侧固定栏目 -->
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<div class="user-id">
|
<div class="user-id">
|
||||||
<h3>用户ID:{{ user_id }}</h3>
|
<h3>你好,{{ username|default:"访客" }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="navigation-links">
|
<div class="navigation-links">
|
||||||
<a href="{% url 'main:home' %}" onclick="return handleNavClick(this, '/');">主页</a>
|
<a href="{% url 'main:home' %}" onclick="return handleNavClick(this, '/');">主页</a>
|
||||||
@@ -147,7 +46,7 @@
|
|||||||
<a href="{% url 'elastic:user_manage' %}" onclick="return handleNavClick(this, '/elastic/user_manage/');">用户管理</a>
|
<a href="{% url 'elastic:user_manage' %}" onclick="return handleNavClick(this, '/elastic/user_manage/');">用户管理</a>
|
||||||
<a href="{% url 'elastic:registration_code_manage_page' %}" onclick="return handleNavClick(this, '/elastic/registration-codes/manage/');">注册码管理</a>
|
<a href="{% url 'elastic:registration_code_manage_page' %}" onclick="return handleNavClick(this, '/elastic/registration-codes/manage/');">注册码管理</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button id="logoutBtn">退出登录</button>
|
<a id="logoutBtn">退出登录</a>
|
||||||
<div id="logoutMsg"></div>
|
<div id="logoutMsg"></div>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user