【Vue | vue3 | spring boot】前端前台项目搭建

vue项目搭建

    • [🚀 第 1 & 2 步:初始化工程与依赖安装 (终端执行)](#🚀 第 1 & 2 步:初始化工程与依赖安装 (终端执行))
    • [`第 3 步:核心构建配置 (Vite & TS)`](#第 3 步:核心构建配置 (Vite & TS))
      • `vite.config.ts`
      • [` tsconfig.json (打通 @ 别名):`](# tsconfig.json (打通 @ 别名):)
    • [第 4 步:定义全局泛型契约 (Types)](#第 4 步:定义全局泛型契约 (Types))
      • [` src/types/global.d.ts`](# src/types/global.d.ts)
    • [📡 第 5 步:C 端专属的 Axios 请求总线 (Utils)](#📡 第 5 步:C 端专属的 Axios 请求总线 (Utils))
      • [`请创建 src/utils/request.ts:`](#请创建 src/utils/request.ts:)

🚀 第 1 & 2 步:初始化工程与依赖安装 (终端执行)

bash 复制代码
# 1. 创建 C端门户工程
npm create vite@latest blog-portal -- --template vue-ts

# 2. 进入工程目录
cd blog-portal

# 3. 安装默认依赖
npm install

# 4. 安装运行时四大件与图标库
npm install vue-router pinia axios element-plus @element-plus/icons-vue

# 5. 安装工程化自动化构建神仙插件
npm install -D unplugin-vue-components unplugin-auto-import @types/node sass

第 3 步:核心构建配置 (Vite & TS)

bash 复制代码
端口隔离:Admin 前端占用了 5173,为了让你能同时启动前后台两个项目联调,我们必须把 Portal 的端口改成 5174。
代理指向:Admin 代理到 8080,Portal 必须代理到你的 C 端后端(假设是 blog-server 的 8081 或 blog-web 的 8082,这里以 8081 为例)。

vite.config.ts

typescript 复制代码
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      imports:['vue', 'vue-router', 'pinia'],
      resolvers: [ElementPlusResolver()],
      dts: 'src/types/auto-imports.d.ts',
    }),
    Components({
      resolvers:[ElementPlusResolver()],
      dts: 'src/types/components.d.ts',
    }),
  ],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  },
  server: {
    port: 5174, // ✨ 架构师细节:与 Admin 的 5173 错开,允许双开!
    open: true,
    proxy: {
      '/api': {
        // ✨ 架构师细节:指向你的 C 端服务端口 (blog-server 或 blog-web)
        target: 'http://localhost:8081', 
        changeOrigin: true,
        // 注意:如果你的后端 Controller 上写了 @RequestMapping("/api/xxx"),这里就不写 rewrite
        // 如果后端没有 /api 前缀,请把下面这行注释打开:
        // rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

tsconfig.json (打通 @ 别名):

typescript 复制代码
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib":["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,

    /* ✨ 让 TS 认识 @ 符号指向 src */
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },

    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

第 4 步:定义全局泛型契约 (Types)

src/types/global.d.ts

清空或创建 src/types/global.d.ts,这是前后端唯一的数据灵魂纽带。

typescript 复制代码
// src/types/global.d.ts

/**
 * 对应后端 Java 的 ApiResponse<T> 统一返回实体
 */
declare interface ApiResponse<T = any> {
  code: number;
  message: string;
  data: T;
}

/**
 * 分页数据标准格式 (对应后端的 PageResponse)
 */
declare interface PageData<T> {
  total: number;
  records: T[];
}

📡 第 5 步:C 端专属的 Axios 请求总线 (Utils)

C 端的 401 柔性处理 在后台管理中,没登录(401)是绝对的死罪,直接 window.location.href = '/login'

踢飞。

但在博客门户中,用户正看着长篇大论的文章,突然 Token 过期了,你如果把他强行踢到另一个页面,他的阅读进度就全毁了!

因此,C

端的 request.ts 拦截器更加"温柔":只清空 Token,弹个警告,然后抛出异常让组件自己决定要不要弹出一个"登录模态框"。

请创建 src/utils/request.ts:

typescript 复制代码
// src/utils/request.ts
import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig, AxiosResponse } from 'axios'
import { ElMessage } from 'element-plus'

// 1. 创建 Axios 实例
const service: AxiosInstance = axios.create({
  baseURL: '/api', // 走 Vite 代理
  timeout: 10000,
})

// 2. 请求拦截器 (携带 Token)
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const token = localStorage.getItem('token')
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  (error: AxiosError) => Promise.reject(error)
)

// 3. 响应拦截器 (✨ C端专属柔性处理)
service.interceptors.response.use(
  (response: AxiosResponse<ApiResponse>) => {
    const res = response.data

    // 假设后端 200 (或 0) 代表成功,请根据你的后端 ApiResponse 实际情况调整
    if (res.code === 200) {
      // 核心剥离:把核心数据直接交给前端业务组件
      return res.data as any
    } else {
      // 💥 业务异常处理
      ElMessage.error(res.message || '业务异常')

      // ✨ C端特有的 401 处理:只清空状态,不强制刷新页面!
      if (res.code === 401) {
        localStorage.removeItem('token')
        localStorage.removeItem('userInfo')
        // 架构提示:这里可以触发一个全局事件(EventBus),让外层的 Layout 弹出一个漂亮的登录 Dialog
        ElMessage.warning('登录已过期,请重新登录以进行互动')
      }

      return Promise.reject(new Error(res.message || 'Error'))
    }
  },
  (error: AxiosError) => {
    // 拦截 404/500/502 等 HTTP 网络异常
    let msg = '网络未知异常'
    if (error.response) {
      const status = error.response.status
      switch (status) {
        case 404: msg = '请求的接口不存在 (404)'; break;
        case 500: msg = '服务器内部错误 (500)'; break;
        case 502: msg = '网关错误,后端服务暂未启动 (502)'; break;
        default:  msg = `请求失败 (${status})`;
      }
    } else if (error.message.includes('timeout')) {
      msg = '网络请求超时'
    }
    ElMessage.error(msg)
    return Promise.reject(error)
  }
)

export default service
相关推荐
Irene19912 小时前
flush 是 Vue3 中控制副作用函数执行时机的配置选项,用于决定响应式数据变化后,副作用(watch、watchEffect、组件渲染)在何时执行
vue.js
用户90443816324602 小时前
大三面字节被问懵?手撕 WebSocket 与 SSE 底层原理,大厂通关指南
前端·面试
回到原点的码农2 小时前
Spring Boot实时推送技术详解:三个经典案例
spring boot·后端·状态模式
mldlds2 小时前
Spring Boot 集成 Kettle
java·spring boot·后端
蓝黑20202 小时前
Vue SFC Playground
前端·javascript·vue.js
qq_406176142 小时前
React与Vue异同点及优缺点深度解析
前端·vue.js·react.js
广州华水科技2 小时前
GNSS位移监测技术在基础设施安全中的应用与单北斗变形监测系统的优势解析
前端
Moment2 小时前
不懂模块化就别谈前端工程化
前端·javascript·面试
majingming1239 小时前
FUNCTION
java·前端·javascript