├── .github └── workflows │ └── deploy.yml ├── .gitignore ├── README.md ├── app.vue ├── assets └── css │ ├── main.css │ └── variables.css ├── components ├── ThemeToggle.vue └── common │ └── Toast.vue ├── composables ├── useAuth.js ├── useTheme.js └── useToast.ts ├── error.vue ├── layouts └── default.vue ├── middleware └── auth.js ├── nuxt.config.js ├── package-lock.json ├── package.json ├── pages ├── dashboard.vue ├── images.vue ├── index.vue ├── login.vue ├── profile.vue └── upload.vue ├── plugins ├── nprogress.client.js └── theme.client.js ├── public ├── favicon.ico ├── logo.png └── robots.txt ├── services └── api.js ├── tsconfig.json └── wrangler.toml /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: 部署布灵图床前端到Cloudflare Pages 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | workflow_dispatch: 9 | 10 | jobs: 11 | deploy: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: read 15 | deployments: write 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - name: 1.Setup Node 21 | uses: actions/setup-node@v4 22 | with: 23 | node-version: '20' 24 | 25 | - name: 2.Install Dependencies 26 | run: | 27 | echo "开始安装依赖..." 28 | npm install &>/dev/null || { 29 | echo "❌ 依赖安装失败" 30 | exit 1 31 | } 32 | npm install -g wrangler &>/dev/null || { 33 | echo "❌ wrangler 安装失败" 34 | exit 1 35 | } 36 | which wrangler # 显示 wrangler 的安装位置 37 | wrangler --version # 显示 wrangler 版本 38 | echo "✅ 依赖安装成功" 39 | 40 | - name: 3.Create Cloudflare Pages Project 41 | env: 42 | CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} 43 | CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} 44 | run: | 45 | echo "检查并创建 Pages 项目..." 46 | curl -X POST "https://api.cloudflare.com/client/v4/accounts/${{ secrets.CF_ACCOUNT_ID }}/pages/projects" \ 47 | -H "Authorization: Bearer ${{ secrets.CF_API_TOKEN }}" \ 48 | -H "Content-Type: application/json" \ 49 | --data '{ 50 | "name": "buling-imgbed-frontend", 51 | "production_branch": "main" 52 | }' > /dev/null 2>&1 || true 53 | echo "✅ Pages 项目检查完成" 54 | 55 | - name: 4.Deploy to Cloudflare Pages 56 | env: 57 | CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} 58 | CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} 59 | NUXT_PUBLIC_API_BASE: ${{ secrets.NUXT_PUBLIC_API_BASE }} 60 | run: | 61 | echo "开始部署到 Cloudflare Pages..." 62 | npm run pages:deploy &>/dev/null || { 63 | echo "❌ 部署失败" 64 | exit 1 65 | } 66 | echo "✅ 部署成功" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | .nuxt 4 | .nitro 5 | .cache 6 | .output 7 | .env 8 | dist 9 | # Node dependencies 10 | node_modules 11 | .wrangler 12 | 13 | 14 | # Logs 15 | logs 16 | *.log 17 | 18 | # Misc 19 | .DS_Store 20 | .fleet 21 | .idea 22 | 23 | # Local env files 24 | .env 25 | .env.* 26 | !.env.example 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🚀 布灵图床 | Buling ImgBed 2 | 3 |
4 |

🌈 布灵图床前端

5 |

布灵图床前端,基于 Vue3 + Nuxt3

6 |

7 | license 8 | version 9 | nuxt 10 | vue 11 |

12 |

13 | 🌍 在线演示 · 14 | 🚀 部署指南 · 15 | 📚 使用文档 · 16 | 🎯 项目详解 17 |

18 |
19 | 20 | > 🎯 基于 Cloudflare 的现代化图床解决方案,零成本易部署,为个人提供便捷的图片托管服务。 21 | > 22 | > ⚠️ 注意:本项目为布灵图床的前端部分,使用前请先完成后端部署:[布灵图床后端](https://github.com/wzs8/buling-imgbed) 23 | > 24 | > 📢 部署顺序: 25 | > 1. 先部署后端服务 [布灵图床后端](https://github.com/wzs8/buling-imgbed) 26 | > 2. 获取后端 API 地址 27 | > 3. 再部署本前端项目 28 | 29 | ## ✨ 功能特性 30 | 31 | - 👤 **用户系统** 32 | - 登录和个人信息管理 33 | - 🖼️ **图片管理** 34 | - 多种上传方式(点击/拖拽/粘贴) 35 | - 智能图片压缩 36 | - 批量操作功能 37 | - 图片预览和删除 38 | - 🤖 **Telegram Bot** 39 | - 便捷的图片上传 40 | - 自动返回多种格式链接 41 | - ⚙️ **自定义配置** 42 | - 自定义域名支持 43 | - CDN 加速 44 | - 图片优化选项 45 | - 存储空间管理 46 | - 🛡️ **安全可靠** 47 | - 私有化部署 48 | - 数据安全保障 49 | - 完善的权限控制 50 | - 🎨 **现代化界面** 51 | - 基于 Vue3 + Nuxt3 开发 52 | - 响应式设计 53 | - 移动端适配 54 | - 亮色/暗色主题切换 55 | - 优雅的交互体验 56 | 57 | 58 | ## 📸 效果预览 59 | 60 | 61 | 62 | 63 | 64 | 65 |
首页预览上传预览
66 | 67 | 68 | ## 🚀 部署指南 69 | 70 | ### 部署准备 71 | 72 | - Cloudflare 账号(生成CF_API_TOKEN、CF_ACCOUNT_ID) 73 | - NUXT_PUBLIC_API_BASE(你的后端API地址) 74 | 75 |
76 | 📝 如何获取这些配置? · 📖 查看图文教程 77 | 78 | #### 1. Cloudflare 配置获取 79 | 1. 注册并登录 [Cloudflare](https://dash.cloudflare.com) 80 | 2. 获取 Account ID: 81 | - 登录后点击右上角的账号图标 82 | - 在下拉菜单中选择 "Account Home" 83 | - 在右侧可以找到你的 Account ID 84 | 3. 创建 API Token: 85 | - 进入 [API Tokens 页面](https://dash.cloudflare.com/profile/api-tokens) 86 | - 点击 "Create Token" 87 | - 选择 "Create Custom Token" 88 | - 权限设置: 89 | - Account.Cloudflare Pages: Edit(如果部署后端时,已配置此权限可复用相同Token) 90 | 91 | #### 2. NUXT_PUBLIC_API_BASE 获取 92 | 1. 登录 Cloudflare 93 | 2. 进入 Workers & Pages 页面 94 | 3. 找到你部署的后端 Worker 95 | 4. 在 Worker 详情页面中找到"自定义域名"部分 96 | 5. 复制你的 Worker 域名(例如: https://your-worker.your-subdomain.workers.dev) 97 | - 如果你配置了自定义域名,也可以使用自定义域名 98 | - 确保域名以 `https://` 开头,末尾不要带斜杠 `/` 99 | 100 |
101 | 102 | ### 一键部署到 Cloudflare Pages(🌟推荐) 103 | 👉 [查看详细图文部署教程](https://anuuu.com/buling-imgbed-frontend-deploy.html) 104 | 105 | 1. Fork 本仓库 106 | 2. 配置 GitHub Secrets: 107 | ``` 108 | CF_API_TOKEN=your_cloudflare_api_token 109 | CF_ACCOUNT_ID=your_cloudflare_account_id 110 | NUXT_PUBLIC_API_BASE=你的后端API地址 111 | ``` 112 | 3. 启用 GitHub Actions 113 | 5. 推送代码触发自动部署(首次部署请点击 Actions 页面手动触发) 114 | 115 | ### 其他部署方式 116 | 117 | #### Vercel 部署 118 | 1. Fork 本仓库 119 | 2. 在 Vercel 导入项目 120 | 3. 配置环境变量: 121 | ``` 122 | NUXT_PUBLIC_API_BASE=你的后端API地址 123 | ``` 124 | 4. 点击 Deploy 开始部署 125 | 126 | 127 | > 注意:无论采用何种部署方式,都需要先完成后端服务的部署并配置正确的API地址。 128 | 129 | ## 📚 技术栈 130 | 131 | - 🎨 前端框架:Vue 3 + Nuxt 3 132 | - 🏗️ 构建工具:Vite 133 | - 🚀 部署平台:Cloudflare Pages 134 | - 📦 图片压缩:browser-image-compression 135 | 136 | ## 🤝 贡献指南 137 | 138 | 欢迎提交 Issue 和 Pull Request 来帮助改进项目。 139 | 140 | 1. Fork 本仓库 141 | 2. 创建你的特性分支 (`git checkout -b feature/AmazingFeature`) 142 | 3. 提交你的改动 (`git commit -m 'Add some AmazingFeature'`) 143 | 4. 推送到分支 (`git push origin feature/AmazingFeature`) 144 | 5. 打开一个 Pull Request 145 | 146 | ## 📜 开源协议 147 | 148 | 本项目基于 [MIT 协议](LICENSE) 开源。 149 | 150 | ## 🎉 鸣谢 151 | - [Cloudflare](https://www.cloudflare.com/) - 提供优秀的基础设施服务 152 | - [Hono](https://hono.dev/) - 优秀的 Web 框架 153 | - [开源社区](https://github.com/) - 感谢所有开源贡献者 154 | 155 | 感谢所有为这个项目做出贡献的开发者们! 156 | 157 | ## 📞 联系作者 158 | 159 | - 博客:[Anuuu.com](https://anuuu.com) 160 | - Telegram:[@wzsxh] 161 | 162 | 163 | --- 164 | 165 | 如果这个项目对你有帮助,欢迎 star ⭐️ 支持一下! 166 | -------------------------------------------------------------------------------- /app.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 18 | -------------------------------------------------------------------------------- /assets/css/main.css: -------------------------------------------------------------------------------- 1 | @import './variables.css'; 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: border-box; 7 | } 8 | 9 | body { 10 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, 11 | Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 12 | background-color: var(--background-color); 13 | color: var(--text-color); 14 | transition: background-color 0.3s, color 0.3s; 15 | } 16 | .container { 17 | max-width: 1200px; 18 | margin: 0 auto; 19 | padding: 0 1rem; 20 | } 21 | .btn { 22 | padding: 0.5rem 1rem; 23 | border: none; 24 | border-radius: 4px; 25 | background-color: var(--primary-color); 26 | color: white; 27 | cursor: pointer; 28 | transition: opacity 0.3s; 29 | } 30 | .btn:hover { 31 | opacity: 0.9; 32 | } 33 | .card { 34 | background-color: var(--card-background); 35 | border-radius: 8px; 36 | padding: 1rem; 37 | box-shadow: 0 2px 4px var(--shadow-color); 38 | } 39 | 40 | /* 添加移动设备的媒体查询 */ 41 | @media screen and (max-width: 768px) { 42 | html { 43 | font-size: 15px; /* 将根元素字体大小调整为14px */ 44 | } 45 | 46 | .container { 47 | padding: 0 0.8rem; /* 适当减小内边距 */ 48 | } 49 | 50 | .btn { 51 | padding: 0.4rem 0.8rem; /* 调整按钮大小 */ 52 | } 53 | 54 | .card { 55 | padding: 0.8rem; /* 调整卡片内边距 */ 56 | } 57 | } 58 | 59 | /* 更小的屏幕尺寸 */ 60 | @media screen and (max-width: 480px) { 61 | html { 62 | font-size: 14px; /* 在更小的屏幕上进一步减小字体 */ 63 | } 64 | } -------------------------------------------------------------------------------- /assets/css/variables.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 亮色主题 */ 3 | --primary-color: #3498db; 4 | --background-color: #ffffff; 5 | --text-color: #333333; 6 | --border-color: #8dc6ff; 7 | --upload-hover-background: #f4f4f5; 8 | --card-background: #f9fafb; 9 | --shadow-color: rgba(0, 0, 0, 0.1); 10 | --card-background-rgb: 255, 255, 255; 11 | --primary-rgb: 124, 58, 237; 12 | } 13 | 14 | /* 暗色主题 */ 15 | [data-theme="dark"] { 16 | --primary-color: #75b3f7; 17 | --background-color:#09090b; 18 | --card-background:#242428; 19 | --upload-hover-background: #09090b; 20 | --text-color: #d4d7d6; 21 | --border-color: #404040; 22 | --card-background-rgb: 30, 30, 30; 23 | --shadow-color: rgba(255, 255, 255, 0.1); 24 | --primary-rgb: 124, 58, 237; 25 | } -------------------------------------------------------------------------------- /components/ThemeToggle.vue: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /components/common/Toast.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | -------------------------------------------------------------------------------- /composables/useAuth.js: -------------------------------------------------------------------------------- 1 | export const useAuth = () => { 2 | const user = useState('user', () => null) 3 | const token = useState('buling-token', () => null) 4 | 5 | const setUser = (tokenData) => { 6 | const payload = JSON.parse(atob(tokenData.split('.')[1])) 7 | user.value = { 8 | chat_id: payload.chat_id, 9 | username: payload.username, 10 | r2_custom_url: payload.r2_custom_url, 11 | enable_baidu_cdn: payload.enable_baidu_cdn, 12 | enable_image_optimization: payload.enable_image_optimization, 13 | } 14 | } 15 | 16 | const setToken = (tokenData) => { 17 | token.value = tokenData 18 | if (process.client) { 19 | localStorage.setItem('buling-token', tokenData) 20 | try { 21 | setUser(tokenData) 22 | } catch (error) { 23 | console.error('Token 解析失败:', error) 24 | } 25 | } 26 | } 27 | 28 | const getUser = () => { 29 | if (!user.value && localStorage.getItem('buling-token')) { 30 | setUser(localStorage.getItem('buling-token')) 31 | } 32 | } 33 | 34 | 35 | const logout = () => { 36 | user.value = null 37 | token.value = null 38 | localStorage.removeItem('buling-token') 39 | } 40 | 41 | const initAuth = () => { 42 | if (process.client) { 43 | const savedToken = localStorage.getItem('buling-token') 44 | if (savedToken) { 45 | token.value = savedToken 46 | setUser(savedToken) 47 | } 48 | } 49 | } 50 | 51 | return { 52 | user, 53 | token, 54 | setUser, 55 | setToken, 56 | logout, 57 | initAuth, 58 | getUser 59 | } 60 | } -------------------------------------------------------------------------------- /composables/useTheme.js: -------------------------------------------------------------------------------- 1 | export const useTheme = () => { 2 | // 使用useState确保状态在客户端和服务端之间同步 3 | const theme = useState('theme', () => 'light') 4 | // 切换主题的方法 5 | const toggleTheme = () => { 6 | theme.value = theme.value === 'light' ? 'dark' : 'light' 7 | // 更新HTML的data-theme属性 8 | if (process.client) { 9 | document.documentElement.setAttribute('data-theme', theme.value) 10 | // 保存到localStorage 11 | localStorage.setItem('theme', theme.value) 12 | } 13 | } 14 | // 初始化主题 15 | const initTheme = () => { 16 | if (process.client) { 17 | const savedTheme = localStorage.getItem('theme') || 'light' 18 | theme.value = savedTheme 19 | document.documentElement.setAttribute('data-theme', savedTheme) 20 | } 21 | } 22 | return { 23 | theme, 24 | toggleTheme, 25 | initTheme 26 | } 27 | } -------------------------------------------------------------------------------- /composables/useToast.ts: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export function useToast() { 4 | const visible = ref(false) 5 | const message = ref('') 6 | const type = ref('info') 7 | 8 | const showToast = (msg: string, toastType: 'info' | 'success' | 'error' = 'info') => { 9 | message.value = msg 10 | type.value = toastType 11 | visible.value = true 12 | 13 | setTimeout(() => { 14 | visible.value = false 15 | }, 2000) 16 | } 17 | 18 | return { 19 | visible, 20 | message, 21 | type, 22 | showToast 23 | } 24 | } 25 | 26 | export const toast = useToast() -------------------------------------------------------------------------------- /error.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 19 | 20 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 60 | 61 | -------------------------------------------------------------------------------- /middleware/auth.js: -------------------------------------------------------------------------------- 1 | export default defineNuxtRouteMiddleware((to, from) => { 2 | const { getUser } = useAuth() 3 | const token = useState('buling-token') 4 | const user = useState('user', () => null) 5 | 6 | if (!user.value && token.value) { 7 | getUser() 8 | } 9 | 10 | if (!token.value && !['/login', '/'].includes(to.path)) { 11 | return navigateTo('/login') 12 | } 13 | 14 | // 已登录用户访问首页时重定向到上传页面 15 | if (user.value && to.path === '/') { 16 | return navigateTo('/upload') 17 | } 18 | }) -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | // 禁用服务端渲染 3 | ssr: false, 4 | 5 | // 开发模式的端口配置 6 | devServer: { 7 | port: 3000 8 | }, 9 | 10 | // 运行时配置 11 | runtimeConfig: { 12 | public: { 13 | apiBase: '' 14 | } 15 | }, 16 | nitro: { 17 | preset: 'cloudflare_pages', 18 | }, 19 | 20 | // 应用级配置 21 | app: { 22 | head: { 23 | title: '布灵图床', 24 | meta: [ 25 | { charset: 'utf-8' }, 26 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 27 | { name: 'description', content: '布灵图床 - 基于 Cloudflare 全家桶(Workers/Pages/D1/R2)打造的简单好用的个人图片托管解决方案' }, 28 | { name: 'keywords', content: '图床,Cloudflare,Workers,Pages,D1,R2,图片托管,图片上传,免费图床' }, 29 | { name: 'author', content: '优优Anuuu.com' }, 30 | { property: 'og:title', content: '布灵图床 - 简单好用的个人图片托管方案' }, 31 | { property: 'og:description', content: '基于 Cloudflare 全家桶(Workers/Pages/D1/R2)打造的简单好用的个人图片托管解决方案' }, 32 | { property: 'og:type', content: 'website' }, 33 | { name: 'robots', content: 'index,follow' } 34 | ], 35 | } 36 | }, 37 | css: [ 38 | '@/assets/css/main.css' 39 | ], 40 | }) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "buling-imgbed-frontend", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "build": "nuxt build", 7 | "dev": "nuxt dev", 8 | "generate": "nuxt generate", 9 | "preview": "nuxt preview", 10 | "pages:dev": "nuxt generate && wrangler pages dev dist --port 3000", 11 | "pages:deploy": "nuxt generate && wrangler pages deploy dist" 12 | }, 13 | "dependencies": { 14 | "browser-image-compression": "^2.0.2", 15 | "nprogress": "^0.2.0", 16 | "nuxt": "^3.14.159", 17 | "vue": "latest", 18 | "vue-router": "latest" 19 | }, 20 | "devDependencies": { 21 | "wrangler": "^3.86.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /pages/dashboard.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 31 | 32 | -------------------------------------------------------------------------------- /pages/images.vue: -------------------------------------------------------------------------------- 1 | 75 | 76 | 229 | 230 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 58 | 59 | 64 | 65 | -------------------------------------------------------------------------------- /pages/login.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 65 | 66 | -------------------------------------------------------------------------------- /pages/profile.vue: -------------------------------------------------------------------------------- 1 | 122 | 123 | 263 | 264 | -------------------------------------------------------------------------------- /pages/upload.vue: -------------------------------------------------------------------------------- 1 | 89 | 90 | 414 | 415 | -------------------------------------------------------------------------------- /plugins/nprogress.client.js: -------------------------------------------------------------------------------- 1 | import NProgress from 'nprogress' 2 | import 'nprogress/nprogress.css' 3 | 4 | export default defineNuxtPlugin(() => { 5 | const router = useRouter() 6 | 7 | router.beforeEach(() => { 8 | NProgress.start() 9 | }) 10 | 11 | router.afterEach(() => { 12 | NProgress.done() 13 | }) 14 | }) -------------------------------------------------------------------------------- /plugins/theme.client.js: -------------------------------------------------------------------------------- 1 | export default defineNuxtPlugin(() => { 2 | const { initTheme } = useTheme() 3 | const { initAuth } = useAuth() 4 | 5 | // 初始化主题和认证状态 6 | initTheme() 7 | initAuth() 8 | }) -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzs8/buling-imgbed-frontend/9b9c8d555132287c6f6dc19671e7d531775ac68c/public/favicon.ico -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzs8/buling-imgbed-frontend/9b9c8d555132287c6f6dc19671e7d531775ac68c/public/logo.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /services/api.js: -------------------------------------------------------------------------------- 1 | import { toast } from '~/composables/useToast' 2 | 3 | const useApi = () => { 4 | const config = useRuntimeConfig() 5 | const { token, logout } = useAuth() 6 | const router = useRouter() 7 | 8 | const baseHeaders = { 9 | 'Content-Type': 'application/json', 10 | } 11 | 12 | const getAuthHeaders = () => ({ 13 | ...baseHeaders, 14 | 'Authorization': `Bearer ${token.value}` 15 | }) 16 | 17 | // 添加统一的响应处理函数 18 | const handleResponse = async (response) => { 19 | if (response.status === 401) { 20 | logout() 21 | toast.showToast('登录已过期,请重新登录', 'error') 22 | setTimeout(() => { 23 | router.push('/login') 24 | }, 2000) 25 | return null 26 | } 27 | return response.json() 28 | } 29 | 30 | return { 31 | // 认证相关 32 | async login(credentials) { 33 | const response = await fetch(`${config.public.apiBase}/auth/login`, { 34 | method: 'POST', 35 | headers: baseHeaders, 36 | body: JSON.stringify(credentials) 37 | }) 38 | return response.json() 39 | }, 40 | 41 | // 列出所有图片 42 | async getImages(body) { 43 | const response = await fetch(`${config.public.apiBase}/image/list`, { 44 | headers: getAuthHeaders(), 45 | method: 'POST', 46 | body: JSON.stringify(body) 47 | }) 48 | return handleResponse(response) 49 | }, 50 | 51 | async deleteImage(files) { 52 | const response = await fetch(`${config.public.apiBase}/image/delete`, { 53 | method: 'DELETE', 54 | headers: getAuthHeaders(), 55 | body: JSON.stringify({ files }) 56 | }) 57 | return handleResponse(response) 58 | }, 59 | 60 | async uploadImage(formData) { 61 | const response = await fetch(`${config.public.apiBase}/image/upload`, { 62 | method: 'POST', 63 | headers: { 64 | 'Authorization': `Bearer ${token.value}` 65 | }, 66 | body: formData 67 | }) 68 | return handleResponse(response) 69 | }, 70 | 71 | // 个人资料相关 72 | async getProfile() { 73 | const response = await fetch(`${config.public.apiBase}/user/profile`, { 74 | headers: getAuthHeaders() 75 | }) 76 | return handleResponse(response) 77 | }, 78 | 79 | async updateProfile(profileData) { 80 | const response = await fetch(`${config.public.apiBase}/user/update`, { 81 | method: 'PUT', 82 | headers: getAuthHeaders(), 83 | body: JSON.stringify(profileData) 84 | }) 85 | return handleResponse(response) 86 | } 87 | } 88 | } 89 | 90 | export default useApi -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "buling-imgbed-frontend" 2 | compatibility_date = "2024-06-06" 3 | pages_build_output_dir = "dist" 4 | 5 | [vars] 6 | NUXT_PUBLIC_API_BASE = "你的API地址" 7 | 8 | --------------------------------------------------------------------------------