(二)前端基础框架构建

内容分享4周前发布
1 0 0

一、环境准备

1.1 技术选型

项目/模块

技术栈

核心库/框架

用途/说明

管理后台 (Web)

Vue 3


vue

(3.3+),
vue-router

,
pinia

构建响应式后台的单页应用(SPA)

UI框架


element-plus

提供丰富、成熟的桌面端UI组件

构建工具


vite

极速的现代化构建与开发体验

HTTP客户端


axios

处理所有API网络请求

微信小程序

小程序框架


uni-app

+
vue 3

使用Vue语法一套代码多端发布(微信小程序为主)

UI库


uview-ui

(或
uni-ui

)

提供小程序风格的UI组件,加快开发

构建工具


@dcloudio/vite-plugin-uni

uni-app的Vite编译插件

通用/工具

语言


TypeScript

提供类型安全,提升代码质量与维护性

CSS预处理


Sass

/
Scss

编写更强大、可维护的样式

包管理器


npm


yarn

管理项目依赖(当前项目用npm即可)

代码规范


ESLint

+
Prettier

统一代码风格,自动格式化

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
)



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 创建核心工具文件


src/utils/request.ts
– Axios封装



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


src/api/modules/course.ts
– 课程API



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 配置小程序项目


vite.config.js
– uni-app配置



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
项目根目录下的
dist/dev/mp-weixin
文件夹重点:是选择这个生成的文件夹本身,而不是它的上层目录。AppID:如果你有自己的小程序AppID,请填写。如果没有,务必选择“测试号” 进行体验和调试。项目名称:可以自定义,例如“教育平台小程序”。后端服务:请选择 “不使用云服务”
填写完毕后,点击 “导入”

第三步:检查与运行

导入成功后,工具会自动编译并在左侧的模拟器中预览你的小程序。右侧的目录树会显示
dist/dev/mp-weixin
文件夹下的所有小程序文件。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...