优化页面效果
This commit is contained in:
parent
04afcb743e
commit
9e4ec1d8df
8 changed files with 634 additions and 20 deletions
|
@ -1 +1 @@
|
||||||
VITE_API_BASE_URL=http://admin.gitdl.cn:50050
|
VITE_API_BASE_URL=http://api.ifileproxy.gitdl.cn
|
30
index.html
30
index.html
|
@ -4,7 +4,35 @@
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>后台管理系统</title>
|
<!-- SEO Meta Tags -->
|
||||||
|
<title>iFileProxy - 文件代理下载系统</title>
|
||||||
|
<meta name="description" content="iFileProxy是一个开源的文件代理下载系统,支持Github加速下载、离线下载等功能,完全免费使用。" />
|
||||||
|
<meta name="keywords" content="iFileProxy,文件代理,Github加速,离线下载,代理下载,开源项目" />
|
||||||
|
<meta name="author" content="iFileProxy Team" />
|
||||||
|
|
||||||
|
<!-- Open Graph Meta Tags -->
|
||||||
|
<meta property="og:title" content="iFileProxy - 文件代理下载系统" />
|
||||||
|
<meta property="og:description" content="开源免费的文件代理下载系统,支持Github加速下载、离线下载等功能。" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:url" content="https://gitdl.cn" />
|
||||||
|
<meta property="og:image" content="/og-image.png" />
|
||||||
|
|
||||||
|
<!-- Twitter Card Meta Tags -->
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:title" content="iFileProxy - 文件代理下载系统" />
|
||||||
|
<meta name="twitter:description" content="开源免费的文件代理下载系统,支持Github加速下载、离线下载等功能。" />
|
||||||
|
<meta name="twitter:image" content="/og-image.png" />
|
||||||
|
|
||||||
|
<!-- Mobile Meta Tags -->
|
||||||
|
<meta name="theme-color" content="#1890ff" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
|
|
||||||
|
<!-- Robots Meta Tag -->
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
|
||||||
|
<!-- Canonical URL -->
|
||||||
|
<link rel="canonical" href="https://gitdl.cn" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
@ -131,5 +131,12 @@ export const TaskAPI = {
|
||||||
*/
|
*/
|
||||||
searchTasks(params) {
|
searchTasks(params) {
|
||||||
return request.get('/Management/SearchTasks', { params })
|
return request.get('/Management/SearchTasks', { params })
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取IP访问限制数据
|
||||||
|
*/
|
||||||
|
getIPAccessLimitData() {
|
||||||
|
return request.get('/Management/GetIPAccessLimitData')
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
export const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://admin.gitdl.cn:50050'
|
export const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://admin.gitdl.cn:50050'
|
||||||
|
export const DOWNLOAD_BASE_URL = import.meta.env.VITE_DOWNLOAD_BASE_URL || 'https://gitdl.cn'
|
||||||
export const API_ENDPOINTS = {
|
export const API_ENDPOINTS = {
|
||||||
TASK: {
|
TASK: {
|
||||||
LIST: '/Management/GetTaskList',
|
LIST: '/Management/GetTaskList',
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, provide, watch } from 'vue'
|
import { ref, provide, watch, onMounted } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
@ -27,6 +27,33 @@ watch(
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 添加结构化数据
|
||||||
|
const schema = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "WebApplication",
|
||||||
|
"name": "iFileProxy",
|
||||||
|
"applicationCategory": "DownloadManager",
|
||||||
|
"operatingSystem": "Web",
|
||||||
|
"offers": {
|
||||||
|
"@type": "Offer",
|
||||||
|
"price": "0",
|
||||||
|
"priceCurrency": "USD"
|
||||||
|
},
|
||||||
|
"description": "开源免费的文件代理下载系统,支持Github加速下载等功能。",
|
||||||
|
"url": "https://gitdl.cn",
|
||||||
|
"author": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": "iFileProxy Team"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const script = document.createElement('script')
|
||||||
|
script.type = 'application/ld+json'
|
||||||
|
script.text = JSON.stringify(schema)
|
||||||
|
document.head.appendChild(script)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -88,8 +88,8 @@ const routes = [
|
||||||
name: 'VisitorDownload',
|
name: 'VisitorDownload',
|
||||||
component: () => import('../views/visitor/DownloadPage.vue'),
|
component: () => import('../views/visitor/DownloadPage.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
public: true,
|
title: 'iFileProxy - 文件代理下载',
|
||||||
title: 'iFileProxy - 文件代理下载'
|
description: '免费开源的文件代理下载系统,支持Github加速下载等功能。'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -97,8 +97,8 @@ const routes = [
|
||||||
name: 'VisitorTasks',
|
name: 'VisitorTasks',
|
||||||
component: () => import('../views/visitor/TaskList.vue'),
|
component: () => import('../views/visitor/TaskList.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
public: true,
|
title: 'iFileProxy - 任务列表',
|
||||||
title: 'iFileProxy - 任务列表'
|
description: '查看和管理您的下载任务进度。'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -170,10 +170,14 @@ router.beforeEach(async (to, from, next) => {
|
||||||
|
|
||||||
// 添加全局路由守卫来更新标题
|
// 添加全局路由守卫来更新标题
|
||||||
router.afterEach((to) => {
|
router.afterEach((to) => {
|
||||||
// 设置默认标题
|
// 更新标题
|
||||||
const defaultTitle = '后台管理系统'
|
document.title = to.meta.title || 'iFileProxy - 文件代理下载系统'
|
||||||
// 如果路由有title元信息,则使用它,否则使用默认标题
|
|
||||||
document.title = to.meta.title || defaultTitle
|
// 更新描述
|
||||||
|
const metaDescription = document.querySelector('meta[name="description"]')
|
||||||
|
if (metaDescription) {
|
||||||
|
metaDescription.setAttribute('content', to.meta.description || 'iFileProxy是一个开源的文件代理下载系统,支持Github加速下载、离线下载等功能,完全免费使用。')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
|
@ -223,13 +223,51 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 添加 IP 访问统计标签页 -->
|
||||||
|
<el-tab-pane label="IP访问统计" name="ipStats">
|
||||||
|
<div class="ip-stats-content">
|
||||||
|
<div class="stats-header">
|
||||||
|
<h3>IP访问统计</h3>
|
||||||
|
<el-button type="primary" @click="refreshIPStats">
|
||||||
|
<el-icon><Refresh /></el-icon>刷新
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
v-loading="ipStatsLoading"
|
||||||
|
:data="ipStatsList"
|
||||||
|
style="width: 100%"
|
||||||
|
border>
|
||||||
|
<el-table-column prop="date" label="日期" width="120" />
|
||||||
|
<el-table-column prop="ip" label="IP地址" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-link
|
||||||
|
type="primary"
|
||||||
|
:href="`https://ip138.com/iplookup.php?ip=${row.ip}`"
|
||||||
|
target="_blank"
|
||||||
|
:underline="false">
|
||||||
|
{{ row.ip }}
|
||||||
|
</el-link>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="count" label="访问次数" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="getAccessCountType(row.count)">
|
||||||
|
{{ row.count }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted, watch } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import {
|
import {
|
||||||
Monitor, Refresh, Search, RefreshLeft,
|
Monitor, Refresh, Search, RefreshLeft,
|
||||||
|
@ -428,6 +466,9 @@ const refreshDebugInfo = async () => {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchLogs()
|
fetchLogs()
|
||||||
refreshDebugInfo()
|
refreshDebugInfo()
|
||||||
|
if (activeTab.value === 'ipStats') {
|
||||||
|
fetchIPStats()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const exceptionDialogVisible = ref(false)
|
const exceptionDialogVisible = ref(false)
|
||||||
|
@ -485,6 +526,61 @@ const isLongMessage = (message) => {
|
||||||
const toggleMessage = (logId) => {
|
const toggleMessage = (logId) => {
|
||||||
expandedMessages.value[logId] = !expandedMessages.value[logId]
|
expandedMessages.value[logId] = !expandedMessages.value[logId]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加 IP 统计相关的状态
|
||||||
|
const ipStatsLoading = ref(false)
|
||||||
|
const ipStatsList = ref([])
|
||||||
|
|
||||||
|
// 获取 IP 访问统计数据
|
||||||
|
const fetchIPStats = async () => {
|
||||||
|
ipStatsLoading.value = true
|
||||||
|
try {
|
||||||
|
const response = await TaskAPI.getIPAccessLimitData()
|
||||||
|
if (response.retcode === 0) {
|
||||||
|
// 转换数据格式
|
||||||
|
const list = []
|
||||||
|
Object.entries(response.data).forEach(([date, ips]) => {
|
||||||
|
Object.entries(ips).forEach(([ip, count]) => {
|
||||||
|
list.push({
|
||||||
|
date,
|
||||||
|
ip,
|
||||||
|
count
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
ipStatsList.value = list.sort((a, b) => {
|
||||||
|
// 先按日期降序,再按访问次数降序
|
||||||
|
const dateCompare = b.date.localeCompare(a.date)
|
||||||
|
if (dateCompare !== 0) return dateCompare
|
||||||
|
return b.count - a.count
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取IP访问统计失败:', error)
|
||||||
|
ElMessage.error('获取IP访问统计失败')
|
||||||
|
} finally {
|
||||||
|
ipStatsLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新 IP 统计数据
|
||||||
|
const refreshIPStats = () => {
|
||||||
|
fetchIPStats()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取访问次数标签类型
|
||||||
|
const getAccessCountType = (count) => {
|
||||||
|
if (count <= 10) return 'success'
|
||||||
|
if (count <= 30) return 'warning'
|
||||||
|
return 'danger'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听标签页切换
|
||||||
|
watch(activeTab, (newTab) => {
|
||||||
|
if (newTab === 'ipStats') {
|
||||||
|
fetchIPStats()
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -723,4 +819,31 @@ const toggleMessage = (logId) => {
|
||||||
color: #909399;
|
color: #909399;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ip-stats-content {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端适配 */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.stats-header {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -3,31 +3,64 @@
|
||||||
<el-card class="download-card">
|
<el-card class="download-card">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2>iFileProxy 离线下载</h2>
|
<h1>iFileProxy 文件代理下载</h1>
|
||||||
|
<div class="domain-highlight">
|
||||||
|
<div class="domain">
|
||||||
|
git<span class="dl-text">dl</span>.cn
|
||||||
|
</div>
|
||||||
|
<div class="domain-meaning">
|
||||||
|
<span class="meaning-item">
|
||||||
|
<el-icon><Download /></el-icon>
|
||||||
|
<span><span class="dl-text">D</span>own<span class="dl-text">l</span>oad(下载)</span>
|
||||||
|
</span>
|
||||||
|
<span class="divider">|</span>
|
||||||
|
<span class="meaning-item">
|
||||||
|
<el-icon><Connection /></el-icon>
|
||||||
|
<span><span class="dl-text">D</span>ai<span class="dl-text">l</span>i(代理)</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="domain-desc">
|
||||||
|
简单易记的文件加速下载域名
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="subtitle">
|
<div class="subtitle">
|
||||||
本程序可实现文件代理下载,如加速Github和一些墙内无法访问的文件等,程序开源免费
|
开源免费的文件代理下载系统,支持多种下载方式,解决网络访问受限问题
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-form @submit.prevent="handleSubmit">
|
<el-form @submit.prevent="handleSubmit">
|
||||||
|
<el-form-item label="下载方式">
|
||||||
|
<el-radio-group v-model="downloadType">
|
||||||
|
<el-radio label="offline">离线下载</el-radio>
|
||||||
|
<el-radio label="stream">直接下载</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="目标文件URL">
|
<el-form-item label="目标文件URL">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="downloadUrl"
|
v-model="downloadUrl"
|
||||||
placeholder="请输入要下载的文件链接"
|
placeholder="请输入要下载的文件链接"
|
||||||
:disabled="loading" />
|
:disabled="loading">
|
||||||
|
<template #append v-if="downloadType === 'stream'">
|
||||||
|
<el-button @click="handleStreamDownload">直接下载</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
|
v-if="downloadType === 'offline'"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handleSubmit"
|
@click="handleSubmit"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
class="submit-btn">
|
class="submit-btn">
|
||||||
提交
|
提交离线任务
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
<br />
|
||||||
|
|
||||||
<div class="status-info">
|
|
||||||
|
<div class="server-status">
|
||||||
<el-descriptions :column="2" border>
|
<el-descriptions :column="2" border>
|
||||||
<el-descriptions-item label="运行中任务">
|
<el-descriptions-item label="运行中任务">
|
||||||
{{ serverLoad.running }}
|
{{ serverLoad.running }}
|
||||||
|
@ -40,11 +73,11 @@
|
||||||
|
|
||||||
<div class="action-links">
|
<div class="action-links">
|
||||||
<el-link type="primary" @click="$router.push('/visitor/tasks')">
|
<el-link type="primary" @click="$router.push('/visitor/tasks')">
|
||||||
查询文件下载任务状态
|
查询任务状态
|
||||||
</el-link>
|
</el-link>
|
||||||
<el-divider direction="vertical" />
|
<el-divider direction="vertical" />
|
||||||
<el-link type="danger" @click="$router.push('/visitor/delete')">
|
<el-link type="danger" @click="$router.push('/visitor/delete')">
|
||||||
删除我的访客信息
|
删除访客信息
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -54,6 +87,157 @@
|
||||||
type="info"
|
type="info"
|
||||||
:closable="false" />
|
:closable="false" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="features">
|
||||||
|
<div class="features-title">主要功能</div>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="8" :xs="24" :sm="12" :md="8" class="feature-item">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<template #header>
|
||||||
|
<div class="feature-header">
|
||||||
|
<el-icon><Download /></el-icon>
|
||||||
|
<span>多种下载方式</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<ul>
|
||||||
|
<li>离线下载任务</li>
|
||||||
|
<li>直接流式下载</li>
|
||||||
|
<li>支持内容缓存,节省存储</li>
|
||||||
|
<li>断点续传支持</li>
|
||||||
|
</ul>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="8" :xs="24" :sm="12" :md="8" class="feature-item">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<template #header>
|
||||||
|
<div class="feature-header">
|
||||||
|
<el-icon><Connection /></el-icon>
|
||||||
|
<span>代理加速</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<ul>
|
||||||
|
<li>GitHub 文件加速</li>
|
||||||
|
<li>超大文件代理支持</li>
|
||||||
|
<li>通用 HTTP(S) 代理</li>
|
||||||
|
<li>Git 克隆支持</li>
|
||||||
|
</ul>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="8" :xs="24" :sm="12" :md="8" class="feature-item">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<template #header>
|
||||||
|
<div class="feature-header">
|
||||||
|
<el-icon><Lock /></el-icon>
|
||||||
|
<span>安全可靠</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<ul>
|
||||||
|
<li>文件哈希校验</li>
|
||||||
|
<li>智能访问控制</li>
|
||||||
|
<li>HTTPS 加密传输</li>
|
||||||
|
<li>设备指纹验证</li>
|
||||||
|
</ul>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="usage">
|
||||||
|
<div class="usage-title">快速上手</div>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="24" class="usage-item">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<template #header>
|
||||||
|
<div class="usage-header">
|
||||||
|
<el-tag type="success" effect="dark">方式一:直接下载</el-tag>
|
||||||
|
<span class="usage-desc">适用于小文件快速下载,无需等待,直接在浏览器打开</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="usage-content">
|
||||||
|
<div class="example-title">
|
||||||
|
<el-icon><Link /></el-icon>
|
||||||
|
<span>在任意链接前加上 <code>{{ DOWNLOAD_BASE_URL }}</code></span>
|
||||||
|
</div>
|
||||||
|
<div class="example-box">
|
||||||
|
<div class="example-label">示例链接:</div>
|
||||||
|
<el-input
|
||||||
|
readonly
|
||||||
|
:value="`${DOWNLOAD_BASE_URL}/https://github.com/user/repo/raw/master/example.zip`">
|
||||||
|
<template #append>
|
||||||
|
<el-button @click="copyText(`${DOWNLOAD_BASE_URL}/https://github.com/user/repo/raw/master/example.zip`)">
|
||||||
|
复制
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="24" class="usage-item">
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<template #header>
|
||||||
|
<div class="usage-header">
|
||||||
|
<el-tag type="primary" effect="dark">方式二:Git克隆加速</el-tag>
|
||||||
|
<span class="usage-desc">加速 GitHub 仓库克隆,解决连接超时问题</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="usage-content">
|
||||||
|
<div class="example-title">
|
||||||
|
<el-icon><Document /></el-icon>
|
||||||
|
<span>替换 git clone 命令中的域名为 <code>gitdl.cn</code></span>
|
||||||
|
</div>
|
||||||
|
<div class="example-box">
|
||||||
|
<div class="example-label">原始命令:</div>
|
||||||
|
<el-input
|
||||||
|
readonly
|
||||||
|
value="git clone https://github.com/user/example.git"
|
||||||
|
class="original-command" />
|
||||||
|
|
||||||
|
<div class="example-label">加速命令:</div>
|
||||||
|
<el-input
|
||||||
|
readonly
|
||||||
|
:value="`git clone ${DOWNLOAD_BASE_URL}/https://github.com/user/example.git`">
|
||||||
|
<template #append>
|
||||||
|
<el-button @click="copyText(`git clone ${DOWNLOAD_BASE_URL}/https://github.com/user/example.git`)">
|
||||||
|
复制
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<div class="example-label">或者:</div>
|
||||||
|
<el-input
|
||||||
|
readonly
|
||||||
|
:value="`git clone ${DOWNLOAD_BASE_URL}/github.com/user/example.git`">
|
||||||
|
<template #append>
|
||||||
|
<el-button @click="copyText(`git clone ${DOWNLOAD_BASE_URL}/github.com/user/example.git`)">
|
||||||
|
复制
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="project-info">
|
||||||
|
<div class="info-title">项目信息</div>
|
||||||
|
<p>
|
||||||
|
本服务完全免费,服务器配置 1Gbps 带宽。项目已开源,欢迎贡献代码:
|
||||||
|
</p>
|
||||||
|
<div class="repo-links">
|
||||||
|
<el-link type="primary" href="https://git.linxi.info/sunxianglin_admin/iFileProxyAdmin" target="_blank">
|
||||||
|
前端仓库
|
||||||
|
</el-link>
|
||||||
|
<el-divider direction="vertical" />
|
||||||
|
<el-link type="primary" href="https://git.linxi.info/sunxianglin_admin/iFileProxy" target="_blank">
|
||||||
|
后端仓库
|
||||||
|
</el-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -63,6 +247,8 @@ import { ref, onMounted, inject } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { getRandomTip } from '@/utils/visitorTips'
|
import { getRandomTip } from '@/utils/visitorTips'
|
||||||
import { VisitorAPI } from '@/api/visitor'
|
import { VisitorAPI } from '@/api/visitor'
|
||||||
|
import { Download, Connection, Lock, Link, Document } from '@element-plus/icons-vue'
|
||||||
|
import { DOWNLOAD_BASE_URL } from '@/config/api.config'
|
||||||
|
|
||||||
const loading = inject('visitorLoading')
|
const loading = inject('visitorLoading')
|
||||||
const downloadUrl = ref('')
|
const downloadUrl = ref('')
|
||||||
|
@ -72,6 +258,7 @@ const serverLoad = ref({
|
||||||
})
|
})
|
||||||
|
|
||||||
const currentTip = ref(getRandomTip())
|
const currentTip = ref(getRandomTip())
|
||||||
|
const downloadType = ref('offline')
|
||||||
|
|
||||||
// 获取服务器负载信息
|
// 获取服务器负载信息
|
||||||
const fetchServerLoad = async () => {
|
const fetchServerLoad = async () => {
|
||||||
|
@ -108,6 +295,19 @@ const handleSubmit = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleStreamDownload = () => {
|
||||||
|
if (!downloadUrl.value) {
|
||||||
|
ElMessage.warning('请输入下载链接')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
window.open(`${DOWNLOAD_BASE_URL}/${downloadUrl.value}`, '_blank')
|
||||||
|
}
|
||||||
|
|
||||||
|
const copyText = (text) => {
|
||||||
|
navigator.clipboard.writeText(text)
|
||||||
|
ElMessage.success('复制成功')
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchServerLoad()
|
fetchServerLoad()
|
||||||
})
|
})
|
||||||
|
@ -163,4 +363,229 @@ onMounted(() => {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
margin: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features-title,
|
||||||
|
.usage-title,
|
||||||
|
.info-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item ul {
|
||||||
|
padding-left: 20px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item li {
|
||||||
|
margin: 8px 0;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.usage-content {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.usage-content p {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-info {
|
||||||
|
margin: 30px 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.repo-links {
|
||||||
|
margin-top: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端适配 */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.feature-item {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.usage-content {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features-title,
|
||||||
|
.usage-title,
|
||||||
|
.info-title {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain-highlight {
|
||||||
|
margin: 16px 0;
|
||||||
|
padding: 16px;
|
||||||
|
background: linear-gradient(135deg, #e6f7ff, #f0f5ff);
|
||||||
|
border-radius: 8px;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain {
|
||||||
|
font-size: 36px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: 'Monaco', 'Courier New', monospace;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dl-text {
|
||||||
|
color: #f56c6c;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dl-text:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
text-shadow: 1px 1px 2px rgba(245,108,108,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain-meaning {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meaning-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: 'Monaco', 'Courier New', monospace;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
color: #999;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain-desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端适配 */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.domain {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain-meaning {
|
||||||
|
font-size: 13px;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain-highlight {
|
||||||
|
margin: 12px 0;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.usage-item {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.usage-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.usage-desc {
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
color: #303133;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-title code {
|
||||||
|
background: #f5f7fa;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #f56c6c;
|
||||||
|
font-family: 'Monaco', 'Courier New', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-box {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-label {
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.original-command {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 移动端适配 */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.usage-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-box {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.usage-desc {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in a new issue