feat: add commit-based release notes, usage loading spinner, and 60s logs timeout

This commit is contained in:
Supra4E8C
2025-12-20 12:34:45 +08:00
parent 10f2262753
commit df472119e7
6 changed files with 62 additions and 26 deletions

View File

@@ -15,6 +15,9 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
@@ -36,27 +39,48 @@ jobs:
mv index.html management.html mv index.html management.html
ls -lh management.html ls -lh management.html
- name: Generate release notes
run: |
set -euo pipefail
current_tag="${GITHUB_REF_NAME}"
previous_tag="$(git tag --list 'v*' --sort=-v:refname | grep -v "^${current_tag}$" | head -n 1 || true)"
if [ -n "${previous_tag}" ]; then
range="${previous_tag}..${current_tag}"
title="Changes since ${previous_tag}"
else
range="${current_tag}"
title="Changes"
fi
{
echo "## CLI Proxy API Management Center - ${current_tag}"
echo
echo "### Download and Usage"
echo "1. Download the \`management.html\` file"
echo "2. Open it directly in your browser"
echo "3. All assets (CSS, JavaScript, images) are bundled into this single file"
echo
echo "### Features"
echo "- Single file, no external dependencies required"
echo "- Complete management interface for CLI Proxy API"
echo "- Support for local and remote connections"
echo "- Multi-language support (Chinese/English)"
echo "- Dark/Light theme support"
echo
echo "### ${title}"
echo
git log --pretty=format:"- %h %s" "${range}"
echo
echo
echo "---"
echo "🤖 Generated with GitHub Actions"
} > release-notes.md
- name: Create Release - name: Create Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
with: with:
files: dist/management.html files: dist/management.html
body: | body_path: release-notes.md
## CLI Proxy API Management Center - ${{ github.ref_name }}
### Download and Usage
1. Download the `management.html` file
2. Open it directly in your browser
3. All assets (CSS, JavaScript, images) are bundled into this single file
### Features
- Single file, no external dependencies required
- Complete management interface for CLI Proxy API
- Support for local and remote connections
- Multi-language support (Chinese/English)
- Dark/Light theme support
---
🤖 Generated with GitHub Actions
draft: false draft: false
prerelease: false prerelease: false
env: env:

View File

@@ -1,7 +1,13 @@
export function LoadingSpinner({ size = 20 }: { size?: number }) { export function LoadingSpinner({
size = 20,
className = ''
}: {
size?: number;
className?: string;
}) {
return ( return (
<div <div
className="loading-spinner" className={`loading-spinner${className ? ` ${className}` : ''}`}
style={{ width: size, height: size, borderWidth: size / 7 }} style={{ width: size, height: size, borderWidth: size / 7 }}
role="status" role="status"
aria-live="polite" aria-live="polite"

View File

@@ -66,11 +66,12 @@
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
background: var(--bg-primary); background: var(--bg-primary);
box-shadow: var(--shadow-lg); box-shadow: var(--shadow-lg);
}
:global(.loading-spinner) { .loadingOverlaySpinner {
border-color: rgba(59, 130, 246, 0.25); border-color: rgba(59, 130, 246, 0.25);
border-top-color: var(--primary-color); border-top-color: var(--primary-color);
} box-shadow: 0 0 10px rgba(59, 130, 246, 0.25);
} }
.loadingOverlayText { .loadingOverlayText {

View File

@@ -520,7 +520,7 @@ export function UsagePage() {
{loading && !usage && ( {loading && !usage && (
<div className={styles.loadingOverlay} aria-busy="true"> <div className={styles.loadingOverlay} aria-busy="true">
<div className={styles.loadingOverlayContent}> <div className={styles.loadingOverlayContent}>
<LoadingSpinner size={28} /> <LoadingSpinner size={28} className={styles.loadingOverlaySpinner} />
<span className={styles.loadingOverlayText}>{t('common.loading')}</span> <span className={styles.loadingOverlayText}>{t('common.loading')}</span>
</div> </div>
</div> </div>

View File

@@ -3,6 +3,7 @@
*/ */
import { apiClient } from './client'; import { apiClient } from './client';
import { LOGS_TIMEOUT_MS } from '@/utils/constants';
export interface LogsQuery { export interface LogsQuery {
after?: number; after?: number;
@@ -25,14 +26,17 @@ export interface ErrorLogsResponse {
} }
export const logsApi = { export const logsApi = {
fetchLogs: (params: LogsQuery = {}): Promise<LogsResponse> => apiClient.get('/logs', { params }), fetchLogs: (params: LogsQuery = {}): Promise<LogsResponse> =>
apiClient.get('/logs', { params, timeout: LOGS_TIMEOUT_MS }),
clearLogs: () => apiClient.delete('/logs'), clearLogs: () => apiClient.delete('/logs'),
fetchErrorLogs: (): Promise<ErrorLogsResponse> => apiClient.get('/request-error-logs'), fetchErrorLogs: (): Promise<ErrorLogsResponse> =>
apiClient.get('/request-error-logs', { timeout: LOGS_TIMEOUT_MS }),
downloadErrorLog: (filename: string) => downloadErrorLog: (filename: string) =>
apiClient.getRaw(`/request-error-logs/${encodeURIComponent(filename)}`, { apiClient.getRaw(`/request-error-logs/${encodeURIComponent(filename)}`, {
responseType: 'blob', responseType: 'blob',
timeout: LOGS_TIMEOUT_MS
}), }),
}; };

View File

@@ -18,6 +18,7 @@ export const LOG_REFRESH_DELAY_MS = 500;
// 日志相关 // 日志相关
export const MAX_LOG_LINES = 2000; export const MAX_LOG_LINES = 2000;
export const LOG_FETCH_LIMIT = 2500; export const LOG_FETCH_LIMIT = 2500;
export const LOGS_TIMEOUT_MS = 60 * 1000;
// 认证文件分页 // 认证文件分页
export const DEFAULT_AUTH_FILES_PAGE_SIZE = 20; export const DEFAULT_AUTH_FILES_PAGE_SIZE = 20;