- New CLI commands: key, user - New internal modules: auth (middleware, password, user), db (db, logs, products), email, gateway (gateway, hooks, middlewares), handler (admin, auth, dev, log, product, settings), middleware/geoblock, ratelimit - New demo frontend page - Updated config, server, analytics, stats, and existing frontend pages
162 lines
8.1 KiB
HTML
162 lines
8.1 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate">
|
||
<meta http-equiv="Pragma" content="no-cache">
|
||
<meta http-equiv="Expires" content="0">
|
||
<title>Sol148 Video - 视频浏览</title>
|
||
<link rel="stylesheet" href="/videoapp/style.css?v=3">
|
||
</head>
|
||
<body>
|
||
<!-- 顶部导航 -->
|
||
<nav class="navbar">
|
||
<div class="nav-inner">
|
||
<a href="/video" class="logo">🎬 Sol148 Video</a>
|
||
<div class="nav-links">
|
||
<a href="/video#/browse" class="nav-link">浏览</a>
|
||
<a href="/video#/categories" class="nav-link">分类</a>
|
||
<a href="/video#/search" class="nav-link">搜索</a>
|
||
</div>
|
||
<div class="nav-stats" id="navStats">
|
||
<span title="QPS">⚡ <b id="navQPS">--</b></span>
|
||
<span title="活跃连接">🔗 <b id="navConn">--</b></span>
|
||
<span title="平均延迟">⏱️ <b id="navLat">--</b>ms</span>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- 主内容区(SPA 路由切换) -->
|
||
<main id="app">
|
||
<!-- 首页 -->
|
||
<section id="page-home" class="page">
|
||
<div class="hero">
|
||
<h1>探索精彩视频内容</h1>
|
||
<p>通过 sol148-extractor API 驱动的视频浏览平台</p>
|
||
<div class="hero-actions">
|
||
<button class="btn btn-primary" onclick="navigate('#/browse')">开始浏览</button>
|
||
<button class="btn btn-outline" onclick="navigate('#/categories')">查看分类</button>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<h2>🔥 热门分类</h2>
|
||
<div class="category-grid" id="homeCategories"></div>
|
||
</div>
|
||
<div class="section">
|
||
<h2>⚡ 实时服务状态</h2>
|
||
<div class="stats-bar" id="homeStats"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 分类浏览页 -->
|
||
<section id="page-browse" class="page hidden">
|
||
<div class="browse-header">
|
||
<h2 id="browseTitle">最近更新</h2>
|
||
<div class="browse-controls">
|
||
<select id="categorySelect" onchange="loadCategoryPage()"></select>
|
||
<button class="btn btn-sm" onclick="prevPage()" id="btnPrev">◀ 上一页</button>
|
||
<span id="pageInfo">第 1 页</span>
|
||
<button class="btn btn-sm" onclick="nextPage()" id="btnNext">下一页 ▶</button>
|
||
<span class="page-jump-group">
|
||
跳至 <input type="number" class="page-jump-input" id="pageJumpTop" min="1" placeholder="页码" onkeydown="if(event.key==='Enter')jumpToPage('top')">
|
||
<button class="btn btn-sm" onclick="jumpToPage('top')">GO</button>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<div class="video-grid" id="videoGrid"></div>
|
||
<div class="loading" id="browseLoading" style="display:none;">加载中...</div>
|
||
<div class="browse-footer-pagination" id="browseFooterPagination">
|
||
<button class="btn btn-sm" onclick="prevPage()" id="btnPrevBottom">◀ 上一页</button>
|
||
<span id="pageInfoBottom">第 1 页</span>
|
||
<button class="btn btn-sm" onclick="nextPage()" id="btnNextBottom">下一页 ▶</button>
|
||
<span class="page-jump-group">
|
||
跳至 <input type="number" class="page-jump-input" id="pageJumpBottom" min="1" placeholder="页码" onkeydown="if(event.key==='Enter')jumpToPage('bottom')">
|
||
<button class="btn btn-sm" onclick="jumpToPage('bottom')">GO</button>
|
||
</span>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 分类列表页 -->
|
||
<section id="page-categories" class="page hidden">
|
||
<h2>📂 视频分类</h2>
|
||
<div class="category-list" id="categoryList"></div>
|
||
</section>
|
||
|
||
<!-- 搜索页 -->
|
||
<section id="page-search" class="page hidden">
|
||
<h2>🔍 搜索视频</h2>
|
||
<div class="search-bar">
|
||
<input type="text" id="searchInput" placeholder="输入关键词搜索(暂搜索标题)..." onkeydown="if(event.key==='Enter')doSearch()">
|
||
<button class="btn btn-primary" onclick="doSearch()">搜索</button>
|
||
</div>
|
||
<div class="video-grid" id="searchResults"></div>
|
||
<div class="loading" id="searchLoading" style="display:none;">搜索中...</div>
|
||
</section>
|
||
|
||
<!-- 视频详情页 -->
|
||
<section id="page-watch" class="page hidden">
|
||
<div class="watch-container">
|
||
<div class="video-player">
|
||
<div class="player-wrapper" id="playerWrapper">
|
||
<div class="player-placeholder" id="playerBox">
|
||
<div class="play-icon">▶</div>
|
||
<p id="playerLabel">正在提取视频源...</p>
|
||
<p class="player-hint" id="playerHint"></p>
|
||
</div>
|
||
<div id="dplayerContainer" class="hidden"></div>
|
||
<div class="player-error-overlay hidden" id="playerError">
|
||
<div class="error-icon">⚠️</div>
|
||
<p id="playerErrorMsg">无法播放</p>
|
||
<p id="playerErrorHint"></p>
|
||
</div>
|
||
</div>
|
||
<div class="player-status hidden" id="playerStatus"></div>
|
||
<div class="player-mode" id="playerMode">
|
||
<span class="mode-label">加载模式</span>
|
||
<div class="mode-toggle" id="modeToggle" onclick="togglePlayMode()" title="切换视频加载方式">
|
||
<span class="mode-option active" data-mode="proxy">🛡️ 代理</span>
|
||
<span class="mode-option" data-mode="direct">🔗 直连</span>
|
||
<span class="mode-slider"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="video-detail">
|
||
<h2 id="videoTitle">--</h2>
|
||
<div class="video-meta" id="videoMeta"></div>
|
||
<div class="video-actions">
|
||
<button class="btn btn-primary" id="btnExtract" onclick="extractCurrent()">🔗 重新提取</button>
|
||
<button class="btn btn-outline" id="btnCopyURL" onclick="copyVideoURL()" disabled>📋 复制源地址</button>
|
||
<a class="btn btn-outline hidden" id="btnOpenNew" target="_blank" rel="noopener">📥 下载</a>
|
||
</div>
|
||
<div class="video-source hidden" id="videoSourceBox">
|
||
<label>视频源地址:</label>
|
||
<input type="text" id="videoSourceURL" readonly onclick="this.select()">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="videoRelated"></div>
|
||
</section>
|
||
|
||
<!-- 作者页 -->
|
||
<section id="page-author" class="page hidden">
|
||
<h2 id="authorName">作者</h2>
|
||
<div class="video-grid" id="authorVideos"></div>
|
||
<div class="loading" id="authorLoading" style="display:none;">加载中...</div>
|
||
</section>
|
||
</main>
|
||
|
||
<footer>
|
||
<span>Sol148 Video Explorer</span>
|
||
<span>Powered by api-server (Gin + Cobra + ip2region)</span>
|
||
<span>Data via sol148-extractor API</span>
|
||
</footer>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/artplayer/dist/artplayer.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/artplayer-plugin-danmuku/dist/artplayer-plugin-danmuku.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js"></script>
|
||
<script src="/videoapp/app.js?v=3"></script>
|
||
</body>
|
||
</html>
|