使用远程桌面连接时提示你的凭据不工作:
解决方法一:关闭 Windows Defender Credential Guard
打开组策略编辑器(gpedit.msc)
展开:计算机配置 - 管理模板 - 系统 - Device Guard,双击右侧的“打开基于虚拟化的安全”,改为“已禁用”
重启电脑
解决方法二【推荐】:使用其他远程桌面客户端
在 Microsoft Store 中查找“Microsoft 远程桌面”,或者点此安装
这个应用同样来自微软,使用方式与传统的远程桌面连接略有区别,如果你在 iPhone 或安卓上使用过,那么就能快速上手。
若要共享剪贴板,在“编辑电脑”中开启,并且在 设置 - 隐私与安全 - 文件系统 中允许“远程桌面”。
相对于传统的远程桌面连接,对高 DPI 兼容性不完美。
默认端口带来安全隐患,建议更改为 50000-60000 之间的端口号。
Windows 远程桌面(RDP)(3389)
在 Windows 防火墙中放行新端口:在“入站规则”中找到“Open RDP Port 3389”复制并粘贴该规则,修改端口和名称。
若没有这个规则:新建规则 - 端口 - TCP - 特定本地端口(填写新的端口号)- 允许连接 - 名称
如有其它防火墙或安全组也一并配置(如阿里云 ECS 的安全组)
打开注册表(regedit),展开到:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp,右侧双击“PortNumber”切换到“十进制”,将 3389 改为新端口号
重启生效
在防火墙和安全组中禁止原默认端口
SSH (22) 之 CentOS
从阿里云控制台登录服务器(如果未设置 root 密码则先设置),直接跳到第 4 步
在外部防火墙中放行新的端口号(如阿里云 ECS 的安全组)
在内部防火墙中放行新的端口号(如 firewalld 或 iptables),使用宝塔面板的直接在面板“安全”页面设置即可
打开 SSH 配置文件
sudo vi /etc/ssh/sshd_config
找到并编辑 Port 行的商品号并启用
#Port 22
重新加载使生效
sudo systemctl reload sshd
在防火墙和安全组中禁止原默认端口
建议使用 SSH 密钥对代替传统账号密码登录
FTP (21) 之 FileZilla Server Windows 版
一般地,在 Windows Defender 防火墙中是以添加应用 filezilla-server.exe 的方式允许的,所以不需要更改端口。如果以端口方式允许的,那么在入站规则中允许新的端口。
如有其它防火墙或安全组也一并配置(如阿里云 ECS 的安全组)
打开 Administer FileZilla Server,打开菜单 - Server - Configure - Server listeners,右侧窗口中将 Port 改为新端口(强烈建议将 Protocol 改为“Require explicit FTP over TLS”,即禁止 FTP 协议,改为使用 FTPS 协议)
从防火墙和安全组移除 21 端口
FTP (21) 之 Pure-Ftpd(宝塔面板)
在防火墙中放行新的端口号(如阿里云 ECS 的安全组)
进入宝塔面板,打开“安全”,添加端口规则 TCP
在宝塔面板中进入软件商店,找到 Pure-Ftpd 并打开,切换到“配置修改”,搜索“Bind”,删除开头的“#”,将端口号 21 改为新端口号,保存(强烈建议将 TLS 项改为 2,即禁止 FTP 协议,仅允许 FTPS 协议)
切换到“服务”选项卡,点击“重启”
从防火墙和安全组移除 21 端口
MySQL (3306) 之阿里云云数据库 RDS MySQL 版
打开控制台 RDS 实例页,左侧菜单点击“白名单与安全组”,切换到“安全组”查看正在使用的安全组ID
(若使用了安全组)打开控制台 ECS 首页,左侧菜单点击“安全组”,找到这个安全组,放行新的端口
打开控制台 RDS 实例页,左侧菜单点击“数据库连接”,点击“修改连接地址”,在弹出框中修改端口
从防火墙和安全组移除原端口(确保没有其它实例正在使用此端口)
PolarDB (3306)
打开控制台 PolarDB 集群实例页,左侧菜单点击“集群白名单”,切换到“安全组”查看正在使用的安全组ID
(若使用了安全组)打开控制台 ECS 首页,左侧菜单点击“安全组”,找到这个安全组,放行新的端口
打开控制台 PolarDB 集群实例页,左侧菜单点击“基本信息”,点击“主地址”和“集群地址”的“配置”,在“网线信息”中点击“更多”更改端口
从防火墙和安全组移除原端口(确保没有其它实例正在使用此端口)
MSSQL (1433) 之阿里云云数据库 RDS SQL Server 版
打开控制台 RDS 实例页,左侧菜单点击“白名单与安全组”,切换到“安全组”查看正在使用的安全组ID
(若使用了安全组)打开控制台 ECS 首页,左侧菜单点击“安全组”,找到这个安全组,放行新的端口
打开控制台 RDS 实例页,左侧菜单点击“数据库连接”,点击“修改连接地址”,在弹出框中修改端口
从防火墙和安全组移除原端口(确保没有其它实例正在使用此端口)
Redis (6379) 之阿里云云数据库 Redis 版
打开控制台 Redis 实例页,左侧菜单点击“白名单设置”,切换到“安全组”查看正在使用的安全组ID
(若使用了安全组)打开控制台 ECS 首页,左侧菜单点击“安全组”,找到这个安全组,放行新的端口
打开控制台 Redis 实例页,在“连接信息”中点击“修改连接地址”,在弹出框中修改端口
从防火墙和安全组移除原端口(确保没有其它实例正在使用此端口)
宝塔面板 (8888)
在防火墙中放行新的端口号(如阿里云 ECS 的安全组),或直接在私网其它 ECS 上的浏览器上直接访问原 8888 端口的地址
进入宝塔面板,打开面板设置,切换到“安全设置”页,找到“面板端口”,点击“设置”
在防火墙和安全组中禁止原默认端口
IIS 管理服务(Web 部署)(8172)
在 Windows 防火墙中放行新端口:在“入站规则”中找到“Web 管理服务(HTTP 流量入站)”因其为预定义规则且复制也无法修改,所以按其设置新建一个,并指定新的端口。
如有其它防火墙或安全组也一并配置(如阿里云 ECS 的安全组)
打开 IIS 管理器 - 管理服务,右侧停止,左侧修改端口,右侧启动
VS 中发布配置修改“服务器(E)”项添加端口
在防火墙和安全组中禁止原默认端口
在 Vue 中,当你将一个布尔对象双向绑定到 radio 输入上时,确保 radio 的 value 属性仍然保持布尔类型是很重要的。如果 value 属性是字符串,那么 Vue 会将其解释为字符串而不是布尔值。以下是一个示例,演示如何正确地将布尔对象双向绑定到 radio 按钮,并确保 value 属性保持布尔类型:
<template>
<div>
<input type="radio" v-model="myBoolean" :value="true" /> True
<input type="radio" v-model="myBoolean" :value="false" /> False
<p>myBoolean: {{ myBoolean }}</p>
</div>
</template>
<script>
export default {
data() {
return {
myBoolean: false, // 布尔对象
};
},
};
</script>
在这个示例中,我们使用了 v-model 指令将 myBoolean 属性与两个 radio 按钮进行了双向绑定。通过将 value 属性设置为 true 和 false,我们确保了 myBoolean 属性保持布尔类型。
这样,当用户选择其中一个 radio 按钮时,myBoolean 属性将保持布尔值而不是字符串。确保 value 属性的类型与要绑定的数据类型匹配,以确保绑定的数据类型保持一致。
同样的问题出现在 select 上也是一样:
<select v-model="cat.colorId" required>
<option :value="null">不选择</option>
<option v-for="color in colors" :value="color.id">{{color.name}}</option>
</select>
语言集成查询(LINQ)为 C# 和 VB 提供语言级查询功能和高阶函数 API,让你能够编写具有很高表达力度的声明性代码。
LINQ 有两种写法:查询语法和方法语法,查询语法又称查询表达式语法。
查询语法:
from 变量名 in 集合 where 条件 select 结果变量
方法语法:
集合.Where(变量名 => 条件)
LINQ 的标准查询运算符及语法示例
类型 | 操作符 | 功能 | 方法语法 | 查询语法 |
投影操作符 | Select | 用于从集合中选择指定的属性或转换元素 |
|
|
SelectMany | 用于在嵌套集合中选择并平铺元素 |
|
| |
限制操作符 | Where | 根据指定的条件筛选集合中的元素 |
|
|
排序操作符 | OrderBy、OrderByDescending、ThenBy、ThenByDescending | 用于对集合中的元素进行排序 |
|
|
Reverse | 将集合中的元素顺序反转 |
| ||
联接操作符 | Join GroupJoin | 用于在两个集合之间执行内连接(Join)操作,或者对一个集合进行分组连接(GroupJoin)操作 | 内联接
左连接
| 内联接
左连接
|
分组操作符 | GroupBy | 根据指定的键对集合中的元素进行分组 | ||
串联操作符 | Concat | 将两个集合连接成一个新集合 | ||
聚合操作符 | Aggregate、Average、Count、LongCount、Max、Min、Sum | Aggregate 可以用于在集合上执行自定义的累积函数,其他方法用于计算集合中的元素的平均值、总数、最大值、最小值和总和 | ||
集合操作符 | Distinct、Union、Intersect、Except | 用于执行集合间的不同操作,Distinct 移除重复元素,Union 计算两个集合的并集,Intersect 计算两个集合的交集,Except 计算一个集合相对于另一个集合的差集 | ||
生成操作符 | Empty、Range、Repeat | Empty 创建一个空集合,Range 创建一个包含一系列连续数字的集合,Repeat 创建一个重复多次相同元素的集合 | ||
转换操作符 | AsEnumerable、Cast、OfType、ToArray、ToDictionary、ToList、ToLookup | 这些方法用于将集合转换为不同类型的集合或字典 | ||
元素操作符 | DefaultIfEmpty、ElementAt、ElementAtOrDefault、First、Last、FirstOrDefault、LastOrDefault、Single、SingleOrDefault | 这些方法用于获取集合中的元素,处理可能的空集合或超出索引的情况 | ||
相等操作符 | SequenceEqual | 用于比较两个集合是否包含相同的元素,顺序也需要相同 | ||
量词操作符 | All、Any、Contains | 用于检查集合中的元素是否满足特定条件,All 检查是否所有元素都满足条件,Any 检查是否有任何元素满足条件,Contains 检查集合是否包含特定元素 | ||
分割操作符 | Skip、SkipWhile、Take、TakeWhile | 用于从集合中跳过一些元素或只取一部分元素,可以结合特定条件进行操作 |
了解立即执行与延迟执行可以大大改善性能。
方法一:
在 DbContext.cs 文件中找到 OnConfiguring 方法,添加代码:
#if DEBUG
optionsBuilder.EnableSensitiveDataLogging();
optionsBuilder.LogTo(Console.WriteLine); // 输出日志到控制台
//optionsBuilder.LogTo(message => Debug.WriteLine(message)); // 输出日志到“输出”窗口
#endif
搞定。
若原来是 => 形式的,改为 { } 形式写法即可。
方法二:使用 Logging
打开 DbContext 文件,添加
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Debug;
将
optionsBuilder.UseMySql
替换为
optionsBuilder.UseLoggerFactory(MyLoggerFactory).UseMySql
添加方法
public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] {
new DebugLoggerProvider()
});
即可在“输出”窗口看到生成的 SQL 语句了。
anichart.js 是一款将数据转化为动态柱状图/线性图的 js/ts 工具,可导出视频。
github: https://github.com/Jannchie/anichart.js
中文使用指南:https://github.com/Jannchie/anichart.js/blob/main/README-CN.md
docs 目录中有更详细的使用方法(英文)。
在线演示:https://xoyozo.net/Demo/BarGraph
目前 release 版本 3.0.0。
这里有一点常用设置示例:https://codesandbox.io/s/anichart-2x-m3xbz?file=/main.js
设置画布尺寸
stage.canvas.width = 1000;
stage.canvas.height = 500;
重设尺寸不会重新计算内部元素的大小和位置,因此对响应式布局不太友好。
配置柱状图
示例:
const barChart = new ani.BarChart({
dy: 2, // 文字下沉
imageField: 'logo', // 图标字段名
itemCount: 16, // 最多显示条数
dateFormat: '%Y年%-m月', // 日期格式
barGap: 10, // 柱条间距
barInfoFormat: () => '', // 隐藏柱条上的文字
});
stage.addChild(barChart);
循环播放
setInterval(function () {
if (!stage.playing) {
stage.sec = 0;
stage.play();
}
}, 1000);
不知道从哪个版本的 Chrome 或 Edge 开始,我们无法通过 ctrl+v 快捷键将时间格式的字符串粘贴到 type 为 date 的 input 框中,我们想办法用 JS 来实现。
方式一、监听 paste 事件:
const input = document.querySelector('input[type="date"]');
input.addEventListener('paste', (event) => {
input.value = event.clipboardData.getData('text');
});
这段代码实现了从页面获取这个 input 元素,监听它的 paste 事件,然后将粘贴板的文本内容赋值给 input。
经测试,当焦点在“年”的位置时可以粘贴成功,但焦点在“月”或“日”上不会触发 paste 事件。
方式二、监听 keydown 事件:
const input = document.querySelector('input[type="date"]');
input.addEventListener('keydown', (event) => {
if ((navigator.platform.match("Mac") ? event.metaKey : event.ctrlKey) && event.key === 'v') {
event.preventDefault();
var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
input.value = clipboardData.getData('text');
}
});
测试发现报错误:
Uncaught TypeError: Cannot read properties of undefined (reading 'getData')
Uncaught TypeError: Cannot read properties of undefined (reading 'clipboardData')
看来 event 中没有 clipboardData 对象,改为从 window.navigator 获取:
const input = document.querySelector('input[type="date"]');
input.addEventListener('keydown', (event) => {
if ((navigator.platform.match("Mac") ? event.metaKey : event.ctrlKey) && event.key === 'v') {
event.preventDefault();
window.navigator.clipboard.readText().then(text => {
input.value = text;
});
}
});
缺点是需要用户授权:
仅第一次需要授权,如果用户拒绝,那么以后就默认拒绝了。
以上两种方式各有优缺点,选择一种适合你的方案就行。接下来继续完善。
兼容更多时间格式,并调整时区
<input type="date" /> 默认的日期格式是 yyyy-MM-dd,如果要兼容 yyyy-M-d 等格式,那么:
const parsedDate = new Date(text);
if (!isNaN(parsedDate.getTime())) {
input.value = parsedDate.toLocaleDateString('en-GB', { year: 'numeric', month: '2-digit', day: '2-digit' }).split('/').reverse().join('-');
}
以 text 为“2023-4-20”举例,先转为 Date,如果成功,再转为英国时间格式“20-04-2023”,以“/”分隔,逆序,再以“-”连接,就变成了“2023-04-20”。
当然如果希望支持中文的年月日,可以先用正则表达式替换一下:
text = text.replace(/\s*(\d{4})\s*年\s*(\d{1,2})\s*月\s*(\d{1,2})\s*日\s*/, "$1-$2-$3");
处理页面上的所有 <input type="date" />
const inputs = document.querySelectorAll('input[type="date"]');
inputs.forEach((input) => {
input.addEventListener(...);
});
封装为独立域
避免全局变量污染,使用 IIFE 函数表达式:
(function() {
// 将代码放在这里
})();
或者封装为函数,在 jQuery 的 ready 中,或 Vue 的 mounted 中调用。
在 Vue 中使用
如果将粘贴板的值直接赋值到 input.value,在 Vue 中是不能同步更新 v-model 绑定的变量的,所以需要直接赋值给变量:
<div id="app">
<input type="date" v-model="a" data-model="a" v-on:paste="fn_pasteToDateInput" />
{{a}}
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const app = Vue.createApp({
data: function () {
return {
a: null,
}
},
methods: {
fn_pasteToDateInput: function (event) {
const text = event.clipboardData.getData('text');
const parsedDate = new Date(text);
if (!isNaN(parsedDate.getTime())) {
const att = event.target.getAttribute('data-model');
this[att] = parsedDate.toLocaleDateString('en-GB', { year: 'numeric', month: '2-digit', day: '2-digit' }).split('/').reverse().join('-');
}
},
}
});
const vm = app.mount('#app');
</script>
示例中 <input /> 添加了 data- 属性,值同 v-model,并使用 getAttribute() 获取,利用 this 对象的属性名赋值。
如果你的 a 中还有嵌套对象 b,那么 data- 属性填写 a.b,方法中以“.”分割逐级查找对象并赋值
let atts = att.split('.');
let target = this;
for (let i = 0; i < atts.length - 1; i++) {
target = target[atts[i]];
}
this.$set(target, atts[atts.length - 1], text);
Pomelo.EntityFrameworkCore.MySql 升级到 7.0 后出现:
System.InvalidOperationException:“The 'sbyte' property could not be mapped to the database type 'tinyint(1)' because the database provider does not support mapping 'sbyte' properties to 'tinyint(1)' columns. Consider mapping to a different database type or converting the property value to a type supported by the database using a value converter. See https://aka.ms/efcore-docs-value-converters for more information. Alternately, exclude the property from the model using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.”
对比 6.0 生成的 DbContext.cs 发现缺少了 UseLoggerFactory,按旧版修改即可。
找到 OnConfiguring 方法,上方插入:
public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] {
new DebugLoggerProvider()
});
在 OnConfiguring 方法中将:
optionsBuilder.UseMySql("连接字符串");
改为:
optionsBuilder.UseLoggerFactory(MyLoggerFactory).UseMySql("连接字符串");
新版本 SDK 已解决这个问题
升级到 .NET 7 后,Senparc.Weixin 6.15.7 正常,6.15.8.1-6.15.8.3 无法正常启动,行
builder.Services.AddSenparcWeixinServices(builder.Configuration);
报错:
System.NullReferenceException:“Object reference not set to an instance of an object.”
临时解决方法,改为:
builder.Services.AddSenparcWeixinServices(builder.Configuration, delegate { });
错误 BLAZOR102 The scoped css file was defined but no associated razor component or view was found for it.
错误 BLAZOR106 The JS module file was defined but no associated razor component or view was found for it.
解决方法:将相关文件从项目中排除,再包括到项目中即可正常生成。
若仍报错,备份这些文件,删除并新建文件,复制代码进去尝试生成。
若仍报错,通过注释代码的方式排查问题原因。