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

.NET WebService \ WCF \ WebAPI 部署总结 以及 window 服务 调试

一、webservice 部署只能部署IIS上,
比较简单,就不做说明了

二、 WCF 部署 1
部署到IIS 跟部署 webservice 部署方法一样的
wcf 部署2
部署到控制台 要以管理员运行vs,或者 管理员运行 控制台的exe
在控制器项目中
创建IUserInfoService 接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApp1
{[ServiceContract]public interface  IUserInfoService{[OperationContract]int Add(int a, int b);}
}

在这里插入图片描述
实现接口
在这里插入图片描述
在app.config中增加
在这里插入图片描述

 <system.serviceModel><services><service name="ConsoleApp1.UserInfoService" behaviorConfiguration="behaviorConfiguration"><!--服务的对象--><host><baseAddresses><add baseAddress="http://localhost:8000/"/><!--服务的IP和端口号--></baseAddresses></host><endpoint address="" binding="basicHttpBinding" contract="ConsoleApp1.IUserInfoService"></endpoint><!--contract:服务契约--></service></services><behaviors><serviceBehaviors><behavior name="behaviorConfiguration"><serviceMetadata httpGetEnabled="true"/></behavior></serviceBehaviors></behaviors></system.serviceModel>

《《《启动服务
在这里插入图片描述
在这里插入图片描述

》》》验证是否有效
在这里插入图片描述
》》》如果不放在配置文件中
在这里插入图片描述
》》》

 using (ServiceHost host = new ServiceHost(typeof(UserInfoService))){host.AddServiceEndpoint(typeof(IUserInfoService), new WSHttpBinding(), "http://localhost:8686/userinfoservice");ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();behavior.HttpGetEnabled = true;behavior.HttpGetUrl = new Uri("http://localhost:8686/userinfoservice/metadata");host.Description.Behaviors.Add(behavior);host.Opened +=delegate{ Console.WriteLine("服务已启动");};host.Open();             Console.ReadKey();host.Close();}

》》》 校验是否成功

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

部署到winform

在这里插入图片描述

 private void button1_Click(object sender, EventArgs e){ServiceHost Host = new ServiceHost(typeof(WCF.Student));//绑定System.ServiceModel.Channels.Binding httpBinding = new BasicHttpBinding();//终结点Host.AddServiceEndpoint(typeof(IWCF.IStudent), httpBinding, "http://localhost:8002/");if (Host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null){//行为ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();behavior.HttpGetEnabled = true;//元数据地址behavior.HttpGetUrl = new Uri("http://localhost:8002");Host.Description.Behaviors.Add(behavior);//启动Host.Open();}}

》》》验证
在这里插入图片描述
app.config 配置

<service name="WCF.Student" behaviorConfiguration="behaviorConfiguration"><!--//服务的对象--><host><baseAddresses><add baseAddress="http://localhost:5678"/><!--// 服务的IP和端口号--></baseAddresses></host><endpoint address="" binding="wsHttpBinding" contract="IWCF.IStudent"></endpoint><!--//contract:服务契约--></service></services><behaviors><serviceBehaviors><behavior name="behaviorConfiguration"><serviceMetadata httpGetEnabled="true"/><serviceDebug includeExceptionDetailInFaults="False"/></behavior></serviceBehaviors></behaviors></system.serviceModel>

在这里插入图片描述

》》》》验证
在这里插入图片描述

WCF 宿主 服务中

在这里插入图片描述
在这里插入图片描述
》》》 app.config 或者写作code 都行
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
LocalService:充当本地计算机上非特权用户的帐户,该帐户将匿名凭据提供给所有远程服务器。

NetworkService:提供广泛的本地特权的帐户,该帐户将计算机的凭据提供给所有远程服务器。

LocalSystem:服务控制管理员使用的帐户,它具有本地计算机上的许多权限并作为网络上的计算机。

User:由网络上特定的用户定义的帐户。如果为 ServiceProcessInstaller.Account 成员指定 User,则会使系统在安装服务时提示输入有效的用户名和密码,除非您为 ServiceProcessInstaller 实例的 Username 和 Password 这两个属性设置值。

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

在这里插入图片描述

删除服务

sc delete 服务名称
在这里插入图片描述
在这里插入图片描述

window 服务调试
正常是无法调试的,可以在window服务中做调整
如下

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

在这里插入图片描述

window 服务 卸载

》》》1 在cmd中 录入 sc delete 服务名称 注意注意 是服务名称 不是显示名称

这种方法 不需要 停车服务,可以直接干掉

》》》2、 代码实现
卸载前,一定要停止掉Windows服务,否则需要重启或注销电脑。代码无法停止服务时,使用services.msc来停止。
获取系统所有window 服务
ServiceController[] services = ServiceController.GetServices();

》》》》“Service1.cs”的代码,增加服务启动日志和停止日志。

using CommonUtils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;namespace ADemoWinSvc
{public partial class Service1 : ServiceBase{public Service1(){InitializeComponent();}protected override void OnStart(string[] args){GLog.WLog("服务已启动");}protected override void OnStop(){GLog.WLog("服务已停止");}}
}

》》》》 工具类

using System;
using System.IO;namespace CommonUtils
{public static class GLog{static object _lockObj = new object();public static void WLog(string content){lock (_lockObj){string curPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName);string logDir = "Logs";string logDirFullName = Path.Combine(curPath, logDir);try{if (!Directory.Exists(logDirFullName))Directory.CreateDirectory(logDirFullName);}catch { return; }string fileName = "Logs" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";string logFullName = Path.Combine(logDirFullName, fileName);try{using (FileStream fs = new FileStream(logFullName, FileMode.Append, FileAccess.Write))using (StreamWriter sw = new StreamWriter(fs))sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " " + content);}catch { return; }}}}
}

========= 上面代码都是 服务中的

下面代码 是winForm程序中的==
在这里插入图片描述

using CommonUtils;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace Windows服务操作
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){}/// <summary>/// windows服务名/// </summary>static string _winSvcName = "ADemoWinSvc";/// <summary>/// windows服务对应的exe 名/// </summary>static string _winSvcExeName = "ADemoWinSvc.exe";private void btnSetup_Click(object sender, EventArgs e){try{//是否存在服务if (ServiceUtil.ServiceIsExisted(_winSvcName)){//已存在,检查是否启动if (ServiceUtil.IsRun(_winSvcName)){//服务是已启动状态lblMsg.Text = "[001]服务是已启动状态";}else{//未启动,则启动ServiceUtil.StarService(_winSvcName);lblMsg.Text = "[002]服务是已启动状态";}}else{//不存在,则安装IDictionary mySavedState = new Hashtable();string curPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName);string apppath = Path.Combine(curPath, _winSvcExeName);ServiceUtil.InstallService(mySavedState, apppath);lblMsg.Text = "[003]服务是已启动状态";//安装后并不会自动启动。需要启动这个服务ServiceUtil.StarService(_winSvcName);lblMsg.Text = "[004]服务是已启动状态";}}catch (Exception ex){MessageBox.Show(ex.Message);}}private void btnUninstall_Click(object sender, EventArgs e){//** 卸载服务最重要的是先停止,否则电脑需要重启或注销 **try{//是否存在服务if (!ServiceUtil.ServiceIsExisted(_winSvcName)){MessageBox.Show("服务不存在,不需要卸载");return;}//如果服务正在运行,停止它if (ServiceUtil.IsRun(_winSvcName)){ServiceUtil.StopService(_winSvcName);}//再检查一次是否在运行if (ServiceUtil.IsRun(_winSvcName)){MessageBox.Show("服务无法停止,请手动停止这个服务");return;}//卸载ServiceUtil.UnInstallServiceByName(_winSvcName);lblMsg.Text = "[005]服务已卸载";}catch (Exception ex){MessageBox.Show(ex.Message);}}}
}

》》》》》
AssemblyInstaller 帮助文件
https://learn.microsoft.com/zh-cn/dotnet/api/system.configuration.install.assemblyinstaller?view=netframework-4.8.1

》》》》 工具类

using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration.Install;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;namespace CommonUtils
{/// <summary>/// windows服务操作工具类/// </summary>public static class ServiceUtil{/// <summary>/// 服务是否正在运行/// </summary>/// <param name="name"></param>/// <returns></returns>public static bool IsRun(string name){bool IsRun = false;try{if (!ServiceIsExisted(name)) return false;var sc = new ServiceController(name);if (sc.Status == ServiceControllerStatus.StartPending || sc.Status == ServiceControllerStatus.Running){IsRun = true;}sc.Close();}catch{IsRun = false;}return IsRun;}/// <summary>/// 启动服务/// </summary>/// <param name="name"></param>/// <returns></returns>public static bool StarService(string name){try{var sc = new ServiceController(name);if (sc.Status == ServiceControllerStatus.Stopped || sc.Status == ServiceControllerStatus.StopPending){sc.Start();sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 10));}else{}sc.Close();return true;}catch (Exception ex){throw ex;}}/// <summary>/// 停止服务(有可能超时)/// </summary>/// <param name="name"></param>/// <returns></returns>public static bool StopService(string name){try{var sc = new ServiceController(name);if (sc.Status == ServiceControllerStatus.Running || sc.Status == ServiceControllerStatus.StartPending){sc.Stop();//停止服务超时时间:56秒。sc.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 56));}else{}sc.Close();return true;}catch (Exception ex){throw ex;}}/// <summary>/// 是否存在/// </summary>/// <param name="serviceName"></param>/// <returns></returns>public static bool ServiceIsExisted(string serviceName){ServiceController[] services = ServiceController.GetServices();foreach (ServiceController s in services)if (s.ServiceName.ToLower() == serviceName.ToLower())return true;return false;}/// <summary>/// 安装/// </summary>/// <param name="stateSaver"></param>/// <param name="filepath"></param>public static void InstallService(IDictionary stateSaver, string filepath){try{AssemblyInstaller myAssemblyInstaller = new AssemblyInstaller();myAssemblyInstaller.UseNewContext = true;myAssemblyInstaller.Path = filepath;myAssemblyInstaller.Install(stateSaver);myAssemblyInstaller.Commit(stateSaver);myAssemblyInstaller.Dispose();}catch (Exception ex){throw ex;}}/// <summary>/// 使用路径卸载(有时候不便于用路径来卸载,则使用SC DELETE 名称来卸载)/// </summary>/// <param name="filepath"></param>public static void UnInstallService(string filepath){try{AssemblyInstaller myAssemblyInstaller = new AssemblyInstaller();myAssemblyInstaller.UseNewContext = true;myAssemblyInstaller.Path = filepath;myAssemblyInstaller.Uninstall(null);myAssemblyInstaller.Dispose();}catch (Exception ex){throw ex;}}/// <summary>/// 使用windows服务名卸载/// </summary>/// <param name="WinServiceName"></param>public static void UnInstallServiceByName(string WinServiceName){ProcessStartInfo pStart = new ProcessStartInfo("sc.exe");Process pRoc = new Process();pStart.Arguments = " delete " + WinServiceName;pStart.UseShellExecute = false;pStart.CreateNoWindow = false;pRoc.StartInfo = pStart;pRoc.Start();pRoc.WaitForExit();}}
}

WebAPI 部署

部署 IIS

跟wcf 、webservice 一样。

部署 控制台

相关文章:

.NET WebService \ WCF \ WebAPI 部署总结 以及 window 服务 调试

一、webservice 部署只能部署IIS上&#xff0c; 比较简单&#xff0c;就不做说明了 二、 WCF 部署 1 部署到IIS 跟部署 webservice 部署方法一样的 wcf 部署2 部署到控制台 要以管理员运行vs&#xff0c;或者 管理员运行 控制台的exe 在控制器项目中 创建IUserInfoService 接口…...

Centos系统实用运维命令记录(持续更新)

本文记录Centos服务器常用的运维命令&#xff0c;备忘 查询当前内存占用最高(前10)的进程列表和占用比例&#xff0c;进程ID ps -eo pid,comm,%mem,cmd --sort-%mem | head -n 11注: 内存警报时定位问题时非常有用 查询占用某个端口号的进程id lsof -i :9000注: 后面的9000…...

大势模方在修模过程中,如何导入su单体模型?

答&#xff1a;在单体化界面右键即可显示导入入口&#xff0c;若仍不可行&#xff0c;需要换最新版dv 模方是一款针对实景三维模型的冗余碎片、水面残缺、道路不平、标牌破损、纹理拉伸模糊等共性问题研发的实景三维模型修复编辑软件。模方4.1新增自动单体化建模功能&#xff…...

uniapp百度地图聚合

// loadBMap.js ak 百度key export default function loadBMap(ak) {return new Promise((resolve, reject) > {//聚合API依赖基础库,因此先加载基础库再加载聚合APIasyncLoadBaiduJs(ak).then(() > {// 调用加载第三方组件js公共方法加载其他资源库// 加载聚合API// Ma…...

nginx的应用部署nginx

这里写目录标题 nginxnginx的优点什么是集群常见的集群什么是正向代理、反向代理、透明代理常见的代理技术正向代理反向代理透明代理 nginx部署 nginx nginx&#xff08;发音同enginex&#xff09;是一款轻量级的Web服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&…...

Centos固定静态ip地址

这里我用的是Vmware虚拟机搭建的三台机器 进入 cd /etc/sysconfig/network-scripts然后使用 ip addr命令&#xff0c;查看自己虚拟机的以太网地址。 我这里是ens33 上面的第一个选项是本地环回地址&#xff0c;不用管它 然后查看刚刚进入的network-scripts目录下的文件 找到…...

豆芽机置入语音芯片WTN6040-8S:开启智能生活新篇章,让豆芽制作更便捷有趣

豆芽机的开发背景&#xff1a; 豆芽作为一种营养丰富、味道鲜美的食品&#xff0c;深受广大消费者的喜爱。然而&#xff0c;传统的豆芽生产过程繁琐&#xff0c;需要耗费大量的时间和人力&#xff0c;且存在生产效率低、质量不稳定等问题。随着人们生活节奏的加快和对健康饮食的…...

BLIP2预研笔记

0. 前言 文章是公司内部分享学习写的预研报告&#xff0c;里面有小部分文段是直接从网上借鉴的&#xff0c;侵删 1. 任务和方法历史进化&#xff1a; 在大模型等类似的预训练模型的方式&#xff08;以包含“预训练阶段”等n阶段训练方式为特色&#xff09;为主流之前&#xf…...

安卓开发问题:安卓Ble出现动态鉴权失败以及扫描设备一直进入不了的问题

问题1描述 1、安卓12需要动态鉴权 // 鉴权函数 requestPermissions(permissionsList.toArray(strings), MyConstants.REQUEST_CODE_PERMISSIONS);但是在鉴权回调函数中如Manifest.permission.BLUETOOTH_SCAN、Manifest.permission.BLUETOOTH_CONNECT一直显示失败&…...

DSP ARM FPGA 实验箱_音频处理_滤波操作教程:3-9 音频信号的滤波实验

一、实验目的 掌握Matlab辅助设计滤波器系数的方法&#xff0c;并实现音频混噪及IIR滤波器滤除&#xff0c;并在LCD上显示音频信号的FFT计算结果。 二、实验原理 音频接口采用的是24.576MHz&#xff08;读兆赫兹&#xff09;晶振&#xff0c;实验板上共有3个音频端口&#x…...

Rust多线程交叉打印+Send Sync特征讲解

导航 Rust多线程交叉打印Send Sync特征讲解 一、Rust多线程交叉打印二、Send Sync 特征讲解 Rust多线程交叉打印Send Sync特征讲解 一、Rust多线程交叉打印 先说背景有两个线程&#xff0c;分别为0号线程和1号线线程两个线程交叉打印共享值&#xff0c;并将共享值1当标志为fa…...

C#爬虫爬取某东商品信息

&#x1f3c6;作者&#xff1a;科技、互联网行业优质创作者 &#x1f3c6;专注领域&#xff1a;.Net技术、软件架构、人工智能、数字化转型、DeveloperSharp、微服务、工业互联网、智能制造 &#x1f3c6;欢迎关注我&#xff08;Net数字智慧化基地&#xff09;&#xff0c;里面…...

【Stylus详解与引入】

文章目录 Stylus详解与引入一、Stylus简介二、Stylus的特性1. 变量2. 嵌套规则3. 混合&#xff08;Mixins&#xff09;4. 函数5. 条件语句和循环 三、Stylus的引入与配置1. 安装Stylus和stylus-loader2. 配置Webpack3. 在Vue项目中使用Stylus4. 编译Stylus代码四、Stylus的性能…...

001 登录(md5加密)

文章目录 pom.xmlLoginController.javaUserMapper.javaUser.javaUserServiceImpl.javaUserService.javaMD5Util.javaMD5UtilTest.javaValidatorUtil.javaLoginVo.javaRespBean.javaRespBeanEnum.javaSeckillApplication.javaUserMapper.xmllogin.htmlapplication.yamlsql 传统方…...

Linux学习笔记5---WSL2编译裸机程序并烧录至SD卡

在用WLS进行开发的时候发现在mnt/底下竟然识别不了U盘&#xff01;&#xff01;也识别不了SD卡&#xff01;&#xff01;那程序不就不能烧录到SD卡上了&#xff1f;&#xff1f;&#xff1f;那还开发个锤子。 在网上查找了一些相关资料&#xff0c;发现可以通过Win32DiskImager…...

React 第二十九章 React 和 Vue 描述页面的区别

面试题&#xff1a;React 和 Vue 是如何描述 UI 界面的&#xff1f;有一些什么样的区别&#xff1f; 标准且浅显的回答&#xff1a; React 中使用的是 JSX&#xff0c;Vue 中使用的是模板来描述界面 前端领域经过长期的发展&#xff0c;目前有两种主流的描述 UI 的方案&#xf…...

Dnspy附加进程调试---代码被优化及无法获取局部变量

代码被优化或者无法获取局部变量的效果图如下&#xff1a; 当你在调试的时候&#xff0c;看到这种情况还是挺恼火的&#xff0c;经过查阅资料后&#xff0c;发现可以这种解决&#xff1a; 参考链接&#xff1a;Making an Image Easier to Debug dnSpy/dnSpy Wiki GitHub 假设…...

Redis---------实现更改数据业务,包括缓存更新,缓存穿透雪崩击穿的处理

三种更新策略 内存淘汰是Redis内存的自动操作&#xff0c;当内存快满了就会触发内存淘汰。超时剔除则是在存储Redis时加上其有限期(expire)&#xff0c;有限期一过就会自动删除掉。而主动更新则是自己编写代码去保持更新&#xff0c;所以接下来研究主动更新策略。 主动更新策略…...

蓝牙小车的具体实现

title: 蓝牙小车开发时的一些细节 cover: >- https://tse1-mm.cn.bing.net/th/id/OIP-C.BrSgB91U1MPHGyaaZEqcbwHaEo?w273&h180&c7&r0&o5&dpr1.3&pid1.7 abbrlink: 842d5faf date: tags: #小车基本运动之最重要的—PWM ##1.PWM&#xff08;Pulse …...

污染修复乙级设计资质中关于设计成果保护的规定

关于污染修复乙级设计资质中设计成果的保护&#xff0c;虽然直接针对该资质的设计成果保护规定可能未在公开资料中有详细阐述&#xff0c;但根据中国知识产权法律体系和行业惯例&#xff0c;设计成果作为智力成果的一部分&#xff0c;主要受以下几个方面的法律保护&#xff1a;…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...