使用的是电信光猫,外网访问本地地址(功能相当于ipv4的内网穿透)。

和安装光猫的师傅套套近乎,师傅应该就会把光猫的管理员账户和密码告诉我们。

登录光猫管理员账户后,在安全=>防火墙中把”启用IPV6 SESSION”关闭

就能在外网访问本地电脑的ipv6地址了。

打开本地电脑的windows的远程桌面开关,就可以在外网使用windows自带的远程桌面访问本地电脑了,无需安装第三方应用。

如果仍然无法访问本地ipv6地址,可能是路由器也有防火墙。一般路由器改成桥接模式可以关闭路由器的防火墙,从而外网使用ipv6访问本地地址。

再加上ddns动态域名解析,就可以实现使用域名访问本地电脑了。cloudflare ddns

或者使用nodejs(版本22),以下是更新dns的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 修改下面的四个变量
// https://dash.cloudflare.com/profile/api-tokens 在这个页面获取Global API Key
import {parse} from "url";
import http from "http";
import https from "https";
import fs from "fs";

var sub = ["域名前缀"]; // 如 ["www"] // 单个IP绑定多个域名则为多个元素的数组,如: ['a', 'b']
var domain = ["主域名"]; // 如 ["qq.com"]
var email = "你的邮箱"; // 如 "abc@qq.com"
var authKey = "Global API Key" // 如 "123456789..."

var auth = {
"X-Auth-Email": email,
"X-Auth-Key": authKey
};

function log(txt) {
fs.appendFile('ddns.txt', (txt + '\n'), err => {
if (err) {
console.error(err)
return
}
});
}


const requestIpv6 = http.get({ 'host': 'api6.ipify.org', 'port': 80, 'path': '/', family: 6 }, function (resp) {
if (resp.statusCode != 200) {
log("non-200 response status code:", resp.statusCode);
return;
}
else {
resp.on('data', function (ip) {
log('get ipv6 success:200');
log("My public IP address is: " + ip);


const url = parse("https://api.cloudflare.com/client/v4/zones/5926705fb3db4a7f866714500ef5a12c/dns_records");
if (url.hash) {
url.path += url.hash;
}
url.method = "GET";
url.headers = auth;

const getDNSList = https.request(url, (DNSListRes) => {
let DNSListBody = '';
DNSListRes.setEncoding("utf8");
DNSListRes.on("data", (resBody) => {
DNSListBody += resBody;
});
DNSListRes.on("end", () => {
log("dns list success");
const getDNSList = JSON.parse(DNSListBody).result;
for (let i = 0; i < sub.length; i++) {
let domainTotal = sub[i] + '.' + domain;
getDNSList.forEach((record) => {

if (record.name === domainTotal && ip.toString() !== record.content) {
makeRequest(ip, domainTotal, "PUT", record);
}
else if (record.name === domainTotal && ip.toString() === record.content) {
log(domainTotal + ":ipv6 doesn't need update.")
}
})
if (getDNSList.filter((record) => record.name === domainTotal).length === 0) {
makeRequest(ip, domainTotal, "POST", { id: '' }); // POST不需要id,设置为空
}


};
});

});
getDNSList.on("error", (error) => {
log(String(error));
});
getDNSList.end();
});
}
});
requestIpv6.on('error', (error) => {
log(String(error));
})

function makeRequest(ipA, domainTotalA, method, record) {
let putBody = {
"content": ipA.toString(),
"name": domainTotalA,
"proxied": false,
"type": "AAAA"
}

let urlPut = parse("https://api.cloudflare.com/client/v4/zones/5926705fb3db4a7f866714500ef5a12c/dns_records/" + record.id);
urlPut.method = method;
urlPut.headers = {
...auth,
"Content-Type": "application/json"
};
const putDNS = https.request(urlPut, (PutDNSRes) => {
let putDNSBody = '';
PutDNSRes.setEncoding("utf8");
PutDNSRes.on("data", (putRes) => {
putDNSBody += putRes;
});
PutDNSRes.on("end", () => {
log(JSON.stringify(JSON.parse(putDNSBody), null, '\t'));
});

});
putDNS.on("error", (error) => {
log(String(error));
});
putDNS.end(JSON.stringify(putBody));
}

如果使用windows系统,则可以使用任务计划程序,设置开机一分钟之后执行脚本、和设置重复间隔一小时执行脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Const ForAppending = 8

Set objFSO = CreateObject("Scripting.FileSystemObject")

' 修改下面一行
Set objFile = objFSO.OpenTextFile([修改为nodejs的输出日志的绝对位置], ForAppending)

objFile.WriteLine Now
objFile.WriteLine("start")
objFile.Close

' 修改下面一行
strCommand = "cmd /c node [修改为nodejs的程序的绝对位置]"
CreateObject("Wscript.Shell").Run strCommand, 0, true

CMR 硬盘不要分区! 直接扫,SMR 硬盘需要写满再扫,空盘会作弊,读的是缓存。

写满磁盘:fsutil file createNew <文件名> <长度>

电源

cpu供电双8pin匹配主板cpu供电接口
gpu供电双8pin

主板

m2接口、pcie接口、sata接口是否冲突
高端型号风扇散热与显卡位置大小是否冲突
内存是否4个插槽
网卡速率

机箱

是否atx m-atx itx
前置usb3
硬盘位几个

显卡

供电
显卡长度匹配机箱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// @name            Bilibili Evolved
// @description 强大的哔哩哔哩增强脚本
// @updateURL https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/dist/bilibili-evolved.user.js
// @downloadURL https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/dist/bilibili-evolved.user.js
// @version 2.10.2

// 修改为

// @name Bilibili Evolved (Local)
// @description Bilibili Evolved (本地)
// @version 300.0

// 在require后面添加

// @require file://<硬盘位置>/Bilibili-Evolved/dist/bilibili-evolved.dev.user.js

Ctrl+Shift+b运行任务

模板语法

reactive() 只适用于对象,它不能持有如 string、number 或 boolean 这样的原始类型,对解构操作不友好。ref() 则可以接受任何类型。ref对象解包后不用使用.value
v-bind:<attribute> :class
v-on也可以@

v-for
v-bind:[attributeName]
@submit.prevent

v-if
v-else​
v-else-if
v-show

<template>

v-if v-for同时使用优先级不明显,v-if优先级更高,无法访问v-for的变量,会报错。使用computed计算filter后再用v-for

v-model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 计算属性
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})

// 挂载后处理原生dom
onMounted(() => {
ElementRef.value.textContent = 'mounted!'
})

// 副作用
watch(todoId, callback)

// 定义获取的属性值
defineProps(['title'])

// 属性传入事件
const emit = defineEmits(['response'])
emit('response', 'hello from child')
<ChildComp @response="(msg) => childMsg = msg" />

事件处理:@keyup.alt.enter="clear"

<tr is="vue:blog-post-row"></tr>

<BlogPost v-bind="Object" />

我们可以通过设定defineOptions({ inheritAttrs: false })和使用 v-bind=”$attrs” 来实现属性透传到非直接子组件

父元素:<slot name="header"></slot>子元素:<template #header>
slot子元素添加样式<div v-if="$slots.footer" class="card-footer">

依赖注入:组件后代提供数据

1
2
3
4
5
6
// 祖先元素处
const message = ref('hello')
provide('message', message)

//后代元素处
const message = inject('message')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// 定义默认值
const props = withDefaults(defineProps<Props>(), {
msg: 'hello',
labels: () => ['one', 'two']
})

// 选项式API路由
$route.fullPath
$router.push('/about')

// 组合式API
import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
const search = computed({
get() {
// route.query
return route.query.search ?? ''
},
set(search) {
router.replace({ query: { search } })
},
})
router.push()
router.replace()
router.go(n)

// 指向/user/erina
<router-link :to="{ name: 'profile', params: { username: 'erina' } }">
User profile
</router-link>

// id路由
const routes = [
// 动态字段以冒号开始
{ path: '/users/:id', component: User },
]
{{ $route.params.id }}

// 对路由变化做出响应...
import { watch } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
watch(() => route.params.id, (newId, oldId) => {
// 对路由变化做出响应...
})


const routes = [
{
path: '/user/:id',
component: User,
children: [
// 当 /user/:id 匹配成功
// UserHome 将被渲染到 User 的 <router-view> 内部
{ path: '', component: UserHome },
{
// 当 /user/:id/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: 'posts',
component: UserPosts,
},
],
},
]
<!-- User.vue -->
<template>
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view />
</div>
</template>

// 请注意redirect,导航守卫并没有应用在跳转路由上,而仅仅应用在其目标上。在上面的例子中,在 /home 路由中添加 beforeEnter 守卫不会有任何效果。

// 以 / 开头,以使嵌套路径中的路径成为绝对路径

// 登录重定向
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})

// 登录重定向
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
// reject the navigation
return false
},
},
]

// 路由重定向
function removeQueryParams(to) {
if (Object.keys(to.query).length)
return { path: to.path, query: {}, hash: to.hash }
}
function removeHash(to) {
if (to.hash) return { path: to.path, query: to.query, hash: '' }
}
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: [removeQueryParams, removeHash],
},
{
path: '/about',
component: UserDetails,
beforeEnter: [removeQueryParams],
},
]

// 路由懒加载,代码分片
const UserDetails = () => import('./views/UserDetails.vue')
const router = createRouter({
// ...
routes: [
{ path: '/users/:id', component: UserDetails }
// 或在路由定义里直接使用它
{ path: '/users/:id', component: () => import('./views/UserDetails.vue') },
],
})

路由

layout.js相当于公共父组件,page.js相当于react-router的index组件

form

zod + server actions

useSearchParams, usePathname, and useRouter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { useSearchParams, usePathname, useRouter } from 'next/navigation';

export default function Search() {
const searchParams = useSearchParams();
const pathname = usePathname();
const { replace } = useRouter();

function handleSearch(term: string) {
const params = new URLSearchParams(searchParams);
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
replace(`${pathname}?${params.toString()}`);
}
return (
<input
className="peer block w-full rounded-md border border-gray-200 py-[9px] pl-10 text-sm outline-2 placeholder:text-gray-500"
placeholder={placeholder}
onChange={(e) => {
handleSearch(e.target.value);
}}
defaultValue={searchParams.get('query')?.toString()}
/>
)
}

Metadata

pnpm不能删除多余的包

登录光猫的管理员账号

不知道密码可以重置光猫后(长按重置的小圆点按钮,所用指示灯全亮后松开。就可以使用默认管理员账户登录。

  1. 电信光猫

    用户名:telecomadmin

    密码:nE7jA%m
  2. 移动光猫

    用户名:CMCCAdmin

    密码:aDm8H%MdA
  3. 联通光猫

    用户名:CUAdmin

    密码:CUAdmin

修改设置

进入光猫”网络=>LAN侧地址配置”

  1. 关闭DHCP
  2. 设置ip地址为交换机对应的网段的地址(如所在网段为192.168.1.0,则可以设置为192.168.1.254,记住设置的地址,重启后使用这个地址才能登录光猫)

调试

打开Tampermonkey的设置里面的Debug scripts后会在代码开头自动添加debugger,使代码开始时进入调试模式。

无痕窗口

无痕窗口更新Tampermonkey的设置不及时,应该在正常窗口调试。

在本地改代码调试

use an external editor to edit my scripts

// @require file://D:/repository/demo/JavaScript/myj.js放在其他脚本(// @require)加载的后面

在后台标签页被冻结(tab freezing)

在设置=>性能=>始终让以下网站保持活跃状态=>选择网站。就可以在开发者工具中刷新,页面也不会被冻结。

安装中文语言包

  1. 下载中文语言包
  2. 第一步:AndroidStudio->设置->插件->从磁盘安装插件->下载的jar包->重启AndroidStudio
    第二步:自定义(Customize)->语言和地区(Language and Region)->语言(Language)->Chinese->重启AndroidStudio
    或者 设置->外观与行为->系统设置->Language and Region->语言(Language)->Chinese->重启AndroidStudio

Gradle-指定Gradle依赖的JDK版本

您的构建当前配置为使用不兼容的 Java 21.0.6 和 Gradle 7.2。无法同步项目。

  1. 需要安装Gradle对应版本的jdk。Gradle 7.2对应jdk 17,下载并解压jdk 17。
  2. 依次点击 “File” - “Settings” - “Build, Execution, Deployment” - “Build Tool” - “Gradle” - “Gradle JDK”, 选择jdk解压的地址即可。
0%