如果富士施乐 DocuPrint P118 w 打印机开启后电脑无法连接,但路由器上显示已连网,很有可能是 IP 已变更(增添新设备后抢占了打印机原来的 IP 地址)。
这时候需要重新安装打印机驱动:(可能有不需要重装驱动的方法)
富士施乐 DocuPrint P118 w 在安装驱动时需要路由器支持 WPS/AOSS,
但小米路由器 Pro 中找不到该功能,而且实测无线方式安装打印机驱动失败。
我的方法是,找一台 TP-LINK 路由器,
将 SSID 和 WIFI 密码改成与小米路由器相同,
关闭小米路由器,
电脑连接这个 SSID,
然后按无线的方式安装打印机驱动程序,
完成后,关闭 TP-LINK 路由器,打开小米路由器,
网络启动后,重启打印机。
(打印时可能需要在窗口中选择另一个打印机名称)
在升级 kernel 后若无法启动系统,网站无法打开,SSH 无法连接,无法 ping 通。
使用 VNC 进入操作界面:

一种界面是可选择次新的内核版本:

应该能正常启动。
另一种界面提示:
Give root password for maintenance
输入密码后可启动。
阿里云工程师的建议:
1、当前默认是以最新内核启动的,由于新版内核文件存在异常无法正常运行,在手动选择低内核版本启动后,可以先更改下默认内核引导顺序,配置默认使用低版本内核运行,避免重启再次出现问题。 修改内核引导顺序 https://help.aliyun.com/knowledge_detail/41463.html 2、升级内核本身属于高危操作,建议操作前先做好快照备份,同时更新时可以参考下文档方案 避免Linux实例升级内核系统无法启动的方法 https://help.aliyun.com/knowledge_detail/59360.html
使用 JS 根据屏幕宽度来计算页面尺寸和字体大小并不是一个好办法。
rem 单位是跟随网页根元素的 font-size 改变而自动改变的,是一个相对的长度单位,非常适合在不同手机界面上自适应屏幕大小。
一般的手机浏览器的默认字体大小为 16px。即:
:root { font-size: 16px; } /* 在 HTML 网页中,:root 选择器相当于 html */也就是说,如果我定义一个宽度为 1rem,那么它的实际宽度为 16px。反过来说,如果设计稿宽度为 1000px,那么相当于 1000÷16=62.5rem。因此,我们设置一个 62.5rem 的宽度,即可正常显示 1000px 的设计效果。
为了适应不同屏幕尺寸的手机,只需按比例换算更改 :root 的 font-size 即可。这个比例是由“窗口宽度 ÷ 设计稿宽度”得到的,姑且称它为“窗设比”。
以 iPhone X 逻辑宽度 375px 为例,设计稿宽度 1000px 时,窗设比为:0.375。:root 的 font-size 将会被重置为 16 * 0.375 = 6px。上面的 62.5rem 宽度将对应 iPhone X 宽度为 62.5 * 6 = 375px,正好是屏幕逻辑宽度。
根据这个思路,理论上,我们只需要使用 CSS 将 :root 的 font-size 设置为 1px,然后使用 JS 重置为与“窗设比”相乘的积(本例中将被重置为 0.375px)。这样,我们可以不通过换算,只需要更改单位,将设计稿中的 500px 直接写入到 CSS 为 500rem,即可实现在 iPhone X 上显示逻辑宽度为(500 * 0.375 =)187.5px,即设计稿中的 1/2 宽度对应到屏幕上 1/2 的宽度。
实际上,部分安卓手机(如华为某旗舰机)不支持 :root 的 font-size 小于 12px,其它一些浏览器也会出现小于 12px 的文字以 12px 显示。
为了避免在任何环节出现小于 12px 的 font-size 值,且不增加设计稿尺寸到 CSS 数值的换算难度,我们设计了以下思路:
约定“设样比(设计稿的 px 值与 CSS 的 rem 值的比)”为 100;
使用 JS 将 :root 的 font-size 重置为“设样比”与“窗设比(窗口宽度 ÷ 设计稿宽度)”的乘积;
计算 CSS 时的 rem 值只需从设计稿中获取 px 值再除以“设样比”100 即可。
这样做的另一个好处是,不用要求设计师必须按多少尺寸来设计,当然按主流尺寸来建议是可行的。
完整代码(jQuery 版):
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<title>Index</title>
<style>
body { margin: 0; text-align: center; }
#app { margin: 0 auto; background-color: #EEE; display: none; }
/* 长度计算方法:从设计稿获得长度(例如 160px),除以 px2rem 值(本例为 100),得到 1.6rem */
.whole { background-color: #D84C40; width: 10rem; }
.half { background-color: #3296FA; width: 5rem; }
.half2 { background-color: #3296FA; width: 5rem; margin-left: 5rem; }
</style>
</head>
<body>
<div id="app">
<div class="whole">100%</div>
<div class="half">50%</div>
<div class="half2">50%</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
// [函数] 重置尺寸
function fn_resize() {
// 设计稿宽度(px)
var designsWidth = 1000;
// 约定的“设计稿 px 值与 CSS rem 值的比”,为方便计算,一般无需改动
var px2rem = 100;
// 限制 #app 的最大宽度为设计稿宽度
$('#app').css('max-width', designsWidth).css('min-height', $(window).height());
// 重置 :root 的 font-size
var appWidth = Math.min($(window).width(), designsWidth);
$(':root').css('font-size', px2rem * appWidth / designsWidth);
$('#app').show();
}
// 页面加载完成后重置尺寸
$(fn_resize);
// 改变窗口大小时重置尺寸
$(window).resize(fn_resize);
</script>
</body>
</html>完整代码(Vue2 版):
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<title>Index</title>
<style>
body { margin: 0; text-align: center; }
#app { margin: 0 auto; background-color: #EEE; }
/* 长度计算方法:从设计稿获得长度(例如 160px),除以 px2rem 值(本例为 100),得到 1.6rem */
.whole { background-color: #D84C40; width: 10rem; }
.half { background-color: #3296FA; width: 5rem; }
.half2 { background-color: #3296FA; width: 5rem; margin-left: 5rem; }
</style>
</head>
<body>
<div id="app" v-bind:style="{ maxWidth: designsWidth + 'px', minHeight: appMinHeight + 'px' }" style="display: none;" v-show="appShow">
<div class="whole">100%</div>
<div class="half">50%</div>
<div class="half2">50%</div>
<div>appWidth: {{ appWidth }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
var app = new Vue({
el: '#app',
data: {
// 设计稿宽度(px)
designsWidth: 1000,
// 约定的“设计稿 px 值与 CSS rem 值的比”,为方便计算,一般无需改动
px2rem: 100,
// #app 的 width
appWidth: 0, // 勿改
appMinHeight: 0, // 勿改
appShow: false, // 勿改
},
mounted: function () {
// 页面加载完成后重置尺寸
this.fn_resize();
const that = this;
// 改变窗口大小时重置尺寸
window.onresize = () => {
return (() => {
console.log('RUN window.onresize()');
that.fn_resize();
})();
};
},
watch: {
// 侦听 appWidth 更改 root 的 font-size
appWidth: function () {
console.log('RUN watch: appWidth');
var root = document.getElementsByTagName("html")[0];
root.style.fontSize = (this.px2rem * this.appWidth / this.designsWidth) + 'px';
this.appShow = true;
}
},
methods: {
fn_resize: function () {
console.log('RUN methods: fn_resize()');
this.appWidth = Math.min(document.body.clientWidth, this.designsWidth);
this.appMinHeight = document.documentElement.clientHeight;
}
}
});
</script>
</body>
</html>完整代码(Vue3 版):
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<title>Index</title>
<style>
body { margin: 0; text-align: center; }
#app > div { display: none; margin: 0 auto; background-color: #EEE; }
/* 长度计算方法:从设计稿获得长度(例如 160px),除以 px2rem 值(本例为 100),得到 1.6rem */
.whole { background-color: #D84C40; width: 10rem; }
.half { background-color: #3296FA; width: 5rem; }
.half2 { background-color: #3296FA; width: 5rem; margin-left: 5rem; }
</style>
</head>
<body>
<div id="app">
<div style="display: none;" v-bind:style="{ maxWidth: designsWidth + 'px', minHeight: appMinHeight + 'px', display: appShow ? 'block' : 'none' }">
<div class="whole">100%</div>
<div class="half">50%</div>
<div class="half2">50%</div>
<div>appWidth: {{ appWidth }}</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@3"></script>
<script>
const app = Vue.createApp({
data: function () {
return {
// 设计稿宽度(px)
designsWidth: 1000,
// 约定的“设计稿 px 值与 CSS rem 值的比”,为方便计算,一般无需改动
px2rem: 100,
// #app 的 width
appWidth: 0, // 勿改
appMinHeight: 0, // 勿改
appShow: false, // 勿改
}
},
mounted: function () {
// 页面加载完成后重置尺寸
this.fn_resize();
const that = this;
// 改变窗口大小时重置尺寸
window.onresize = () => {
return (() => {
console.log('RUN window.onresize()');
that.fn_resize();
})();
};
},
watch: {
// 侦听 appWidth 更改 root 的 font-size
appWidth: function () {
console.log('RUN watch: appWidth');
var root = document.getElementsByTagName("html")[0];
root.style.fontSize = (this.px2rem * this.appWidth / this.designsWidth) + 'px';
this.appShow = true;
}
},
methods: {
fn_resize: function () {
console.log('RUN methods: fn_resize()');
this.appWidth = Math.min(document.body.clientWidth, this.designsWidth);
this.appMinHeight = document.documentElement.clientHeight;
}
}
});
const vm = app.mount('#app');
</script>
</body>
</html>示例中 CSS 初始 :root 的 font-size 为 16px(一个较小值,防止页面加载时瞬间出现大号文字影响用户体验),经过 fn_resize 后,:root 的 font-size 被设置为(100 * 375 / 1000 =)37.5px(iPhone X 中),那么宽度为 1000px 的设计稿中的 500px 换算到 CSS 中为 5rem,也即 37.5 * 5 = 187.5px,就是 iPhone X 的屏幕宽度的一半。
示例中 id 为 app 的 div 是用来在 PC 浏览器中限制页面内容最大宽度的(类似微信公众号发布的文章),如果网页不需要在 PC 端显示,jQuery 版代码中的 $('#app').width() 可以用 $(window).width() 来代替。
这个 div#app 一般设计有背景色,用于在宽度超过设计稿的设备上显示时区别于 body 的背景。但是当网页内容不超过一屏时,div#app 高度小于窗口,示例中与 appMinHeight 相关的代码就是为了解决这个问题。
示例中 div#app 隐藏/显示相关代码用于解决在页面加载初期由于 font-size 值变化引起的一闪而过的排版错乱。

最后补充一点,如果改变窗口大小时涉及执行耗时的操作,为避免页面卡顿,可以参考这篇文章添加函数防抖:https://xoyozo.net/Blog/Details/js-function-anti-shake

引用
jQuery、moment.js、daterangepicker
例子
$('.x_dates').daterangepicker({
"timePicker": false, // 是否显示时间
//"dateLimit": {
// "days": 7 // 可选中的最大区间(天)
//},
"ranges": { // 快捷栏
"今天": [moment(), moment()],
"昨天": [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
"最近 7 天": [moment().subtract(6, 'days'), moment()],
"最近 30 天": [moment().subtract(29, 'days'), moment()],
"本月": [moment().startOf('month'), moment().endOf('month')],
"上个月": [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
},
startDate: daterangepicker_startDate, // moment(),
endDate: daterangepicker_endDate, // moment(),
autoUpdateInput: true,
"locale": {
"direction": "ltr",
"format": "YYYY-MM-DD", // YYYY-MM-DD HH:mm
"separator": " 至 ",
"applyLabel": "确定",
"cancelLabel": "取消",
"fromLabel": "From",
"toLabel": "To",
"customRangeLabel": "自定义",
"daysOfWeek": ["日", "一", "二", "三", "四", "五", "六"],
"monthNames": ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
"firstDay": 1
}
}, function (start, end, label) {
//console.log('New date range selected: ' + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD') + ' (predefined range: ' + label + ')');
fn_daterangepicker_changed(start.format('YYYY-MM-DD'), end.format('YYYY-MM-DD'))
});官网(含配置工具)
http://www.daterangepicker.com/
GitHub
https://github.com/dangrossman/daterangepicker
配置工具
下载的包中的 demo.html
Demo
https://awio.iljmp.com/5/drpdemo
ASP.NET Core 缓存 Caching 提供了包括但不限于以下几种存储方式:
内存缓存:https://xoyozo.net/Blog/Details/aspnetcore-memory-cache
SQL Server 缓存:https://xoyozo.net/Blog/Details/aspnetcore-sql-cache
Redis 缓存:https://xoyozo.net/Blog/Details/aspnetcore-redis-cache
MySQL 缓存:https://xoyozo.net/Blog/Details/aspnetcore-mysql-cache
本文介绍内存缓存
Memory Caching
1.新建一个 ASP.NET Core 项目,选择 Web 应用程序,将身份验证 改为 不进行身份验证。
2.添加引用
Install-Package Microsoft.Extensions.Caching.Memory
3.使用
在 Startup.cs 中 ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
// Add framework services.
services.AddMvc();
}然后在
public class HomeController : Controller
{
private IMemoryCache _memoryCache;
public HomeController(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
public IActionResult Index()
{
string cacheKey = "key";
string result;
if (!_memoryCache.TryGetValue(cacheKey, out result))
{
result = $"LineZero{DateTime.Now}";
_memoryCache.Set(cacheKey, result);
}
ViewBag.Cache = result;
return View();
}
}这里是简单使用,直接设置缓存。
我们还可以加上过期时间,以及移除缓存,还可以在移除时回掉方法。
过期时间支持相对和绝对。
下面是详细的各种用法。
public IActionResult Index()
{
string cacheKey = "key";
string result;
if (!_memoryCache.TryGetValue(cacheKey, out result))
{
result = $"LineZero{DateTime.Now}";
_memoryCache.Set(cacheKey, result);
//设置相对过期时间2分钟
_memoryCache.Set(cacheKey, result, new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromMinutes(2)));
//设置绝对过期时间2分钟
_memoryCache.Set(cacheKey, result, new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromMinutes(2)));
//移除缓存
_memoryCache.Remove(cacheKey);
//缓存优先级 (程序压力大时,会根据优先级自动回收)
_memoryCache.Set(cacheKey, result, new MemoryCacheEntryOptions()
.SetPriority(CacheItemPriority.NeverRemove));
//缓存回调 10秒过期会回调
_memoryCache.Set(cacheKey, result, new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromSeconds(10))
.RegisterPostEvictionCallback((key, value, reason, substate) =>
{
Console.WriteLine($"键{key}值{value}改变,因为{reason}");
}));
//缓存回调 根据Token过期
var cts = new CancellationTokenSource();
_memoryCache.Set(cacheKey, result, new MemoryCacheEntryOptions()
.AddExpirationToken(new CancellationChangeToken(cts.Token))
.RegisterPostEvictionCallback((key, value, reason, substate) =>
{
Console.WriteLine($"键{key}值{value}改变,因为{reason}");
}));
cts.Cancel();
}
ViewBag.Cache = result;
return View();
}Distributed Cache Tag Helper
在 ASP.NET Core MVC 中有一个 Distributed Cache 我们可以使用。
我们直接在页面上增加 distributed-cache 标签即可。
<distributed-cache name="mycache" expires-after="TimeSpan.FromSeconds(10)">
<p>缓存项10秒过期-LineZero</p>
@DateTime.Now
</distributed-cache>
<distributed-cache name="mycachenew" expires-sliding="TimeSpan.FromSeconds(10)">
<p>缓存项有人访问就不会过期,无人访问10秒过期-LineZero</p>
@DateTime.Now
</distributed-cache>这样就能缓存标签内的内容。
本文环境:CentOS 7、nginx 1.16、ASP.NET Core 3.0
安装 nginx,可以使用宝塔面板。
创建网站,保证网站静态页面能够正常访问。
必要时配置 SSL 证书。
安装 ASP.NET Core 运行时:
安装说明见:https://dotnet.microsoft.com/download,切换到 Linux,选择 Install .NET Core Runtime
选择操作系统,按页面说明安装即可。
发布一个 ASP.NET Core 项目到网站目录,运行应用程序:
dotnet 应用的程序集文件名.dll必须先 cd 到项目所在目录再执行,否则“Content root path”不会指向网站根目录,从而导致无法访问静态文件。

观察到端口为 5000(默认),该 Url 用于下一步设置反向代理。
配置 nginx 反向代理:(使用宝塔面板时建议使用面板中提供的“反向代理”功能)
location / { proxy_pass http://localhost:5000; }查看官方详细说明:使用 Nginx 在 Linux 上托管 ASP.NET Core
错误如下:

解决方法:
在“解决方案资源管理器”中点击项目右键,选择“编辑项目文件”

手动添加内容:
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.3" />
完成。如果编译出错,关闭项目并重新打开项目再试。

路由器模式:使用 mesh 主体拨号,缺点是由于 mesh 主体不适合放入弱电箱,那么就有两条网线连接到弱电箱(不需要有线回程或不需要接交换机的忽略此缺点)。
AP 模式:适合已有拨号路由器的环境,mesh 路由器主体与分身之间用 AP 模式连接(小米路由器 Mesh 不支持 AP 模式,估计跟“不分子母”有关);
布线方案:
如果 mesh 作拨号路由器功能够用,那么直接使用路由器模式。家庭新装修的朋友建议在合适的位置(如客厅电视机柜)预留两条网线到弱电箱,一条用于连接光猫到 Mesh 主体,再用另一条有线回程到弱电箱的交换机,无线回程者随意。
如果选择其它路由器作拨号路由器(如软路由,或看中小米路由器强大的 App 功能又不想用小米 mesh),那么 mesh 路由器使用 AP 模式,本体接任意墙壁网口即可。建议关闭拨号路由器的 WiFi,并考虑带机量。
顺便提一下 AC+AP 方案的布线:
同样的,如果无其它拨号路由器,那么可以选择路由/AC/PoE 一体机,配合 AP 使用;如果有指定的拨号路由器,那么选择单独的 AC 控制器 + 交换机 + AP 即可。
AC 和 AP 可二层组网、三层组网,可直连式组网、旁挂式组网。
旁挂组网时,如果 AC 控制器选择百兆网口,不会影响千兆交换机和 AP 的传输效率,因为 AC 控制器仅用来管理 AP,不进行数据传输。
AP 有面板式、吸顶式、户外等可选,PoE 或 DC 供电,有胖瘦之分。胖 AP 有独立管理后台,瘦 AP 无管理后台,必须与 AC 配合使用。
据说:TL-AC100 支持快速漫游,TL-AC300 支持无缝漫游。

