parent
5fafbe2dfd
commit
3d0a8fb4c9
Binary file not shown.
@ -0,0 +1,6 @@
|
||||
flask
|
||||
opencv-python
|
||||
mammoth
|
||||
ultralytics
|
||||
numpy
|
||||
av
|
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 292 KiB |
After Width: | Height: | Size: 88 KiB |
@ -0,0 +1,39 @@
|
||||
body, html {
|
||||
font-family: 'Microsoft YaHei', 'Arial', 'KaiTi', '楷体', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
button {
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
button:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #bdbdbd;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #999;
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>关于本系统的介绍</title>
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.doc-container {
|
||||
max-width: 1000px;
|
||||
margin: 40px auto 0 auto;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 32px rgba(0,0,0,0.10);
|
||||
padding: 40px 48px;
|
||||
}
|
||||
.doc-title {
|
||||
font-size: 36px;
|
||||
font-family: KaiTi, 楷体, serif;
|
||||
color: #1976d2;
|
||||
margin-bottom: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
.doc-content {
|
||||
font-size: 18px;
|
||||
color: #222;
|
||||
line-height: 1.8;
|
||||
}
|
||||
.back-btn {
|
||||
display: block;
|
||||
margin: 32px auto 0 auto;
|
||||
font-size: 22px;
|
||||
padding: 10px 40px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
background: #4CAF50;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
.back-btn:hover {
|
||||
background: #388e3c;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="doc-container">
|
||||
<div class="doc-title">关于本系统的介绍</div>
|
||||
<div class="doc-content">{{ doc_html|safe }}</div>
|
||||
<button class="back-btn" onclick="window.location.href='/'">返回首页</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,92 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>找回密码</title>
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
<style>
|
||||
.forgot-container {
|
||||
width: 400px;
|
||||
margin: 100px auto;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 32px rgba(0,0,0,0.10);
|
||||
padding: 40px 48px;
|
||||
text-align: center;
|
||||
}
|
||||
.forgot-title {
|
||||
font-size: 32px;
|
||||
margin-bottom: 32px;
|
||||
color: #1976d2;
|
||||
}
|
||||
.forgot-input {
|
||||
width: 90%;
|
||||
padding: 12px;
|
||||
margin: 16px 0;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #bdbdbd;
|
||||
font-size: 18px;
|
||||
}
|
||||
.forgot-btn {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-size: 20px;
|
||||
background: #388e3c;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
margin-top: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.forgot-btn:hover {
|
||||
background: #1976d2;
|
||||
}
|
||||
.error-msg {
|
||||
color: #d32f2f;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.success-msg {
|
||||
color: #388e3c;
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="forgot-container">
|
||||
<div class="forgot-title">找回密码</div>
|
||||
<form id="forgotForm">
|
||||
<input class="forgot-input" type="text" name="username" placeholder="用户名" required><br>
|
||||
<input class="forgot-input" type="text" name="answer" placeholder="你的安全问题答案" required><br>
|
||||
<input class="forgot-input" type="password" name="new_password" placeholder="新密码" required><br>
|
||||
<button class="forgot-btn" type="submit">重置密码</button>
|
||||
</form>
|
||||
<div class="error-msg" id="forgotError"></div>
|
||||
<div class="success-msg" id="forgotSuccess"></div>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById('forgotForm').onsubmit = function(e) {
|
||||
e.preventDefault();
|
||||
var form = e.target;
|
||||
var data = new URLSearchParams(new FormData(form));
|
||||
fetch('/forgot', {
|
||||
method: 'POST',
|
||||
body: data
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(res => {
|
||||
if(res.success) {
|
||||
document.getElementById('forgotSuccess').textContent = '密码重置成功,请返回登录';
|
||||
document.getElementById('forgotError').textContent = '';
|
||||
} else {
|
||||
document.getElementById('forgotError').textContent = res.msg || '重置失败';
|
||||
document.getElementById('forgotSuccess').textContent = '';
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
document.getElementById('forgotError').textContent = '网络错误,请重试';
|
||||
document.getElementById('forgotSuccess').textContent = '';
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,483 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>导入已有路径进行分析</title>
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: url('/static/background/page.png') no-repeat center center fixed;
|
||||
background-size: cover;
|
||||
font-family: 'Microsoft YaHei', 'Arial', sans-serif;
|
||||
}
|
||||
|
||||
/* 顶部导航栏 */
|
||||
.top-nav {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 60px;
|
||||
background: rgba(0,0,0,0.8);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 40px;
|
||||
z-index: 1000;
|
||||
border-bottom: 2px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
background: linear-gradient(135deg, #1976d2, #1565c0);
|
||||
color: #fff;
|
||||
padding: 8px 20px;
|
||||
border-radius: 6px;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-btn:hover {
|
||||
background: linear-gradient(135deg, #1565c0, #0d47a1);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.import-container {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: rgba(255,255,255,0.95);
|
||||
padding: 40px 50px;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,0.15);
|
||||
text-align: center;
|
||||
min-width: 500px;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.import-title {
|
||||
font-size: 32px;
|
||||
font-family: KaiTi, 楷体, serif;
|
||||
margin-bottom: 30px;
|
||||
color: #1976d2;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
border: 3px dashed #4CAF50;
|
||||
border-radius: 12px;
|
||||
padding: 40px 20px;
|
||||
margin: 20px 0;
|
||||
background: rgba(76,175,80,0.05);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.upload-area:hover {
|
||||
border-color: #388e3c;
|
||||
background: rgba(76,175,80,0.1);
|
||||
}
|
||||
|
||||
.upload-area.dragover {
|
||||
border-color: #388e3c;
|
||||
background: rgba(76,175,80,0.15);
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 48px;
|
||||
color: #4CAF50;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.file-label {
|
||||
font-size: 18px;
|
||||
margin-bottom: 15px;
|
||||
display: block;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.file-input {
|
||||
font-size: 16px;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
border: 2px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.file-input:focus {
|
||||
border-color: #4CAF50;
|
||||
box-shadow: 0 0 0 3px rgba(76,175,80,0.1);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.run-btn {
|
||||
font-size: 18px;
|
||||
padding: 12px 30px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
background: linear-gradient(135deg, #4CAF50, #388e3c);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(76,175,80,0.3);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.run-btn:hover {
|
||||
background: linear-gradient(135deg, #388e3c, #2e7d32);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(76,175,80,0.4);
|
||||
}
|
||||
|
||||
.run-btn:disabled {
|
||||
background: linear-gradient(135deg, #9e9e9e, #757575);
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
box-shadow: 0 4px 15px rgba(158,158,158,0.3);
|
||||
}
|
||||
|
||||
.result-msg {
|
||||
margin-top: 20px;
|
||||
font-size: 16px;
|
||||
color: #1976d2;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
background: rgba(25,118,210,0.1);
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
color: #d32f2f;
|
||||
background: rgba(211,47,47,0.1);
|
||||
}
|
||||
|
||||
.success-msg {
|
||||
color: #388e3c;
|
||||
background: rgba(76,175,80,0.1);
|
||||
}
|
||||
|
||||
/* 文件信息卡片 */
|
||||
.file-info {
|
||||
background: rgba(76,175,80,0.1);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
border-left: 4px solid #4CAF50;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* 任务描述卡片 */
|
||||
.task-desc {
|
||||
background: rgba(25,118,210,0.1);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
border-left: 4px solid #1976d2;
|
||||
}
|
||||
|
||||
.task-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #1976d2;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.task-content {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* 动作序列表格 */
|
||||
.actions-table {
|
||||
background: rgba(255,255,255,0.9);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.actions-table table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.actions-table th {
|
||||
background: linear-gradient(135deg, #4CAF50, #388e3c);
|
||||
color: #fff;
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.actions-table td {
|
||||
padding: 10px 12px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.actions-table tr:hover {
|
||||
background: rgba(76,175,80,0.05);
|
||||
}
|
||||
|
||||
/* 进度指示器 */
|
||||
.progress-container {
|
||||
margin: 20px 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background: rgba(255,255,255,0.3);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #4CAF50, #388e3c);
|
||||
width: 0%;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 加载动画 */
|
||||
.loading-spinner {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 3px solid rgba(255,255,255,0.3);
|
||||
border-radius: 50%;
|
||||
border-top-color: #fff;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* 返回按钮 */
|
||||
.back-btn {
|
||||
background: linear-gradient(135deg, #1976d2, #1565c0);
|
||||
color: #fff;
|
||||
padding: 10px 25px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(25,118,210,0.3);
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.back-btn:hover {
|
||||
background: linear-gradient(135deg, #1565c0, #0d47a1);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(25,118,210,0.4);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 顶部导航栏 -->
|
||||
<div class="top-nav">
|
||||
<div class="nav-title">路径分析系统</div>
|
||||
<a href="/main_menu" class="nav-btn">返回主菜单</a>
|
||||
</div>
|
||||
|
||||
<div class="import-container">
|
||||
<div class="import-title">📁 导入已有路径进行分析</div>
|
||||
|
||||
{% if not uploaded %}
|
||||
<form method="post" enctype="multipart/form-data" id="uploadForm">
|
||||
<div class="upload-area" id="uploadArea">
|
||||
<div class="upload-icon">📄</div>
|
||||
<label class="file-label">选择Python文件</label>
|
||||
<input class="file-input" type="file" name="file" accept=".py" required id="fileInput">
|
||||
<div style="font-size: 14px; color: #666; margin-top: 10px;">
|
||||
支持的文件格式:.py
|
||||
</div>
|
||||
</div>
|
||||
<button class="run-btn" type="submit">🚀 上传并分析</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% if uploaded %}
|
||||
<div class="file-info">
|
||||
<div class="file-name">📄 {{ filename }}</div>
|
||||
<div style="font-size: 14px; color: #666;">文件已成功上传</div>
|
||||
</div>
|
||||
|
||||
<button class="run-btn" id="runBtn">▶️ 开始运行任务</button>
|
||||
|
||||
{% if nl_desc %}
|
||||
<div class="task-desc">
|
||||
<div class="task-title">📋 任务描述</div>
|
||||
<div class="task-content">{{ nl_desc }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if actions %}
|
||||
<div class="actions-table">
|
||||
<div class="task-title">⚡ 动作序列</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>动作</th>
|
||||
<th>参数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for a in actions %}
|
||||
<tr>
|
||||
<td>{{ a.action }}</td>
|
||||
<td>{{ a.params }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if error %}
|
||||
<div class="result-msg error-msg">❌ {{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="result-msg" id="resultMsg" style="display: none;"></div>
|
||||
|
||||
<!-- 进度指示器 -->
|
||||
<div class="progress-container" id="progressContainer">
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill" id="progressFill"></div>
|
||||
</div>
|
||||
<div class="progress-text" id="progressText">准备中...</div>
|
||||
</div>
|
||||
|
||||
<button class="back-btn" onclick="window.location.href='/main_menu'">← 返回主菜单</button>
|
||||
</div>
|
||||
|
||||
{% if uploaded %}
|
||||
<script>
|
||||
document.getElementById('runBtn').onclick = function() {
|
||||
var btn = this;
|
||||
var progressContainer = document.getElementById('progressContainer');
|
||||
var progressFill = document.getElementById('progressFill');
|
||||
var progressText = document.getElementById('progressText');
|
||||
var resultMsg = document.getElementById('resultMsg');
|
||||
|
||||
// 显示进度指示器
|
||||
progressContainer.style.display = 'block';
|
||||
resultMsg.style.display = 'none';
|
||||
|
||||
// 更新按钮状态
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<span class="loading-spinner"></span>运行中...';
|
||||
|
||||
// 模拟进度更新
|
||||
let progress = 0;
|
||||
const progressInterval = setInterval(() => {
|
||||
progress += Math.random() * 15;
|
||||
if (progress > 90) progress = 90;
|
||||
progressFill.style.width = progress + '%';
|
||||
progressText.textContent = '任务执行中... ' + Math.round(progress) + '%';
|
||||
}, 500);
|
||||
|
||||
fetch('/run_path', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
|
||||
body: 'filename={{ filename }}'
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
clearInterval(progressInterval);
|
||||
progressFill.style.width = '100%';
|
||||
progressText.textContent = '任务完成!';
|
||||
|
||||
// 显示结果
|
||||
resultMsg.style.display = 'block';
|
||||
resultMsg.textContent = data.msg;
|
||||
resultMsg.className = 'result-msg ' + (data.success ? 'success-msg' : 'error-msg');
|
||||
|
||||
// 恢复按钮状态
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '▶️ 开始运行任务';
|
||||
|
||||
// 隐藏进度条
|
||||
setTimeout(() => {
|
||||
progressContainer.style.display = 'none';
|
||||
}, 2000);
|
||||
})
|
||||
.catch(e => {
|
||||
clearInterval(progressInterval);
|
||||
progressContainer.style.display = 'none';
|
||||
|
||||
resultMsg.style.display = 'block';
|
||||
resultMsg.textContent = '❌ 运行出错:' + e;
|
||||
resultMsg.className = 'result-msg error-msg';
|
||||
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '▶️ 开始运行任务';
|
||||
});
|
||||
};
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
// 文件拖拽上传功能
|
||||
const uploadArea = document.getElementById('uploadArea');
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
|
||||
if (uploadArea && fileInput) {
|
||||
uploadArea.addEventListener('click', () => fileInput.click());
|
||||
|
||||
uploadArea.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
uploadArea.classList.add('dragover');
|
||||
});
|
||||
|
||||
uploadArea.addEventListener('dragleave', () => {
|
||||
uploadArea.classList.remove('dragover');
|
||||
});
|
||||
|
||||
uploadArea.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
uploadArea.classList.remove('dragover');
|
||||
const files = e.dataTransfer.files;
|
||||
if (files.length > 0) {
|
||||
fileInput.files = files;
|
||||
// 自动提交表单
|
||||
document.getElementById('uploadForm').submit();
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,144 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>用户登录</title>
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
<style>
|
||||
body {
|
||||
background: url('/static/background/OIP-C.webp') center center/cover no-repeat fixed;
|
||||
}
|
||||
.login-container {
|
||||
width: 400px;
|
||||
margin: 100px auto;
|
||||
background: rgba(255,255,255,0.95);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,0.15);
|
||||
padding: 40px 48px;
|
||||
text-align: center;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
.login-title {
|
||||
font-size: 32px;
|
||||
margin-bottom: 32px;
|
||||
color: #1976d2;
|
||||
}
|
||||
.login-input {
|
||||
width: 90%;
|
||||
padding: 12px;
|
||||
margin: 16px 0;
|
||||
border-radius: 8px;
|
||||
border: 2px solid #e0e0e0;
|
||||
font-size: 18px;
|
||||
transition: all 0.3s ease;
|
||||
background: rgba(255,255,255,0.9);
|
||||
}
|
||||
.login-input:focus {
|
||||
border-color: #4CAF50;
|
||||
box-shadow: 0 0 0 3px rgba(76,175,80,0.1);
|
||||
outline: none;
|
||||
}
|
||||
.login-btn {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-size: 20px;
|
||||
background: linear-gradient(135deg, #1976d2, #1565c0);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(25,118,210,0.3);
|
||||
}
|
||||
.login-btn:hover {
|
||||
background: linear-gradient(135deg, #1565c0, #0d47a1);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(25,118,210,0.4);
|
||||
}
|
||||
.register-link {
|
||||
margin-top: 24px;
|
||||
display: block;
|
||||
color: #388e3c;
|
||||
cursor: pointer;
|
||||
}
|
||||
.error-msg {
|
||||
color: #d32f2f;
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login-container">
|
||||
<div class="login-title">用户登录</div>
|
||||
<form id="loginForm">
|
||||
<input class="login-input" type="text" name="username" placeholder="用户名" required><br>
|
||||
<input class="login-input" type="password" name="password" placeholder="密码" required><br>
|
||||
<button class="login-btn" type="submit">登录</button>
|
||||
</form>
|
||||
<div class="error-msg" id="loginError"></div>
|
||||
<span class="register-link" onclick="window.location.href='/register'">没有账号?点击注册</span>
|
||||
<span class="register-link" onclick="window.location.href='/forgot'">忘记密码?</span>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById('loginForm').onsubmit = function(e) {
|
||||
e.preventDefault();
|
||||
var form = e.target;
|
||||
var data = new URLSearchParams(new FormData(form));
|
||||
fetch('/login', {
|
||||
method: 'POST',
|
||||
body: data
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(res => {
|
||||
if(res.success) {
|
||||
showWelcomeAndRedirect();
|
||||
} else {
|
||||
document.getElementById('loginError').textContent = res.msg || '登录失败';
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
document.getElementById('loginError').textContent = '网络错误,请重试';
|
||||
});
|
||||
};
|
||||
|
||||
function showWelcomeAndRedirect() {
|
||||
var welcomeDiv = document.createElement('div');
|
||||
welcomeDiv.style.position = 'fixed';
|
||||
welcomeDiv.style.left = 0;
|
||||
welcomeDiv.style.top = 0;
|
||||
welcomeDiv.style.width = '100vw';
|
||||
welcomeDiv.style.height = '100vh';
|
||||
welcomeDiv.style.zIndex = 9999;
|
||||
welcomeDiv.style.background = "url('/static/background/welcome.jpg') center center/cover no-repeat";
|
||||
welcomeDiv.style.display = 'flex';
|
||||
welcomeDiv.style.alignItems = 'center';
|
||||
welcomeDiv.style.justifyContent = 'center';
|
||||
welcomeDiv.style.opacity = 0;
|
||||
welcomeDiv.style.transition = 'opacity 0.8s';
|
||||
var text = document.createElement('div');
|
||||
text.textContent = '欢迎使用基于大模型的无人机定点打击系统';
|
||||
text.style.fontSize = '2.5rem';
|
||||
text.style.color = '#fff';
|
||||
text.style.textShadow = '2px 2px 8px #000, 0 0 16px #f00';
|
||||
text.style.fontWeight = 'bold';
|
||||
text.style.background = 'rgba(0,0,0,0.25)';
|
||||
text.style.padding = '32px 48px';
|
||||
text.style.borderRadius = '18px';
|
||||
welcomeDiv.appendChild(text);
|
||||
document.body.appendChild(welcomeDiv);
|
||||
setTimeout(function(){
|
||||
welcomeDiv.style.opacity = 1;
|
||||
}, 10);
|
||||
setTimeout(function(){
|
||||
welcomeDiv.style.opacity = 0;
|
||||
setTimeout(function(){
|
||||
document.body.removeChild(welcomeDiv);
|
||||
window.location.href = '/';
|
||||
}, 800);
|
||||
}, 2000);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,146 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>请选择你的操作类型</title>
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: url('/static/background/page.png') no-repeat center center fixed;
|
||||
background-size: cover;
|
||||
}
|
||||
.main-title {
|
||||
margin-top: 60px;
|
||||
text-align: center;
|
||||
font-family: KaiTi, 楷体, serif;
|
||||
font-size: 54px;
|
||||
color: #fff;
|
||||
text-shadow: 2px 2px 8px #333;
|
||||
}
|
||||
.menu-btns {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 80px;
|
||||
gap: 40px;
|
||||
}
|
||||
.menu-btn {
|
||||
font-size: 32px;
|
||||
padding: 20px 80px;
|
||||
border-radius: 12px;
|
||||
border: none;
|
||||
background: linear-gradient(135deg, #1976d2, #1565c0);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
margin: 0 0 0 0;
|
||||
box-shadow: 0 6px 20px rgba(25,118,210,0.3);
|
||||
font-family: inherit;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.menu-btn::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
|
||||
transition: left 0.5s;
|
||||
}
|
||||
.menu-btn:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
.menu-btn:hover {
|
||||
background: linear-gradient(135deg, #1565c0, #0d47a1);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 25px rgba(25,118,210,0.4);
|
||||
}
|
||||
.menu-btn:active {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
#logout-btn {
|
||||
position: fixed;
|
||||
top: 28px;
|
||||
right: 40px;
|
||||
background: linear-gradient(135deg, #d32f2f, #c62828);
|
||||
color: #fff;
|
||||
padding: 12px 28px;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
box-shadow: 0 4px 15px rgba(211,47,47,0.3);
|
||||
z-index: 1000;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
#logout-btn:hover {
|
||||
background: linear-gradient(135deg, #c62828, #b71c1c);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(211,47,47,0.4);
|
||||
}
|
||||
#doc-btn {
|
||||
position: fixed;
|
||||
top: 28px;
|
||||
left: 40px;
|
||||
background: linear-gradient(135deg, #1976d2, #1565c0);
|
||||
color: #fff;
|
||||
padding: 12px 28px;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
box-shadow: 0 4px 15px rgba(25,118,210,0.3);
|
||||
z-index: 1000;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
#doc-btn:hover {
|
||||
background: linear-gradient(135deg, #1565c0, #0d47a1);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(25,118,210,0.4);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a href="/doc" id="doc-btn">系统信息</a>
|
||||
<a href="/logout" id="logout-btn">退出登录</a>
|
||||
<div class="main-title">请选择你的操作类型</div>
|
||||
<div class="menu-btns">
|
||||
<button class="menu-btn" onclick="window.location.href='/import_path'">导入已有路径进行分析</button>
|
||||
<button class="menu-btn" onclick="window.location.href='/drone_control'">实时操控无人机</button>
|
||||
<button class="menu-btn" id="analyzeBtn">进行结果分析</button>
|
||||
<button class="menu-btn" disabled>导出决策结果(待添加)</button>
|
||||
</div>
|
||||
<div id="analyzeResult" style="margin-top:40px;text-align:center;font-size:20px;color:#1976d2;"></div>
|
||||
<script>
|
||||
document.getElementById('analyzeBtn').onclick = function() {
|
||||
var btn = this;
|
||||
btn.disabled = true;
|
||||
btn.textContent = '分析中...';
|
||||
fetch('/analyze_results')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if(data.result && data.result.indexOf('分析完成') !== -1) {
|
||||
let addr = data.summary_file || '';
|
||||
let summary = (data.summary || []).join('<br>');
|
||||
document.getElementById('analyzeResult').innerHTML = `分析完成,结果已保存在:<span style='color:#388e3c'>${addr}</span><br><br>${summary}`;
|
||||
} else {
|
||||
alert('分析失败,请重新再试');
|
||||
window.location.href = '/main_menu';
|
||||
}
|
||||
btn.disabled = false;
|
||||
btn.textContent = '进行结果分析';
|
||||
})
|
||||
.catch(e => {
|
||||
alert('分析失败,请重新再试');
|
||||
window.location.href = '/main_menu';
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,97 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>用户注册</title>
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
<style>
|
||||
.register-container {
|
||||
width: 400px;
|
||||
margin: 100px auto;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 32px rgba(0,0,0,0.10);
|
||||
padding: 40px 48px;
|
||||
text-align: center;
|
||||
}
|
||||
.register-title {
|
||||
font-size: 32px;
|
||||
margin-bottom: 32px;
|
||||
color: #1976d2;
|
||||
}
|
||||
.register-input {
|
||||
width: 90%;
|
||||
padding: 12px;
|
||||
margin: 16px 0;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #bdbdbd;
|
||||
font-size: 18px;
|
||||
}
|
||||
.register-btn {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-size: 20px;
|
||||
background: #388e3c;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
margin-top: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.register-btn:hover {
|
||||
background: #1976d2;
|
||||
}
|
||||
.login-link {
|
||||
margin-top: 24px;
|
||||
display: block;
|
||||
color: #1976d2;
|
||||
cursor: pointer;
|
||||
}
|
||||
.error-msg {
|
||||
color: #d32f2f;
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="register-container">
|
||||
<div class="register-title">用户注册</div>
|
||||
<form id="registerForm">
|
||||
<input class="register-input" type="text" name="username" placeholder="用户名" required><br>
|
||||
<input class="register-input" type="password" name="password" placeholder="密码" required><br>
|
||||
<input class="register-input" type="password" name="confirm" placeholder="确认密码" required><br>
|
||||
<input class="register-input" type="text" name="security_answer" placeholder="你的安全问题答案(如你母亲的姓名)" required><br>
|
||||
<button class="register-btn" type="submit">注册</button>
|
||||
</form>
|
||||
<div class="error-msg" id="registerError"></div>
|
||||
<span class="login-link" onclick="window.location.href='/login'">已有账号?点击登录</span>
|
||||
<span class="login-link" onclick="window.location.href='/forgot'">忘记密码?</span>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById('registerForm').onsubmit = function(e) {
|
||||
e.preventDefault();
|
||||
var form = e.target;
|
||||
var data = new URLSearchParams(new FormData(form));
|
||||
if(form.password.value !== form.confirm.value) {
|
||||
document.getElementById('registerError').textContent = '两次密码输入不一致';
|
||||
return;
|
||||
}
|
||||
fetch('/register', {
|
||||
method: 'POST',
|
||||
body: data
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(res => {
|
||||
if(res.success) {
|
||||
window.location.href = '/login';
|
||||
} else {
|
||||
document.getElementById('registerError').textContent = res.msg || '注册失败';
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
document.getElementById('registerError').textContent = '网络错误,请重试';
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,65 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>用户中心</title>
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
<style>
|
||||
.user-center-container {
|
||||
width: 400px;
|
||||
margin: 100px auto;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 32px rgba(0,0,0,0.10);
|
||||
padding: 40px 48px;
|
||||
text-align: center;
|
||||
}
|
||||
.user-title {
|
||||
font-size: 32px;
|
||||
margin-bottom: 32px;
|
||||
color: #1976d2;
|
||||
}
|
||||
.user-info {
|
||||
font-size: 20px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
.logout-btn {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-size: 20px;
|
||||
background: #d32f2f;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
margin-top: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.logout-btn:hover {
|
||||
background: #b71c1c;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="user-center-container">
|
||||
<div class="user-title">用户中心</div>
|
||||
<div class="user-info">用户名:<span id="username"></span></div>
|
||||
<div class="user-info">权限:<span id="role"></span></div>
|
||||
<button class="logout-btn" onclick="logout()">退出登录</button>
|
||||
</div>
|
||||
<script>
|
||||
fetch('/user_info').then(r=>r.json()).then(data=>{
|
||||
if(data.success) {
|
||||
document.getElementById('username').textContent = data.username;
|
||||
document.getElementById('role').textContent = data.role;
|
||||
} else {
|
||||
window.location.href = '/login';
|
||||
}
|
||||
});
|
||||
function logout() {
|
||||
fetch('/logout').then(()=>{
|
||||
window.location.href = '/login';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>欢迎使用基于大模型的无人机定点打击系统</title>
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
body {
|
||||
min-height: 100vh;
|
||||
min-width: 100vw;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.bg-img {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
object-fit: cover;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
.welcome-title {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -60%);
|
||||
font-family: KaiTi, 楷体, serif;
|
||||
font-size: 96px;
|
||||
color: #fff;
|
||||
text-shadow: 2px 2px 8px #333;
|
||||
text-align: center;
|
||||
z-index: 2;
|
||||
}
|
||||
.about-btn {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 40px;
|
||||
font-size: 24px;
|
||||
font-family: inherit;
|
||||
padding: 12px 32px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
background: rgba(0,0,0,0.5);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
}
|
||||
.about-btn:hover {
|
||||
background: rgba(0,0,0,0.7);
|
||||
}
|
||||
.enter-btn {
|
||||
position: absolute;
|
||||
top: calc(50% + 200px);
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
font-size: 36px;
|
||||
font-family: inherit;
|
||||
padding: 18px 60px;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
background: #4CAF50;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.2);
|
||||
z-index: 2;
|
||||
}
|
||||
.enter-btn:hover {
|
||||
background: #388e3c;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img class="bg-img" src="/static/background/bg1.png">
|
||||
<button class="about-btn" onclick="window.location.href='/doc'">关于本系统的介绍</button>
|
||||
<div class="welcome-title">欢迎使用基于大模型的无人机定点打击系统</div>
|
||||
<button class="enter-btn" onclick="window.location.href='/main_menu'">进入使用</button>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,53 @@
|
||||
# Ultralytics YOLO 🚀, GPL-3.0 license
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import pkg_resources as pkg
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
# Settings
|
||||
FILE = Path(__file__).resolve()
|
||||
ROOT = FILE.parent # root directory
|
||||
README = (ROOT / "README.md").read_text(encoding="utf-8")
|
||||
REQUIREMENTS = [f'{x.name}{x.specifier}' for x in pkg.parse_requirements((ROOT / 'requirements.txt').read_text())]
|
||||
|
||||
|
||||
def get_version():
|
||||
file = ROOT / 'ultralytics/__init__.py'
|
||||
return re.search(r'^__version__ = [\'"]([^\'"]*)[\'"]', file.read_text(), re.M)[1]
|
||||
|
||||
|
||||
setup(
|
||||
name="ultralytics", # name of pypi package
|
||||
version=get_version(), # version of pypi package
|
||||
python_requires=">=3.7.0",
|
||||
license='GPL-3.0',
|
||||
description='Ultralytics YOLOv8 and HUB',
|
||||
long_description=README,
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/ultralytics/ultralytics",
|
||||
project_urls={
|
||||
'Bug Reports': 'https://github.com/ultralytics/ultralytics/issues',
|
||||
'Funding': 'https://ultralytics.com',
|
||||
'Source': 'https://github.com/ultralytics/ultralytics',},
|
||||
author="Ultralytics",
|
||||
author_email='hello@ultralytics.com',
|
||||
packages=find_packages(), # required
|
||||
include_package_data=True,
|
||||
install_requires=REQUIREMENTS,
|
||||
extras_require={
|
||||
'dev':
|
||||
['check-manifest', 'pytest', 'pytest-cov', 'coverage', 'mkdocs', 'mkdocstrings[python]', 'mkdocs-material'],},
|
||||
classifiers=[
|
||||
"Intended Audience :: Developers", "Intended Audience :: Science/Research",
|
||||
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10",
|
||||
"Topic :: Software Development", "Topic :: Scientific/Engineering",
|
||||
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
||||
"Topic :: Scientific/Engineering :: Image Recognition", "Operating System :: POSIX :: Linux",
|
||||
"Operating System :: MacOS", "Operating System :: Microsoft :: Windows"],
|
||||
keywords="machine-learning, deep-learning, vision, ML, DL, AI, YOLO, YOLOv3, YOLOv5, YOLOv8, HUB, Ultralytics",
|
||||
entry_points={
|
||||
'console_scripts': ['yolo = ultralytics.yolo.cli:cli', 'ultralytics = ultralytics.yolo.cli:cli'],})
|
Loading…
Reference in new issue