前言

先说结论:blazor做Web开发绝对好东西。对于我个人来说,有两个重要的原因:

  • 特别喜欢C#
  • 特别不喜欢JavaScript

在了解到blazor居然可以使用c#做Web开发且完全可以不用编写JavaScript代码时,第一感受是,居然有这么懂自己的东西,果断尝鲜体验!

网上大概也了解了一下,基本上都说得过于官方和理论,不够简单直接,这里直接说调研的结论。

  • 使用blazor做web开发非常地高效(包括前后端),而且还是在资料不多的情况下(生态不太好,但绝对是好东西)。
  • blazor提供两种模式:WebAssemblyServer
  • 建议使用 Server 模式,WebAssembly慢的受不了,一个简单的demo首次启动和每次刷新时都要将近 10秒钟时间,而相同demo项目Server模式基本是瞬间显示的。
  • WebAssembly模式还有一个弊端:目前只有一个线程,容易出现 UI 界面卡死的问题。据说以后会改,谁知道啥时候呢。
  • 简单的项目没必要搞什么前后分离,前后端分离也要看项目大小,小项目直接用混合模式也挺好的。
  • 简单项目使用 Server 模式就可以完全前后端一锅端了,非常的简单高效。
  • 如果前端设计能像客户端界面开发那样有控件拖放,就无敌了。

笔者本身不是做web开发的,但是对全栈比较感兴趣,在前几年也接触和体验了一下SpringBoot开发框架,参见:SpringBoot极简教程,因为个人不喜欢Java更青睐c#,所以体验之后弄清楚如何使用及流程也就作罢了,日后并没有再接触使用。但是有了之前的了解,至少有了web开发的基础知识储备,因此此次使用blazor也会比较地快和顺利。这一次也会以一个具体的demo项目来做介绍:搭建一个局域网环境使用的APP管理平台

背景是这样的:在很久之前我们团队就想搭建一个这样的内部平台,但是我们都是客户端开发(非前端开发),对这块没有经验也不擅长,也就作罢了。我们是做安卓安全研究的,日常会遇到各种各样的样本,具有重复使用的价值,但是都散落在组内各人自己的电脑里,没有汇总起来,时间久了也容易找不到。如果能在内网搭建一个这样的样本管理平台就好了,遇到新样本的时候上传上去,需要的时候检索下载下来。我们也想过用共享文件夹ftp服务器的形式搭建,但是这都是单纯的文件上传和下载,没有样本的基础信息,并没有使用开来。

但这个需求也不算是刚需,只能说有了更好。但是在遇到blazor的时候,我就想大胆试一下,本身C#的开发效率非常高,心想应该花不了多少时间,于是开始构思:

  • 需要有文件上传的功能;
  • 需要有对APP样本文件进行解析的功能,并做基础信息的展示;
  • 能检索和下载样本文件;

本着快速编程实现的想法,就想着如果能找到现成的代码改一改就行了,于是从blazor文件上传的关键词找到了这个demo:File Upload with Blazor WebAssembly and ASP.NET Core Web API,GitHub地址:CodeMazeBlog/blazor-series at blazor-file-upload。工程里面有两个项目,分别是server(服务端)和client(客户端)。这是一个前后端分离的项目,结构比较清晰,如果打算上手学习blazor,是一个非常好的入门练手项目。这是一个管理产品(product)的demo,基本上和我的需求类似,所以就拿这个开刀修改起来。遇到了一些坑:

  • 这个前端是WebAssembly模式,问题很严重,就是前面提的速度超级慢和界面卡死问题;
  • 服务端连接的数据库是SQL Server的,这个遇到问题不好解决花了一些时间,网上MySQL的资料多一些,好在及时换成了MySQL

全程是以逆向工程的思路去实现的,遇到了非常多的问题,基本就是遇到一个解决一个,最终把项目跑起来了,效果图如下:

主要功能介绍:

  • 打开链接 http://[ip地址]:5000/apps 即可显示样本列表;
  • 支持按照名称检索样本;
  • 支持按照不同字段排序,默认按照更新时间倒叙显示;
  • 支持一键浏览本地文件上传,服务端自动解析样本信息并入库;
  • 支持样本信息的删除和更新;
  • 默认局域网内http方式无登录授权访问;
  • 点击图标下载样本到本地电脑;

后面的教程会以正向工程的顺序讲解,然后穿插一些实际修改demo项目的经验和问题。

一、数据库配置

1、数据库软件安装

  • MariaDB,账号密码弄个测试的简单一点的:root/123
  • 安装:ODBC Connector - MariaDB Knowledge Base
  • Navicat:可视化操作数据库,不用敲SQL命令,方面快捷;

2、VisualStudio连接MySQL

VisualStudio默认使用的数据库是SQL Server,先改为链接MySQL的数据库,这里使用开源的MariaDBVisualStudio链接MariaDB数据库需要通过ODBC方式,因此需要安装ODBC Connector - MariaDB Knowledge Base,然后进行ODBC数据源配置:

  • 打开 ODBC数据源管理程序(Win + R 输入命令:odbcad32 );
  • 添加,选择:MariaDB ODBC 3.0 Driver,Name填:MariaDB,下一步;
  • 选择:TCP/IP,ServerName填:127.0.0.1,User name和Password分别填:root 123
  • Test DSN,提示成功说明配置正确,后面一路下一步即可。
  • VisualStudio里打开菜单工具 - 连接到数据库,选择:Microsoft ODBC 数据源,刚刚的MariaDB名称,就能在服务器资源管理器里看到数据库链接了。

参考:

  • MariaDB + Visual Studio 2017 环境下的 ODBC 入门开发

  • 参考:How to Use MySQL Database With .Net Core And Entity Framework?

3、创建数据库和表

  • 打开MariaDB控制台,创建数据库:CREATE DATABASE appdb;然后source apps.sql;,apps.sql内容如下(可以在Navicat里设计,比较方便):
/*Navicat Premium Data TransferSource Server         : 127.0.0.1Source Server Type    : MySQLSource Server Version : 101100 (10.11.0-MariaDB)Source Host           : localhost:3306Source Schema         : appdbTarget Server Type    : MySQLTarget Server Version : 101100 (10.11.0-MariaDB)File Encoding         : 65001Date: 18/11/2022 00:16:42
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for apps
-- ----------------------------
DROP TABLE IF EXISTS `apps`;
CREATE TABLE `apps`  (`Id` bigint NOT NULL AUTO_INCREMENT,`Name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,`Package` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,`Icon` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,`VersionName` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`VersionCode` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`ShellName` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`Tags` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`Memo` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`Operator` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`dbPath` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,`Url` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,`CreationDate` datetime(6) NOT NULL DEFAULT current_timestamp(6),`ModifiedDate` datetime(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE CURRENT_TIMESTAMP(6),`Md5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '',`FileSize` int UNSIGNED NULL DEFAULT 0,PRIMARY KEY (`Id`) USING BTREE,UNIQUE INDEX `index_id`(`Id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 41 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;-- ----------------------------
-- Records of apps
-- ----------------------------
INSERT INTO `apps` VALUES (36, '测试App', 'com.test', 'https://appimg.dbankcdn.com/application/icon144/629336112d984dc1950f3992e0efdae0.png', '1.1', '2133', '360', NULL, '这个包有xxx的问题,版本发布的时候可以测一下', 'zhangsan', 'share\\app\\dytt8.apk', 'file:\\\\192.168.1.2\\share\\app\\dytt8.apk', '2022-11-17 23:44:00.872375', '2022-11-17 23:55:03.068345', NULL, 1973292);
INSERT INTO `apps` VALUES (38, '测试App', 'com.test', 'https://appimg.dbankcdn.com/application/icon144/629336112d984dc1950f3992e0efdae0.png', '1.1', '2133', '无', '加固 隐私', '这个包有xxx的问题,版本发布的时候可以测一下', 'zhangsan', 'share\\app\\184543_3.apk', 'file:\\\\192.168.1.2\\share\\app\\184543_3.apk', '2022-11-17 23:47:57.061125', '2022-11-18 00:10:47.843875', NULL, 46668230);
INSERT INTO `apps` VALUES (39, '测试App', 'com.test', 'https://appimg.dbankcdn.com/application/icon144/629336112d984dc1950f3992e0efdae0.png', '1.1', '2133', '无', NULL, '这个包有xxx的问题,版本发布的时候可以测一下', 'zhangsan', 'share\\app\\dytt8.apk', 'file:\\\\192.168.1.2\\share\\app\\dytt8.apk', '2022-11-18 00:02:13.713289', '2022-11-18 00:02:13.715084', NULL, 1973292);SET FOREIGN_KEY_CHECKS = 1;
  • 创建一个名为AppInfo的Model:

    public class AppInfo {//[Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)]public long Id { get; set; }// App名称//[Required(ErrorMessage = "Name is required field")][StringLength(maximumLength: 64)]public string Name { get; set; }// 包名//[Required(ErrorMessage = "Package is required field")][StringLength(maximumLength: 100, MinimumLength = 3)]public string Package { get; set; }// 图标public string Icon { get; set; }// 版本号[StringLength(maximumLength: 32)]public string VersionName { get; set; }[StringLength(maximumLength: 32)]public string VersionCode { get; set; }// 壳特征名称[StringLength(maximumLength: 32)]public string ShellName { get; set; } = "null";// 标签[StringLength(maximumLength: 64)]public string Tags { get; set; }// 备注[StringLength(maximumLength: 128)]public string Memo { get; set; }// 操作人员[StringLength(maximumLength: 32)]public string Operator { get; set; }// 数据库存储路径(相对路径)public string dbPath { get; set; }public string Url { get; set; }public DateTime CreationDate { get; set; }// 对应的是自动更新时间的数据库字段[DatabaseGenerated(DatabaseGeneratedOption.Computed)]public DateTime ModifiedDate { get; set; }public string Md5 { get; set; }public long FileSize { get; set; }
    }
    
  • 服务端项目(BlazorDemo.Server)添加三方库:Pomelo.EntityFrameworkCore.MySql,然后修改Startup.cs函数ConfigureServices的代码为:

    var connectionString = Configuration.GetConnectionString("sqlConnection");
    services.AddDbContext<ProductContext>(opt => opt.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));
    
  • 服务端appsettings.json修改为:

    {"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information","Microsoft.EntityFrameworkCore": "Information"}},"ConnectionStrings": {"sqlConnection": "SERVER=127.0.0.1;UID=root;PWD=123; database=appdb;"},"AllowedHosts": "*"
    }
    

4、数据库迁移操作

在VisualStudio的PM控制台下输入命令。

Add-Migration Initial
Update-Database
Remove-Migration

二、服务器配置

一共需要设置 4 个服务器,分别是:

  1. 部署前端的服务器;

  2. 部署API接口的服务器;

  3. 数据库服务器;

  4. 文件下载服务器;

其实前两个服务器可以合并为一个。因为我们是内网使用,所有的服务器最后都用了同一台Windows普通电脑来完成。

先说最简单的文件服务器,直接使用Python的一句话命令就可以完成了。在电脑上选择一个目录作为存储样本文件使用,例如E:\share,然后在该目录下创建一个批处理文件httpServer.bat,内容:python -m http.server,每次需要启动文件服务器的时候运行下httpServer.bat即可。如果全部使用dotnet技术栈,内容也可以是:

Rem python -m http.server
Rem dotnet tool install --global dotnet-serve
dotnet-serve -p 8000 -a 0.0.0.0

前后端可以分离开发,也可以混合开发。一开始借鉴的开源代码是前后端分离的,但是后来因为修改成了server模式,变成了混合模式。但是无论哪种都可以把前后端的项目部署在同一台服务器上,仅仅是开放的端口不一样罢了。最终配置如下:

  • 服务端(BlazorDemo.Server)的launchSettings.json内容:

    {"iisSettings": {"windowsAuthentication": false,"anonymousAuthentication": true,"iisExpress": {"applicationUrl": "http://localhost:52497","sslPort": 0}},"profiles": {"BlazorDemo.Server": {"commandName": "Project","launchBrowser": false,"applicationUrl": "http://localhost:5010;http://*:5010","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}}}
    }
    
  • 前端(BlazorDemo.Client)的appsettings.json内容:

    {"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": "*"
    }
    

三、支持局域网访问

https的配置比较麻烦,而且第一次玩这个,不想太花时间折腾,本着先跑通的想法,先简单弄起来。如果是新创建项目的话,就不要勾选https即可。

  • server项目里面Startup.cs文件Configure函数注释掉这两句调用:

    //app.UseHttpsRedirection();
    //app.UseAuthorization();
    
  • server项目launchSettings.json去掉对https的支持,修改为:

    {"iisSettings": {"windowsAuthentication": false,"anonymousAuthentication": true,"iisExpress": {"applicationUrl": "http://localhost:52497","sslPort": 0}},"profiles": {"BlazorProducts.Server": {"commandName": "Project","launchBrowser": false,"applicationUrl": "http://localhost:5010;http://*:5010","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}}}
    }
    
  • client项目的launchSettings.json去掉对https的支持,修改为:

{"profiles": {"BlazorProducts.Client": {"commandName": "Project","dotnetRunMessages": "true","launchBrowser": true,"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}","applicationUrl": "http://localhost:5000;http://*:5000;","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}}}
}
  • client项目代码里面凡是涉及到API接口调用的地方,一律修改为 http://作为服务器的电脑的具体IP地址:5010

四、界面组件

千万不要自己从零去写,没经验的话比较花时间,强烈推荐使用 Bootstrap Blazor - 企业级 UI 组件库 ,是个开源项目,GitHub地址见:BootstrapBlazor,总体使用比较方便,官网有详细使用教程和示例代码,直接拿来使用即可。文件上传功能就是直接用了这个 上传组件 Upload ,很方便,开发效率很高,使用的组件情况如下。

删除确认弹框:

<PopConfirmButton OnConfirm="()=>{Apps.Remove(app); Delete(app); StateHasChanged(); return Task.CompletedTask; }" Placement="Placement.Bottom" Color="Color.Danger" ConfirmIcon="fa-solid fa-triangle-exclamation text-danger" ConfirmButtonColor="Color.Danger" Text="删除" Content="确定删除数据吗?" />

文件上传:

<ButtonUpload BrowserButtonText="上传APP" TValue="string" IsMultiple="true" ShowProgress="true" OnChange="@OnClickToUpload" OnDelete="@(fileName => Task.FromResult(true))"></ButtonUpload>private async Task OnClickToUpload(UploadFile file) {await SaveToFile(file);
}

消息通知(消息提示):

[Inject]
[NotNull]
private MessageService? MessageService { get; set; }await MessageService.Show(new MessageOption() {Content = e.Message
});

五、全局异常处理

这个可以借鉴 深入浅出Blazor webassembly之异常错误显示,也可以直接使用 全局异常 - Bootstrap Blazor - 企业级 UI 组件库。

六、发布部署

发布

两种方法:

  1. 使用VisualStudio菜单:生成 - 发布,按照向导生成。
  2. 使用dotnet命令:dotnet publish -c Release

部署

  • 选择一台Windows电脑作为服务器使用,记录其 IP 地址;

  • 安装:dotnet、MariaDB(账号密码弄个测试的简单一点的:root/123)、ODBC Connector - MariaDB Knowledge Base

  • 配置好数据库;

  • 选择一个文件夹作为http服务器,目录下放好httpServer.bat,一键运行开启http服务。

  • 为保证局域网的其他设备能够访问,客户端和服务端的appsettings.json做好类似如下配置:

    "AllowedHosts": "*",
    "Urls": "http://*:5010",
    
  • 配置ApkInfoTool工具;

  • 启动服务端:dotnet run

  • 启动前端:dotnet run

  • 其他设备访问地址:http://IP地址:5000

七、注意事项

  • 服务器项目里的接口函数一律要用anync Task返回类型,否则容易出现错误:Cannot access a disposed context instance,参考:Resolved- DBContext ObjectDisposedException:Cannot access a disposed of object

  • WebAssembly的缺点:不支持多线程容易UI卡死;启动和刷新速度特别慢;

  • 新建项目的时候勾选ASP.NET Core托管自动生成的解决方案包含三个项目,服务端也一并包含;

  • 回调函数用await InvokeAsync,例如:

    _timer = new Timer(async (sender) => {await InvokeAsync(() => {SearchCallback.InvokeAsync(SearchText);});_timer.Dispose();
    }, null, 500, 0);
    
  • UI的响应函数类型要用async Task,如果内部没有调用异步函数,可以在最后调用下:await Task.CompletedTask;,例如:

    public partial class Search {private Timer _timer;public string SearchText { get; set; }[Parameter]public EventCallback<string> SearchCallback { get; set; }private async Task OnSearch() {if (_timer != null)_timer.Dispose();_timer = new Timer(async (sender) => {await InvokeAsync(() => {SearchCallback.InvokeAsync(SearchText);});_timer.Dispose();}, null, 500, 0);await Task.CompletedTask;}
    }
    

参考

  • 学习ASP.NET Core Blazor编程系列四——迁移 - DotNet菜园
  • net::ERR_CERT_AUTHORITY_INVALID 在 ASP.NET Core 中
  • ASP.NET内核中的net::ERR_CERT_AUTHORITY_INVALID - 问答 - 腾讯云开发者社区-腾讯云
  • MariaDB + Visual Studio 2017 环境下的 ODBC 入门开发
  • 文件上传参考:Upload files using InputFile component in Blazor,上传进度参考:c# web api post with progress reporting
  • 增删改查参考:Asp.Net Core Blazor 开发体验
  • fix to OnInitializedAsync being called twice in Blazor server project
  • Blazor Navigation: Update URL without changing reloading page

开源项目参考:

  • CodeMazeBlog/blazor-series at blazor-file-upload
  • ErikXu/kubernetes-filesystem: System to browse, upload or download files for pods or containers in kubernetes.
  • WebApiClient: An open source project based on the HttpClient. You only need to define the c# interface and modify the related features to invoke the client library of the remote http interface asynchronously.
  • 原文 — 朱皮特的烂笔头

C#Web开发之blazor体验相关推荐

  1. 17. 【移动Web开发之flex布局】

    文章目录 [移动Web开发之flex布局]前端小抄(17) 一.flex布局体验 1.1 传统布局与flex布局 1.2 初体验 二.flex布局原理 2.1 布局原理 三.flex布局父项常见属性 ...

  2. 「学习笔记」移动Web开发之flex布局9

    「学习笔记」移动Web开发之flex布局9 一.flex布局体验 1.1 传统布局与flex布局 1.2 初体验 二.flex布局原理 2.1 布局原理 三.flex布局父项常见属性 3.1 常见父项 ...

  3. 移动web开发之rem布局(rem基础、媒体查询、 less 基础、rem适配方案)

    移动web开发之rem布局 一.rem基础 rem单位 rem (root em)是一个相对单位,类似于em,em是父元素字体大小. 不同的是rem的基准是相对于html元素的字体大小. 比如,根元素 ...

  4. WEB开发之HTML与CSS够用即可-庞永旺-专题视频课程

    WEB开发之HTML与CSS够用即可-113人已学习 课程介绍         讲解常用的HTML标签与CSS样式.这些常用的HTML标签与CSS样式都是本人多年从业经验的总结.只要熟练我总结的HTM ...

  5. 移动WEB开发之-REM(rem)布局

    目录 移动WEB开发之REM布局 rem基础 rem单位 媒体查询 什么是媒体查询 媒体查询语法规范 1.mediatype 查询类型 2.关键字 3.媒体特性 4.媒体查询书写规则 less 基础 ...

  6. Python Web开发之WSGI

    Python Web开发之WSGI WSGI(全称Web Server Gate Interface,Web服务器网关接口)是Python为了规范和简化Web服务开发过程,定义了一种Web服务器和应用 ...

  7. Swift Web 开发之 Vapor - 入门(一)

    简介 Vapor 是一个基于纯 Swift 构建出的 Web 开发框架,目前可以运行在 macOS 和 Ubuntu ,用于构建出漂亮易用的网站或者 API 服务. 官方称是用的最多的 Swift w ...

  8. Swift Web 开发之 Vapor - 模版 Leaf(三)

    模版引擎,对现在的 Web 开发极为重要,几乎所有主流 Web 框架都会支持一种或多种模版引擎,模版引擎可以分离用户界面和业务逻辑,工作原理主要是一种翻译,后端对特定的标记.语法.变量等渲染后再输送给 ...

  9. 18. 【移动Web开发之rem适配布局】

    文章目录 [移动Web开发之rem适配布局]前端小抄(18) 一.rem单位 1.1 rem 单位 二.媒体查询 2.1 什么是媒体查询 2.2 语法规范 2.2.1 mediatype 查询类型 2 ...

最新文章

  1. 幼儿园python_[Python]猜数字游戏AI版的实现(幼儿园智商AI)
  2. 解决在Ubuntu下打开txt文件乱码的问题
  3. RelativeLayout和LinearLayout性能比较
  4. 使用Samba服务器构建私有和公共共享目录
  5. linux网络编程之sockaddr_in和in_addr区别
  6. python二进制、字符编码及文件操作
  7. linux系统安装windows 环境中文字体
  8. 浅谈微信小程序开发工具
  9. android剪贴板历史,可能是史上最便捷的剪贴板应用 -- Native Clipboard #Android
  10. 在php中插入表格,word怎么插入表格
  11. Burg法求解AR(p)模型参数(一)自回归模型
  12. 怎么把ppt文字大小设置一致_iPhone12暖屏怎么办 iPhone12暖屏解决方法
  13. [Python爬虫] 九、机器视觉与机器图像识别之Tesseract
  14. 关于 z-Stack MT层的使用
  15. NV显卡 终于被我查到了
  16. layui实现导出全部数据Excel
  17. python清洗文本_用python清洗文本文件
  18. 组件嵌套(对应米斯特吴19)
  19. 西门子触摸屏脚本程序_触摸屏脚本调试-工业支持中心-西门子中国
  20. 蓝牙低功耗技术的传输速率

热门文章

  1. 谷粒商城项目1——分布式基础概念、环境搭建
  2. golang环境-linux
  3. 如何快速将json文件转换为对应的ts类型
  4. DatabaseMetaData查询集群下的库名
  5. PHP一句话木马免杀学习
  6. 一把王者荣耀的时间打卡剑指 Offer简单入门题
  7. MYSQL--架构--MGR--理论--01--MGR是什么
  8. 九龙证券|直逼1.5万亿!A股融资余额创年内新高,青睐这些行业和个股
  9. MAC/Linux 压缩/解压缩命令大全整理 gzip / tar / zip
  10. 赤金烈焰显示与服务器断开,赤金烈焰单职业迷失版