feat: initialize Vue 3 frontend project

This commit is contained in:
Claude
2026-03-24 15:20:05 +08:00
parent b281a85cb2
commit 1990571333
9 changed files with 162 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Image Creator</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+27
View File
@@ -0,0 +1,27 @@
{
"name": "imagecreator-frontend",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.4.0",
"vue-router": "^4.2.0",
"pinia": "^2.1.0",
"axios": "^1.6.0",
"naive-ui": "^2.38.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.0",
"typescript": "^5.3.0",
"vite": "^5.0.0",
"vue-tsc": "^1.8.0",
"tailwindcss": "^3.4.0",
"autoprefixer": "^10.4.0",
"postcss": "^8.4.0"
}
}
+14
View File
@@ -0,0 +1,14 @@
<!-- src/App.vue -->
<template>
<n-config-provider :theme-overlord="themeOverrides">
<n-message-provider>
<router-view />
</n-message-provider>
</n-config-provider>
</template>
<script setup lang="ts">
import { NConfigProvider, NMessageProvider } from 'naive-ui'
const themeOverrides = {}
</script>
+28
View File
@@ -0,0 +1,28 @@
// src/api/index.ts
import axios from 'axios'
const api = axios.create({
baseURL: '/api',
timeout: 30000,
})
api.interceptors.request.use((config) => {
const token = localStorage.getItem('access_token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
api.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response?.status === 401) {
localStorage.removeItem('access_token')
window.location.href = '/login'
}
return Promise.reject(error)
}
)
export default api
+13
View File
@@ -0,0 +1,13 @@
// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import naive from 'naive-ui'
import App from './App.vue'
import router from './router'
import './style.css'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(naive)
app.mount('#app')
+27
View File
@@ -0,0 +1,27 @@
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{ path: '/login', name: 'Login', component: () => import('../views/Login.vue') },
{ path: '/register', name: 'Register', component: () => import('../views/Register.vue') },
{ path: '/', name: 'Home', component: () => import('../views/Home.vue'), meta: { requiresAuth: true } },
{ path: '/history', name: 'History', component: () => import('../views/History.vue'), meta: { requiresAuth: true } },
]
const router = createRouter({
history: createWebHistory(),
routes,
})
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('access_token')
if (to.meta.requiresAuth && !token) {
next('/login')
} else if ((to.path === '/login' || to.path === '/register') && token) {
next('/')
} else {
next()
}
})
export default router
+10
View File
@@ -0,0 +1,10 @@
/* src/style.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
+11
View File
@@ -0,0 +1,11 @@
// tailwind.config.js
export default {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
+20
View File
@@ -0,0 +1,20 @@
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true
},
'/uploads': {
target: 'http://localhost:8000',
changeOrigin: true
}
}
}
})