在知识经济时代,在线教育平台已成为内容创作者、教育机构实现知识变现的核心工具。本文将以ThinkPHP6.0+Vue3.0+MySQL8.0技术栈为例,详细拆解知识付费系统的核心功能开发流程,提供可复用的源码框架及部署方案,助力开发者7天内完成从0到1的MVP搭建。
源码:zs.xcxyms.top
一、系统架构设计
1.1技术选型
模块技术方案优势说明
后端框架ThinkPHP6.0+Swoole高性能ORM、协程支持、企业级开发规范
前端框架Vue3.0+TypeScript组合式API、类型安全、响应式优化
数据库MySQL8.0+Redis事务支持、缓存加速、JSON字段扩展
支付集成微信支付/支付宝SDK企业级支付安全方案
部署环境Docker+Nginx+PM2容器化部署、进程守护、负载均衡
1.2核心功能模块
用户体系:多角色(学员/讲师/管理员)权限控制
课程管理:视频/图文/直播课程发布与分类
支付系统:订单生成、支付回调、退款流程
分销系统:三级分销、佣金结算、推广海报
数据分析:课程销量统计、用户行为分析
二、核心功能开发详解
2.1用户体系开发
数据库设计(User表)
sql
CREATE TABLE`edu_user`(
`id`int(11)NOT NULL AUTO_INCREMENT,
`username`varchar(50)NOT NULL COMMENT'用户名',
`password`varchar(255)NOT NULL COMMENT'密码(bcrypt加密)',
`role`tinyint(1)DEFAULT'0'COMMENT'0学员1讲师2管理员',
`avatar`varchar(255)DEFAULT NULL COMMENT'头像',
`balance`decimal(10,2)DEFAULT'0.00'COMMENT'账户余额',
`created_at`datetime DEFAULT CURRENT_TIMESTAMP,
`updated_at`datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(`id`),
UNIQUE KEY`username`(`username`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
JWT认证实现(ThinkPHP中间件)
php
//app/middleware/JwtAuth.php
namespace appmiddleware;
use thinkfacadeRequest;
use thinkfacadeResponse;
use FirebaseJWTJWT;
use FirebaseJWTKey;
class JwtAuth
{
public function handle($request,Closure$next)
{
$token=Request::header('Authorization');
if(!$token){
return json(['code'=>401,'msg'=>'未提供token']);
}
try{
$decoded=JWT::decode($token,new Key(config('jwt.secret'),'HS256'));
Request::user=$decoded;//挂载用户信息到请求对象
}catch(Exception$e){
return json(['code'=>401,'msg'=>'token无效']);
}
return$next($request);
}
}
2.2课程管理系统
课程表设计(Course表)
sql
CREATE TABLE`edu_course`(
`id`int(11)NOT NULL AUTO_INCREMENT,
`title`varchar(100)NOT NULL COMMENT'课程标题',
`cover`varchar(255)NOT NULL COMMENT'封面图',
`price`decimal(10,2)NOT NULL COMMENT'价格',
`type`tinyint(1)DEFAULT'0'COMMENT'0视频1图文2直播',
`status`tinyint(1)DEFAULT'0'COMMENT'0未发布1已发布',
`lecturer_id`int(11)NOT NULL COMMENT'讲师ID',
`created_at`datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(`id`),
KEY`idx_lecturer`(`lecturer_id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
视频课程上传接口(TP6控制器)
php
//app/controller/Course.php
namespace appcontroller;
use appBaseController;
use appmodelCourse;
use thinkfacadeFilesystem;
class Course extends BaseController
{
public function uploadVideo()
{
$file=request()->file('video');
if(!$file){
return json(['code'=>400,'msg'=>'请上传视频文件']);
}
//验证文件类型
$info=$file->validate([
'size'=>1024*1024*1024,//1GB
'ext'=>'mp4,avi,mov'
])->move('uploads/course');
if(!$info){
return json(['code'=>400,'msg'=>$file->getError()]);
}
//保存课程信息
$course=new Course();
$course->title=request()->post('title');
$course->cover=request()->post('cover');
$course->price=request()->post('price');
$course->type=0;//视频类型
$course->lecturer_id=request()->user()->id;
$course->video_path='/uploads/course/'.$info->getSaveName();
$course->save();
return json(['code'=>200,'msg'=>'上传成功','data'=>$course]);
}
}
2.3支付系统开发
微信支付回调处理(TP6事件监听)
php
//app/listener/WechatPayNotify.php
namespace applistener;
use thinkfacadeDb;
use thinkfacadeLog;
class WechatPayNotify
{
public function handle($event)
{
$notifyData=$event->getData();
//验证签名
$sign=$this->makeSign($notifyData);
if($sign!==$notifyData['sign']){
Log::error('微信支付签名验证失败');
return false;
}
//查询订单
$order=Db::name('order')
->where('out_trade_no',$notifyData['out_trade_no'])
->find();
if(!$order||$order['status']==1){
return true;//已处理或订单不存在
}
//更新订单状态
Db::startTrans();
try{
Db::name('order')
->where('id',$order['id'])
->update([
'status'=>1,
'transaction_id'=>$notifyData['transaction_id'],
'pay_time'=>date('Y-m-d H:i:s')
]);
//增加用户课程权限
Db::name('user_course')
->insert([
'user_id'=>$order['user_id'],
'course_id'=>$order['course_id'],
'created_at'=>date('Y-m-d H:i:s')
]);
Db::commit();
return true;
}catch(Exception$e){
Db::rollback();
Log::error('支付回调处理失败:'.$e->getMessage());
return false;
}
}
private function makeSign($data)
{
//微信支付签名算法实现
ksort($data);
$string='';
foreach($data as$k=>$v){
if($k!='sign'&&$v!=''&&!is_array($v)){
$string.=$k.'='.$v.'&';
}
}
$string=trim($string,'&');
$string.='&key='.config('wechat.pay_key');
return strtoupper(md5($string));
}
}
2.4分销系统实现
分销关系表设计(Distribution表)
sql
CREATE TABLE`edu_distribution`(
`id`int(11)NOT NULL AUTO_INCREMENT,
`user_id`int(11)NOT NULL COMMENT'用户ID',
`parent_id`int(11)DEFAULT NULL COMMENT'上级ID',
`level`tinyint(1)DEFAULT'1'COMMENT'1一级2二级3三级',
`created_at`datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(`id`),
KEY`idx_user`(`user_id`),
KEY`idx_parent`(`parent_id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
分销佣金计算逻辑
php
//app/service/DistributionService.php
namespace appservice;
use thinkfacadeDb;
class DistributionService
{
public function calculateCommission($order)
{
//获取分销关系链
$chain=$this->getDistributionChain($order['user_id']);
//计算佣金(示例:一级10%,二级5%,三级3%)
$commissionRules=[
1=>0.10,//一级
2=>0.05,//二级
3=>0.03//三级
];
Db::startTrans();
try{
foreach($chain as$level=>$parentId){
if(!isset($commissionRules[$level]))continue;
$commission=$order['amount']*$commissionRules[$level];
if($commission<=0)continue;
//增加上级账户余额
Db::name('user')
->where('id',$parentId)
->inc('balance',$commission)
->update();
//记录佣金明细
Db::name('commission_log')
->insert([
'order_id'=>$order['id'],
'user_id'=>$parentId,
'amount'=>$commission,
'level'=>$level,
'created_at'=>date('Y-m-d H:i:s')
]);
}
Db::commit();
}catch(Exception$e){
Db::rollback();
throw newException('佣金结算失败:'.$e->getMessage());
}
}
private function getDistributionChain($userId)
{
$chain=[];
$current=$userId;
//最多查询3级
for($i=1;$i<=3;$i++){
$parent=Db::name('distribution')
->where('user_id',$current)
->value('parent_id');
if(!$parent)break;
$chain[$i]=$parent;
$current=$parent;
}
return$chain;
}
}
三、前端实现(Vue3示例)
3.1课程列表组件
vue
<template>
<div class="course-list">
<div v-for="course in courses":key="course.id"class="course-item">
<img:src="course.cover"class="course-cover"/>
<h3>{{course.title}}</h3>
<p class="price">¥{{course.price}}</p>
<button click="buyCourse(course)">立即购买</button>
</div>
</div>
</template>
<script setup>
import{ref,onMounted}from'vue';
import{useRouter}from'vue-router';
import{getCourseList}from' /api/course';
import{useUserStore}from' /stores/user';
const router=useRouter();
const userStore=useUserStore();
const courses=ref([]);
onMounted(async()=>{
try{
const res=await getCourseList();
courses.value=res.data;
}catch(error){
console.error('获取课程列表失败:',error);
}
});
const buyCourse=async(course)=>{
if(!userStore.token){
router.push('/login');
return;
}
try{
//调用支付接口
const res=await createOrder({
course_id:course.id,
amount:course.price
});
//跳转支付页面(实际项目中应调用微信/支付宝JS SDK)
window.location.href=`/pay?order_id=${res.data.order_id}`;
}catch(error){
console.error('创建订单失败:',error);
}
};
</script>
<style scoped>
.course-list{
display:grid;
grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
gap:20px;
padding:20px;
}
.course-item{
border:1px solid#eee;
border-radius:8px;
overflow:hidden;
transition:transform 0.2s;
}
.course-item:hover{
transform:translateY(-5px);
box-shadow:0 5px 15px rgba(0,0,0,0.1);
}
.course-cover{
width:100%;
height:160px;
object-fit:cover;
}
.price{
color:#f56c6c;
font-size:18px;
font-weight:bold;
margin:10px 0;
}
</style>
3.2视频播放器组件
vue
<template>
<div class="video-player">
<video
ref="videoPlayer"
:src="videoUrl"
controls
play="onPlay"
pause="onPause"
timeupdate="onTimeUpdate"
></video>
<div class="progress-bar">
<div
class="progress"
:style="{width:progress+'%'}"
></div>
</div>
<div class="time-display">
{{currentTime}}/{{duration}}
</div>
</div>
</template>
<script setup>
import{ref,computed,onMounted}from'vue';
const props=defineProps({
videoUrl:{
type:String,
required:true
}
});
const videoPlayer=ref(null);
const progress=ref(0);
const currentTime=ref('00:00');
const duration=ref('00:00');
const formatTime=(seconds)=>{
const mins=Math.floor(seconds/60);
const secs=Math.floor(seconds%60);
return`${mins.toString().padStart(2,'0')}:${secs.toString().padStart(2,'0')}`;
};
const onPlay=()=>{
console.log('视频开始播放');
};
const onPause=()=>{
console.log('视频暂停');
};
const onTimeUpdate=()=>{
if(videoPlayer.value){
const current=videoPlayer.value.currentTime;
const total=videoPlayer.value.duration;
progress.value=(current/total)*100;
currentTime.value=formatTime(current);
duration.value=formatTime(total);
}
};
onMounted(()=>{
//监听视频加载完成事件
if(videoPlayer.value){
videoPlayer.value.addEventListener('loadedmetadata',()=>{
duration.value=formatTime(videoPlayer.value.duration);
});
}
});
</script>
<style scoped>
.video-player{
max-width:800px;
margin:0 auto;
}
video{
width:100%;
background:#000;
}
.progress-bar{
height:4px;
background:#eee;
margin:10px 0;
cursor:pointer;
}
.progress{
height:100%;
background:#409eff;
transition:width 0.1s;
}
.time-display{
text-align:center;
color:#666;
font-size:14px;
}
</style>
四、部署指南
4.1 Docker容器化部署
docker-compose.yml配置
yaml
version:'3.8'
services:
nginx:
image:nginx:alpine
ports:
-"80:80"
volumes:
-./nginx.conf:/etc/nginx/conf.d/default.conf
-./public:/var/www/html/public
depends_on:
-php
php:
build:
context:.
dockerfile:Dockerfile.php
volumes:
-.:/var/www/html
depends_on:
-mysql
-redis
mysql:
image:mysql:8.0
environment:
MYSQL_ROOT_PASSWORD:rootpassword
MYSQL_DATABASE:knowledge_pay
MYSQL_USER:app
MYSQL_PASSWORD:apppassword
volumes:
-mysql_data:/var/lib/mysql
ports:
-"3306:3306"
redis:
image:redis:alpine
ports:
-"6379:6379"
volumes:
mysql_data:
Nginx配置示例
nginx
server{
listen 80;
server_name yourdomain.com;
root/var/www/html/public;
index index.php index.html;
location/{
try_files$uri$uri//index.php?$query_string;
}
location~.php${
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME$document_root$fastcgi_script_name;
include fastcgi_params;
}
location~/.(?!well-known).*{
deny all;
}
}
4.2服务器安全配置
防火墙规则
bash
#允许HTTP/HTTPS/SSH/MySQL
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 22/tcp
sudo ufw allow 3306/tcp
sudo ufw enable
SSL证书配置
使用Let's Encrypt免费证书:
bash
sudo apt install certbot python3-certbot-nginx
sudo certbot--nginx-d yourdomain.com-d www.yourdomain.com
定时备份
bash
#每天凌晨3点备份数据库
0 3***/usr/bin/mysqldump-u app-p'apppassword'knowledge_pay|gzip>/backup/db_$(date+%Y%m%d).sql.gz
五、性能优化方案
数据库优化
为高频查询字段添加索引(如user_id、course_id)
使用Redis缓存热门课程数据(设置TTL为1小时)
开启MySQL慢查询日志,优化复杂SQL
代码优化
使用Swoole协程处理支付回调等耗时操作
启用ThinkPHP的OPcache加速
前端资源压缩(Vue CLI的production模式)
CDN加速
将静态资源(视频封面、课程资料)托管至七牛云/阿里云OSS
配置Nginx反向代理静态资源
六、源码获取与二次开发建议
完整源码获取方式
GitHub仓库:知识付费系统源码
关键文件说明:
/app/controller/:后端API接口
/resources/vue/:前端Vue3项目
/database/migrations/:数据库表结构
/docker/:部署配置文件
二次开发建议
功能扩展:
增加直播功能(集成SRS或OBS)
开发移动端APP(使用Uni-app跨平台框架)
添加AI智能推荐系统
安全加固:
实现CSRF防护
敏感操作增加短信/邮箱验证
定期更新依赖库版本
监控告警:
集成Prometheus+Grafana监控系统状态
设置支付失败、订单超时等告警规则
本文提供的完整技术方案已通过实际项目验证,开发者可根据自身需求调整技术栈或功能模块。建议优先完成MVP版本上线,再通过用户反馈迭代优化。对于非技术背景的创业者,可选择基于开源系统进行二次开发,或采购成熟SaaS服务快速启动业务。