当前位置: 首页 > article >正文

体育直播系统趣猜功能开发技术实现方案

功能概述

趣猜功能是“东莞梦幻网络科技”体育直播系统源码中的互动功能,主播可以发起竞猜题目,观众使用虚拟货币进行投注,增加直播间的互动性和趣味性。所有货币均为虚拟货币,通过系统活动获取,不可充值提现。

数据库设计 (MySQL)

-- 趣猜表
CREATE TABLE `live_quiz` (`id` int(11) NOT NULL AUTO_INCREMENT,`live_id` int(11) NOT NULL COMMENT '直播间ID',`anchor_id` int(11) NOT NULL COMMENT '主播ID',`title` varchar(255) NOT NULL COMMENT '趣猜主题',`option_a` varchar(100) NOT NULL COMMENT '选项A',`option_b` varchar(100) NOT NULL COMMENT '选项B',`odds_a` decimal(5,2) NOT NULL DEFAULT '1.00' COMMENT 'A选项赔率',`odds_b` decimal(5,2) NOT NULL DEFAULT '1.00' COMMENT 'B选项赔率',`end_time` int(11) NOT NULL COMMENT '截止时间',`result` tinyint(1) DEFAULT NULL COMMENT '结果:0-A赢,1-B赢,NULL-未开奖',`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态:0-进行中,1-已结束,2-已开奖',`create_time` int(11) NOT NULL,`update_time` int(11) NOT NULL,PRIMARY KEY (`id`),KEY `live_id` (`live_id`),KEY `anchor_id` (`anchor_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='直播间趣猜表';-- 用户投注表
CREATE TABLE `live_quiz_bet` (`id` int(11) NOT NULL AUTO_INCREMENT,`quiz_id` int(11) NOT NULL COMMENT '趣猜ID',`user_id` int(11) NOT NULL COMMENT '用户ID',`option` tinyint(1) NOT NULL COMMENT '投注选项:0-A,1-B',`amount` int(11) NOT NULL COMMENT '投注金额',`potential_win` int(11) NOT NULL COMMENT '潜在收益',`is_win` tinyint(1) DEFAULT NULL COMMENT '是否赢:0-输,1-赢,NULL-未开奖',`win_amount` int(11) DEFAULT NULL COMMENT '实际赢取金额',`create_time` int(11) NOT NULL,`update_time` int(11) NOT NULL,PRIMARY KEY (`id`),KEY `quiz_id` (`quiz_id`),KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户投注表';-- 用户虚拟货币表
CREATE TABLE `user_virtual_currency` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) NOT NULL,`balance` int(11) NOT NULL DEFAULT '0' COMMENT '余额',`total_earn` int(11) NOT NULL DEFAULT '0' COMMENT '累计获得',`total_spend` int(11) NOT NULL DEFAULT '0' COMMENT '累计消费',`create_time` int(11) NOT NULL,`update_time` int(11) NOT NULL,PRIMARY KEY (`id`),UNIQUE KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户虚拟货币表';

PHP后端实现 (ThinkPHP)

控制器 LiveQuizController.php

<?php
namespace app\api\controller;use think\Controller;
use think\Request;
use app\common\model\LiveQuiz;
use app\common\model\LiveQuizBet;
use app\common\model\UserVirtualCurrency;class LiveQuizController extends Controller
{// 主播发起趣猜public function create(Request $request){$user = $request->user;$data = $request->only(['live_id', 'title', 'option_a', 'option_b', 'odds_a', 'odds_b', 'end_time']);// 验证数据$validate = new \think\Validate(['live_id' => 'require|number','title' => 'require|max:255','option_a' => 'require|max:100','option_b' => 'require|max:100','odds_a' => 'require|float|>:0','odds_b' => 'require|float|>:0','end_time' => 'require|number|>:time']);if (!$validate->check($data)) {return json(['code' => 400, 'msg' => $validate->getError()]);}$data['anchor_id'] = $user->id;$data['create_time'] = time();$data['update_time'] = time();$quiz = LiveQuiz::create($data);// 广播消息到直播间$this->broadcastQuizCreate($quiz);return json(['code' => 200, 'msg' => '趣猜创建成功', 'data' => $quiz]);}// 用户投注public function bet(Request $request){$user = $request->user;$data = $request->only(['quiz_id', 'option', 'amount']);// 验证数据$validate = new \think\Validate(['quiz_id' => 'require|number','option' => 'require|in:0,1','amount' => 'require|number|>:0']);if (!$validate->check($data)) {return json(['code' => 400, 'msg' => $validate->getError()]);}// 检查趣猜是否存在且可投注$quiz = LiveQuiz::where('id', $data['quiz_id'])->where('status', 0)->where('end_time', '>', time())->find();if (!$quiz) {return json(['code' => 400, 'msg' => '该趣猜已结束或不存在']);}// 检查用户余额$currency = UserVirtualCurrency::where('user_id', $user->id)->find();if (!$currency || $currency->balance < $data['amount']) {return json(['code' => 400, 'msg' => '虚拟货币不足']);}// 计算潜在收益$odds = $data['option'] == 0 ? $quiz->odds_a : $quiz->odds_b;$potential_win = floor($data['amount'] * $odds);// 开始事务Db::startTrans();try {// 扣除用户余额UserVirtualCurrency::where('user_id', $user->id)->update(['balance' => Db::raw('balance-'.$data['amount']),'total_spend' => Db::raw('total_spend+'.$data['amount']),'update_time' => time()]);// 创建投注记录$bet = LiveQuizBet::create(['quiz_id' => $data['quiz_id'],'user_id' => $user->id,'option' => $data['option'],'amount' => $data['amount'],'potential_win' => $potential_win,'create_time' => time(),'update_time' => time()]);// 广播投注消息到直播间$this->broadcastBet($quiz->live_id, ['user_id' => $user->id,'nickname' => $user->nickname,'option' => $data['option'],'amount' => $data['amount']]);Db::commit();return json(['code' => 200, 'msg' => '投注成功', 'data' => $bet]);} catch (\Exception $e) {Db::rollback();return json(['code' => 500, 'msg' => '投注失败:'.$e->getMessage()]);}}// 主播开奖public function settle(Request $request){$user = $request->user;$quiz_id = $request->param('quiz_id');$result = $request->param('result');// 验证数据if (!in_array($result, [0, 1])) {return json(['code' => 400, 'msg' => '无效的结果']);}// 检查趣猜是否存在且可开奖$quiz = LiveQuiz::where('id', $quiz_id)->where('anchor_id', $user->id)->where('status', 0)->where('end_time', '<', time())->find();if (!$quiz) {return json(['code' => 400, 'msg' => '该趣猜不能开奖']);}// 开始事务Db::startTrans();try {// 更新趣猜结果$quiz->result = $result;$quiz->status = 2;$quiz->update_time = time();$quiz->save();// 获取所有赢的投注$winBets = LiveQuizBet::where('quiz_id', $quiz_id)->where('option', $result)->select();// 发放奖励foreach ($winBets as $bet) {$winAmount = $bet->potential_win;// 更新投注记录$bet->is_win = 1;$bet->win_amount = $winAmount;$bet->update_time = time();$bet->save();// 增加用户余额UserVirtualCurrency::where('user_id', $bet->user_id)->update(['balance' => Db::raw('balance+'.$winAmount),'total_earn' => Db::raw('total_earn+'.$winAmount),'update_time' => time()]);}// 更新输的投注LiveQuizBet::where('quiz_id', $quiz_id)->where('option', $result == 0 ? 1 : 0)->update(['is_win' => 0,'win_amount' => 0,'update_time' => time()]);// 广播开奖消息到直播间$this->broadcastSettle($quiz->live_id, ['quiz_id' => $quiz->id,'result' => $result,'option_a' => $quiz->option_a,'option_b' => $quiz->option_b]);Db::commit();return json(['code' => 200, 'msg' => '开奖成功']);} catch (\Exception $e) {Db::rollback();return json(['code' => 500, 'msg' => '开奖失败:'.$e->getMessage()]);}}// 获取趣猜列表public function list(Request $request){$live_id = $request->param('live_id');$status = $request->param('status', 0);$list = LiveQuiz::where('live_id', $live_id)->where('status', $status)->order('create_time', 'desc')->select();return json(['code' => 200, 'msg' => 'success', 'data' => $list]);}// 获取趣猜详情public function detail(Request $request){$quiz_id = $request->param('quiz_id');$user_id = $request->user->id;$quiz = LiveQuiz::find($quiz_id);if (!$quiz) {return json(['code' => 404, 'msg' => '趣猜不存在']);}// 获取投注统计$betStats = LiveQuizBet::where('quiz_id', $quiz_id)->field('option, count(*) as bet_count, sum(amount) as total_amount')->group('option')->select();$stats = ['option_a' => ['bet_count' => 0, 'total_amount' => 0],'option_b' => ['bet_count' => 0, 'total_amount' => 0]];foreach ($betStats as $stat) {if ($stat['option'] == 0) {$stats['option_a'] = ['bet_count' => $stat['bet_count'],'total_amount' => $stat['total_amount']];} else {$stats['option_b'] = ['bet_count' => $stat['bet_count'],'total_amount' => $stat['total_amount']];}}// 获取用户投注$userBet = LiveQuizBet::where('quiz_id', $quiz_id)->where('user_id', $user_id)->find();$quiz->stats = $stats;$quiz->user_bet = $userBet;return json(['code' => 200, 'msg' => 'success', 'data' => $quiz]);}// 广播消息方法private function broadcastQuizCreate($quiz){// 这里实现WebSocket或其它方式的消息广播// 实际项目中可以使用Swoole、Workerman或第三方推送服务}private function broadcastBet($live_id, $data){// 广播投注消息}private function broadcastSettle($live_id, $data){// 广播开奖消息}
}

前端Vue.js实现

主播端组件 AnchorQuizPanel.vue

<template><div class="quiz-panel"><h3>发起趣猜</h3><el-form :model="quizForm" :rules="rules" ref="quizForm" label-width="100px"><el-form-item label="趣猜主题" prop="title"><el-input v-model="quizForm.title" placeholder="例如:本场比赛哪队会获胜?"></el-input></el-form-item><el-form-item label="选项A" prop="option_a"><el-input v-model="quizForm.option_a" placeholder="例如:主队"></el-input></el-form-item><el-form-item label="选项B" prop="option_b"><el-input v-model="quizForm.option_b" placeholder="例如:客队"></el-input></el-form-item><el-form-item label="赔率A" prop="odds_a"><el-input-number v-model="quizForm.odds_a" :min="1" :step="0.1" :precision="2"></el-input-number></el-form-item><el-form-item label="赔率B" prop="odds_b"><el-input-number v-model="quizForm.odds_b" :min="1" :step="0.1" :precision="2"></el-input-number></el-form-item><el-form-item label="截止时间" prop="end_time"><el-date-pickerv-model="quizForm.end_time"type="datetime"placeholder="选择截止时间":picker-options="pickerOptions"></el-date-picker></el-form-item><el-form-item><el-button type="primary" @click="submitQuiz">发起趣猜</el-button></el-form-item></el-form><div class="active-quiz-list" v-if="activeQuizzes.length > 0"><h3>进行中的趣猜</h3><div class="quiz-item" v-for="quiz in activeQuizzes" :key="quiz.id"><div class="quiz-title">{{ quiz.title }}</div><div class="quiz-options"><span class="option-a">{{ quiz.option_a }} (赔率:{{ quiz.odds_a }})</span><span class="vs">VS</span><span class="option-b">{{ quiz.option_b }} (赔率:{{ quiz.odds_b }})</span></div><div class="quiz-endtime">截止时间: {{ formatTime(quiz.end_time) }}</div><div class="quiz-stats"><span>A: {{ quiz.stats.option_a.bet_count }}人投注, {{ quiz.stats.option_a.total_amount }}</span><span>B: {{ quiz.stats.option_b.bet_count }}人投注, {{ quiz.stats.option_b.total_amount }}</span></div><el-button type="success" size="small" @click="settleQuiz(quiz.id, 0)":disabled="quiz.end_time > (Date.now()/1000)">开奖: {{ quiz.option_a }}</el-button><el-button type="danger" size="small" @click="settleQuiz(quiz.id, 1)":disabled="quiz.end_time > (Date.now()/1000)">开奖: {{ quiz.option_b }}</el-button></div></div></div>
</template><script>
import { createQuiz, settleQuiz, getActiveQuizzes } from '@/api/liveQuiz';export default {props: {liveId: {type: Number,required: true}},data() {return {quizForm: {live_id: this.liveId,title: '',option_a: '',option_b: '',odds_a: 1.8,odds_b: 1.8,end_time: new Date(Date.now() + 30 * 60 * 1000) // 默认30分钟后截止},rules: {title: [{ required: true, message: '请输入趣猜主题', trigger: 'blur' }],option_a: [{ required: true, message: '请输入选项A', trigger: 'blur' }],

在这里插入图片描述在这里插入图片描述

相关文章:

体育直播系统趣猜功能开发技术实现方案

功能概述 趣猜功能是“东莞梦幻网络科技”体育直播系统源码中的互动功能&#xff0c;主播可以发起竞猜题目&#xff0c;观众使用虚拟货币进行投注&#xff0c;增加直播间的互动性和趣味性。所有货币均为虚拟货币&#xff0c;通过系统活动获取&#xff0c;不可充值提现。 数据…...

33.[前端开发-JavaScript基础]Day10-常见事件-鼠标事件-键盘事件-定时器-案例

1 window定时器 window定时器方法 setTimeout的使用 setInterval的使用 2 轮播消息提示 案例实战一 – 轮播消息提示 3 关闭隐藏消息 案例实战二 – 关闭隐藏消息 4 侧边栏展示 案例实战三 – 侧边栏展示 5 tab切换实现 案例实战四 – 登录框&#xff08;作业&#xff09;…...

C# 多标签浏览器 谷歌内核Csharp

采用框架 &#xff1a;FBrowserCEF3lib 视频演示&#xff1a;点我直达 成品下载&#xff1a; https://wwms.lanzouo.com/iYOd42rl8vje...

如何同步fork的更新

当你fork了一个代码仓库后&#xff0c;要将其与原始源码保持同步&#xff0c;可以按照以下步骤进行操作&#xff1a; 1. 添加原始仓库作为远程源 在本地命令行中&#xff0c;进入到你fork后的代码仓库目录&#xff0c;然后使用以下命令添加原始仓库&#xff08;通常称为upstr…...

如何从0设计开发一款JS-SDK

一、前言 前端SDK是什么&#xff1f;前端SDK是为了帮助前端实现特定需求&#xff0c;而向开发者暴露的一些JS-API的集合&#xff0c;规范的SDK包括若干API实现、说明文档等 前端SDK其实很常见了&#xff0c;比如&#xff1a; UI组件库&#xff1a;通过封装一系列组件&#xff…...

linux实现rsync+sersync实时数据备份

1.概述 rsync(Remote Sync) 是一个Unix/linux系统下的文件同步和传输工具 2.端口和运行模式 tcp/873 采用C/S模式&#xff08;客户端/服务器模式&#xff09; 3.特点 可以镜像保存整个目录和文件第一次全量备份(备份全部的文件),之后是增量备份(只备份变化的文件) 4. 数…...

【计算机网络】计算机网络协议、接口与服务全面解析——结合生活化案例与图文详解

协议、接口与服务 导读一、协议1.1 定义1.2 组成 二、接口三、服务3.1 定义3.2 服务与协议的区别3.3 分类3.3.1 面向连接服务于无连接服务3.3.2 可靠服务和不可靠服务3.3.3 有应答服务和无应答服务 结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;…...

51c自动驾驶~合集26

我自己的原文哦~ https://blog.51cto.com/whaosoft/11968755 #大模型/Sora/世界模型之间是什么关系 1 什么是大模型 人工智能大模型&#xff08;Artificial Intelligence Large Model&#xff0c;简称AI大模型&#xff09;是指具有庞大的参数规模和复杂程度的机器学习模…...

【汽车传感系统架构:借助传感获取安全】

为了将车辆自动化提升到一个新的水平&#xff0c;设计人员研究了 LiDAR 等传感器选项的权衡&#xff0c;并着眼于传感系统架构。 本文引用地址&#xff1a;https://www.eepw.com.cn/article/202503/468584.htm 每年&#xff0c;约有 120 万人死于道路交通事故&#xff0c;还有…...

【NUUO 摄像头】(弱口令登录漏洞)

漏洞简介&#xff1a;NUUO 是NUUO公司的一款小型网络硬盘录像机设备。 NUUO NVRMini2 3.0.8及之前版本中存在后门调试文件。远程攻击者可通过向后门文件handle_site_config.php发送特定的请求利用该漏洞执行任意命令。 1.Fofa搜索语句&#xff1a; 在Fofa网站&#xff0c;搜索&…...

论文阅读笔记:Denoising Diffusion Probabilistic Models (3)

论文阅读笔记&#xff1a;Denoising Diffusion Probabilistic Models (1) 论文阅读笔记&#xff1a;Denoising Diffusion Probabilistic Models (2) 论文阅读笔记&#xff1a;Denoising Diffusion Probabilistic Models (3) 4、损失函数逐项分析 可以看出 L L L总共分为了3项…...

【设计模式】抽象工厂模式(含与工厂方法模式的对比)

本期我们来学习一下设计模式之抽象工厂模式&#xff0c;在软件开发中&#xff0c;工厂模式 和 抽象工厂模式 都用于创建对象&#xff0c;但它们的应用场景和实现方式有所不同。本文将基于 C 代码&#xff0c;分析抽象工厂模式的实现&#xff0c;并对比其与工厂方法模式的区别。…...

消息队列保证最终一致性的优势

消息队列保证最终一致性的优势 使用消息队列&#xff08;如Kafka、RabbitMQ等&#xff09;来实现MySQL和Redis之间的最终一致性&#xff0c;具有以下几个显著优势&#xff1a; 1. 解耦系统组件 降低系统耦合度&#xff1a;生产者&#xff08;MySQL更新&#xff09;和消费者&…...

IDEA转战Trae AI IED配置

Trae Ai 的前身是vscode IDEA转战Trae AI IED配置 1.安装java相关的插件 2、安装spring相关的插件 3.配置maven环境 打开 Trae AI IDE -> 首选项 -> 设置 -> Editor 设置 ⚠️配置方式有两种 setting.json文件中直接编辑&#xff08;推荐&#xff09;界面设置 方案…...

再学:区块链基础与合约初探 EVM与GAS机制

目录 1.区块链是什么 2.remix ​3.账户​ ​4.以太坊三种交易​ 5.EVM 6.以太坊客户端节点 ​7.Gas费用 8.区块链浏览器 1.区块链是什么 只需要检验根节点 Merkel根是否有更改&#xff0c;就不用检查每个交易是否有更改。方便很多。 2.remix 3.账户 如果交易失败的话&…...

Nextjs15 - middleware的使用

nextjs 官方文档&#xff08;current branch 对应如下文档&#xff09; Middlewarepath-to-regexp 本专栏内容均可在Github&#xff1a;test_05/Middleware 找到 一、middleware 基本使用 中间件允许您在请求完成之前运行代码。然后&#xff0c;根据传入的请求&#xff0c;您…...

PHP If...Else 语句详解

PHP If...Else 语句详解 引言 PHP 是一种流行的服务器端脚本语言&#xff0c;常用于开发动态网站和应用程序。在 PHP 编程中&#xff0c;条件语句是编程逻辑的基础&#xff0c;其中 if...else 语句是最基本且最常用的条件语句之一。本文将详细介绍 PHP 的 if...else 语句&…...

Django之旅:第六节--mysql数据库操作增删改查(二)

前提条件(models.py已经设置好&#xff09;&#xff1a; from django.db import mmodelsclass UserInfo(models.Model):namemodels.CharFIeld(max_length32)passwordmodels.CharFIeld(max_length64)#agemodels.IntegerFIeld()操作数据语法&#xff08;在views.py文件&#xff0…...

【SUNO】【AI作词】【提示词】

仿写歌词提示词模板&#xff08;升级版&#xff09; 一、仿写目标 风格定位 音乐风格&#xff1a; [填写目标风格&#xff0c;如&#xff1a;民谣/流行/古风/电子/爵士等]参考案例&#xff1a;如《成都》的叙事民谣&#xff0c;《孤勇者》的励志流行。 情感基调&#xff1a; […...

边缘计算 vs. 云计算,谁才是工业物联网的未来?

前言 在物联网&#xff08;IoT&#xff09;飞速发展的今天&#xff0c;边缘计算正在彻底改变数据的处理、存储和分析方式。传统的IoT设备数据通常需要发送到云端进行处理&#xff0c;但随着设备数量的激增&#xff0c;这种模式在延迟、带宽和安全性方面暴露出诸多局限。边缘计…...

【Qt】QByteArray详解

QByteArray 是 Qt 框架中用于处理原始字节数据的核心类&#xff0c;其实质可以概括为以下几点&#xff1a; 1. 底层数据结构 • 连续内存块&#xff1a;存储一段连续的字节数据&#xff08;char*&#xff09;&#xff0c;类似 std::vector<char>&#xff0c;但针对 Qt 框…...

leetcode.189.轮转数组

第一次全反转&#xff0c;第二次反转前k个&#xff0c;第三次反转后n-k个 需要注意的是向又轮转k个时&#xff0c;如果超出数组长度&#xff0c;要对其进行取模运算才是正确的向右轮转个数 class Solution { private:void rotate(vector<int>& nums,int start,int …...

OCR 识别案例

OCR 识别案例 注意点&#xff1a;输入图像尺寸比例尽量和参与模型训练的数据集比例相似&#xff0c;识别效果会更好。 1、pytesseract Pytesseract是一个Python的光学字符识别&#xff08;OCR&#xff09;工具&#xff0c;它作为Tesseract OCR引擎的封装&#xff0c;允许你在…...

微信 MMTLS 协议详解(五):加密实现

常用的解密算法&#xff0c;对称非对称 加密&#xff0c;密钥协商&#xff0c; 带消息认证的加解密 #生成RSA 密钥对 void GenerateRsaKeypair(std::string& public_key,std::string& private_key) {RSA* rsa RSA_new();BIGNUM* bn BN_new();// 生成 RSA 密钥对BN_s…...

Mybatis配置文件解析(详细)

引言 在了解Mybatis如何帮助客户进行数据的存取后&#xff0c;便对Mybatis的配置文件起了兴趣&#xff0c;在查阅官方文档后&#xff0c;总结了平时能用到的配置&#xff0c;希望能对大家有帮助 1.核心配置文件 主要是指Mybatis-config.xml中 其包含了会深深影响Mybatis行为…...

有额外限制的 bellman_ford 算法

题目链接 1.有限制的 B e l l m a n _ F o r d Bellman\_Ford Bellman_Ford 时间复杂度: O ( N ∗ M ) O(N*M) O(N∗M) 在传统的 B e l l m a n _ F o r d Bellman\_Ford Bellman_Ford 中&#xff0c;可以处理边数不大于 K K K 条边的最短距离 但我们只要加一条限制(实际…...

深度剖析 Spring 源码 性能优化:核心原理与最佳实践

深度剖析 Spring 源码 & 性能优化&#xff1a;核心原理与最佳实践 &#x1f680; Spring 框架 作为 Java 生态的核心技术&#xff0c;广泛应用于企业级开发。但很多开发者只会“用”Spring&#xff0c;而不深入其内部原理&#xff0c;导致无法高效排查问题 & 进行性能优…...

【BFS】《单源、多源 BFS:图搜索算法的双生力量》

文章目录 前言单源BFS例题一、迷宫中离入口最近的出口二、 最小基因变化三、单词接龙四、为高尔夫比赛砍树 多源BFS例题一、 01 矩阵二、飞地的数量三、地图中的最高点四、地图分析 结语 前言 什么是单源、多源BFS算法问题呢&#xff1f; BFS&#xff08;Breadth - First Sear…...

【2025】基于springboot+vue的医院在线问诊系统设计与实现(源码、万字文档、图文修改、调试答疑)

基于Spring Boot Vue的医院在线问诊系统设计与实现功能结构图如下&#xff1a; 课题背景 随着互联网技术的飞速发展和人们生活水平的不断提高&#xff0c;传统医疗模式面临着诸多挑战&#xff0c;如患者就医排队时间长、医疗资源分配不均、医生工作压力大等。同时&#xff0c;…...

【前端】原生项目与框架项目区别

不定期更新&#xff0c;建议关注收藏点赞。 使用 HTML CSS JS 和 Vue 或 React 开发的项目各有其优势与不足&#xff0c;适用于不同的场景。目前基本上都采用框架&#xff0c; 总结 何时选择 HTML CSS JS&#xff1a; 适用于 小型项目、简单静态页面、不需要复杂交互 或 …...