From d66c6945d161474657669872c7558b88f297067a Mon Sep 17 00:00:00 2001 From: root Date: Sun, 1 Dec 2024 12:52:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=8A=E5=8E=9F=E6=9D=A5bootstrap=E5=86=99?= =?UTF-8?q?=E7=9A=84=E9=82=A3=E5=87=A0=E4=B8=AA=E9=A1=B5=E9=9D=A2=E9=A1=B5?= =?UTF-8?q?=E7=94=A8Vue=E9=87=8D=E5=86=99=E4=BA=86=E4=B8=80=E9=81=8D=20?= =?UTF-8?q?=E5=AF=B9=E6=89=8B=E6=9C=BA=E7=AB=AF=E8=BF=9B=E8=A1=8C=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- src/api/request.js | 29 ++-- src/api/visitor.js | 49 +++++++ src/layout/Layout.vue | 47 +++++-- src/layout/VisitorLayout.vue | 46 +++++++ src/router/index.js | 55 +++++++- src/utils/visitorTips.js | 13 ++ src/views/ConfigView.vue | 62 +++++++++ src/views/Dashboard.vue | 87 ++++++++++-- src/views/TaskManagement.vue | 199 ++++++++++++++++++++++++++- src/views/UserEvents.vue | 203 +++++++++++++++++++++++++--- src/views/UserManagement.vue | 115 +++++++++++++++- src/views/UserProfile.vue | 74 +++++++++- src/views/visitor/DeleteInfo.vue | 155 +++++++++++++++++++++ src/views/visitor/DownloadPage.vue | 166 +++++++++++++++++++++++ src/views/visitor/TaskList.vue | 210 +++++++++++++++++++++++++++++ 16 files changed, 1447 insertions(+), 65 deletions(-) create mode 100644 src/api/visitor.js create mode 100644 src/layout/VisitorLayout.vue create mode 100644 src/utils/visitorTips.js create mode 100644 src/views/visitor/DeleteInfo.vue create mode 100644 src/views/visitor/DownloadPage.vue create mode 100644 src/views/visitor/TaskList.vue diff --git a/index.html b/index.html index a6507ff..af20025 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + diff --git a/src/api/request.js b/src/api/request.js index 1b8eff6..ce78618 100644 --- a/src/api/request.js +++ b/src/api/request.js @@ -14,13 +14,13 @@ const request = axios.create({ // 请求拦截器 request.interceptors.request.use( config => { - // 如果不是登录请求,就添加token - if (!config.url.includes('/user/login') && !config.url.includes('/user/register')) { - const token = JSON.parse(localStorage.getItem('token')).token + // 如果是访客页面的请求,不需要添加 token + if (!config.url.startsWith('/visitor')) { + const token = localStorage.getItem('token') if (token) { - config.headers.Authorization = `Bearer ${token}` + const tokenData = JSON.parse(token) + config.headers.Authorization = `Bearer ${tokenData.token}` } - console.log('Request Headers:', config.headers.Authorization) } return config }, @@ -38,11 +38,9 @@ request.interceptors.response.use( if (data.retcode === 0) { return data } - // 显示错误消息对话框 - ElMessageBox.alert(data.message || '操作失败', '错误', { - type: 'error', - confirmButtonText: '确定' - }) + + // 显示错误消息 + ElMessage.error(data.message || '操作失败') return Promise.reject(new Error(data.message || '操作失败')) }, error => { @@ -51,9 +49,12 @@ request.interceptors.response.use( if (error.response) { switch (error.response.status) { case 401: - localStorage.removeItem('token') - localStorage.removeItem('userRole') - router.push('/login') + // 只有非访客页面才需要清除登录状态并跳转 + if (!router.currentRoute.value.path.startsWith('/visitor')) { + localStorage.removeItem('token') + localStorage.removeItem('userRole') + router.push('/login') + } break case 403: ElMessage.error('没有权限访问') @@ -62,10 +63,8 @@ request.interceptors.response.use( ElMessage.error(error.response.data?.message || '请求失败') } } else if (error.request) { - // 请求已发出但没有收到响应 ElMessage.error('服务器无响应,请检查后端服务是否启动') } else { - // 请求配置出错 ElMessage.error('请求配置错误') } return Promise.reject(error) diff --git a/src/api/visitor.js b/src/api/visitor.js new file mode 100644 index 0000000..3bf5a2b --- /dev/null +++ b/src/api/visitor.js @@ -0,0 +1,49 @@ +import request from './request' + +export const VisitorAPI = { + /** + * 获取服务器负载信息 + */ + getServerLoad() { + return request.get('/GetServerLoad', { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }) + }, + + /** + * 添加离线下载任务 + * @param {string} url 下载链接 + */ + addOfflineTask(url) { + return request.post('/AddOfflineTask', null, { + params: { url }, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }) + }, + + /** + * 获取我的任务列表 + */ + getMyTasks() { + return request.get('/GetMyTasks', { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }) + }, + + /** + * 删除访客信息 + */ + deleteVisitorInfo() { + return request.delete('/VisitorManagement/DeleteInfo', { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }) + } +} \ No newline at end of file diff --git a/src/layout/Layout.vue b/src/layout/Layout.vue index 1b92365..36d2a31 100644 --- a/src/layout/Layout.vue +++ b/src/layout/Layout.vue @@ -1,9 +1,9 @@ \ No newline at end of file diff --git a/src/layout/VisitorLayout.vue b/src/layout/VisitorLayout.vue new file mode 100644 index 0000000..93aca5b --- /dev/null +++ b/src/layout/VisitorLayout.vue @@ -0,0 +1,46 @@ + + + + + \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index f5232b8..6cd0e47 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -57,9 +57,42 @@ const routes = [ } ] }, + { + path: '/visitor', + component: () => import('../layout/VisitorLayout.vue'), + children: [ + { + path: '', + name: 'VisitorDownload', + component: () => import('../views/visitor/DownloadPage.vue'), + meta: { + public: true, + title: 'iFileProxy - 文件代理下载' + } + }, + { + path: 'tasks', + name: 'VisitorTasks', + component: () => import('../views/visitor/TaskList.vue'), + meta: { + public: true, + title: 'iFileProxy - 任务列表' + } + }, + { + path: 'delete', + name: 'VisitorDelete', + component: () => import('../views/visitor/DeleteInfo.vue'), + meta: { + public: true, + title: 'iFileProxy - 删除访客信息' + } + } + ] + }, { path: '/:pathMatch(.*)*', - redirect: '/dashboard' + redirect: '/visitor' } ] @@ -70,6 +103,12 @@ const router = createRouter({ // 简化路由守卫 router.beforeEach(async (to, from, next) => { + // 如果是访客页面,直接放行 + if (to.path.startsWith('/visitor')) { + next() + return + } + const token = localStorage.getItem('token') const isAuthenticated = localStorage.getItem('isAuthenticated') const userRole = localStorage.getItem('userRole') @@ -106,6 +145,12 @@ router.beforeEach(async (to, from, next) => { } } + // 如果是公开页面,直接放行 + if (to.meta.public) { + next() + return + } + // 检查权限 if (to.meta.roles && !to.meta.roles.includes(userRole)) { ElMessage.error('没有访问权限') @@ -116,4 +161,12 @@ router.beforeEach(async (to, from, next) => { next() }) +// 添加全局路由守卫来更新标题 +router.afterEach((to) => { + // 设置默认标题 + const defaultTitle = '后台管理系统' + // 如果路由有title元信息,则使用它,否则使用默认标题 + document.title = to.meta.title || defaultTitle +}) + export default router \ No newline at end of file diff --git a/src/utils/visitorTips.js b/src/utils/visitorTips.js new file mode 100644 index 0000000..31776ce --- /dev/null +++ b/src/utils/visitorTips.js @@ -0,0 +1,13 @@ +export const tips = [ + '任务列表每个IP相互隔离,不必担心任务信息泄露。', + '哈希算法为MD5。', + '下载的文件不会永久存储在服务器上, 每隔一段时间服务器会自动清理那些文件, 并且任务状态会转变为"已被清理"。', + '本站会收集一些访客信息用于访客数据分析, 若你不想被收集相关信息用于分析, 请点击"删除我的访客信息"自助删除已经存储在服务器上的信息(新加任务仍然会收集)。', + '服务器同时下载的任务达到限制时候, 新的任务会被加入队列(即 排队), 若队列达到管理员设置的最大值则不再接受新任务, 直至队列空出余量。', + '本站为了节省成本和照顾其他访客的感受, 每个IP有一定的下载和任务提交配额, 达到限制后当天内不能再下载文件或者新增任务, 请勿浪费公共资源。' +] + +export function getRandomTip() { + const index = Math.floor(Math.random() * tips.length) + return tips[index] +} \ No newline at end of file diff --git a/src/views/ConfigView.vue b/src/views/ConfigView.vue index 8fbc619..dd54539 100644 --- a/src/views/ConfigView.vue +++ b/src/views/ConfigView.vue @@ -244,4 +244,66 @@ onMounted(() => { :deep(.el-tag) { margin: 4px; } + +/* 添加响应式样式 */ +@media screen and (max-width: 768px) { + .config-view { + padding: 10px; + } + + .card-header { + flex-direction: column; + gap: 12px; + } + + .title { + font-size: 14px; + } + + /* 调整描述列表在移动端的显示 */ + :deep(.el-descriptions) { + .el-descriptions__label { + width: 100px; + min-width: 100px; + font-size: 12px; + } + + .el-descriptions__content { + font-size: 12px; + word-break: break-all; + } + + .el-descriptions__cell { + padding: 12px !important; + } + } + + /* 调整标签在移动端的显示 */ + :deep(.el-tag) { + margin: 2px; + font-size: 11px; + } + + /* 调整选项卡在移动端的显示 */ + :deep(.el-tabs__item) { + font-size: 13px; + padding: 0 10px; + } + + /* 调整刷新按钮 */ + .card-header .el-button { + width: 100%; + } +} + +/* 平板端样式调整 */ +@media screen and (min-width: 769px) and (max-width: 1024px) { + .config-view { + padding: 15px; + } + + :deep(.el-descriptions__label) { + width: 120px; + } +} \ No newline at end of file diff --git a/src/views/Dashboard.vue b/src/views/Dashboard.vue index 40c03bc..e02a565 100644 --- a/src/views/Dashboard.vue +++ b/src/views/Dashboard.vue @@ -1,7 +1,7 @@ - + - + {{ userInfo.userId }} @@ -39,10 +42,10 @@
- + 修改昵称 - + 修改密码
@@ -119,7 +122,7 @@ \ No newline at end of file diff --git a/src/views/visitor/DeleteInfo.vue b/src/views/visitor/DeleteInfo.vue new file mode 100644 index 0000000..30b968b --- /dev/null +++ b/src/views/visitor/DeleteInfo.vue @@ -0,0 +1,155 @@ + + + + + \ No newline at end of file diff --git a/src/views/visitor/DownloadPage.vue b/src/views/visitor/DownloadPage.vue new file mode 100644 index 0000000..884a763 --- /dev/null +++ b/src/views/visitor/DownloadPage.vue @@ -0,0 +1,166 @@ + + + + + \ No newline at end of file diff --git a/src/views/visitor/TaskList.vue b/src/views/visitor/TaskList.vue new file mode 100644 index 0000000..a019ef5 --- /dev/null +++ b/src/views/visitor/TaskList.vue @@ -0,0 +1,210 @@ + + + + + \ No newline at end of file