博客 (39)

有一个项目,在 VS2022 中正常打开,在 VS2019 中无法加载项目,项目目标框架是 .NET Standard 2.0。报错内容:

error: 无法打开项目文件。 .NET SDK 的版本 7.0.306 至少需要 MSBuild 的 17.4.0 版本。当前可用的 MSBuild 版本为 16.11.2.50704。请将在 global.json 中指定的 .NET SDK 更改为需要当前可用的 MSBuild 版本的旧版本。

解决方法:

运行 Visual Studio Installer,选择 Visual Studio 2019 进行修改,切换到“单个组件”,勾选“.NET SDK (out of support)”,会联动勾选“.NET 5.0 Runtime (Out of support)”与“.NET Core 3.1 Runtime (Out of support)”。

QQ截图20230728135007.png

xoyozo 2 年前
8,876

不知道从哪个版本的 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;
        });
    }
});

缺点是需要用户授权:

image.png

仅第一次需要授权,如果用户拒绝,那么以后就默认拒绝了。


以上两种方式各有优缺点,选择一种适合你的方案就行。接下来继续完善。


兼容更多时间格式,并调整时区

<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); // vue2
target[atts[atts.length - 1]] = text; // vue3


xoyozo 3 年前
2,041

在代码

app.Run();

处报错:

System.IO.IOException:“Failed to bind to address http://localhost:5182.”

SocketException: 以一种访问权限不允许的方式做了一个访问套接字的尝试。

原因是端口被占用,解决方法:

方法一、重启电脑可能解决该问题。

方法二、使用命令 netstat -ano 找到占用该端口的进程,关闭即可。

方法三、修改运行端口。展开解决方案资源管理器中项目根目录下的“Properties”目录,打开“launchSettings.json”,找到对应你运行方式的配置,修改相应 Url 中的端口。


xoyozo 3 年前
3,757

新版本 SDK 已解决这个问题


image.png

升级到 .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 { });



a
转自 adaxiong 3 年前
2,445

错误 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.

解决方法:将相关文件从项目中排除,再包括到项目中即可正常生成。

若仍报错,备份这些文件,删除并新建文件,复制代码进去尝试生成。

若仍报错,通过注释代码的方式排查问题原因。

xoyozo 3 年前
2,887

错误 TS5055 无法写入文件“***.js”,因为它会覆盖输入文件。

添加 tsconfig.json 文件有助于组织包含 TypeScript 和 JavaScript 文件的项目。有关详细信息,请访问 https://aka.ms/tsconfig。

检查“输出”窗口,找到“error”的行,并修复该错误。

一种可能的情况是,使用了 vue3 的 computed 计算属性。原因未知,尝试又定义了一个变量并使用 watch 侦听原变量来给它赋值,同样报错。

xoyozo 3 年前
5,492

System.ComponentModel.Win32Exception: 拒绝访问。

[ExternalException (0x80004005): 无法执行程序。所执行的命令为 "\bin\roslyn\csc.exe" /shared /keepalive:"10" /noconfig  /fullpaths @"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\8c8f68eb\880f02b5\alczcu1a.cmdline"。]

解决方法:

web 部署发布时勾选“在发布期间预编译”

image.png

在“配置”中,去掉“允许更新预编辑站点”前的勾,勾选“不合并。为每个页面和控件创建单独的程序集”

image.png

xoyozo 3 年前
3,245

开发环境正常,发布到 IIS 报错

Could not load file or assembly 'Microsoft.EntityFrameworkCore.Relational, Version=6.0.x.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. 系统找不到指定的文件。

尝试在 UI 层安装 Pomelo.EntityFrameworkCore.MySql 无果。

最终,在发布时文件发布选项中,去掉“启用 ReadyToRun 编译”就正常了。

当然这种情况不是在所有启用了 ReadyToRun 编译的项目中遇到,但该项目改为不启用 ReadyToRun 后恢复正常了,原因暂时未知。

xoyozo 4 年前
4,294

查看错误信息方式:

宝塔面板:网站 - 站点 - 网站日志 - 错误日志

或 /www/server/php/[版本]/var/log

xoyozo 4 年前
2,846

直接运行项目启动程序(在发布目录中,以项目名称为文件名,扩展名为 .exe 的可执行程序)

启动后可在“Now listening on:”所在行看到访问入口 URL(如图中 http://localhost:5000)。

在同服浏览器中打开该地址,访问到报错页面,回到该命令行窗口可见“fail”异常的详细信息。

QQ截图20211003173208.png

xoyozo 4 年前
2,484