博客 (101)

image.png

打开项目文件,在 <ItemGroup /> 中添加一个 <DotNetCliToolReference />:(注意版本号)

<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.3" />

image.png

参考:https://stackoverflow.com/questions/45091909/dotnet-ef-database-update-no-executable-found-matching-command-dotnet-ef?r=SearchResults

结果:

image.png

xoyozo 6 年前
6,734
  1. 微信的 H5 页面前端引导到:

    https://api.magcloud.cc/magshare/{siteId}?jump_url={jump_url}&content_url={content_url}

    各参数含义见官方文档:http://doc.magcloud.net/325339

    content_url 地址(一般仍为活动页面)接收参数 magshareredirect,值为 1 则跳转到自定义的引导页。

  2. 自定义引导页按 iOS 和安卓显示图文和箭头,引导用户点击右上角菜单,在浏览器中打开。

  3. 在浏览器 H5 中引导打开:

    {siteId}://pagejump?jump_url={jump_url}

    各参数含义见第 1 步中的文档。

    这里涉及一个“若未安装则引导安装”的过程,可以选择下方合适的一种方式实现:

    • A 标签的 href 填入下载地址,onclick 事件 location 到 App

    • onclick 事件 location 到 App,再用 setTimeOut location 到下载地址

    • 若仍无法实现预期效果,可以在弹出层中放置“未安装,前往下载”和“已安装,立即打开”两个按钮,让用户自己选择

  4. 若下载地址为应用宝,那么在 iOS 中可能会出现“打开 App 后继而自动打开 App Store”的情况,可以自建中转的 App 介绍页引导到 App Store 或应用宝。

  5. 分别实现微信和 MAGAPP 客户端的分享

xoyozo 6 年前
6,455

本文介绍 ASP.NET 的 Swagger 部署,若您使用 ASP.NET Core 应用程序,请移步 ASP.NET Core Web API Swagger 官方文档:

https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/first-web-api?view=aspnetcore-5.0&tabs=visual-studio

https://github.com/domaindrivendev/Swashbuckle.AspNetCore


安装

NuGet 中搜索安装 Swashbuckle,作者 Richard Morris


访问

http://您的域名/swagger


配置


显示描述

以将描述文件(xml)存放到项目的 bin 目录为例:

  1. 打开项目属性,切换到“生成”选项卡

  2. 在“配置”下拉框选择“所有配置”

  3. 更改“输出路径”为:bin\

  4. 勾选“XML 文档文件”:bin\******.xml,(默认以程序集名称命名)

  5. 打开文件:App_Start/SwaggerConfig.cs

  6. 取消注释:c.IncludeXmlComments(GetXmlCommentsPath());

  7. 添加方法:

    public static string GetXmlCommentsPath()
    {
        return System.IO.Path.Combine(
            System.AppDomain.CurrentDomain.BaseDirectory,
            "bin",
            string.Format("{0}.xml", typeof(SwaggerConfig).Assembly.GetName().Name));
    }

    其中 Combine 方法的第 2 个参数是项目中存放 xml 描述文件的位置,第 3 个参数即以程序集名称作为文件名,与项目属性中配置一致。

如遇到以下错误,请检查第 2、3、4 步骤中的配置(Debug / Release)

500 : {"Message":"An error has occurred."} /swagger/docs/v1


使枚举类型按实际文本作为参数值(而非转成索引数字)

  1. 打开文件:App_Start/SwaggerConfig.cs

  2. 取消注释:c.DescribeAllEnumsAsStrings();

xoyozo 6 年前
3,943

之前已经介绍了百度编辑器在 ASP.NET 环境下的配置,本文继续补充改进其将图片等附件上传到阿里云 OSS。

首先从阿里云控制台下载相关 SDK,并阅读相关的 API 文档。链接:https://promotion.aliyun.com/ntms/act/ossdoclist.html


改造上传代码


打开文件 UploadHandler.cs,在 Process() 方法中找到:

File.WriteAllBytes(localPath, uploadFileBytes);

在其下方插入代码:

client.PutObject(bucketName, "upload/ueditor/" + savePath, localPath);

实现图标按钮上传和 HTML5 拖放上传。

PutObject() 的第 2 个参数是 OSS 中的图片路径,第 3 个参数是图片在网站目录下的磁盘路径。


打开文件 CrawlerHandler.cs,在 Fetch() 方法中找到:

File.WriteAllBytes(savePath, bytes);

在其下方插入代码:

client.PutObject(bucketName, "upload/ueditor/" + ServerUrl, savePath);

实现粘贴板图片上传。

同样注意两个参数变量。


修改路径前缀


上传成功后,编辑器会拼装路径到 HTML 代码中,这个前缀是在 config.json 文件中配置的,具体找到以 UrlPrefix 结尾的属性,如 imageUrlPrefix,进行相应的修改即可:

"imageUrlPrefix": "//oss.xoyozo.net/upload/ueditor/", /* 图片访问路径前缀 */

路径以“//”开头能更好地兼容 https。

xoyozo 6 年前
7,449

传统的 LIKE 模糊查询(前置百分号)无法利用索引,特别是多个关键词 OR,或在多个字段中 LIKE,更是效率低下。本文研究对文章进行分词以提高检索的准确度和查询效率。


根据自己的编程语言选择一款合适的中文分词组件,我在 ASP.NET 平台下选择了 jieba.NET。


设想的步骤:

  1. 分别对文章标题、标签、正文进行分词,保存到一张分词表上。该表把“文章 ID”和“词语”设为联合主键,用 3 个字段记录该词语分别在标题、标签、正文中出现的次数,另外还可以按需要添加文章分类 ID、文章创建时间等字段。

  2. 当用户输入关键词进行检索时,先将关键词分词,在分词表中用 in 语法查询到所有相关的记录;

  3. 使用 group by 语法对查询结果按文章 ID 分组;

  4. 关键在排序上,理想的排序是:

    a. 先按搜索关键词中不同词语的出现量排序,即:若搜索关键词分词后是 3 个词语,那么全部包含这 3 个词的文章优先,只匹配其中 2 个词语的其次;

    b. 再按搜索关键词在文中累计出现的次数排序(考虑权重),即:我们先假定标题和标签的分词权重为 5(意思是一个分词在标题中出现 1 次相当于在正文中出现 5 次),那么累加每个分词在标题、标签、正文的权重次数,得分高的优先;

    c. 再进一步考虑文章的发布时间,即将文章的发布时间距离最早一篇文章的发布时间(或一个较早的固定日期)相隔的天数,乘以一个系数加入到权重中,这个系数按不同文章分类(场景)不同,比如新闻类的大一点,情感类的小一点)。乘以系数时一篇文章只加权一次,不要加权到每个分词。

    d. 根据需求还可以加入文章热度(阅读数)的权重。


根据上述逻辑对一个有 18 万篇文章的内容管理系统进行改造,循环所有文章进行分词统计,得到一张包含 5 千万条记录的分词表(系统中部分文章只有标题、标签和外链,没有正文,否则更多)。

由于查询中包含 in、group by、count、sum、运算等,再若分类是无级限的,即文章分类 ID 也是 in 查询,然后分页,即使创建索引,效率也只能呵呵了。


简化:

不对正文进行分词;

不按权重进行排序;


那么分词表的记录数降到 250 万条,同样用 in 查询分词,先按搜索关键词中不同词语的出现量排序,再按发布时间排序,分页后获得一页的文章 ID 集合,再去文章表中 in 获取详细信息(注意保持一页中的排序)。

添加相关索引后,查询一个包含 3 个分词的关键词仅需十几毫秒。因为 in 的内容比较离散,所以索引的利用率比较高。



xoyozo 6 年前
5,179

前言:

ChatGPT 给了 3 条建议:

  1. 在应用程序中正确释放数据库连接。确保在使用完数据库连接后,将其关闭并将其返回到连接池中。您可以使用 using 语句来确保连接在使用完毕后被正确释放。

  2. 调整连接池的大小。默认情况下,连接池的最大大小为 100。如果您的应用程序需要更多的连接,则可以增加连接池的大小。您可以在连接字符串中设置 Max Pool Size 属性来调整连接池的大小。

  3. 调整连接池的超时时间。默认情况下,连接池中的连接在 30 秒钟内未使用时将被关闭。如果您的应用程序需要更长的连接时间,则可以增加连接池的超时时间。您可以在连接字符串中设置 Connection Lifetime 属性来调整连接池的超时时间。

亲测有效,尤其是第 3 条,原因是 Connection Lifetime 的默认值是 0,即没有超时限制。

—— 2023.5

一般地,我们使用 EF 连接数据库前会先初始化一个数据库上下文:

dbEntities db = new dbEntities();

虽然 ASP.NET 会在查询完毕后自动关闭该连接,但是在什么情况下回收等都是不确定的,所以会导致 MySQL 中出现很多 Sleep 的连接(执行命令 SHOW FULL PROCESSLIST 可见),占用数据库的连接数,除非主动调用 Dispose():

db.Dispose();

官方建议的写法是使用 using 语法:

using (dbEntities db = new dbEntities())
{
}

using 会自动调用 Dispose()。这样对减少连接数是很有效的,但官方提示为了提高下一次连接的速度,并不会完全关闭所有连接。

C# 8 建议写法:

using dbEntities db = new dbEntities();

在实际项目中(该项目有 500+处数据库连接)测试结果,在不执行 Dispose() 时稳定为 140 个左右连接数,使用 using 或 Dispose() 后稳定变为 40 个左右。


如果不小心在 using 外部或 Dispose() 后再次对该上下文执行查询操作会出现异常:

无法完成该操作,因为 DbContext 已释放。

此 ObjectContext 实例已释放,不可再用于需要连接的操作。

所以要避免出现这种情况。这里还有一种另类的解决方法(不建议),根据上下文的特性,只要在 using 内查询一次(譬如视图中需要用到的导航属性,即外键关联的表),就可以在外部使用这个属性。


(建议)在 ASP.NET MVC 或 Web API 项目中,如果一个控制器中仅在 Action 外部定义一个 DbContext,那么,只要重写该控制器的 Dispose() 方法即可:

private dbEntities db = new dbEntities();

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        db.Dispose();
    }
    base.Dispose(disposing);
}

上下文使用 private 修饰即可。


参考:SQL Server 连接池 (ADO.NET)

xoyozo 6 年前
6,572

这是一篇可能解决困扰了 .NET 程序猿多年的文章!

首先,使用 Visual Studio 2019 创建一个 ASP.NET WEB 应用程序,直接选用了 MVC 模板。

直接发布项目,默认的设置如下图:

image.png

对于小型项目,按默认设置发布基本可满足正常运行,首次运行打开第一个页面基本在 5~6 秒(视服务器配置),其它页面的首次打开也基本在 1~2 秒完成,非首次瞬间打开。

一旦项目功能变得复杂,文件增多,会导致发布后首次运行打开第一个页面 30 秒以上,其它页面的首次打开 10 秒左右,非首次瞬间打开。

这是因为项目在发布时没有进行预编译,而是在用户访问网页时动态编译,一旦应用程序池回收,或项目文件改动,都会重新编译,再次经历缓慢的“第一次”,这是不能忍的。

于是咱们来研究一下“预编译”。

在发布页面勾选“在发布期间预编译”,这时发布会在“输出”窗口显示正在执行编译命令(编译时间会比较长):

image.png

该选项对发布后的文件结构和内容影响不大,因此对首次执行效率的提升也不大,重要的在后面。

在“高级预编译设置”窗口中:

image.png

我们针对预编译选项和合并选项分别做测试。

不勾选“允许更新预编译站点”,会致 bin 目录中生成许多 .compiled 文件,而所有 .cshtml 文件的内容都是:

这是预编译工具生成的标记文件,不应删除!

如果是 Web From 网站,.aspx/.ashx 等文件内容同上。

尝试打开网站页面,你会发现,除了项目启动后的第一个页面仍然需要 1~2 秒(无 EF),其余每个页面的首次都是瞬间打开的(EF 的首次慢不在本文讨论范围)。这让我对预编译有一种相见恨晚的感觉!

这里偷偷地告诉你,把 Views 目录删掉也不影响网页正常打开哦~为什么不让删,咱也不敢问,咱也不敢删。

目的达到了,有一些后遗症需要解决,比如 bin 目录内杂乱无章。

选“不合并。为每个页面和控件创建单独的程序集”,结果是 bin 多出许多 App_Web_*.dll 文件。

选“将所有输出合并到单个程序集”,填写程序集名称。这时会发现“输出”窗口执行了命令:

image.png

如果程序集名称跟已有名称冲突,会发生错误:

合并程序集时出错: ILMerge.Merge: The target assembly '******' lists itself as an external reference.

查看 bin 目录,.compiled 文件还在,但 App_Web_*.dll 合并成了一个程序集。FTP 的“不合并”也是把所有 App_Web_*.dll 上传一遍,所以不存在相对于“合并”的增量发布优势。

是不是勾了“视为库组件删除(AppCode.compiled 文件)”.compiled 文件就会不见?意外之外,情理之中,bin 没有什么变化。

继续选择“将各个文件夹输出合并到其自己的程序集”,呃,bin 中文件数不降反增。

最后选择“将所有页和控件输出合并到单个程序集”,同样程序集名称不能冲突。结局令人失望,bin 中仍然一大堆 .compiled 和 App_Web_*.dll。


整理成表格:

1
允许更新预编译站点

aspnet_compiler.exe -v / -p \Source -u \TempBuildDir 

重复发布后 bin 目录文件数:不会增多(页面不进行预编译)

2

不允许更新预编译站点,不合并

aspnet_compiler.exe -v / -p \Source \TempBuildDir 

重复发布后 bin 目录文件数:.compiled 不会增多,App_Web_*.dll 增多

3

不允许更新预编译站点,不合并。为每个页面和控件创建单独的程序集

aspnet_compiler.exe -v / -p \Source -c -fixednames \TempBuildDir 

重复发布后 bin 目录文件数:不会增多(编译后的文件名固定,FTP 方式的部分 App_Web_*.dll 文件可能实现增量上传)

4

不允许更新预编译站点,将所有输出合并到单个程序集,不勾选“视为库组件”

aspnet_compiler.exe -v / -p \Source -c \TempBuildDir 

aspnet_merge.exe \TempBuildDir -o 程序集名称 -copyattrs AssemblyInfo.dll -a

重复发布后 bin 目录文件数:不会增多(.compiled 固定名称,App_Web_*.dll 合并为一个)

5

不允许更新预编译站点,将所有输出合并到单个程序集,勾选“视为库组件”

aspnet_compiler.exe -v / -p \Source \TempBuildDir 

aspnet_merge.exe \TempBuildDir -o 程序集名称 -copyattrs AssemblyInfo.dll -a -r 

重复发布后 bin 目录文件数:不会增多(.compiled 固定名称,App_Web_*.dll 合并为一个)

6

不允许更新预编译站点,将每个文件夹输出合并到其自己的程序集,前缀

aspnet_compiler.exe -v / -p \Source -c \TempBuildDir 

aspnet_merge.exe \TempBuildDir -prefix 前缀 -copyattrs AssemblyInfo.dll -a  

重复发布后 bin 目录文件数:.compiled 不会增多,App_Web_*.dll 增多

7

不允许更新预编译站点,将所有页和控件输出合并到单个程序集

aspnet_compiler.exe -v / -p \Source -c \TempBuildDir 

aspnet_merge.exe \TempBuildDir -w 程序集名称 -copyattrs AssemblyInfo.dll -a  

重复发布后 bin 目录文件数:.compiled 不会增多,App_Web_*.dll 增多

bin 目录下,页面的程序集文件(App_Web_*.dll)增多的原因是编译后的文件名不固定,发布到会导致残留许多无用的程序集文件。

相比较,如果第 3 种能实现 FTP 稳定的增量上传的话是比较完美的(还有一个缺点是:如果页面有删除,目标 bin 内对应该页面的 .compiled 和 .dll 不会删除,这跟“允许更新预编译站点”是一个情况),那么第 4 种 或第 5 种也是不错的选择(同样有缺点:执行合并比较慢)。

测试一个有 300 个页面的项目,compiler 用时约 2 分钟,merge 用时约 5 分钟,发布用时约 4 分钟。

这里有个槽点,执行预编译和合并是佛系的,CPU 和磁盘使用率永远保持在最低水平。

所以如果是要经常修改的项目,那么建议选择“不合并”的第 3 种发布方式:

微信图片_20190715160035.png

“视为库组件(删除 AppCode.compiled 文件)”:移除主代码程序集(App_Code 文件夹中的代码)的 .compiled 文件。 如果应用程序包含对主代码程序集的显式类型引用,则不要使用此选项。


补充:

  • 不允许更新预编译站点发布后,因为前端页面没有内容,因此无法单独修改发布(单独发布一个页面后,在访问时不会生效!),只能全站发布,耗时较长;bin 目录有变动将导致使用 InProc 方式存储的 Session 丢失。

  • 预编译的另一个优点是可以检查 .aspx / .cshtml 页面 C# 部分的错误(特别是命名空间和路径引用)。

  • 改为预编译发布后,可以将服务器上残留的 .master / .ascx / .asax 删除,但不能删除 .aspx / .ashx /.config 等。

  • VS 发布到 FTP 经常会遗漏一些页面文件,不合并时会遗漏独立文件,合并后也会遗漏合并后的 .dll 的文件,合并的好处就是方便检查是否完全上传发布。

  • 慎选“在发布前删除所有现有文件”!一旦勾选发布,世界就清静了,所有网友上传的图片附件以及网站运行产生的其它文件,消失得无影无踪。不管发布到文件系统还是发布到 FTP 都一样。当然,如果是先发布到文件系统,再通过 FileZilla 等 FTP 软件上传到服务器的,建议勾选此项。

  • .NET Core 应用程序部署:https://docs.microsoft.com/zh-cn/dotnet/core/deploying/index

  • 由于上传文件时 bin 目录文件较多,理论上 bin 目录内的文件有任何改动都会重启应用池,而且 VS 是单线程上传的,导致期间网站访问缓慢,服务器 CPU 升高,我的做法是:发布到文件系统,再使用专用 FTP 工具上传,上传用时约半分钟(如果大小不同或源文件较新则覆盖文件)。还嫌慢?那就打包上传,解压覆盖。

  • 关于本文研究对象的官方解释:高级预编译设置对话框

  • 出现“未能加载文件或程序集“***”或它的某一个依赖项。试图加载格式不正确的程序。”的问题时,先用改用 Debug 方式发布会报详细错误,一般是 .aspx 等客户端页面有 C# 语法问题,注意提示报错的是 /obj/ 目录下的克隆文件,应更改原文件。排除错误后关闭所有页面,再使用 Release 方式发布。

xoyozo 6 年前
12,364

当使用在线编辑器编辑一篇文章(或从 Word 复制)后,会得到包含 HTML 标签的字符串内容,可以直接将它输出到页面上而不需要进行 HTML 编码。

但是,当我们需要改变图片大小时,我们发现有些图片的尺寸是直接使用 style 属性固定的,除了用 JS 进行后期处理,我们可以在服务端对 <img /> 进行修正。

这个场景会在小程序开发的时候遇到。

网上一般使用正则表达式直接将 <img 替换成 <img style="max-width: 100%; height: auto;" ,缺点是如果该 <img /> 本身就带有 style 属性,那么会出现一个标签两个 style,很多情况导致这两个样式同时失效,所以我们应针对有 style 和无 style 分别处理。

// 把 <img src="a.jpg" style="display: block;" /> 替换成 <img src="a.jpg" style="display: block;;max-width:100%;height:auto;" />
Content = Content.replace(/(\<img\s+[^>]*style\s*\=\s*['"][^'"]*)(['"])/gi, '$1;max-width:100%;height:auto;$2');

// 把 <img src="b.jpg" /> 替换成 <img src="b.jpg" style="max-width:100%;height:auto;" />
Content = Content.replace(/(\<img\s+((?!style).)+?)(\/?>)/gi, '$1 style="max-width:100%;height:auto;" $3');

复制以上代码时,半角空格可能会变成全角空格,请注意修正。

当有 style 时,我们将 max-width: 100%; height: auto;追加在原样式之后,以重写原样式。这里没有直接判断原样式是否以 ; 结尾,而是直接追加 ;,这并不会影响实现展示效果。

在判断没有 style 用到正则表达式的“断言”,参:https://blog.csdn.net/xuyangxinlei/article/details/81359366

延伸阅读:C# 用 HtmlAgilityPack 给 HTML 节点加上 style

xoyozo 6 年前
6,026

这是一个数据可视化项目,基于D3.js。能够将历史数据排名转化为动态柱状图图表。

先来看看效果:

https://xoyozo.net/Demo/BarGraph

作者 Jannchie 见齐还提供了官方视频教程:

https://www.bilibili.com/video/av28087807

不过由于开源项目的不断更新,该教程的部分内容已失效,本文针对 2018-12-25 版本总结了一些常用的配置说明,仅供参考。


从 GitHub 下载源代码,在 src 目录中可以看到 4 个文件:

bargraph.html --> 运行示例页面

config.js --> 配置文件

stylesheet.css --> 样式表

visual.js --> 核心文件


作者并没有将代码封装为插件的方式,所以我们是通过修改 config.js 配置文件的方式应用到自己的项目中的。

visual.js 虽然是核心文件,但作者将部分示例中的代码也包含其中,但并不影响我们直接在自己的项目中引用。

以下是 config.js 中的主要属性:

属性说明参考值
encoding数据源(csv、json)等的文件编码GBK / UTF-8 等
max_number每个时间节点最多显示的条目数10
showMessage控制是否显示顶部附加信息文字true / false
auto_sort时间自动排序(详细含义、作用及限制见代码中注释)true / false
timeFormat时间格式,显示于图表右下角的时间%Y、%Y-%M-%D 等
reverse是否倒序true / false
divide_by类型根据什么字段区分?如果是 name,则关闭类型显示
divide_color_by

颜色根据什么字段区分?

须要注意的是,如果配置成 name,则各条颜色不同(因为 name 值各异),如果配置成 type 等,那么相同 type 值的条颜色相同。

字段名
color指定部分或所有条的颜色,该项与 divide_color_by 设置有关。

以 divide_color_by = 'name' 为例,"中国"是其中的一项 name 值,那么该项将显示 #D62728 色:

color: {

      '中国': '#D62728'

}

changeable_color若 true 则颜色的深浅将根据数据的增长率实时改变
itemLabel
左边文字
typeLabel右边文字
item_x


interval_time
时间点间隔时间2
text_y


text_x


offset


display_barInfo如果希望不显示,则可以设置较大的值,单位像素
use_counter

step

format格式化数值
left_margin

right_margin

top_margin

bottom_margin

dateLabel_x

dateLabel_y

allow_up

enter_from_0

big_value

use_semilogarithmic_coordinate

long

wait数据加载完成后开始播放前的等待时间0
update_rate


xoyozo 7 年前
9,724

当我们用 ASP.NET Web API 作服务端接口时,如果客户端以 GET 方式请求的 URL 中,由于拼接错误导致“?”和“&”并列出现,会发生 400 Bad Request,那么需要在 IIS 中使用 URL 重写模块来纠正。

请求 URL 如:

http://www.abc.com/api/obj?&foo=bar

需要重写为:

http://www.abc.com/api/obj?foo=bar


打开 IIS 管理器中对应网站的 URL 重写

image.png


添加空白规则。

匹配的 URL 不包含域名,如上述 URL 则匹配的范围是:

api/obj

不包含我们要查找的字符串 ?&,所以此处模式只能匹配所有:

.*

又因为重定向路径中需要包含这部分,所以用括号包裹,即:

(.*)

image.png

继续添加条件匹配:

条件输入:{QUERY_STRING},表示匹配查询字符串,

匹配的部分是“?”后面的字符串:

&foo=bar

那么可以填写模式:

^\&.*

因为 & 后面的部分仍然需要使用,所以用括号包裹:

^\&(.*)

image.png

“操作”中选择类型“重定向”,URL 填写:

{R:1}?{C:1}

其中 {R:1} 指代 api/obj,{C:1} 指代 foo=bar

取消“附加查询字符串”前面的勾

重定向类型在测试时可以选择 302 或 307,没问题后选择 301。

image.png

完成。

最终我们可以在网站的配置文件 web.config 中看到:

<rewrite>
    <rules>
        <rule name="uni-app-h5-replace-q" stopProcessing="true">
            <match url="(.*)" />
            <conditions>
                <add input="{QUERY_STRING}" pattern="^\&amp;(.*)" />
            </conditions>
            <action type="Redirect" url="{R:1}?{C:1}" appendQueryString="false" redirectType="Temporary" />
        </rule>
    </rules>
</rewrite>

我们要把这段代码复制到开发环境源代码的 web.config 中,以免发布网站时将我们设置好的配置覆盖掉。

xoyozo 7 年前
9,395