一、环境准备
1.1 技术选型
|
项目/模块 |
技术栈 |
核心库/框架 |
用途/说明 |
|
管理后台 (Web) |
Vue 3 |
(3.3+), , |
构建响应式后台的单页应用(SPA) |
|
UI框架 |
|
提供丰富、成熟的桌面端UI组件 |
|
|
构建工具 |
|
极速的现代化构建与开发体验 |
|
|
HTTP客户端 |
|
处理所有API网络请求 |
|
|
微信小程序 |
小程序框架 |
+ |
使用Vue语法一套代码多端发布(微信小程序为主) |
|
UI库 |
(或 ) |
提供小程序风格的UI组件,加快开发 |
|
|
构建工具 |
|
uni-app的Vite编译插件 |
|
|
通用/工具 |
语言 |
|
提供类型安全,提升代码质量与维护性 |
|
CSS预处理 |
/ |
编写更强大、可维护的样式 |
|
|
包管理器 |
或 |
管理项目依赖(当前项目用npm即可) |
|
|
代码规范 |
+ |
统一代码风格,自动格式化 |
1.2 环境准备
|
步骤 |
所需工具 |
状态 |
|
1. 安装Node.js (18+) |
nodejs.org |
□ |
|
2. 安装VSCode |
code.visualstudio.com |
□ |
二、创建管理后端
2.1 初始化Vue项目
# 1. 使用Vite官方模板创建项目(速度最快)
npm create vue@latest . -- --typescript --router --pinia
# 按提示选择配置:
# - TypeScript: Yes
# - JSX: No
# - Router: Yes (已选)
# - Pinia: Yes (已选)
# - ESLint: Yes
# - Prettier: Yes
# 2. 安装Element Plus和图标库
npm install element-plus @element-plus/icons-vue
npm install axios
npm install sass
# 3. 安装开发依赖
npm install -D unplugin-auto-import unplugin-vue-components
2.2 配置Vite (
vite.config.ts)
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
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({
resolvers: [ElementPlusResolver()],
imports: ['vue', 'vue-router', 'pinia'],
dts: 'src/auto-imports.d.ts'
}),
Components({
resolvers: [ElementPlusResolver()],
dts: 'src/components.d.ts'
})
],
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080', // 你的后端地址
changeOrigin: true,
rewrite: (path) => path.replace(/^/api/, '')
}
}
}
})
2.3 配置环境变量
# 创建环境变量文件
echo "VITE_API_BASE_URL=/api" > .env.development
echo "VITE_API_BASE_URL=https://your-domain.com/api" > .env.production
2.4 创建关键文件结构
这是linux命令,手动创建也可以
# 创建API目录和文件
mkdir -p src/api/modules
touch src/api/index.ts
touch src/api/modules/course.ts
touch src/api/modules/user.ts
# 创建工具目录
mkdir -p src/utils
touch src/utils/request.ts
touch src/utils/auth.ts
# 创建页面目录
mkdir -p src/views/course
mkdir -p src/views/user
mkdir -p src/views/dashboard
# 创建布局目录
mkdir -p src/layout
2.5 创建核心工具文件
– Axios封装
src/utils/request.ts
import axios, { AxiosRequestConfig } from 'axios'
import { ElMessage } from 'element-plus'
import router from '@/router'
const service = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000
})
service.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error) => Promise.reject(error)
)
service.interceptors.response.use(
(response) => {
const res = response.data
if (res.code !== 200) {
ElMessage.error(res.message || '请求失败')
if (res.code === 401) {
router.push('/login')
}
return Promise.reject(new Error(res.message || 'Error'))
}
return res.data
},
(error) => {
ElMessage.error(error.message || '请求失败')
return Promise.reject(error)
}
)
export default service
– 课程API
src/api/modules/course.ts
import request from '@/utils/request'
import type { Course, CourseListParams } from '@/types/course'
export function listCourses(params: CourseListParams) {
return request({
url: '/courses',
method: 'get',
params
})
}
export function addCourse(data: Partial<Course>) {
return request({
url: '/courses',
method: 'post',
data
})
}
export function updateCourse(data: Course) {
return request({
url: `/courses/${data.id}`,
method: 'put',
data
})
}
export function deleteCourse(id: number) {
return request({
url: `/courses/${id}`,
method: 'delete'
})
}
2.6 创建课程管理页面
– 课程列表页
src/views/course/CourseList.vue
<template>
<div class="course-container">
<!-- 搜索栏 -->
<el-card class="search-card">
<el-form :inline="true" :model="searchForm">
<el-form-item label="课程名称">
<el-input v-model="searchForm.title" placeholder="请输入课程名称" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="resetSearch">重置</el-button>
<el-button type="success" @click="handleAdd">新增课程</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 表格 -->
<el-table :data="tableData" v-loading="loading">
<el-table-column prop="title" label="课程标题" />
<el-table-column prop="price" label="价格">
<template #default="{row}">¥{{row.price}}</template>
</el-table-column>
<el-table-column label="操作">
<template #default="{row}">
<el-button size="small" @click="handleEdit(row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { listCourses } from '@/api/modules/course'
const loading = ref(false)
const tableData = ref<any[]>([])
const searchForm = reactive({
title: ''
})
const loadData = async () => {
loading.value = true
try {
const data = await listCourses(searchForm)
tableData.value = data
} finally {
loading.value = false
}
}
const handleSearch = () => loadData()
const resetSearch = () => {
searchForm.title = ''
loadData()
}
const handleAdd = () => console.log('新增')
const handleEdit = (row: any) => console.log('编辑', row)
const handleDelete = (row: any) => console.log('删除', row)
onMounted(() => loadData())
</script>
<style scoped>
.course-container {
padding: 20px;
}
.search-card {
margin-bottom: 20px;
}
</style>
2.7 配置路由
– 添加课程路由
src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import CourseList from '@/views/course/CourseList.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
redirect: '/course'
},
{
path: '/course',
name: 'Course',
component: CourseList
}
]
})
export default router
2.8 启动项目
# 安装所有依赖
npm install
# 启动开发服务器
npm run dev
# 浏览器访问:http://localhost:3000
三、创建小程序端(uni-app项目)
3.1 返回项目根目录并创建小程序
# 返回项目根目录
cd ..
#从官方仓库拉取 Vite 模板,创建名为 miniapp文件夹
npx degit dcloudio/uni-preset-vue#vite miniapp
# 安装uView UI
npm install uview-ui
# 安装sass
npm install sass sass-loader@10
3.2 配置小程序项目
– uni-app配置
vite.config.js
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
export default defineConfig({
plugins: [uni()],
server: {
port: 8080,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^/api/, '')
}
}
}
})
3.3 创建小程序工具文件
utils/request.js
const request = (options) => {
return new Promise((resolve, reject) => {
uni.request({
url: 'http://localhost:8080' + options.url,
method: options.method || 'GET',
data: options.data || {},
header: {
'Content-Type': 'application/json',
'Authorization': uni.getStorageSync('token') || ''
},
success: (res) => {
if (res.data.code === 200) {
resolve(res.data.data)
} else {
uni.showToast({ title: res.data.message, icon: 'none' })
reject(res.data)
}
},
fail: (error) => {
uni.showToast({ title: '网络错误', icon: 'none' })
reject(error)
}
})
})
}
export default request
3.4 创建小程序首页
pages/index/index.vue
<template>
<view class="container">
<u-navbar title="教育平台" :border="true"></u-navbar>
<view class="course-list">
<view v-for="item in courses" :key="item.id" class="course-card">
<image :src="item.coverImage" mode="aspectFill" class="course-cover"></image>
<view class="course-info">
<text class="course-title">{{ item.title }}</text>
<text class="course-price">¥{{ item.price }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import request from '@/utils/request'
const courses = ref([])
const loadCourses = async () => {
try {
const data = await request({ url: '/courses', method: 'GET' })
courses.value = data
} catch (error) {
console.error('加载课程失败', error)
}
}
onMounted(() => loadCourses())
</script>
<style scoped>
.container {
padding: 20rpx;
}
.course-list {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.course-card {
background: white;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
}
.course-cover {
width: 100%;
height: 300rpx;
}
.course-info {
padding: 20rpx;
}
.course-title {
font-size: 32rpx;
font-weight: bold;
display: block;
margin-bottom: 10rpx;
}
.course-price {
color: #e4393c;
font-size: 36rpx;
font-weight: bold;
}
</style>
3.5 运行小程序
# 安装依赖
npm install
# 启动开发服务(微信小程序)
npm run dev:mp-weixin
# 用微信开发者工具打开 dist/dev/mp-weixin 目录
3.6、微信开发者工具
第一步:启动微信开发者工具
打开电脑上的微信开发者工具(如果还未下载,请前往微信官方下载)。启动后,使用微信扫码登录。
第二步:导入项目并填写配置
这是最核心的一步,请确保你选择了正确的文件夹。
在工具主界面,点击 “导入项目”。在弹出的窗口中,按如下要求填写:
目录:点击“目录”后的文件夹图标,找到并选择你的 项目根目录下的
miniapp 文件夹。重点:是选择这个生成的文件夹本身,而不是它的上层目录。AppID:如果你有自己的小程序AppID,请填写。如果没有,务必选择“测试号” 进行体验和调试。项目名称:可以自定义,例如“教育平台小程序”。后端服务:请选择 “不使用云服务”。
dist/dev/mp-weixin
填写完毕后,点击 “导入”。
第三步:检查与运行
导入成功后,工具会自动编译并在左侧的模拟器中预览你的小程序。右侧的目录树会显示 文件夹下的所有小程序文件。
dist/dev/mp-weixin