DevMentor - 智能面试与学习平台

DevMentor - 智能面试与学习平台

文章说明

文章是为了给这个项目邀请开发者所著,考虑到本项目涉及到的功能较多,而且还蛮有难度的,所以邀请一些同学一起参与开发,共同交流技术;具体项目链接参见文章末尾的 gitee 地址

项目简介

DevMentor 是一个开源的智能编程学习与面试平台,融合 AI 技术,提供全面的技术课程学习和智能面试模拟功能。通过 AI 辅助和角色切换,帮助开发者提升技术实力,快速适应真实面试场景。

🎯 项目目标

  • 打造优质的开源学习平台
  • 提供智能化的学习体验
  • 构建活跃的技术社区
  • 帮助开发者快速成长

✨ 特性

  • 📚 系统化的课程学习

    • 前端、后端、算法等多个方向
    • 循序渐进的课程体系
    • 实战项目驱动学习
  • 🤖 智能面试系统

    • AI 模拟面试官
    • 真实面试场景还原
    • 智能反馈与建议
  • 👥 活跃的技术社区

    • 技术讨论与分享
    • 经验交流与解答
    • 开发者社交网络

🚀 快速开始

环境要求

  • Node.js >= 14
  • Java >= 8
  • MySQL >= 5.7
  • Redis >= 6.0

本地开发

  1. 克隆项目
git clone https://gitee.com/anxwefndu/DevMentor.git
cd DevMentor
  1. 前端启动
cd code/front
npm install
npm run serve
  1. Mock 服务启动
cd code/mock
npm install
npm run start
  1. 后端启动
cd code/end
mvn spring-boot:run

🔨 技术栈

前端

  • Vue 3
  • Vue Router
  • TailwindCSS
  • Axios
  • ECharts
  • Markdown 编辑器

后端

  • Spring Boot
  • MyBatis Plus
  • MySQL
  • Redis
  • JWT
  • Spring Mail

📋 开发进度

已完成

  • ✅ 项目基础架构搭建
  • ✅ 首页布局和基础组件
  • ✅ 课程列表页面
  • ✅ 课程详情页面
  • ✅ 学习路径页面
  • ✅ 社区基础页面
  • ✅ Mock 数据服务

开发中

  • 🚧 用户认证系统
  • 🚧 课程视频系统
  • 🚧 面试模拟系统
  • 🚧 社区互动功能

项目链接

DevMentor - 智能面试与学习平台

演示截图

1.系统首页
在这里插入图片描述

2.课程列表页面
在这里插入图片描述

3.面试题库页面
在这里插入图片描述

4.学习路径页面
在这里插入图片描述

5.技术社区页面
在这里插入图片描述

6.课程详情页面
在这里插入图片描述

7.关于我们页面
在这里插入图片描述

8.帮助中心页面
在这里插入图片描述

部分页面代码

code/front/src/views/Home.vue

<template>
  <Layout>
    <main class="pt-16 bg-gradient-to-b from-gray-50 to-white">
      <section class="hero-section h-[600px] flex items-center bg-gradient-to-r from-primary/5 to-primary/10">
        <div class="max-w-7xl mx-auto px-4 w-full">
          <div class="max-w-2xl">
            <h1 class="text-5xl font-bold text-gray-900 mb-6">打造你的技术能力,<br>开启职业新篇章</h1>
            <p class="text-xl text-gray-600 mb-8">超过 10,000 名学员已经通过我们的平台提升技能,获得理想工作</p>
            <router-link
                to="/paths"
                class="!rounded-button bg-primary text-white px-8 py-3 text-lg hover:bg-primary/90 whitespace-nowrap inline-block"
            >
              立即开始学习
            </router-link>
          </div>
        </div>
      </section>

      <section class="py-16 bg-white">
        <div class="max-w-7xl mx-auto px-4">
          <h2 class="text-3xl font-bold text-center mb-12">热门课程推荐</h2>
          <div class="grid grid-cols-4 gap-8">
            <template v-for="course in courses" :key="course.id">
              <div class="category-card bg-white rounded-lg shadow-sm overflow-hidden group">
                <div class="image-wrapper overflow-hidden">
                  <img :src="course.imageUrl"
                       class="w-full h-[200px] object-cover transition-transform duration-500 group-hover:scale-110">
                </div>
                <div class="p-6">
                  <h3 class="text-xl font-bold mb-2">{{ course.title }}</h3>
                  <p class="text-gray-600 mb-4 line-clamp-2">{{ course.description }}</p>
                  <div class="flex items-center justify-between">
                    <span class="text-sm text-gray-500">{{ course.studentCount }} 人在学</span>
                    <router-link
                        :to="`/courses/${course.id}`"
                        class="!rounded-button bg-primary/10 text-primary px-4 py-2 hover:bg-primary/20 whitespace-nowrap"
                    >
                      查看详情
                    </router-link>
                  </div>
                </div>
              </div>
            </template>
          </div>
        </div>
      </section>

      <section class="py-16">
        <div class="max-w-7xl mx-auto px-4">
          <h2 class="text-3xl font-bold text-center mb-12">精选面试题</h2>
          <div class="flex gap-8">
            <div class="w-64 bg-white rounded-lg p-6 shadow-sm">
              <h3 class="text-lg font-bold mb-4">题目分类</h3>
              <ul class="space-y-2">
                <li v-for="category in categories" :key="category.id">
                  <a href="#" class="flex items-center text-gray-700 hover:text-primary">
                    <i :class="['fas', `fa-${category.icon}`, 'mr-2']"></i>
                    {{ category.name }}
                  </a>
                </li>
              </ul>
            </div>
            <div class="flex-1 bg-white rounded-lg p-6 shadow-sm">
              <div class="flex items-center justify-between mb-6">
                <h3 class="text-lg font-bold">最新题目</h3>
                <div class="flex items-center space-x-2">
                  <button
                      class="!rounded-button px-4 py-2 bg-gray-100 text-gray-700 hover:bg-gray-200 whitespace-nowrap">难度</button>
                  <button
                      class="!rounded-button px-4 py-2 bg-gray-100 text-gray-700 hover:bg-gray-200 whitespace-nowrap">热度</button>
                </div>
              </div>
              <div class="space-y-4">
                <template v-for="question in questions" :key="question.id">
                  <div class="p-4 border border-gray-200 rounded-lg hover:border-primary/30 hover:bg-primary/5">
                    <router-link :to="`/questions/${question.id}`">
                      <div class="flex items-center justify-between mb-2">
                        <h4 class="font-medium">{{ question.title }}</h4>
                        <span :class="[
                          'px-2 py-1 text-xs rounded',
                          question.difficulty === '简单' ? 'bg-green-100 text-green-800' :
                          question.difficulty === '中等' ? 'bg-yellow-100 text-yellow-800' :
                          'bg-red-100 text-red-800'
                        ]">
                        {{ question.difficulty }}
                      </span>
                      </div>
                      <div class="flex items-center text-sm text-gray-500">
                        <span class="mr-4">通过率:{{ question.passRate }}</span>
                        <span>提交次数:{{ question.submitCount }}</span>
                      </div>
                    </router-link>
                  </div>
                </template>
              </div>
            </div>
          </div>
        </div>
      </section>

      <section class="py-16 bg-white">
        <div class="max-w-7xl mx-auto px-4">
          <h2 class="text-3xl font-bold text-center mb-12">学习数据</h2>
          <div class="grid grid-cols-2 gap-8">
            <div class="bg-white rounded-lg shadow-sm p-6">
              <h3 class="text-lg font-bold mb-4">课程学习趋势</h3>
              <div id="trendChart" class="w-full h-[300px]"></div>
            </div>
            <div class="bg-white rounded-lg shadow-sm p-6">
              <h3 class="text-lg font-bold mb-4">技能分布</h3>
              <div id="skillChart" class="w-full h-[300px]"></div>
            </div>
          </div>
        </div>
      </section>

      <section class="py-16">
        <div class="max-w-7xl mx-auto px-4">
          <h2 class="text-3xl font-bold text-center mb-12">学习动态</h2>
          <div class="grid grid-cols-3 gap-8">
            <template v-for="activity in activities" :key="activity.id">
              <div class="bg-white rounded-lg shadow-sm p-6">
                <div class="flex items-center mb-4">
                  <img :src="activity.userAvatar" class="w-10 h-10 rounded-full mr-3">
                  <div>
                    <h4 class="font-medium">{{ activity.userName }}</h4>
                    <p class="text-sm text-gray-500">{{ activity.time }}</p>
                  </div>
                </div>
                <p class="text-gray-700">{{ activity.content }}</p>
              </div>
            </template>
          </div>
        </div>
      </section>
    </main>
  </Layout>
</template>

<script setup>
import { onMounted, ref } from "vue";
import * as echarts from "echarts";
import request from '@/utils/request';
import Layout from '@/components/Layout.vue'

// 定义响应式数据
const courses = ref([]);
const categories = ref([]);
const questions = ref([]);

// 获取课程数据
const fetchCourses = async () => {
  try {
    const response = await request.get('/courses');
    courses.value = response.data.data;
  } catch (error) {
    console.error('获取课程数据失败:', error);
  }
};

// 获取题目分类
const fetchCategories = async () => {
  try {
    const response = await request.get('/questions/categories');
    categories.value = response.data.data;
  } catch (error) {
    console.error('获取题目分类失败:', error);
  }
};

// 获取题目列表
const fetchQuestions = async () => {
  try {
    const response = await request.get('/questions/list');
    questions.value = response.data.data;
  } catch (error) {
    console.error('获取题目列表失败:', error);
  }
};

// 获取趋势数据
const fetchTrendData = async () => {
  try {
    const response = await request.get('/statistics/trend');
    return response.data.data;
  } catch (error) {
    console.error('获取趋势数据失败:', error);
    return null;
  }
};

// 获取技能分布数据
const fetchSkillData = async () => {
  try {
    const response = await request.get('/statistics/skills');
    return response.data.data;
  } catch (error) {
    console.error('获取技能分布数据失败:', error);
    return null;
  }
};

// 添加响应式数据
const activities = ref([]);

// 添加获取学习动态的方法
const fetchActivities = async () => {
  try {
    const response = await request.get('/statistics/activities');
    activities.value = response.data.data;
  } catch (error) {
    console.error('获取学习动态失败:', error);
  }
};

onMounted(async () => {
  // 获取所有数据
  await Promise.all([
    fetchCourses(),
    fetchCategories(),
    fetchQuestions(),
    fetchActivities()
  ]);

  // 初始化图表
  const trendChart = echarts.init(document.getElementById('trendChart'));
  const skillChart = echarts.init(document.getElementById('skillChart'));

  // 获取图表数据
  const trendData = await fetchTrendData();
  const skillData = await fetchSkillData();

  if (trendData) {
    trendChart.setOption({
      animation: false,
      tooltip: {
        trigger: 'axis'
      },
      xAxis: {
        type: 'category',
        data: trendData.dates
      },
      yAxis: {
        type: 'value'
      },
      series: [{
        data: trendData.data,
        type: 'line',
        smooth: true,
        itemStyle: {
          color: '#2D8CF0'
        }
      }]
    });
  }

  if (skillData) {
    skillChart.setOption({
      animation: false,
      tooltip: {
        trigger: 'item'
      },
      series: [{
        type: 'pie',
        radius: ['40%', '70%'],
        data: skillData,
        itemStyle: {
          borderRadius: 10,
          borderColor: '#fff',
          borderWidth: 2
        },
        emphasis: {
          itemStyle: {
            shadowBlur: 10,
            shadowOffsetX: 0,
            shadowColor: 'rgba(0, 0, 0, 0.5)'
          }
        }
      }]
    });
  }

  window.addEventListener('resize', function () {
    trendChart.resize();
    skillChart.resize();
  });
});
</script>

<style scoped>
.category-card {
  transition: all 0.3s ease;
}

.category-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}

.image-wrapper::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 200px;
  background: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.2) 100%);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.category-card:hover .image-wrapper::after {
  opacity: 1;
}

.line-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  height: 3rem;
}
</style>

code/front/src/views/Courses.vue

<template>
  <Layout>
    <div class="max-w-7xl mx-auto px-4 py-8">
      <!-- 页面标题 -->
      <div class="mb-8">
        <h1 class="text-3xl font-bold text-gray-900">全部课程</h1>
        <p class="mt-2 text-gray-600">探索丰富的技术课程,提升你的专业技能</p>
      </div>

      <!-- 筛选区域 -->
      <div class="bg-white rounded-lg shadow-sm p-6 mb-8">
        <div class="space-y-4">
          <!-- 课程方向 -->
          <div>
            <h3 class="font-medium mb-2">课程方向</h3>
            <div class="flex flex-wrap gap-2">
              <button
                v-for="direction in directions"
                :key="direction.id"
                :class="[
                  'px-4 py-2 rounded-full text-sm',
                  selectedDirection === direction.id
                    ? 'bg-primary text-white'
                    : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
                ]"
                @click="selectedDirection = direction.id"
              >
                {{ direction.name }}
              </button>
            </div>
          </div>

          <!-- 难度级别 -->
          <div>
            <h3 class="font-medium mb-2">难度级别</h3>
            <div class="flex flex-wrap gap-2">
              <button
                v-for="level in levels"
                :key="level.id"
                :class="[
                  'px-4 py-2 rounded-full text-sm',
                  selectedLevel === level.id
                    ? 'bg-primary text-white'
                    : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
                ]"
                @click="selectedLevel = level.id"
              >
                {{ level.name }}
              </button>
            </div>
          </div>
        </div>
      </div>

      <!-- 课程列表 -->
      <div class="grid grid-cols-3 gap-6">
        <div
          v-for="course in filteredCourses"
          :key="course.id"
          class="category-card bg-white rounded-lg shadow-sm overflow-hidden group hover:shadow-md transition-shadow"
        >
          <div class="relative overflow-hidden image-wrapper">
            <img
              :src="course.imageUrl"
              :alt="course.title"
              class="w-full h-48 object-cover transition-transform duration-300 group-hover:scale-105"
            >
            <div class="absolute top-2 right-2">
              <span
                :class="[
                  'px-2 py-1 text-xs rounded',
                  course.level === '入门' ? 'bg-green-100 text-green-800' :
                  course.level === '进阶' ? 'bg-blue-100 text-blue-800' :
                  'bg-orange-100 text-orange-800'
                ]"
              >
                {{ course.level }}
              </span>
            </div>
          </div>
          <div class="p-4">
            <router-link :to="`/courses/${course.id}`">
              <h3 class="text-lg font-bold text-gray-900 mb-2 hover:text-primary">{{ course.title }}</h3>
            </router-link>
            <p class="text-gray-600 text-sm mb-4 line-clamp-2">{{ course.description }}</p>
            <div class="flex items-center justify-between">
              <div class="flex items-center space-x-2">
                <span class="text-sm text-gray-500">
                  <i class="fas fa-user-graduate mr-1"></i>
                  {{ course.studentCount }} 人在学
                </span>
                <span class="text-sm text-gray-500">
                  <i class="fas fa-clock mr-1"></i>
                  {{ course.duration }}
                </span>
              </div>
              <button class="text-primary hover:text-primary/80">
                <router-link :to="`/courses/${course.id}`">
                  <i class="fas fa-arrow-right hover:text-primary"></i>
                </router-link>
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </Layout>
</template>

<script setup>
import Layout from '@/components/Layout.vue'
import {ref, computed, onMounted} from 'vue'
import request from '@/utils/request'

// 课程方向
const directions = [
  { id: 0, name: '全部' },
  { id: 1, name: '前端开发' },
  { id: 2, name: '后端开发' },
  { id: 3, name: '移动开发' },
  { id: 4, name: '算法与数据结构' },
  { id: 5, name: '人工智能' },
  { id: 6, name: '云计算与架构' }
]

// 难度级别
const levels = [
  { id: 0, name: '全部' },
  { id: 1, name: '入门' },
  { id: 2, name: '进阶' },
  { id: 3, name: '高级' }
]

const courses = ref([])
const selectedDirection = ref(0)
const selectedLevel = ref(0)

// 获取课程数据
const fetchCourses = async () => {
  try {
    const response = await request.get('/courses/list')
    courses.value = response.data.data
  } catch (error) {
    console.error('获取课程数据失败:', error)
  }
}

// 过滤后的课程列表
const filteredCourses = computed(() => {
  return courses.value.filter(course => {
    const directionMatch = selectedDirection.value === 0 || course.directionId === selectedDirection.value
    const levelMatch = selectedLevel.value === 0 || course.levelId === selectedLevel.value
    return directionMatch && levelMatch
  })
})

onMounted(() => {
  fetchCourses()
})
</script>

<style scoped>
.category-card {
  transition: all 0.3s ease;
}

.category-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}

.image-wrapper::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 200px;
  background: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.2) 100%);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.category-card:hover .image-wrapper::after {
  opacity: 1;
}

.line-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  height: 2.5rem;
}
</style>

code/front/src/views/Community.vue

<template>
  <Layout>
    <div class="max-w-7xl mx-auto px-4 py-8">
      <!-- 页面标题 -->
      <div class="mb-8">
        <h1 class="text-3xl font-bold text-gray-900">技术社区</h1>
        <p class="mt-2 text-gray-600">分享经验,交流技术,一起成长</p>
      </div>

      <!-- 主要内容区 -->
      <div class="flex gap-8">
        <!-- 左侧主内容区 -->
        <div class="flex-1">
          <!-- 发帖按钮和筛选 -->
          <div class="bg-white rounded-lg shadow-sm p-6 mb-6">
            <div class="flex items-center justify-between mb-6">
              <button class="!rounded-lg bg-primary text-white px-6 py-2 hover:bg-primary/90 flex items-center">
                <i class="fas fa-pen-to-square mr-2"></i>
                发布帖子
              </button>
              <div class="flex items-center space-x-4">
                <button class="text-gray-600 hover:text-primary flex items-center">
                  <i class="fas fa-fire mr-1"></i>
                  热门
                </button>
                <button class="text-gray-600 hover:text-primary flex items-center">
                  <i class="fas fa-clock mr-1"></i>
                  最新
                </button>
              </div>
            </div>

            <!-- 标签筛选 -->
            <div class="flex flex-wrap gap-2">
              <span
                v-for="tag in tags"
                :key="tag.id"
                :class="[
                  'px-3 py-1 rounded-full text-sm cursor-pointer transition-colors',
                  tag.active ? 'bg-primary text-white' : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
                ]"
                @click="toggleTag(tag)"
              >
                {{ tag.name }}
              </span>
            </div>
          </div>

          <!-- 帖子列表 -->
          <div class="space-y-6">
            <div
              v-for="post in posts"
              :key="post.id"
              class="bg-white rounded-lg shadow-sm p-6 hover:shadow-md transition-shadow"
            >
              <!-- 作者信息 -->
              <div class="flex items-center justify-between mb-4">
                <div class="flex items-center">
                  <img :src="post.authorAvatar" :alt="post.authorName" class="w-10 h-10 rounded-full">
                  <div class="ml-3">
                    <h3 class="font-medium text-gray-900">{{ post.authorName }}</h3>
                    <p class="text-sm text-gray-500">{{ post.createTime }}</p>
                  </div>
                </div>
                <button class="text-gray-400 hover:text-gray-600">
                  <i class="fas fa-ellipsis-h"></i>
                </button>
              </div>

              <!-- 帖子内容 -->
              <h2 class="text-xl font-bold text-gray-900 mb-2 hover:text-primary" style="cursor: pointer">{{ post.title }}</h2>
              <p class="text-gray-600 mb-4 line-clamp-3">{{ post.content }}</p>

              <!-- 帖子标签 -->
              <div class="flex flex-wrap gap-2 mb-4">
                <span
                  v-for="tag in post.tags"
                  :key="tag"
                  class="px-2 py-1 bg-gray-100 text-gray-600 text-sm rounded"
                >
                  {{ tag }}
                </span>
              </div>

              <!-- 互动数据 -->
              <div class="flex items-center space-x-6 text-gray-500">
                <button class="hover:text-primary flex items-center">
                  <i class="far fa-thumbs-up mr-1"></i>
                  {{ post.likes }}
                </button>
                <button class="hover:text-primary flex items-center">
                  <i class="far fa-comment mr-1"></i>
                  {{ post.comments }}
                </button>
                <button class="hover:text-primary flex items-center">
                  <i class="far fa-bookmark mr-1"></i>
                  {{ post.collects }}
                </button>
              </div>
            </div>
          </div>
        </div>

        <!-- 右侧边栏 -->
        <div class="w-80">
          <!-- 活跃用户 -->
          <div class="bg-white rounded-lg shadow-sm p-6 mb-6">
            <h3 class="text-lg font-bold text-gray-900 mb-4">活跃用户</h3>
            <div class="space-y-4">
              <div
                v-for="user in activeUsers"
                :key="user.id"
                class="flex items-center"
              >
                <img :src="user.avatar" :alt="user.name" class="w-10 h-10 rounded-full">
                <div class="ml-3">
                  <h4 class="font-medium text-gray-900">{{ user.name }}</h4>
                  <p class="text-sm text-gray-500">{{ user.title }}</p>
                </div>
              </div>
            </div>
          </div>

          <!-- 热门话题 -->
          <div class="bg-white rounded-lg shadow-sm p-6">
            <h3 class="text-lg font-bold text-gray-900 mb-4">热门话题</h3>
            <div class="space-y-3">
              <div
                v-for="topic in hotTopics"
                :key="topic.id"
                class="flex items-center justify-between hover:bg-gray-50 p-2 rounded cursor-pointer"
              >
                <span class="text-gray-600"># {{ topic.name }}</span>
                <span class="text-sm text-gray-500">{{ topic.count }}个讨论</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </Layout>
</template>

<script setup>
import { ref } from 'vue'
import Layout from '@/components/Layout.vue'
import request from '@/utils/request'

// 标签数据
const tags = ref([
  { id: 1, name: '全部', active: true },
  { id: 2, name: '前端开发', active: false },
  { id: 3, name: '后端开发', active: false },
  { id: 4, name: '算法', active: false },
  { id: 5, name: '面试经验', active: false },
  { id: 6, name: '职业发展', active: false }
])

// 切换标签
const toggleTag = (tag) => {
  tags.value.forEach(t => t.active = t.id === tag.id)
  fetchPosts() // 重新获取帖子数据
}

// 帖子数据
const posts = ref([])
const fetchPosts = async () => {
  try {
    const response = await request.get('/community/posts')
    posts.value = response.data.data
  } catch (error) {
    console.error('获取帖子数据失败:', error)
  }
}

// 活跃用户数据
const activeUsers = ref([])
const fetchActiveUsers = async () => {
  try {
    const response = await request.get('/community/active-users')
    activeUsers.value = response.data.data
  } catch (error) {
    console.error('获取活跃用户数据失败:', error)
  }
}

// 热门话题数据
const hotTopics = ref([])
const fetchHotTopics = async () => {
  try {
    const response = await request.get('/community/hot-topics')
    hotTopics.value = response.data.data
  } catch (error) {
    console.error('获取热门话题数据失败:', error)
  }
}

// 页面加载时获取数据
fetchPosts()
fetchActiveUsers()
fetchHotTopics()
</script>

附注

目前主要代码由 trae 编写,相关文档也由该工具生成;页面原型由mastergo和trae设计实现;后续开发中主要也会使用这两款工具

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值