feat(版本管理): 添加应用版本列表功能
- 在GUI中添加查看全部版本按钮和版本列表窗口 - 实现API接口获取应用版本列表数据 - 优化文件下载路径处理,解决open_basedir限制问题 - 重构分页控件布局,增加弹性空间
This commit is contained in:
BIN
APP Store.zip
BIN
APP Store.zip
Binary file not shown.
181
api.php
181
api.php
@@ -11,6 +11,7 @@
|
|||||||
* - /api.php?t=getdeveloperinfo&id={developerid} - 获取开发者信息
|
* - /api.php?t=getdeveloperinfo&id={developerid} - 获取开发者信息
|
||||||
* - /api.php?t=getacc - 获取所有公告
|
* - /api.php?t=getacc - 获取所有公告
|
||||||
* - /api.php?t=getcount - 获取计数信息
|
* - /api.php?t=getcount - 获取计数信息
|
||||||
|
* - /api.php?t=getappversions&id={appid} - 获取某个应用的版本列表
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 关闭错误显示(生产环境)
|
// 关闭错误显示(生产环境)
|
||||||
@@ -67,6 +68,9 @@ switch ($apiType) {
|
|||||||
case 'getcount':
|
case 'getcount':
|
||||||
getCountInfo();
|
getCountInfo();
|
||||||
break;
|
break;
|
||||||
|
case 'getappversions':
|
||||||
|
getAppVersions();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
showApiEndpoints();
|
showApiEndpoints();
|
||||||
break;
|
break;
|
||||||
@@ -112,7 +116,8 @@ function showApiEndpoints() {
|
|||||||
'/api.php?t=getdeveloperapp&id={developerid}' => '获取某开发者的APP列表',
|
'/api.php?t=getdeveloperapp&id={developerid}' => '获取某开发者的APP列表',
|
||||||
'/api.php?t=getdeveloperinfo&id={developerid}' => '获取开发者信息',
|
'/api.php?t=getdeveloperinfo&id={developerid}' => '获取开发者信息',
|
||||||
'/api.php?t=getacc' => '获取所有公告',
|
'/api.php?t=getacc' => '获取所有公告',
|
||||||
'/api.php?t=getcount' => '获取计数信息(如所有APP的数量、开发者的数量等)'
|
'/api.php?t=getcount' => '获取计数信息(如所有APP的数量、开发者的数量等)',
|
||||||
|
'/api.php?t=getappversions&id={appid}' => '获取某个应用的版本列表'
|
||||||
];
|
];
|
||||||
|
|
||||||
$response = [
|
$response = [
|
||||||
@@ -378,8 +383,8 @@ function getDeveloperApps() {
|
|||||||
$limit = isset($_GET['limit']) ? min(100, max(1, intval($_GET['limit']))) : 20;
|
$limit = isset($_GET['limit']) ? min(100, max(1, intval($_GET['limit']))) : 20;
|
||||||
$offset = ($page - 1) * $limit;
|
$offset = ($page - 1) * $limit;
|
||||||
|
|
||||||
// 获取开发者邮箱(用于关联apps表)
|
// 获取开发者信息
|
||||||
$sqlDeveloper = "SELECT email FROM developers WHERE id = ?";
|
$sqlDeveloper = "SELECT username FROM developers WHERE id = ?";
|
||||||
$stmtDeveloper = $conn->prepare($sqlDeveloper);
|
$stmtDeveloper = $conn->prepare($sqlDeveloper);
|
||||||
$stmtDeveloper->bind_param("i", $developerId);
|
$stmtDeveloper->bind_param("i", $developerId);
|
||||||
$stmtDeveloper->execute();
|
$stmtDeveloper->execute();
|
||||||
@@ -390,30 +395,25 @@ function getDeveloperApps() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$developerInfo = $resultDeveloper->fetch_assoc();
|
$developerInfo = $resultDeveloper->fetch_assoc();
|
||||||
$developerEmail = $developerInfo['email'];
|
|
||||||
|
|
||||||
// 获取总数量
|
// 获取总数量
|
||||||
$countSql = "SELECT COUNT(*) as total FROM apps WHERE developer_email = ? AND status = 'approved' AND is_approved = 1";
|
$countSql = "SELECT COUNT(*) as total FROM apps WHERE developer_id = ? AND status = 'approved' AND is_approved = 1";
|
||||||
$countStmt = $conn->prepare($countSql);
|
$countStmt = $conn->prepare($countSql);
|
||||||
$countStmt->bind_param("s", $developerEmail);
|
$countStmt->bind_param("i", $developerId);
|
||||||
$countStmt->execute();
|
$countStmt->execute();
|
||||||
$countResult = $countStmt->get_result();
|
$countResult = $countStmt->get_result();
|
||||||
$total = $countResult->fetch_assoc()['total'] ?? 0;
|
$total = $countResult->fetch_assoc()['total'] ?? 0;
|
||||||
$totalPages = ceil($total / $limit);
|
$totalPages = ceil($total / $limit);
|
||||||
|
|
||||||
// 获取应用列表
|
// 获取应用列表
|
||||||
$sql = "SELECT apps.id, apps.name, apps.description, apps.age_rating, apps.version,
|
$sql = "SELECT id, name, description, age_rating, version, created_at
|
||||||
AVG(reviews.rating) as avg_rating, SUM(app_versions.download_count) as total_downloads
|
|
||||||
FROM apps
|
FROM apps
|
||||||
LEFT JOIN reviews ON apps.id = reviews.app_id
|
WHERE developer_id = ? AND status = 'approved' AND is_approved = 1
|
||||||
LEFT JOIN app_versions ON apps.id = app_versions.app_id
|
ORDER BY created_at DESC
|
||||||
WHERE apps.developer_email = ? AND apps.status = 'approved' AND apps.is_approved = 1
|
|
||||||
GROUP BY apps.id, apps.name, apps.description, apps.age_rating, apps.version
|
|
||||||
ORDER BY apps.created_at DESC
|
|
||||||
LIMIT ?, ?";
|
LIMIT ?, ?";
|
||||||
|
|
||||||
$stmt = $conn->prepare($sql);
|
$stmt = $conn->prepare($sql);
|
||||||
$stmt->bind_param("sii", $developerEmail, $offset, $limit);
|
$stmt->bind_param("iii", $developerId, $offset, $limit);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$result = $stmt->get_result();
|
$result = $stmt->get_result();
|
||||||
|
|
||||||
@@ -423,7 +423,7 @@ function getDeveloperApps() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$response = [
|
$response = [
|
||||||
'developer_id' => $developerId,
|
'developer' => $developerInfo,
|
||||||
'apps' => $apps,
|
'apps' => $apps,
|
||||||
'pagination' => [
|
'pagination' => [
|
||||||
'total' => $total,
|
'total' => $total,
|
||||||
@@ -449,34 +449,39 @@ function getDeveloperInfo() {
|
|||||||
|
|
||||||
$developerId = intval($_GET['id']);
|
$developerId = intval($_GET['id']);
|
||||||
|
|
||||||
// 获取开发者信息(不包含密码等敏感信息)
|
// 获取开发者基本信息
|
||||||
$sql = "SELECT id, username, email, created_at, is_verified, verified_at
|
$sqlDeveloper = "SELECT id, username, email, created_at FROM developers WHERE id = ?";
|
||||||
FROM developers
|
$stmtDeveloper = $conn->prepare($sqlDeveloper);
|
||||||
WHERE id = ?";
|
$stmtDeveloper->bind_param("i", $developerId);
|
||||||
|
$stmtDeveloper->execute();
|
||||||
|
$resultDeveloper = $stmtDeveloper->get_result();
|
||||||
|
|
||||||
$stmt = $conn->prepare($sql);
|
if ($resultDeveloper->num_rows === 0) {
|
||||||
$stmt->bind_param("i", $developerId);
|
|
||||||
$stmt->execute();
|
|
||||||
$result = $stmt->get_result();
|
|
||||||
|
|
||||||
if ($result->num_rows === 0) {
|
|
||||||
sendErrorResponse('未找到该开发者', 404);
|
sendErrorResponse('未找到该开发者', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$developer = $result->fetch_assoc();
|
$developer = $resultDeveloper->fetch_assoc();
|
||||||
|
|
||||||
// 获取开发者的应用数量
|
// 获取开发者的应用数量
|
||||||
$appCountSql = "SELECT COUNT(*) as app_count
|
$appCountSql = "SELECT COUNT(*) as count FROM apps WHERE developer_id = ? AND status = 'approved' AND is_approved = 1";
|
||||||
FROM apps
|
|
||||||
WHERE developer_email = ? AND status = 'approved' AND is_approved = 1";
|
|
||||||
$appCountStmt = $conn->prepare($appCountSql);
|
$appCountStmt = $conn->prepare($appCountSql);
|
||||||
$appCountStmt->bind_param("s", $developer['email']);
|
$appCountStmt->bind_param("i", $developerId);
|
||||||
$appCountStmt->execute();
|
$appCountStmt->execute();
|
||||||
$appCountResult = $appCountStmt->get_result();
|
$appCountResult = $appCountStmt->get_result();
|
||||||
$appCount = $appCountResult->fetch_assoc()['app_count'] ?? 0;
|
$appCount = $appCountResult->fetch_assoc()['count'] ?? 0;
|
||||||
|
|
||||||
$developer['app_count'] = $appCount;
|
$developer['app_count'] = $appCount;
|
||||||
|
|
||||||
|
// 获取开发者的总下载量
|
||||||
|
$downloadCountSql = "SELECT SUM(download_count) as count FROM app_versions
|
||||||
|
JOIN apps ON app_versions.app_id = apps.id
|
||||||
|
WHERE apps.developer_id = ?";
|
||||||
|
$downloadCountStmt = $conn->prepare($downloadCountSql);
|
||||||
|
$downloadCountStmt->bind_param("i", $developerId);
|
||||||
|
$downloadCountStmt->execute();
|
||||||
|
$downloadCountResult = $downloadCountStmt->get_result();
|
||||||
|
$downloadCount = $downloadCountResult->fetch_assoc()['count'] ?? 0;
|
||||||
|
$developer['total_downloads'] = $downloadCount;
|
||||||
|
|
||||||
sendSuccessResponse($developer);
|
sendSuccessResponse($developer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,44 +491,15 @@ function getDeveloperInfo() {
|
|||||||
function getAllAnnouncements() {
|
function getAllAnnouncements() {
|
||||||
global $conn;
|
global $conn;
|
||||||
|
|
||||||
// 获取分页参数
|
$sql = "SELECT id, title, content, created_at FROM announcements ORDER BY created_at DESC";
|
||||||
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
|
$result = $conn->query($sql);
|
||||||
$limit = isset($_GET['limit']) ? min(100, max(1, intval($_GET['limit']))) : 20;
|
|
||||||
$offset = ($page - 1) * $limit;
|
|
||||||
|
|
||||||
// 获取总数量
|
|
||||||
$countSql = "SELECT COUNT(*) as total FROM announcements";
|
|
||||||
$countResult = $conn->query($countSql);
|
|
||||||
$total = $countResult->fetch_assoc()['total'] ?? 0;
|
|
||||||
$totalPages = ceil($total / $limit);
|
|
||||||
|
|
||||||
// 获取公告列表
|
|
||||||
$sql = "SELECT id, title, content, created_at, admin_id
|
|
||||||
FROM announcements
|
|
||||||
ORDER BY created_at DESC
|
|
||||||
LIMIT ?, ?";
|
|
||||||
|
|
||||||
$stmt = $conn->prepare($sql);
|
|
||||||
$stmt->bind_param("ii", $offset, $limit);
|
|
||||||
$stmt->execute();
|
|
||||||
$result = $stmt->get_result();
|
|
||||||
|
|
||||||
$announcements = [];
|
$announcements = [];
|
||||||
while ($row = $result->fetch_assoc()) {
|
while ($row = $result->fetch_assoc()) {
|
||||||
$announcements[] = $row;
|
$announcements[] = $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = [
|
sendSuccessResponse($announcements);
|
||||||
'announcements' => $announcements,
|
|
||||||
'pagination' => [
|
|
||||||
'total' => $total,
|
|
||||||
'page' => $page,
|
|
||||||
'limit' => $limit,
|
|
||||||
'totalPages' => $totalPages
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
sendSuccessResponse($response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -532,22 +508,22 @@ function getAllAnnouncements() {
|
|||||||
function getCountInfo() {
|
function getCountInfo() {
|
||||||
global $conn;
|
global $conn;
|
||||||
|
|
||||||
// 应用总数
|
// 总应用数
|
||||||
$appCountSql = "SELECT COUNT(*) as count FROM apps WHERE status = 'approved' AND is_approved = 1";
|
$appCountSql = "SELECT COUNT(*) as count FROM apps WHERE status = 'approved' AND is_approved = 1";
|
||||||
$appCountResult = $conn->query($appCountSql);
|
$appCountResult = $conn->query($appCountSql);
|
||||||
$appCount = $appCountResult->fetch_assoc()['count'] ?? 0;
|
$appCount = $appCountResult->fetch_assoc()['count'] ?? 0;
|
||||||
|
|
||||||
// 开发者总数
|
// 总开发者数
|
||||||
$developerCountSql = "SELECT COUNT(*) as count FROM developers";
|
$developerCountSql = "SELECT COUNT(*) as count FROM developers";
|
||||||
$developerCountResult = $conn->query($developerCountSql);
|
$developerCountResult = $conn->query($developerCountSql);
|
||||||
$developerCount = $developerCountResult->fetch_assoc()['count'] ?? 0;
|
$developerCount = $developerCountResult->fetch_assoc()['count'] ?? 0;
|
||||||
|
|
||||||
// 标签总数
|
// 总标签数
|
||||||
$tagCountSql = "SELECT COUNT(*) as count FROM tags";
|
$tagCountSql = "SELECT COUNT(*) as count FROM tags";
|
||||||
$tagCountResult = $conn->query($tagCountSql);
|
$tagCountResult = $conn->query($tagCountSql);
|
||||||
$tagCount = $tagCountResult->fetch_assoc()['count'] ?? 0;
|
$tagCount = $tagCountResult->fetch_assoc()['count'] ?? 0;
|
||||||
|
|
||||||
// 公告总数
|
// 总公告数
|
||||||
$announcementCountSql = "SELECT COUNT(*) as count FROM announcements";
|
$announcementCountSql = "SELECT COUNT(*) as count FROM announcements";
|
||||||
$announcementCountResult = $conn->query($announcementCountSql);
|
$announcementCountResult = $conn->query($announcementCountSql);
|
||||||
$announcementCount = $announcementCountResult->fetch_assoc()['count'] ?? 0;
|
$announcementCount = $announcementCountResult->fetch_assoc()['count'] ?? 0;
|
||||||
@@ -568,6 +544,75 @@ function getCountInfo() {
|
|||||||
sendSuccessResponse($counts);
|
sendSuccessResponse($counts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定应用的版本列表
|
||||||
|
*/
|
||||||
|
function getAppVersions() {
|
||||||
|
global $conn;
|
||||||
|
|
||||||
|
// 检查是否提供了app_id参数
|
||||||
|
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
||||||
|
sendErrorResponse('请提供有效的应用ID', 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$appId = intval($_GET['id']);
|
||||||
|
|
||||||
|
// 检查应用是否存在
|
||||||
|
$appCheckSql = "SELECT id FROM apps WHERE id = ? AND status = 'approved' AND is_approved = 1";
|
||||||
|
$appCheckStmt = $conn->prepare($appCheckSql);
|
||||||
|
$appCheckStmt->bind_param("i", $appId);
|
||||||
|
$appCheckStmt->execute();
|
||||||
|
$appCheckResult = $appCheckStmt->get_result();
|
||||||
|
|
||||||
|
if ($appCheckResult->num_rows === 0) {
|
||||||
|
sendErrorResponse('未找到该应用', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取分页参数
|
||||||
|
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
|
||||||
|
$limit = isset($_GET['limit']) ? min(100, max(1, intval($_GET['limit']))) : 20;
|
||||||
|
$offset = ($page - 1) * $limit;
|
||||||
|
|
||||||
|
// 获取总数量
|
||||||
|
$countSql = "SELECT COUNT(*) as total FROM app_versions WHERE app_id = ?";
|
||||||
|
$countStmt = $conn->prepare($countSql);
|
||||||
|
$countStmt->bind_param("i", $appId);
|
||||||
|
$countStmt->execute();
|
||||||
|
$countResult = $countStmt->get_result();
|
||||||
|
$total = $countResult->fetch_assoc()['total'] ?? 0;
|
||||||
|
$totalPages = ceil($total / $limit);
|
||||||
|
|
||||||
|
// 获取版本列表
|
||||||
|
$sqlVersions = "SELECT id, version, changelog, file_path, download_count, created_at
|
||||||
|
FROM app_versions
|
||||||
|
WHERE app_id = ?
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT ?, ?";
|
||||||
|
$stmtVersions = $conn->prepare($sqlVersions);
|
||||||
|
$stmtVersions->bind_param("iii", $appId, $offset, $limit);
|
||||||
|
$stmtVersions->execute();
|
||||||
|
$resultVersions = $stmtVersions->get_result();
|
||||||
|
|
||||||
|
$versions = [];
|
||||||
|
while ($version = $resultVersions->fetch_assoc()) {
|
||||||
|
$versions[] = $version;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建响应数据
|
||||||
|
$response = [
|
||||||
|
'app_id' => $appId,
|
||||||
|
'versions' => $versions,
|
||||||
|
'pagination' => [
|
||||||
|
'total' => $total,
|
||||||
|
'page' => $page,
|
||||||
|
'limit' => $limit,
|
||||||
|
'totalPages' => $totalPages
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
sendSuccessResponse($response);
|
||||||
|
}
|
||||||
|
|
||||||
// 关闭数据库连接
|
// 关闭数据库连接
|
||||||
$conn->close();
|
$conn->close();
|
||||||
?>
|
?>
|
||||||
@@ -851,6 +851,17 @@ class AppDetailWindow(QMainWindow):
|
|||||||
versions_text = "\n".join([f"- 版本 {v['version']} ({v['download_count']} 下载)" for v in data['versions'][:3]])
|
versions_text = "\n".join([f"- 版本 {v['version']} ({v['download_count']} 下载)" for v in data['versions'][:3]])
|
||||||
self.info_layout.addWidget(CaptionLabel(versions_text))
|
self.info_layout.addWidget(CaptionLabel(versions_text))
|
||||||
|
|
||||||
|
# 添加"查看全部版本"按钮
|
||||||
|
if len(data['versions']) > 3:
|
||||||
|
self.view_all_versions_button = PushButton("查看全部版本")
|
||||||
|
self.view_all_versions_button.clicked.connect(lambda: self.view_all_versions())
|
||||||
|
self.info_layout.addWidget(self.view_all_versions_button)
|
||||||
|
|
||||||
|
def view_all_versions(self):
|
||||||
|
"""查看全部版本"""
|
||||||
|
versions_window = AppVersionsWindow(self.api_client, self.app_id, self.app_title.text(), self)
|
||||||
|
versions_window.show()
|
||||||
|
|
||||||
# 添加图片数量信息
|
# 添加图片数量信息
|
||||||
if 'images' in data and data['images']:
|
if 'images' in data and data['images']:
|
||||||
images_label = SubtitleLabel("图片")
|
images_label = SubtitleLabel("图片")
|
||||||
@@ -920,21 +931,18 @@ class TagAppsWindow(QMainWindow):
|
|||||||
self.app_table.cellDoubleClicked.connect(self.show_app_detail)
|
self.app_table.cellDoubleClicked.connect(self.show_app_detail)
|
||||||
main_layout.addWidget(self.app_table)
|
main_layout.addWidget(self.app_table)
|
||||||
|
|
||||||
# 创建分页控制
|
# 创建分页控件
|
||||||
pagination_layout = QHBoxLayout()
|
pagination_layout = QHBoxLayout()
|
||||||
pagination_layout.setContentsMargins(0, 10, 0, 0)
|
|
||||||
|
|
||||||
self.prev_button = PushButton("上一页")
|
self.prev_button = PushButton("上一页")
|
||||||
self.prev_button.clicked.connect(self.prev_page)
|
self.prev_button.clicked.connect(self.prev_page)
|
||||||
pagination_layout.addWidget(self.prev_button)
|
|
||||||
|
|
||||||
self.page_label = CaptionLabel("第 1 页,共 1 页")
|
self.page_label = CaptionLabel("第 1 页,共 1 页")
|
||||||
pagination_layout.addWidget(self.page_label, alignment=Qt.AlignCenter)
|
|
||||||
|
|
||||||
self.next_button = PushButton("下一页")
|
self.next_button = PushButton("下一页")
|
||||||
self.next_button.clicked.connect(self.next_page)
|
self.next_button.clicked.connect(self.next_page)
|
||||||
|
pagination_layout.addWidget(self.prev_button)
|
||||||
|
pagination_layout.addStretch()
|
||||||
|
pagination_layout.addWidget(self.page_label)
|
||||||
|
pagination_layout.addStretch()
|
||||||
pagination_layout.addWidget(self.next_button)
|
pagination_layout.addWidget(self.next_button)
|
||||||
|
|
||||||
main_layout.addLayout(pagination_layout)
|
main_layout.addLayout(pagination_layout)
|
||||||
|
|
||||||
# 创建进度条
|
# 创建进度条
|
||||||
@@ -1071,7 +1079,7 @@ class DeveloperAppsWindow(QMainWindow):
|
|||||||
self.app_table.cellDoubleClicked.connect(self.show_app_detail)
|
self.app_table.cellDoubleClicked.connect(self.show_app_detail)
|
||||||
main_layout.addWidget(self.app_table)
|
main_layout.addWidget(self.app_table)
|
||||||
|
|
||||||
# 创建分页控制
|
# 创建分页控件
|
||||||
pagination_layout = QHBoxLayout()
|
pagination_layout = QHBoxLayout()
|
||||||
pagination_layout.setContentsMargins(0, 10, 0, 0)
|
pagination_layout.setContentsMargins(0, 10, 0, 0)
|
||||||
|
|
||||||
@@ -1284,6 +1292,147 @@ class DeveloperInfoWindow(QMainWindow):
|
|||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class AppVersionsWindow(QMainWindow):
|
||||||
|
"""应用版本列表窗口"""
|
||||||
|
def __init__(self, api_client, app_id, app_name, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.api_client = api_client
|
||||||
|
self.app_id = app_id
|
||||||
|
self.app_name = app_name
|
||||||
|
self.setWindowTitle(f"{app_name} - 版本历史")
|
||||||
|
self.resize(800, 600)
|
||||||
|
self.current_page = 1
|
||||||
|
self.items_per_page = 20
|
||||||
|
self.total_pages = 1
|
||||||
|
self.init_ui()
|
||||||
|
self.load_versions()
|
||||||
|
|
||||||
|
def init_ui(self):
|
||||||
|
"""初始化界面"""
|
||||||
|
# 创建中心部件
|
||||||
|
central_widget = QWidget()
|
||||||
|
self.setCentralWidget(central_widget)
|
||||||
|
|
||||||
|
# 创建主布局
|
||||||
|
main_layout = QVBoxLayout(central_widget)
|
||||||
|
main_layout.setContentsMargins(20, 20, 20, 20)
|
||||||
|
|
||||||
|
# 创建标题
|
||||||
|
title = TitleLabel(f"{self.app_name} - 版本历史")
|
||||||
|
main_layout.addWidget(title)
|
||||||
|
|
||||||
|
# 创建版本列表
|
||||||
|
self.versions_table = TableWidget()
|
||||||
|
self.versions_table.setColumnCount(5)
|
||||||
|
self.versions_table.setHorizontalHeaderLabels(["版本号", "发布日期", "操作系统", "文件大小", "下载量"])
|
||||||
|
main_layout.addWidget(self.versions_table)
|
||||||
|
|
||||||
|
# 创建分页控件
|
||||||
|
pagination_layout = QHBoxLayout()
|
||||||
|
self.prev_button = PushButton("上一页")
|
||||||
|
self.prev_button.clicked.connect(self.prev_page)
|
||||||
|
self.page_label = CaptionLabel("第 1 页,共 1 页")
|
||||||
|
self.next_button = PushButton("下一页")
|
||||||
|
self.next_button.clicked.connect(self.next_page)
|
||||||
|
|
||||||
|
pagination_layout.addWidget(self.prev_button)
|
||||||
|
pagination_layout.addStretch()
|
||||||
|
pagination_layout.addWidget(self.page_label)
|
||||||
|
pagination_layout.addStretch()
|
||||||
|
pagination_layout.addWidget(self.next_button)
|
||||||
|
main_layout.addLayout(pagination_layout)
|
||||||
|
|
||||||
|
# 创建进度条
|
||||||
|
self.progress_bar = ProgressBar()
|
||||||
|
self.progress_bar.setVisible(False)
|
||||||
|
main_layout.addWidget(self.progress_bar)
|
||||||
|
|
||||||
|
def load_versions(self):
|
||||||
|
"""加载版本列表"""
|
||||||
|
self.show_progress()
|
||||||
|
self.worker = WorkerThread(self.api_client, 'getappversions',
|
||||||
|
{'id': self.app_id,
|
||||||
|
'page': self.current_page,
|
||||||
|
'limit': self.items_per_page})
|
||||||
|
self.worker.finished.connect(self.on_versions_loaded)
|
||||||
|
self.worker.progress.connect(self.update_progress)
|
||||||
|
self.worker.error.connect(self.show_error)
|
||||||
|
self.worker.start()
|
||||||
|
|
||||||
|
def on_versions_loaded(self, data):
|
||||||
|
"""版本列表加载完成处理"""
|
||||||
|
self.hide_progress()
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
self.show_error("版本列表加载失败")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 清空表格
|
||||||
|
self.versions_table.setRowCount(0)
|
||||||
|
|
||||||
|
# 更新分页信息
|
||||||
|
pagination = data.get('pagination', {})
|
||||||
|
self.total_pages = pagination.get('totalPages', 1)
|
||||||
|
self.page_label.setText(f"第 {self.current_page} 页,共 {self.total_pages} 页")
|
||||||
|
|
||||||
|
# 更新按钮状态
|
||||||
|
self.prev_button.setEnabled(self.current_page > 1)
|
||||||
|
self.next_button.setEnabled(self.current_page < self.total_pages)
|
||||||
|
|
||||||
|
# 填充表格
|
||||||
|
versions = data.get('versions', [])
|
||||||
|
for version in versions:
|
||||||
|
row_position = self.versions_table.rowCount()
|
||||||
|
self.versions_table.insertRow(row_position)
|
||||||
|
|
||||||
|
# 添加版本数据
|
||||||
|
self.versions_table.setItem(row_position, 0, QTableWidgetItem(version.get('version', '未知')))
|
||||||
|
self.versions_table.setItem(row_position, 1, QTableWidgetItem(version.get('created_at', '未知')))
|
||||||
|
self.versions_table.setItem(row_position, 2, QTableWidgetItem(version.get('platform', '未知')))
|
||||||
|
self.versions_table.setItem(row_position, 3, QTableWidgetItem(version.get('file_size', '未知')))
|
||||||
|
self.versions_table.setItem(row_position, 4, QTableWidgetItem(str(version.get('download_count', 0))))
|
||||||
|
|
||||||
|
# 自动调整列宽
|
||||||
|
self.versions_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
||||||
|
|
||||||
|
def prev_page(self):
|
||||||
|
"""上一页"""
|
||||||
|
if self.current_page > 1:
|
||||||
|
self.current_page -= 1
|
||||||
|
self.load_versions()
|
||||||
|
|
||||||
|
def next_page(self):
|
||||||
|
"""下一页"""
|
||||||
|
if self.current_page < self.total_pages:
|
||||||
|
self.current_page += 1
|
||||||
|
self.load_versions()
|
||||||
|
|
||||||
|
def show_progress(self):
|
||||||
|
"""显示进度条"""
|
||||||
|
self.progress_bar.setVisible(True)
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
|
||||||
|
def update_progress(self, value):
|
||||||
|
"""更新进度条"""
|
||||||
|
self.progress_bar.setValue(value)
|
||||||
|
|
||||||
|
def hide_progress(self):
|
||||||
|
"""隐藏进度条"""
|
||||||
|
self.progress_bar.setVisible(False)
|
||||||
|
|
||||||
|
def show_error(self, message):
|
||||||
|
"""显示错误消息"""
|
||||||
|
self.hide_progress()
|
||||||
|
InfoBar.error(
|
||||||
|
title="错误",
|
||||||
|
content=message,
|
||||||
|
orient=Qt.Horizontal,
|
||||||
|
isClosable=True,
|
||||||
|
position=InfoBarPosition.BOTTOM_RIGHT,
|
||||||
|
duration=5000,
|
||||||
|
parent=self
|
||||||
|
)
|
||||||
|
|
||||||
class LeonAppGUI(FluentWindow):
|
class LeonAppGUI(FluentWindow):
|
||||||
"""主应用窗口"""
|
"""主应用窗口"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -1343,6 +1492,11 @@ class LeonAppGUI(FluentWindow):
|
|||||||
developer_info_window = DeveloperInfoWindow(self.api_client, developer_id, self)
|
developer_info_window = DeveloperInfoWindow(self.api_client, developer_id, self)
|
||||||
developer_info_window.show()
|
developer_info_window.show()
|
||||||
|
|
||||||
|
def show_app_versions(self, app_id, app_name):
|
||||||
|
"""显示应用的版本列表"""
|
||||||
|
versions_window = AppVersionsWindow(self.api_client, app_id, app_name, self)
|
||||||
|
versions_window.show()
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""主函数"""
|
"""主函数"""
|
||||||
# 创建应用实例
|
# 创建应用实例
|
||||||
|
|||||||
@@ -145,31 +145,25 @@ while ($row = $result->fetch_assoc()) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-footer bg-transparent d-flex justify-content-between align-items-center">
|
<div class="card-footer bg-transparent d-flex justify-content-between align-items-center">
|
||||||
<?php
|
<?php
|
||||||
// 简化路径处理以避免open_basedir限制问题
|
// 安全地处理文件大小和路径,避免open_basedir限制问题
|
||||||
$originalFilePath = trim($version['file_path']);
|
$fileName = trim($version['file_path']);
|
||||||
$fileSize = false;
|
$fileSize = false;
|
||||||
|
|
||||||
|
// 使用__DIR__构建安全的绝对路径,与version_control.php保持一致
|
||||||
|
$uploadDir = __DIR__ . '/../files/';
|
||||||
|
$absoluteFilePath = $uploadDir . $fileName;
|
||||||
|
|
||||||
// 尝试安全地获取文件大小,处理open_basedir限制
|
// 尝试安全地获取文件大小,处理open_basedir限制
|
||||||
try {
|
if (file_exists($absoluteFilePath)) {
|
||||||
// 首先尝试使用原始路径(相对路径通常在web环境中更安全)
|
$fileSize = filesize($absoluteFilePath);
|
||||||
if (file_exists($originalFilePath)) {
|
|
||||||
$fileSize = filesize($originalFilePath);
|
|
||||||
}
|
|
||||||
// 尝试相对于当前脚本的路径
|
|
||||||
else {
|
|
||||||
$relativePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . $originalFilePath;
|
|
||||||
if (file_exists($relativePath)) {
|
|
||||||
$fileSize = filesize($relativePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// 如果遇到open_basedir限制或其他安全限制,优雅地处理
|
|
||||||
$fileSize = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$sizeText = formatFileSize($fileSize);
|
$sizeText = formatFileSize($fileSize);
|
||||||
|
|
||||||
|
// 构建安全的下载链接
|
||||||
|
$downloadUrl = '/files/' . $fileName;
|
||||||
?>
|
?>
|
||||||
<a href="<?php echo htmlspecialchars($version['file_path']); ?>" class="btn btn-primary" download>下载(大小:<?php echo $sizeText; ?>)</a>
|
<a href="<?php echo htmlspecialchars($downloadUrl); ?>" class="btn btn-primary" download>下载(大小:<?php echo $sizeText; ?>)</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|||||||
Reference in New Issue
Block a user