docs: 添加了更健壮的注释

This commit is contained in:
2025-12-25 00:55:57 +08:00
parent d2c42ba4c2
commit 4fb50e6b56
4 changed files with 230 additions and 66 deletions

View 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请求错误处理
* 网络异常情况处理
* 各种边界情况测试
* 保持极简风格不变

View File

@@ -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
View File

@@ -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获取文档
} }
// 页面加载完成后初始化 // 页面加载完成后初始化

View File

@@ -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;
} }