侧边栏壁纸
博主头像
云BLOG 博主等级

行动起来,活在当下

  • 累计撰写 318 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

VUE3构建基本命令

Administrator
2025-12-20 / 0 评论 / 0 点赞 / 3 阅读 / 0 字

前端搭建 (Vue 3 + Vite + UnoCSS + Element Plus)

这是重头戏,我们将使用 2025 年主流的“自动引入”配置。

1. 初始化 Vue 3 项目

打开一个新的终端窗口(保持后端运行):

npm create vite@latest vue3-admin-web
# 选项选择:
# Framework: Vue
# Variant: JavaScript (或 TypeScript,这里为了通用性选 JS)

gemini 3 pro 给出的

cd vue3-admin-web
npm install

npm create vite@latest admin

VUE JS NO 

npm install vue vue-router pinia element-plus @element-plus/icons-vue

npm install unocss -D

npm install axios

npm install unplugin-auto-import unplugin-vue-components -D

2. 安装核心插件

一次性安装所有需要的依赖:

# UI库 和 图标
npm install element-plus @element-plus/icons-vue

# CSS 引擎 (替代 WindiCSS)
npm install unocss -D

# 路由 和 状态管理
npm install vue-router pinia

# 网络请求
npm install axios

# 自动导入插件 (极力推荐,2025年标配,省去大量 import 语句)
npm install unplugin-auto-import unplugin-vue-components -D

3. 配置 Vite (vite.config.js)

这是现代前端工程化的核心。我们将配置 Element Plus 的按需自动引入和 UnoCSS。

修改 vite.config.js:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import UnoCSS from 'unocss/vite'
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(),
    // UnoCSS 插件
    UnoCSS(),
    // 自动导入 Vue API (ref, reactive 等) 和 Element Plus
    AutoImport({
      imports: ['vue', 'vue-router'],
      resolvers: [ElementPlusResolver()],
    }),
    // 自动注册组件
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
  server: {
    port: 3000, // 前端端口
  }
})

4. 配置 UnoCSS (uno.config.js)

在根目录新建 uno.config.js。这比 WindiCSS 更灵活。

import { defineConfig, presetUno, presetAttributify } from 'unocss'

export default defineConfig({
  presets: [
    presetUno(), // 默认预设 (兼容 Tailwind/Windi)
    presetAttributify(), // 属性化模式 (例如 <div text="red">)
  ],
  rules: [
    // 自定义规则示例
    ['bg-login', { 'background-image': 'linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%)' }]
  ]
})

5. 初始化入口文件 (src/main.js)

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

// 引入 UnoCSS
import 'virtual:uno.css' 
// 引入 Element Plus 样式 (虽然组件自动引入,但基础样式建议全局引入以免丢失)
import 'element-plus/dist/index.css'

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.mount('#app')

第四阶段:编写业务代码

1. 配置路由 (src/router/index.js)

新建此文件:

import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('../views/Login.vue')
  },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: () => import('../views/Dashboard.vue') // 暂时留空
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

2. 封装 Axios (src/utils/request.js)

新建 src/utils/request.js:

import axios from 'axios'
import { ElMessage } from 'element-plus'

const service = axios.create({
  baseURL: 'http://127.0.0.1:8000', // 指向 ThinkPHP 端口
  timeout: 5000
})

// 响应拦截器
service.interceptors.response.use(
  response => {
    const res = response.data
    if (res.code !== 200) {
      ElMessage.error(res.msg || 'Error')
      return Promise.reject(new Error(res.msg || 'Error'))
    } else {
      return res
    }
  },
  error => {
    ElMessage.error(error.message)
    return Promise.reject(error)
  }
)

export default service

3. 编写漂亮的登录页面 (src/views/Login.vue)

新建 src/views/Login.vue。我们将利用 UnoCSS 的强大样式能力和 Element Plus 的组件。

注意:由于配置了 unplugin-auto-import,代码中不需要 import { ref } from 'vue'import { User, Lock } from ...,直接用即可,VS Code 可能会提示未定义,但编译是可以通过的(或者安装 Vue Official 插件并配置 eslint)。

<template>
  <!-- 使用 UnoCSS 类名:全屏、Flex居中、自定义背景 -->
  <div class="w-screen h-screen flex justify-center items-center bg-login">
    
    <!-- 登录卡片 -->
    <div class="w-96 bg-white rounded-xl shadow-2xl p-8 animate-fade-in-up">
      <div class="text-center mb-8">
        <h1 class="text-2xl font-bold text-gray-700">管理系统登录</h1>
        <p class="text-gray-400 text-sm mt-2">Vue3 + TP8 + UnoCSS</p>
      </div>

      <el-form :model="loginForm" :rules="rules" ref="loginFormRef" size="large">
        
        <el-form-item prop="username">
          <el-input 
            v-model="loginForm.username" 
            placeholder="请输入用户名: admin"
            :prefix-icon="User"
          />
        </el-form-item>

        <el-form-item prop="password">
          <el-input 
            v-model="loginForm.password" 
            type="password" 
            placeholder="请输入密码: 123456"
            show-password
            :prefix-icon="Lock"
            @keyup.enter="handleLogin"
          />
        </el-form-item>

        <el-form-item>
          <!-- w-full 是 UnoCSS 类,让按钮宽度100% -->
          <el-button 
            type="primary" 
            :loading="loading" 
            class="w-full font-bold" 
            @click="handleLogin"
          >
            登 录
          </el-button>
        </el-form-item>
        
      </el-form>
      
      <div class="text-center text-xs text-gray-300 mt-4">
        &copy; 2025 Future Admin System
      </div>
    </div>
  </div>
</template>

<script setup>
// 自动导入生效,无需手动 import ref, reactive 等
// 只有 Icons 需要手动引入或通过自动导入解析器配置,这里为了演示简单,手动引入图标
import { User, Lock } from '@element-plus/icons-vue'
import request from '../utils/request'
import { useRouter } from 'vue-router'

const router = useRouter()
const loginFormRef = ref(null)
const loading = ref(false)

const loginForm = reactive({
  username: '',
  password: ''
})

const rules = {
  username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
  password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
}

const handleLogin = async () => {
  if (!loginFormRef.value) return
  
  await loginFormRef.value.validate(async (valid) => {
    if (valid) {
      loading.value = true
      try {
        // 调用 ThinkPHP 接口
        const res = await request.post('/login/index', loginForm)
        
        ElMessage.success('登录成功') // ElMessage 也是自动导入的
        
        // 存储 Token (实际开发建议用 Pinia)
        localStorage.setItem('token', res.data.token)
        
        // 跳转
        // router.push('/dashboard') 
        console.log('跳转到 Dashboard', res)
        
      } catch (error) {
        console.error(error)
      } finally {
        loading.value = false
      }
    }
  })
}
</script>

<style scoped>
/* 自定义动画示例 */
.animate-fade-in-up {
  animation: fadeInUp 0.5s ease-out;
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
</style>

4. 清理 App.vue

修改 src/App.vue,只保留路由出口:

<template>
  <router-view></router-view>
</template>

<style>
/* 重置默认的 margin */
body {
  margin: 0;
  padding: 0;
}
</style>

第五阶段:运行与测试

  1. 启动后端
    确保 ThinkPHP 在运行:

    cd tp8-admin-api
    php think run
    
  2. 启动前端
    确保 Vue 在运行:

    cd vue3-admin-web
    npm run dev
    
  3. 浏览器测试

    • 打开前端地址(通常是 http://localhost:3000)。

    • 你应该能看到一个带有渐变背景的现代化登录卡片。

    • 测试失败情况:输入随意账号密码,右上角应弹出 Element Plus 的错误提示(红色)。

    • 测试成功情况:输入 admin / 123456

    • 查看浏览器的 Network (F12),你会看到一个发往 http://127.0.0.1:8000/login/index 的请求,并且返回 200 OK

    • 页面提示“登录成功”。

总结 (2025 视角)

这个搭建方案的特点:

  1. Vite + UnoCSS: 极速的开发体验,原子化 CSS 是构建通用后台的最高效方式。

  2. Auto Import: 彻底告别了并在文件头部写一大堆 import 的时代,代码极简。

  3. ThinkPHP 8: 依然是 PHP 生态中最适合快速开发 API 的框架之一,PHP 8.2+ 的性能也非常强劲。

  4. Pinia: 状态管理的标准答案。

这套架构非常适合作为通用后台管理系统(CMS/CRM/ERP)的基石。

基于当前最稳定且在未来一两年内依然是主流的技术栈进行构建。

重要说明:关于 WindiCSS
在开始之前,有一个重要的技术选型调整。WindiCSS 官方团队已于2023年停止维护,并建议用户迁移到 UnoCSS。到2025年,WindiCSS 将完全过时。因此,本教程将使用 UnoCSS,它是 Vue 核心团队成员 Antfu 开发的,被认为是 WindiCSS 的精神继承者,更快、更轻量,且完美适配 Vite。

以下是基于 Windows 系统,从零开始搭建 Vue 3 + ThinkPHP 8 前后端分离通用后台登录页的详细步骤。


第一阶段:环境准备 (Windows)

在 2025 年,你需要以下基础环境(请确保已安装):

  1. Node.js: 建议版本 v20.x 或 v22.x (LTS)。

  2. PHP: 建议版本 8.2 或 8.3 (ThinkPHP 8 需要 PHP >= 8.0)。

  3. Composer: PHP 包管理器。

  4. MySQL: 数据库 (建议 8.0)。

  5. VS Code: 编辑器。

  6. Git BashPowerShell: 用于运行命令。


第二阶段:后端搭建 (ThinkPHP 8)

我们将创建一个只负责提供 API 的后端。

1. 安装 ThinkPHP 8

在你的工作目录下(例如 D:\Projects),打开终端:

composer create-project topthink/think tp8-admin-api
cd tp8-admin-api

2. 处理跨域 (CORS)

前后端分离必须解决跨域问题。ThinkPHP 8 内置了中间件,但默认没开启。

  • 步骤:找到 app/middleware.php,去掉注释或添加:

<?php
// 全局中间件定义文件
return [
    // ... 其他中间件
    // 跨域请求支持
    \think\middleware\AllowCrossDomain::class,
];

3. 创建简单的登录接口

为了演示,我们创建一个简单的控制器返回 Token。

  • 文件: app/controller/Login.php

<?php
namespace app\controller;

use think\facade\Request;
use think\Response;

class Login
{
    public function index()
    {
        // 获取 POST 数据
        $params = Request::post();
        $username = $params['username'] ?? '';
        $password = $params['password'] ?? '';

        // 模拟验证 (实际项目中请查询数据库并验证 Hash 密码)
        if ($username === 'admin' && $password === '123456') {
            return json([
                'code' => 200,
                'msg'  => '登录成功',
                'data' => [
                    'token' => 'eyJh...mock_token_2025...' // 模拟 Token
                ]
            ]);
        }

        return json(['code' => 400, 'msg' => '用户名或密码错误']);
    }
}

4. 启动后端

在终端运行:

php think run

后端将在 http://127.0.0.1:8000 运行。


第三阶段:前端搭建 (Vue 3 + Vite + UnoCSS + Element Plus)

这是重头戏,我们将使用 2025 年主流的“自动引入”配置。

1. 初始化 Vue 3 项目

打开一个新的终端窗口(保持后端运行):

npm create vite@latest vue3-admin-web
# 选项选择:
# Framework: Vue
# Variant: JavaScript (或 TypeScript,这里为了通用性选 JS)

cd vue3-admin-web
npm install

2. 安装核心插件

一次性安装所有需要的依赖:

# UI库 和 图标
npm install element-plus @element-plus/icons-vue

# CSS 引擎 (替代 WindiCSS)
npm install unocss -D

# 路由 和 状态管理
npm install vue-router pinia

# 网络请求
npm install axios

# 自动导入插件 (极力推荐,2025年标配,省去大量 import 语句)
npm install unplugin-auto-import unplugin-vue-components -D

3. 配置 Vite (vite.config.js)

这是现代前端工程化的核心。我们将配置 Element Plus 的按需自动引入和 UnoCSS。

修改 vite.config.js:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import UnoCSS from 'unocss/vite'
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(),
    // UnoCSS 插件
    UnoCSS(),
    // 自动导入 Vue API (ref, reactive 等) 和 Element Plus
    AutoImport({
      imports: ['vue', 'vue-router'],
      resolvers: [ElementPlusResolver()],
    }),
    // 自动注册组件
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
  server: {
    port: 3000, // 前端端口
  }
})

4. 配置 UnoCSS (uno.config.js)

在根目录新建 uno.config.js。这比 WindiCSS 更灵活。

import { defineConfig, presetUno, presetAttributify } from 'unocss'

export default defineConfig({
  presets: [
    presetUno(), // 默认预设 (兼容 Tailwind/Windi)
    presetAttributify(), // 属性化模式 (例如 <div text="red">)
  ],
  rules: [
    // 自定义规则示例
    ['bg-login', { 'background-image': 'linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%)' }]
  ]
})

5. 初始化入口文件 (src/main.js)

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'

// 引入 UnoCSS
import 'virtual:uno.css' 
// 引入 Element Plus 样式 (虽然组件自动引入,但基础样式建议全局引入以免丢失)
import 'element-plus/dist/index.css'

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.mount('#app')

第四阶段:编写业务代码

1. 配置路由 (src/router/index.js)

新建此文件:

import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('../views/Login.vue')
  },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: () => import('../views/Dashboard.vue') // 暂时留空
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

2. 封装 Axios (src/utils/request.js)

新建 src/utils/request.js:

import axios from 'axios'
import { ElMessage } from 'element-plus'

const service = axios.create({
  baseURL: 'http://127.0.0.1:8000', // 指向 ThinkPHP 端口
  timeout: 5000
})

// 响应拦截器
service.interceptors.response.use(
  response => {
    const res = response.data
    if (res.code !== 200) {
      ElMessage.error(res.msg || 'Error')
      return Promise.reject(new Error(res.msg || 'Error'))
    } else {
      return res
    }
  },
  error => {
    ElMessage.error(error.message)
    return Promise.reject(error)
  }
)

export default service

3. 编写漂亮的登录页面 (src/views/Login.vue)

新建 src/views/Login.vue。我们将利用 UnoCSS 的强大样式能力和 Element Plus 的组件。

注意:由于配置了 unplugin-auto-import,代码中不需要 import { ref } from 'vue'import { User, Lock } from ...,直接用即可,VS Code 可能会提示未定义,但编译是可以通过的(或者安装 Vue Official 插件并配置 eslint)。

<template>
  <!-- 使用 UnoCSS 类名:全屏、Flex居中、自定义背景 -->
  <div class="w-screen h-screen flex justify-center items-center bg-login">
    
    <!-- 登录卡片 -->
    <div class="w-96 bg-white rounded-xl shadow-2xl p-8 animate-fade-in-up">
      <div class="text-center mb-8">
        <h1 class="text-2xl font-bold text-gray-700">管理系统登录</h1>
        <p class="text-gray-400 text-sm mt-2">Vue3 + TP8 + UnoCSS</p>
      </div>

      <el-form :model="loginForm" :rules="rules" ref="loginFormRef" size="large">
        
        <el-form-item prop="username">
          <el-input 
            v-model="loginForm.username" 
            placeholder="请输入用户名: admin"
            :prefix-icon="User"
          />
        </el-form-item>

        <el-form-item prop="password">
          <el-input 
            v-model="loginForm.password" 
            type="password" 
            placeholder="请输入密码: 123456"
            show-password
            :prefix-icon="Lock"
            @keyup.enter="handleLogin"
          />
        </el-form-item>

        <el-form-item>
          <!-- w-full 是 UnoCSS 类,让按钮宽度100% -->
          <el-button 
            type="primary" 
            :loading="loading" 
            class="w-full font-bold" 
            @click="handleLogin"
          >
            登 录
          </el-button>
        </el-form-item>
        
      </el-form>
      
      <div class="text-center text-xs text-gray-300 mt-4">
        &copy; 2025 Future Admin System
      </div>
    </div>
  </div>
</template>

<script setup>
// 自动导入生效,无需手动 import ref, reactive 等
// 只有 Icons 需要手动引入或通过自动导入解析器配置,这里为了演示简单,手动引入图标
import { User, Lock } from '@element-plus/icons-vue'
import request from '../utils/request'
import { useRouter } from 'vue-router'

const router = useRouter()
const loginFormRef = ref(null)
const loading = ref(false)

const loginForm = reactive({
  username: '',
  password: ''
})

const rules = {
  username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
  password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
}

const handleLogin = async () => {
  if (!loginFormRef.value) return
  
  await loginFormRef.value.validate(async (valid) => {
    if (valid) {
      loading.value = true
      try {
        // 调用 ThinkPHP 接口
        const res = await request.post('/login/index', loginForm)
        
        ElMessage.success('登录成功') // ElMessage 也是自动导入的
        
        // 存储 Token (实际开发建议用 Pinia)
        localStorage.setItem('token', res.data.token)
        
        // 跳转
        // router.push('/dashboard') 
        console.log('跳转到 Dashboard', res)
        
      } catch (error) {
        console.error(error)
      } finally {
        loading.value = false
      }
    }
  })
}
</script>

<style scoped>
/* 自定义动画示例 */
.animate-fade-in-up {
  animation: fadeInUp 0.5s ease-out;
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
</style>

4. 清理 App.vue

修改 src/App.vue,只保留路由出口:

<template>
  <router-view></router-view>
</template>

<style>
/* 重置默认的 margin */
body {
  margin: 0;
  padding: 0;
}
</style>

第五阶段:运行与测试

  1. 启动后端
    确保 ThinkPHP 在运行:

    cd tp8-admin-api
    php think run
    
  2. 启动前端
    确保 Vue 在运行:

    cd vue3-admin-web
    npm run dev
    
  3. 浏览器测试

    • 打开前端地址(通常是 http://localhost:3000)。

    • 你应该能看到一个带有渐变背景的现代化登录卡片。

    • 测试失败情况:输入随意账号密码,右上角应弹出 Element Plus 的错误提示(红色)。

    • 测试成功情况:输入 admin / 123456

    • 查看浏览器的 Network (F12),你会看到一个发往 http://127.0.0.1:8000/login/index 的请求,并且返回 200 OK

    • 页面提示“登录成功”。

总结 (2025 视角)

这个搭建方案的特点:

  1. Vite + UnoCSS: 极速的开发体验,原子化 CSS 是构建通用后台的最高效方式。

  2. Auto Import: 彻底告别了并在文件头部写一大堆 import 的时代,代码极简。

  3. ThinkPHP 8: 依然是 PHP 生态中最适合快速开发 API 的框架之一,PHP 8.2+ 的性能也非常强劲。

  4. Pinia: 状态管理的标准答案。

这套架构非常适合作为通用后台管理系统(CMS/CRM/ERP)的基石。

0

评论区