docs: 添加了更健壮的注释
This commit is contained in:
108
.trae/documents/plan_20251224_165001.md
Normal file
108
.trae/documents/plan_20251224_165001.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
## 前端生产级健壮性提升计划
|
||||||
|
|
||||||
|
### 1. 核心改进点
|
||||||
|
|
||||||
|
#### 添加刷新按钮
|
||||||
|
|
||||||
|
* 在下载区域标题旁添加刷新按钮
|
||||||
|
|
||||||
|
* 点击按钮重新加载App列表
|
||||||
|
|
||||||
|
* 保持与现有按钮风格一致
|
||||||
|
|
||||||
|
#### 增强API调用健壮性
|
||||||
|
|
||||||
|
* 统一API请求处理,添加错误处理
|
||||||
|
|
||||||
|
* 完善各种错误场景的用户反馈
|
||||||
|
|
||||||
|
* 添加加载状态提示
|
||||||
|
|
||||||
|
* 处理网络错误和超时情况
|
||||||
|
|
||||||
|
#### 改进用户体验
|
||||||
|
|
||||||
|
* 添加操作成功/失败的视觉反馈
|
||||||
|
|
||||||
|
* 优化表单验证
|
||||||
|
|
||||||
|
* 改进文件上传反馈
|
||||||
|
|
||||||
|
#### 前后端适配协调
|
||||||
|
|
||||||
|
* 确保前端请求与后端API完全匹配
|
||||||
|
|
||||||
|
* 处理后端返回的各种响应状态
|
||||||
|
|
||||||
|
* 优化数据处理逻辑
|
||||||
|
|
||||||
|
### 2. 实现细节
|
||||||
|
|
||||||
|
#### 文件修改
|
||||||
|
|
||||||
|
1. **index.html**
|
||||||
|
|
||||||
|
* 在下载区域标题旁添加刷新按钮
|
||||||
|
|
||||||
|
* 添加加载状态指示器
|
||||||
|
|
||||||
|
2. **script.js**
|
||||||
|
|
||||||
|
* 添加`refreshAppList()`函数
|
||||||
|
|
||||||
|
* 统一API请求处理函数
|
||||||
|
|
||||||
|
* 完善错误处理逻辑
|
||||||
|
|
||||||
|
* 添加加载状态管理
|
||||||
|
|
||||||
|
* 优化现有函数,确保与后端API适配
|
||||||
|
|
||||||
|
3. **style.css**
|
||||||
|
|
||||||
|
* 微调样式以适应刷新按钮
|
||||||
|
|
||||||
|
* 添加加载状态样式
|
||||||
|
|
||||||
|
#### 关键功能实现
|
||||||
|
|
||||||
|
* **刷新功能**:点击按钮调用`loadAppList()`重新加载App列表
|
||||||
|
|
||||||
|
* **API健壮性**:添加try-catch、错误状态码处理、超时处理
|
||||||
|
|
||||||
|
* **用户反馈**:添加加载中提示、操作结果反馈
|
||||||
|
|
||||||
|
* **表单验证**:增强对输入的验证,防止无效请求
|
||||||
|
|
||||||
|
### 3. 保持极简风格
|
||||||
|
|
||||||
|
* 不添加复杂UI元素
|
||||||
|
|
||||||
|
* 保持现有配色和布局
|
||||||
|
|
||||||
|
* 使用原生JavaScript实现
|
||||||
|
|
||||||
|
* 不引入额外库
|
||||||
|
|
||||||
|
### 4. 预期效果
|
||||||
|
|
||||||
|
* 前端与后端API适配更协调
|
||||||
|
|
||||||
|
* 提供更好的用户反馈和错误处理
|
||||||
|
|
||||||
|
* 添加刷新功能方便用户手动更新App列表
|
||||||
|
|
||||||
|
* 提升系统整体健壮性和用户体验
|
||||||
|
|
||||||
|
### 5. 测试要点
|
||||||
|
|
||||||
|
* 刷新功能正常工作
|
||||||
|
|
||||||
|
* API请求错误处理
|
||||||
|
|
||||||
|
* 网络异常情况处理
|
||||||
|
|
||||||
|
* 各种边界情况测试
|
||||||
|
|
||||||
|
* 保持极简风格不变
|
||||||
|
|
||||||
13
index.html
13
index.html
@@ -1,19 +1,23 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
|
<!-- 页面元信息配置 -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>App分发系统</title>
|
<title>App分发系统</title>
|
||||||
|
<!-- 引入外部样式文件 -->
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!-- 主容器,限制最大宽度并居中显示 -->
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
<!-- 页面头部,显示系统标题和人员信息 -->
|
||||||
<header>
|
<header>
|
||||||
<h1>App分发系统By拉面王</h1>
|
<h1>App分发系统By拉面王</h1>
|
||||||
<h6>项目经理:Qwen3max,测试经理:Doubao-seed-1.8,开发经理:Doubao-seed-1.8,bug修复和模块整合:拉面王</h6>
|
<h6>项目经理:Qwen3max,测试经理:Doubao-seed-1.8,开发经理:Doubao-seed-1.8,bug修复和模块整合:拉面王</h6>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- 文档区域 -->
|
<!-- 文档区域,显示系统相关文档 -->
|
||||||
<div id="docSection" class="section">
|
<div id="docSection" class="section">
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
||||||
<h2>文档</h2>
|
<h2>文档</h2>
|
||||||
@@ -22,7 +26,7 @@
|
|||||||
<div id="docContent"></div>
|
<div id="docContent"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 登录区域 -->
|
<!-- 登录区域,管理员登录功能 -->
|
||||||
<div id="loginSection" class="section">
|
<div id="loginSection" class="section">
|
||||||
<h2>管理员登录</h2>
|
<h2>管理员登录</h2>
|
||||||
<input type="password" id="password" placeholder="请输入密码" maxlength="20">
|
<input type="password" id="password" placeholder="请输入密码" maxlength="20">
|
||||||
@@ -30,7 +34,7 @@
|
|||||||
<p id="loginMessage"></p>
|
<p id="loginMessage"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 上传区域 -->
|
<!-- 上传区域,管理员上传App功能,默认隐藏 -->
|
||||||
<div id="uploadSection" class="section" style="display: none;">
|
<div id="uploadSection" class="section" style="display: none;">
|
||||||
<h2>上传App</h2>
|
<h2>上传App</h2>
|
||||||
<input type="text" id="appName" placeholder="App名称" maxlength="50">
|
<input type="text" id="appName" placeholder="App名称" maxlength="50">
|
||||||
@@ -39,7 +43,7 @@
|
|||||||
<p id="uploadMessage"></p>
|
<p id="uploadMessage"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 下载区域 -->
|
<!-- 下载区域,显示可用App列表 -->
|
||||||
<div id="downloadSection" class="section">
|
<div id="downloadSection" class="section">
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
||||||
<h2>可用App</h2>
|
<h2>可用App</h2>
|
||||||
@@ -52,6 +56,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 引入外部JavaScript文件,实现交互功能 -->
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
146
script.js
146
script.js
@@ -1,147 +1,156 @@
|
|||||||
// 配置
|
// 配置常量定义
|
||||||
const ADMIN_PASSWORD = 'admin123'; // 管理员密码
|
const ADMIN_PASSWORD = 'admin123'; // 管理员密码
|
||||||
const API_BASE_URL = 'http://localhost:6903/api'; // 后端API基础URL
|
const API_BASE_URL = 'http://localhost:6903/api'; // 后端API基础URL
|
||||||
|
|
||||||
// 初始化
|
// 初始化函数,页面加载完成后执行
|
||||||
function init() {
|
function init() {
|
||||||
checkLoginStatus();
|
checkLoginStatus(); // 检查登录状态
|
||||||
loadAppList();
|
loadAppList(); // 加载App列表
|
||||||
getDoc();
|
getDoc(); // 获取文档内容
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查登录状态
|
// 检查登录状态函数
|
||||||
function checkLoginStatus() {
|
function checkLoginStatus() {
|
||||||
|
// 从本地存储获取登录状态
|
||||||
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
|
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
showUploadSection();
|
showUploadSection(); // 如果已登录,显示上传区域
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 登录功能
|
// 登录功能函数
|
||||||
function login() {
|
function login() {
|
||||||
const password = document.getElementById('password').value;
|
const password = document.getElementById('password').value; // 获取输入的密码
|
||||||
const message = document.getElementById('loginMessage');
|
const message = document.getElementById('loginMessage'); // 获取登录消息元素
|
||||||
|
|
||||||
|
// 验证密码是否为空
|
||||||
if (!password.trim()) {
|
if (!password.trim()) {
|
||||||
message.textContent = '密码不能为空!';
|
message.textContent = '密码不能为空!';
|
||||||
message.style.color = '#ff0000';
|
message.style.color = '#ff0000';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验证密码是否正确
|
||||||
if (password === ADMIN_PASSWORD) {
|
if (password === ADMIN_PASSWORD) {
|
||||||
localStorage.setItem('isLoggedIn', 'true');
|
localStorage.setItem('isLoggedIn', 'true'); // 保存登录状态到本地存储
|
||||||
showUploadSection();
|
showUploadSection(); // 显示上传区域
|
||||||
message.textContent = '登录成功!';
|
message.textContent = '登录成功!';
|
||||||
message.style.color = '#008000';
|
message.style.color = '#008000';
|
||||||
document.getElementById('password').value = '';
|
document.getElementById('password').value = ''; // 清空密码输入框
|
||||||
} else {
|
} else {
|
||||||
message.textContent = '密码错误,请重试!';
|
message.textContent = '密码错误,请重试!';
|
||||||
message.style.color = '#ff0000';
|
message.style.color = '#ff0000';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示上传区域
|
// 显示上传区域函数
|
||||||
function showUploadSection() {
|
function showUploadSection() {
|
||||||
document.getElementById('loginSection').style.display = 'none';
|
document.getElementById('loginSection').style.display = 'none'; // 隐藏登录区域
|
||||||
document.getElementById('uploadSection').style.display = 'block';
|
document.getElementById('uploadSection').style.display = 'block'; // 显示上传区域
|
||||||
const loginSection = document.getElementById('loginSection');
|
const loginSection = document.getElementById('loginSection');
|
||||||
|
|
||||||
// 检查是否已经添加了退出按钮,避免重复添加
|
// 检查是否已经添加了退出按钮,避免重复添加
|
||||||
if (!loginSection.querySelector('.logout-btn')) {
|
if (!loginSection.querySelector('.logout-btn')) {
|
||||||
const logoutBtn = document.createElement('button');
|
const logoutBtn = document.createElement('button'); // 创建退出按钮
|
||||||
logoutBtn.textContent = '退出登录';
|
logoutBtn.textContent = '退出登录';
|
||||||
logoutBtn.className = 'logout-btn';
|
logoutBtn.className = 'logout-btn';
|
||||||
logoutBtn.onclick = logout;
|
logoutBtn.onclick = logout; // 绑定退出登录事件
|
||||||
loginSection.appendChild(logoutBtn);
|
loginSection.appendChild(logoutBtn); // 添加按钮到登录区域
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 退出登录
|
// 退出登录函数
|
||||||
function logout() {
|
function logout() {
|
||||||
localStorage.removeItem('isLoggedIn');
|
localStorage.removeItem('isLoggedIn'); // 清除本地存储中的登录状态
|
||||||
location.reload();
|
location.reload(); // 刷新页面
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示加载状态
|
// 显示加载状态函数
|
||||||
function showLoading() {
|
function showLoading() {
|
||||||
const loadingIndicator = document.getElementById('loadingIndicator');
|
const loadingIndicator = document.getElementById('loadingIndicator');
|
||||||
if (loadingIndicator) {
|
if (loadingIndicator) {
|
||||||
loadingIndicator.style.display = 'inline';
|
loadingIndicator.style.display = 'inline'; // 显示加载指示器
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 隐藏加载状态
|
// 隐藏加载状态函数
|
||||||
function hideLoading() {
|
function hideLoading() {
|
||||||
const loadingIndicator = document.getElementById('loadingIndicator');
|
const loadingIndicator = document.getElementById('loadingIndicator');
|
||||||
if (loadingIndicator) {
|
if (loadingIndicator) {
|
||||||
loadingIndicator.style.display = 'none';
|
loadingIndicator.style.display = 'none'; // 隐藏加载指示器
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新App列表
|
// 刷新App列表函数
|
||||||
function refreshAppList() {
|
function refreshAppList() {
|
||||||
loadAppList();
|
loadAppList(); // 调用加载App列表函数
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载App列表
|
// 加载App列表函数
|
||||||
async function loadAppList() {
|
async function loadAppList() {
|
||||||
const appList = document.getElementById('appList');
|
const appList = document.getElementById('appList'); // 获取App列表容器
|
||||||
|
|
||||||
try {
|
try {
|
||||||
showLoading();
|
showLoading(); // 显示加载状态
|
||||||
|
|
||||||
|
// 发送GET请求获取App列表
|
||||||
const response = await fetch(`${API_BASE_URL}/apps`, {
|
const response = await fetch(`${API_BASE_URL}/apps`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
},
|
},
|
||||||
timeout: 10000 // 10秒超时
|
timeout: 10000 // 10秒超时设置
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP错误!状态:${response.status}`);
|
throw new Error(`HTTP错误!状态:${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const apps = await response.json();
|
const apps = await response.json(); // 解析响应数据
|
||||||
|
|
||||||
|
// 处理空列表情况
|
||||||
if (apps.length === 0) {
|
if (apps.length === 0) {
|
||||||
appList.innerHTML = '<p style="text-align: center;">暂无App</p>';
|
appList.innerHTML = '<p style="text-align: center;">暂无App</p>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 清空列表并重新渲染
|
||||||
appList.innerHTML = '';
|
appList.innerHTML = '';
|
||||||
apps.forEach(app => {
|
apps.forEach(app => {
|
||||||
const appItem = document.createElement('div');
|
const appItem = document.createElement('div'); // 创建App项元素
|
||||||
appItem.className = 'app-item';
|
appItem.className = 'app-item';
|
||||||
|
|
||||||
const appInfo = document.createElement('div');
|
const appInfo = document.createElement('div'); // 创建App信息容器
|
||||||
appInfo.className = 'app-info';
|
appInfo.className = 'app-info';
|
||||||
|
|
||||||
const appName = document.createElement('h3');
|
const appName = document.createElement('h3'); // 创建App名称元素
|
||||||
appName.textContent = app.name;
|
appName.textContent = app.name;
|
||||||
|
|
||||||
const appDate = document.createElement('p');
|
const appDate = document.createElement('p'); // 创建App日期元素
|
||||||
appDate.textContent = `上传时间:${app.date}`;
|
appDate.textContent = `上传时间:${app.date}`;
|
||||||
|
|
||||||
const downloadBtn = document.createElement('button');
|
const downloadBtn = document.createElement('button'); // 创建下载按钮
|
||||||
downloadBtn.className = 'download-btn';
|
downloadBtn.className = 'download-btn';
|
||||||
downloadBtn.textContent = '下载';
|
downloadBtn.textContent = '下载';
|
||||||
downloadBtn.onclick = () => downloadApp(app.id, app.fileName);
|
downloadBtn.onclick = () => downloadApp(app.id, app.fileName);
|
||||||
|
|
||||||
const deleteBtn = document.createElement('button');
|
const deleteBtn = document.createElement('button'); // 创建删除按钮
|
||||||
deleteBtn.className = 'download-btn';
|
deleteBtn.className = 'download-btn';
|
||||||
deleteBtn.textContent = '删除';
|
deleteBtn.textContent = '删除';
|
||||||
deleteBtn.onclick = () => deleteApp(app.id);
|
deleteBtn.onclick = () => deleteApp(app.id);
|
||||||
|
|
||||||
const copyLinkBtn = document.createElement('button');
|
const copyLinkBtn = document.createElement('button'); // 创建复制直链按钮
|
||||||
copyLinkBtn.className = 'download-btn';
|
copyLinkBtn.className = 'download-btn';
|
||||||
copyLinkBtn.textContent = '复制直链';
|
copyLinkBtn.textContent = '复制直链';
|
||||||
copyLinkBtn.onclick = () => copyDirectLink(app.id, app.fileName);
|
copyLinkBtn.onclick = () => copyDirectLink(app.id, app.fileName);
|
||||||
|
|
||||||
|
// 组装App项
|
||||||
appInfo.appendChild(appName);
|
appInfo.appendChild(appName);
|
||||||
appInfo.appendChild(appDate);
|
appInfo.appendChild(appDate);
|
||||||
appItem.appendChild(appInfo);
|
appItem.appendChild(appInfo);
|
||||||
|
|
||||||
|
// 创建按钮容器并添加按钮
|
||||||
const buttonsContainer = document.createElement('div');
|
const buttonsContainer = document.createElement('div');
|
||||||
buttonsContainer.style.display = 'flex';
|
buttonsContainer.style.display = 'flex';
|
||||||
buttonsContainer.style.gap = '10px';
|
buttonsContainer.style.gap = '10px';
|
||||||
@@ -156,22 +165,24 @@ async function loadAppList() {
|
|||||||
console.error('获取App列表失败:', error);
|
console.error('获取App列表失败:', error);
|
||||||
appList.innerHTML = `<p style="color: #ff0000; text-align: center;">获取App列表失败:${error.message}</p>`;
|
appList.innerHTML = `<p style="color: #ff0000; text-align: center;">获取App列表失败:${error.message}</p>`;
|
||||||
} finally {
|
} finally {
|
||||||
hideLoading();
|
hideLoading(); // 无论成功失败,都隐藏加载状态
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传App
|
// 上传App函数
|
||||||
async function uploadApp() {
|
async function uploadApp() {
|
||||||
let appName = document.getElementById('appName').value;
|
let appName = document.getElementById('appName').value; // 获取App名称
|
||||||
const appFile = document.getElementById('appFile').files[0];
|
const appFile = document.getElementById('appFile').files[0]; // 获取选择的文件
|
||||||
const message = document.getElementById('uploadMessage');
|
const message = document.getElementById('uploadMessage'); // 获取上传消息元素
|
||||||
|
|
||||||
|
// 验证文件是否选择
|
||||||
if (!appFile) {
|
if (!appFile) {
|
||||||
message.textContent = '请选择文件!';
|
message.textContent = '请选择文件!';
|
||||||
message.style.color = '#ff0000';
|
message.style.color = '#ff0000';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验证文件大小(限制1GB)
|
||||||
if (appFile.size > 100 * 1024 * 1024 * 1024) { // 限制1000MB
|
if (appFile.size > 100 * 1024 * 1024 * 1024) { // 限制1000MB
|
||||||
message.textContent = '文件大小不能超过1GB!';
|
message.textContent = '文件大小不能超过1GB!';
|
||||||
message.style.color = '#ff0000';
|
message.style.color = '#ff0000';
|
||||||
@@ -184,6 +195,7 @@ async function uploadApp() {
|
|||||||
appName = appFile.name.replace(/\.[^/.]+$/, '');
|
appName = appFile.name.replace(/\.[^/.]+$/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建FormData对象,用于发送文件
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('name', appName);
|
formData.append('name', appName);
|
||||||
formData.append('file', appFile);
|
formData.append('file', appFile);
|
||||||
@@ -192,22 +204,25 @@ async function uploadApp() {
|
|||||||
message.textContent = '上传中...';
|
message.textContent = '上传中...';
|
||||||
message.style.color = '#0000ff';
|
message.style.color = '#0000ff';
|
||||||
|
|
||||||
|
// 发送POST请求上传文件
|
||||||
const response = await fetch(`${API_BASE_URL}/apps`, {
|
const response = await fetch(`${API_BASE_URL}/apps`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
timeout: 30000 // 30秒超时
|
timeout: 30000 // 30秒超时设置
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP错误!状态:${response.status}`);
|
throw new Error(`HTTP错误!状态:${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json(); // 解析响应数据
|
||||||
|
|
||||||
|
// 处理上传结果
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
message.textContent = '上传成功!';
|
message.textContent = '上传成功!';
|
||||||
message.style.color = '#008000';
|
message.style.color = '#008000';
|
||||||
loadAppList();
|
loadAppList(); // 重新加载App列表
|
||||||
// 清空表单
|
// 清空表单
|
||||||
document.getElementById('appName').value = '';
|
document.getElementById('appName').value = '';
|
||||||
document.getElementById('appFile').value = '';
|
document.getElementById('appFile').value = '';
|
||||||
@@ -222,16 +237,18 @@ async function uploadApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除App
|
// 删除App函数
|
||||||
function deleteApp(appId) {
|
function deleteApp(appId) {
|
||||||
|
// 显示确认对话框,包含特殊问题验证
|
||||||
if (!confirm('如果确定删除此APP,请将矩阵 A = [[3,1,0],[1,2,1],[0,1,1]]的特征值、特征向量,并验证A是正定矩阵的解题步骤做出来,然后我也没做')) {
|
if (!confirm('如果确定删除此APP,请将矩阵 A = [[3,1,0],[1,2,1],[0,1,1]]的特征值、特征向量,并验证A是正定矩阵的解题步骤做出来,然后我也没做')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下载App
|
// 下载App函数
|
||||||
function downloadApp(appId, fileName) {
|
function downloadApp(appId, fileName) {
|
||||||
try {
|
try {
|
||||||
|
// 创建下载链接并触发点击
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
link.href = `${API_BASE_URL}/apps/${appId}`;
|
link.href = `${API_BASE_URL}/apps/${appId}`;
|
||||||
link.download = fileName;
|
link.download = fileName;
|
||||||
@@ -244,9 +261,9 @@ function downloadApp(appId, fileName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 复制直链
|
// 复制直链函数
|
||||||
function copyDirectLink(appId, fileName) {
|
function copyDirectLink(appId, fileName) {
|
||||||
const directLink = `${API_BASE_URL}/apps/${appId}`;
|
const directLink = `${API_BASE_URL}/apps/${appId}`; // 生成直链URL
|
||||||
|
|
||||||
// 复制到剪贴板
|
// 复制到剪贴板
|
||||||
navigator.clipboard.writeText(directLink)
|
navigator.clipboard.writeText(directLink)
|
||||||
@@ -280,39 +297,45 @@ function copyDirectLink(appId, fileName) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取文档内容的API调用函数
|
||||||
async function getDocApi() {
|
async function getDocApi() {
|
||||||
try {
|
try {
|
||||||
showLoading();
|
showLoading(); // 显示加载状态
|
||||||
|
|
||||||
const docContent = document.getElementById('docContent');
|
const docContent = document.getElementById('docContent'); // 获取文档内容容器
|
||||||
docContent.innerHTML = ``;
|
docContent.innerHTML = ``; // 清空现有内容
|
||||||
|
|
||||||
|
// 发送GET请求获取文档
|
||||||
const response = await fetch(`${API_BASE_URL}/docs`, {
|
const response = await fetch(`${API_BASE_URL}/docs`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
},
|
},
|
||||||
timeout: 10000 // 10秒超时
|
timeout: 10000 // 10秒超时设置
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP错误!状态:${response.status}`);
|
throw new Error(`HTTP错误!状态:${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const docs = await response.json();
|
const docs = await response.json(); // 解析响应数据
|
||||||
|
|
||||||
|
// 处理空文档情况
|
||||||
if (docs.length === 0) {
|
if (docs.length === 0) {
|
||||||
docContent.innerHTML = '<p style="text-align: center;">暂无文档</p>';
|
docContent.innerHTML = '<p style="text-align: center;">暂无文档</p>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 渲染文档列表
|
||||||
for (let i = 0; i < docs.length; i++) {
|
for (let i = 0; i < docs.length; i++) {
|
||||||
const doc = docs[i];
|
const doc = docs[i];
|
||||||
const docItem = document.createElement('div');
|
const docItem = document.createElement('div'); // 创建文档项元素
|
||||||
docItem.className = 'doc-item';
|
docItem.className = 'doc-item';
|
||||||
docItem.innerHTML = `
|
docItem.innerHTML = `
|
||||||
<p>${doc.docBody}</p>
|
<p>${doc.docBody}</p>
|
||||||
`;
|
`;
|
||||||
docContent.appendChild(docItem);
|
docContent.appendChild(docItem); // 添加到文档容器
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -322,9 +345,10 @@ async function getDocApi() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 获取文档内容
|
|
||||||
|
// 获取文档内容的入口函数
|
||||||
function getDoc() {
|
function getDoc() {
|
||||||
getDocApi();
|
getDocApi(); // 调用API获取文档
|
||||||
}
|
}
|
||||||
|
|
||||||
// 页面加载完成后初始化
|
// 页面加载完成后初始化
|
||||||
|
|||||||
29
style.css
29
style.css
@@ -1,19 +1,23 @@
|
|||||||
|
/* 全局样式重置 */
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 页面基础样式 */
|
||||||
body {
|
body {
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 主容器样式 */
|
||||||
.container {
|
.container {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 页面头部样式 */
|
||||||
header {
|
header {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
@@ -21,21 +25,25 @@ header {
|
|||||||
border-bottom: 1px solid #000;
|
border-bottom: 1px solid #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 页面标题样式 */
|
||||||
header h1 {
|
header h1 {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 通用区块样式 */
|
||||||
.section {
|
.section {
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border: 1px solid #000;
|
border: 1px solid #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 区块标题样式 */
|
||||||
.section h2 {
|
.section h2 {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 输入框通用样式 */
|
||||||
input {
|
input {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -45,6 +53,7 @@ input {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 按钮通用样式 */
|
||||||
button {
|
button {
|
||||||
border: 1px solid #000;
|
border: 1px solid #000;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
@@ -54,19 +63,23 @@ button {
|
|||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 按钮悬停效果 */
|
||||||
button:hover {
|
button:hover {
|
||||||
background-color: #f0f0f0;
|
background-color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 按钮点击效果 */
|
||||||
button:active {
|
button:active {
|
||||||
background-color: #e0e0e0;
|
background-color: #e0e0e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 段落通用样式 */
|
||||||
p {
|
p {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 文档项样式 */
|
||||||
.doc-item{
|
.doc-item{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -75,11 +88,14 @@ p {
|
|||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
border: 1px solid #000;
|
border: 1px solid #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 文档项内段落样式 */
|
||||||
.doc-item p{
|
.doc-item p{
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* App项样式 */
|
||||||
.app-item {
|
.app-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -89,56 +105,67 @@ p {
|
|||||||
border: 1px solid #000;
|
border: 1px solid #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* App信息区域样式 */
|
||||||
.app-info {
|
.app-info {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* App名称样式 */
|
||||||
.app-info h3 {
|
.app-info h3 {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* App日期样式 */
|
||||||
.app-info p {
|
.app-info p {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 下载按钮样式 */
|
||||||
.download-btn {
|
.download-btn {
|
||||||
padding: 8px 15px;
|
padding: 8px 15px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 退出按钮样式 */
|
||||||
.logout-btn {
|
.logout-btn {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 加载指示器样式 */
|
||||||
#loadingIndicator {
|
#loadingIndicator {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式设计 */
|
/* 响应式设计 - 移动端适配 */
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
|
/* 移动端主容器样式 */
|
||||||
.container {
|
.container {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端区块样式 */
|
||||||
.section {
|
.section {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端App项样式,改为垂直排列 */
|
||||||
.app-item {
|
.app-item {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端文档项样式,改为垂直排列 */
|
||||||
.doc-item {
|
.doc-item {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 移动端下载按钮样式,添加顶部间距 */
|
||||||
.download-btn {
|
.download-btn {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user