edgeone-cli 1.0.13 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.js +1 -210
- package/dist/commands/config.js +1 -312
- package/dist/commands/edgeone.js +1 -414
- package/dist/constants/index.js +1 -60
- package/dist/index.js +1 -37
- package/dist/repl/config-menu.js +1 -264
- package/dist/repl/index.js +1 -95
- package/dist/repl/prefetch-menu.js +1 -192
- package/dist/repl/purge-menu.js +1 -228
- package/dist/repl/ui.js +1 -29
- package/dist/repl/zone-menu.js +1 -219
- package/dist/types/index.js +1 -5
- package/dist/utils/crypto.js +1 -85
- package/dist/utils/date.js +1 -52
- package/dist/utils/display.js +1 -72
- package/dist/utils/signature.js +1 -49
- package/package.json +1 -1
package/dist/repl/purge-menu.js
CHANGED
|
@@ -1,228 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 清除缓存菜单
|
|
3
|
-
*/
|
|
4
|
-
import chalk from "chalk";
|
|
5
|
-
import inquirer from "inquirer";
|
|
6
|
-
import { EdgeOneClient } from "../api/client.js";
|
|
7
|
-
import { pauseToContinue } from "./ui.js";
|
|
8
|
-
/**
|
|
9
|
-
* 清除缓存菜单
|
|
10
|
-
*/
|
|
11
|
-
export async function purgeMenu(config) {
|
|
12
|
-
const actionAnswers = await inquirer.prompt([
|
|
13
|
-
{
|
|
14
|
-
type: "list",
|
|
15
|
-
name: "type",
|
|
16
|
-
message: "选择操作:",
|
|
17
|
-
choices: [
|
|
18
|
-
{ name: "清除缓存", value: "purge" },
|
|
19
|
-
{ name: "查询历史", value: "history" },
|
|
20
|
-
new inquirer.Separator(),
|
|
21
|
-
{ name: "← 返回", value: "back" },
|
|
22
|
-
],
|
|
23
|
-
},
|
|
24
|
-
]);
|
|
25
|
-
if (actionAnswers.type === "back")
|
|
26
|
-
return;
|
|
27
|
-
if (actionAnswers.type === "history") {
|
|
28
|
-
await queryPurgeHistoryMenu(config);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const answers = await inquirer.prompt([
|
|
32
|
-
{
|
|
33
|
-
type: "list",
|
|
34
|
-
name: "type",
|
|
35
|
-
message: "选择清除类型:",
|
|
36
|
-
choices: [
|
|
37
|
-
{ name: "清除全部缓存", value: "all" },
|
|
38
|
-
{ name: "清除指定目录缓存", value: "dir" },
|
|
39
|
-
{ name: "清除指定 URL 缓存", value: "url" },
|
|
40
|
-
new inquirer.Separator(),
|
|
41
|
-
{ name: "← 返回", value: "back" },
|
|
42
|
-
],
|
|
43
|
-
},
|
|
44
|
-
]);
|
|
45
|
-
if (answers.type === "back")
|
|
46
|
-
return;
|
|
47
|
-
let targets = [];
|
|
48
|
-
let purgeType = "purge_all";
|
|
49
|
-
let zoneId = "*";
|
|
50
|
-
// 选择 Zone ID
|
|
51
|
-
if (config.domainIdList && config.domainIdList.length > 0) {
|
|
52
|
-
const zoneChoices = config.domainIdList.map((zone) => ({
|
|
53
|
-
name: zone.name || zone.id,
|
|
54
|
-
value: zone.id,
|
|
55
|
-
}));
|
|
56
|
-
const zoneAnswers = await inquirer.prompt([
|
|
57
|
-
{
|
|
58
|
-
type: "list",
|
|
59
|
-
name: "zone",
|
|
60
|
-
message: "选择站点:",
|
|
61
|
-
choices: ["* (全部站点)", ...zoneChoices],
|
|
62
|
-
},
|
|
63
|
-
]);
|
|
64
|
-
if (zoneAnswers.zone !== "* (全部站点)") {
|
|
65
|
-
zoneId = zoneAnswers.zone;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (answers.type === "all") {
|
|
69
|
-
const confirm = await inquirer.prompt([
|
|
70
|
-
{ type: "confirm", name: "confirm", message: `确认清除全部缓存? (Zone: ${zoneId})`, default: false },
|
|
71
|
-
]);
|
|
72
|
-
if (!confirm.confirm) {
|
|
73
|
-
console.log(chalk.gray("\n❌️ 已取消"));
|
|
74
|
-
await pauseToContinue();
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
purgeType = "purge_all";
|
|
78
|
-
}
|
|
79
|
-
else if (answers.type === "dir") {
|
|
80
|
-
const dirAnswers = await inquirer.prompt([
|
|
81
|
-
{ type: "input", name: "dir", message: "请输入目录路径 (留空取消):" },
|
|
82
|
-
]);
|
|
83
|
-
if (!dirAnswers.dir || !dirAnswers.dir.trim()) {
|
|
84
|
-
console.log(chalk.gray("\n❌️ 已取消"));
|
|
85
|
-
await pauseToContinue();
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
targets = [dirAnswers.dir];
|
|
89
|
-
purgeType = "purge_prefix";
|
|
90
|
-
}
|
|
91
|
-
else if (answers.type === "url") {
|
|
92
|
-
const urlAnswers = await inquirer.prompt([
|
|
93
|
-
{ type: "input", name: "urls", message: "请输入 URL (多个用空格分隔,留空取消):" },
|
|
94
|
-
]);
|
|
95
|
-
if (!urlAnswers.urls || !urlAnswers.urls.trim()) {
|
|
96
|
-
console.log(chalk.gray("\n❌️ 已取消"));
|
|
97
|
-
await pauseToContinue();
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
targets = urlAnswers.urls.split(/\s+/).filter(u => u.trim());
|
|
101
|
-
purgeType = "purge_url";
|
|
102
|
-
}
|
|
103
|
-
// 执行清除缓存
|
|
104
|
-
await executePurge(config, purgeType, targets, zoneId);
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* 执行清除缓存
|
|
108
|
-
*/
|
|
109
|
-
async function executePurge(config, type, targets, zoneId) {
|
|
110
|
-
const client = new EdgeOneClient(config.secretId, config.secretKey, config.endpoint || "teo.tencentcloudapi.com", "ap-guangzhou", config.mode);
|
|
111
|
-
const isDebug = config.mode === "debug";
|
|
112
|
-
if (isDebug) {
|
|
113
|
-
console.log(chalk.cyan("\n🔄 清除缓存任务\n"));
|
|
114
|
-
console.log(chalk.gray("API 参数:"));
|
|
115
|
-
console.log(` ZoneId: ${chalk.green(zoneId)}`);
|
|
116
|
-
console.log(` Type: ${chalk.green(type)}`);
|
|
117
|
-
if (targets.length > 0) {
|
|
118
|
-
console.log(` Targets: ${chalk.green(JSON.stringify(targets))}`);
|
|
119
|
-
}
|
|
120
|
-
console.log("");
|
|
121
|
-
}
|
|
122
|
-
try {
|
|
123
|
-
const result = await client.createPurgeTask({ zoneId, type, targets });
|
|
124
|
-
if ("Error" in result.Response) {
|
|
125
|
-
const error = result.Response.Error;
|
|
126
|
-
console.log(chalk.red("\n❌ 请求失败:"));
|
|
127
|
-
console.log(` 错误码: ${chalk.yellow(error.Code)}`);
|
|
128
|
-
console.log(` 错误信息: ${chalk.yellow(error.Message)}`);
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
console.log(chalk.green("\n✅ 请求成功!"));
|
|
132
|
-
console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);
|
|
133
|
-
if (result.Response.JobId) {
|
|
134
|
-
console.log(` JobId: ${chalk.yellow(result.Response.JobId)}`);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
catch (error) {
|
|
139
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
140
|
-
console.log(chalk.red("\n❌ 请求异常:"));
|
|
141
|
-
console.log(` ${errMsg}`);
|
|
142
|
-
}
|
|
143
|
-
console.log("");
|
|
144
|
-
await pauseToContinue();
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* 查询清除缓存历史菜单
|
|
148
|
-
*/
|
|
149
|
-
async function queryPurgeHistoryMenu(config) {
|
|
150
|
-
// 选择 Zone ID
|
|
151
|
-
let zoneIds = [];
|
|
152
|
-
if (config.domainIdList && config.domainIdList.length > 0) {
|
|
153
|
-
const zoneChoices = config.domainIdList.map((zone) => ({
|
|
154
|
-
name: zone.name || zone.id,
|
|
155
|
-
value: zone.id,
|
|
156
|
-
short: zone.name || zone.id,
|
|
157
|
-
}));
|
|
158
|
-
const zoneAnswers = await inquirer.prompt([
|
|
159
|
-
{
|
|
160
|
-
type: "checkbox",
|
|
161
|
-
name: "zones",
|
|
162
|
-
message: "选择站点 (可多选):",
|
|
163
|
-
choices: zoneChoices,
|
|
164
|
-
validate: input => input.length > 0 || "请至少选择一个站点",
|
|
165
|
-
},
|
|
166
|
-
]);
|
|
167
|
-
zoneIds = zoneAnswers.zones;
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
console.log(chalk.yellow("\n⚠️ 未配置站点列表,请使用 --zone 参数指定或在配置中添加\n"));
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
await queryPurgeHistory(config, zoneIds);
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* 查询清除缓存历史
|
|
177
|
-
*/
|
|
178
|
-
async function queryPurgeHistory(config, zoneIds) {
|
|
179
|
-
const { default: Table } = await import("cli-table3");
|
|
180
|
-
const client = new EdgeOneClient(config.secretId, config.secretKey, config.endpoint || "teo.tencentcloudapi.com", "", config.mode);
|
|
181
|
-
const isDebug = config.mode === "debug";
|
|
182
|
-
if (isDebug) {
|
|
183
|
-
console.log(chalk.cyan("\n📋 清除缓存历史记录\n"));
|
|
184
|
-
console.log(chalk.gray("ZoneIds: " + zoneIds.join(", ")));
|
|
185
|
-
}
|
|
186
|
-
try {
|
|
187
|
-
const result = await client.describePurgeTasks(zoneIds);
|
|
188
|
-
if ("Error" in result.Response) {
|
|
189
|
-
const error = result.Response.Error;
|
|
190
|
-
console.log(chalk.red("\n❌ 请求失败:"));
|
|
191
|
-
console.log(` 错误码: ${chalk.yellow(error.Code)}`);
|
|
192
|
-
console.log(` 错误信息: ${chalk.yellow(error.Message)}`);
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
console.log(chalk.green("\n✅ 查询成功!"));
|
|
196
|
-
console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);
|
|
197
|
-
const tasks = result.Response.Tasks || [];
|
|
198
|
-
if (tasks.length > 0) {
|
|
199
|
-
const table = new Table({
|
|
200
|
-
head: [chalk.gray("状态"), chalk.gray("清除地址"), chalk.gray("时间"), chalk.gray("类型")],
|
|
201
|
-
colWidths: [8, 50, 30, 8],
|
|
202
|
-
chars: { mid: "", "left-mid": "", "mid-mid": "", "right-mid": "" },
|
|
203
|
-
});
|
|
204
|
-
tasks.forEach(task => {
|
|
205
|
-
const status = task.Status === "success" ? chalk.green("✓") : chalk.red("✗");
|
|
206
|
-
const target = task.Target || "all";
|
|
207
|
-
const type = task.Type === "purge_url" ? "URL" : task.Type === "purge_prefix" ? "目录" : "全部";
|
|
208
|
-
// 截断过长的目标地址
|
|
209
|
-
const displayTarget = target.length > 47 ? target.slice(0, 44) + "..." : target;
|
|
210
|
-
table.push([status, chalk.yellow(displayTarget), chalk.gray(task.CreateTime.slice(0, 19).replace("T", " ")), type]);
|
|
211
|
-
});
|
|
212
|
-
console.log(chalk.cyan("\n📋 清除缓存记录:\n"));
|
|
213
|
-
console.log(table.toString());
|
|
214
|
-
console.log(` 总计: ${chalk.yellow(result.Response.TotalCount || tasks.length)} 条记录`);
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
console.log(chalk.gray("\n 暂无清除记录\n"));
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
catch (error) {
|
|
222
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
223
|
-
console.log(chalk.red("\n❌ 请求异常:"));
|
|
224
|
-
console.log(` ${errMsg}`);
|
|
225
|
-
}
|
|
226
|
-
console.log("");
|
|
227
|
-
await pauseToContinue();
|
|
228
|
-
}
|
|
1
|
+
import chalk from"chalk";import inquirer from"inquirer";import{EdgeOneClient}from"../api/client.js";import{pauseToContinue}from"./ui.js";export async function purgeMenu(config){const actionAnswers=await inquirer.prompt([{type:"list",name:"type",message:"选择操作:",choices:[{name:"清除缓存",value:"purge"},{name:"查询历史",value:"history"},new inquirer.Separator,{name:"← 返回",value:"back"}]}]);if("back"===actionAnswers.type)return;if("history"===actionAnswers.type)return void await async function(config){let zoneIds=[];if(!(config.domainIdList&&config.domainIdList.length>0))return void console.log(chalk.yellow("\n⚠️ 未配置站点列表,请使用 --zone 参数指定或在配置中添加\n"));{const zoneChoices=config.domainIdList.map(zone=>({name:zone.name||zone.id,value:zone.id,short:zone.name||zone.id}));zoneIds=(await inquirer.prompt([{type:"checkbox",name:"zones",message:"选择站点 (可多选):",choices:zoneChoices,validate:input=>input.length>0||"请至少选择一个站点"}])).zones}await async function(config,zoneIds){const{default:Table}=await import("cli-table3"),client=new EdgeOneClient(config.secretId,config.secretKey,config.endpoint||"teo.tencentcloudapi.com","",config.mode),isDebug="debug"===config.mode;isDebug&&(console.log(chalk.cyan("\n📋 清除缓存历史记录\n")),console.log(chalk.gray("ZoneIds: "+zoneIds.join(", "))));try{const result=await client.describePurgeTasks(zoneIds);if("Error"in result.Response){const error=result.Response.Error;console.log(chalk.red("\n❌ 请求失败:")),console.log(` 错误码: ${chalk.yellow(error.Code)}`),console.log(` 错误信息: ${chalk.yellow(error.Message)}`)}else{console.log(chalk.green("\n✅ 查询成功!")),console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);const tasks=result.Response.Tasks||[];if(tasks.length>0){const table=new Table({head:[chalk.gray("状态"),chalk.gray("清除地址"),chalk.gray("时间"),chalk.gray("类型")],colWidths:[8,50,30,8],chars:{mid:"","left-mid":"","mid-mid":"","right-mid":""}});tasks.forEach(task=>{const status="success"===task.Status?chalk.green("✓"):chalk.red("✗"),target=task.Target||"all",type="purge_url"===task.Type?"URL":"purge_prefix"===task.Type?"目录":"全部",displayTarget=target.length>47?target.slice(0,44)+"...":target;table.push([status,chalk.yellow(displayTarget),chalk.gray(task.CreateTime.slice(0,19).replace("T"," ")),type])}),console.log(chalk.cyan("\n📋 清除缓存记录:\n")),console.log(table.toString()),console.log(` 总计: ${chalk.yellow(result.Response.TotalCount||tasks.length)} 条记录`)}else console.log(chalk.gray("\n 暂无清除记录\n"))}}catch(error){const errMsg=error instanceof Error?error.message:String(error);console.log(chalk.red("\n❌ 请求异常:")),console.log(` ${errMsg}`)}console.log(""),await pauseToContinue()}(config,zoneIds)}(config);const answers=await inquirer.prompt([{type:"list",name:"type",message:"选择清除类型:",choices:[{name:"清除全部缓存",value:"all"},{name:"清除指定目录缓存",value:"dir"},{name:"清除指定 URL 缓存",value:"url"},new inquirer.Separator,{name:"← 返回",value:"back"}]}]);if("back"===answers.type)return;let targets=[],purgeType="purge_all",zoneId="*";if(config.domainIdList&&config.domainIdList.length>0){const zoneChoices=config.domainIdList.map(zone=>({name:zone.name||zone.id,value:zone.id})),zoneAnswers=await inquirer.prompt([{type:"list",name:"zone",message:"选择站点:",choices:["* (全部站点)",...zoneChoices]}]);"* (全部站点)"!==zoneAnswers.zone&&(zoneId=zoneAnswers.zone)}if("all"===answers.type){if(!(await inquirer.prompt([{type:"confirm",name:"confirm",message:`确认清除全部缓存? (Zone: ${zoneId})`,default:!1}])).confirm)return console.log(chalk.gray("\n❌️ 已取消")),void await pauseToContinue();purgeType="purge_all"}else if("dir"===answers.type){const dirAnswers=await inquirer.prompt([{type:"input",name:"dir",message:"请输入目录路径 (留空取消):"}]);if(!dirAnswers.dir||!dirAnswers.dir.trim())return console.log(chalk.gray("\n❌️ 已取消")),void await pauseToContinue();targets=[dirAnswers.dir],purgeType="purge_prefix"}else if("url"===answers.type){const urlAnswers=await inquirer.prompt([{type:"input",name:"urls",message:"请输入 URL (多个用空格分隔,留空取消):"}]);if(!urlAnswers.urls||!urlAnswers.urls.trim())return console.log(chalk.gray("\n❌️ 已取消")),void await pauseToContinue();targets=urlAnswers.urls.split(/\s+/).filter(u=>u.trim()),purgeType="purge_url"}await async function(config,type,targets,zoneId){const client=new EdgeOneClient(config.secretId,config.secretKey,config.endpoint||"teo.tencentcloudapi.com","ap-guangzhou",config.mode),isDebug="debug"===config.mode;isDebug&&(console.log(chalk.cyan("\n🔄 清除缓存任务\n")),console.log(chalk.gray("API 参数:")),console.log(` ZoneId: ${chalk.green(zoneId)}`),console.log(` Type: ${chalk.green(type)}`),targets.length>0&&console.log(` Targets: ${chalk.green(JSON.stringify(targets))}`),console.log(""));try{const result=await client.createPurgeTask({zoneId,type,targets});if("Error"in result.Response){const error=result.Response.Error;console.log(chalk.red("\n❌ 请求失败:")),console.log(` 错误码: ${chalk.yellow(error.Code)}`),console.log(` 错误信息: ${chalk.yellow(error.Message)}`)}else console.log(chalk.green("\n✅ 请求成功!")),console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`),result.Response.JobId&&console.log(` JobId: ${chalk.yellow(result.Response.JobId)}`)}catch(error){const errMsg=error instanceof Error?error.message:String(error);console.log(chalk.red("\n❌ 请求异常:")),console.log(` ${errMsg}`)}console.log(""),await pauseToContinue()}(config,purgeType,targets,zoneId)}
|
package/dist/repl/ui.js
CHANGED
|
@@ -1,29 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 交互式菜单 UI 工具函数
|
|
3
|
-
*/
|
|
4
|
-
import chalk from "chalk";
|
|
5
|
-
import inquirer from "inquirer";
|
|
6
|
-
/**
|
|
7
|
-
* 暂停等待用户确认后返回
|
|
8
|
-
*/
|
|
9
|
-
export async function pauseToContinue() {
|
|
10
|
-
await inquirer.prompt([{ type: "input", name: "continue", message: "按 Enter 键返回..." }]);
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* 显示欢迎横幅
|
|
14
|
-
*/
|
|
15
|
-
export function showBanner() {
|
|
16
|
-
console.log("");
|
|
17
|
-
console.log(chalk.cyan("╔════════════════════════════════════╗"));
|
|
18
|
-
console.log(chalk.cyan("║") + " " + chalk.white.bold("EdgeOne CLI") + " " + chalk.cyan("║"));
|
|
19
|
-
console.log(chalk.cyan("║") + " " + chalk.gray("本地化 EdgeOne 服务管理工具") + " " + chalk.cyan("║"));
|
|
20
|
-
console.log(chalk.cyan("╚════════════════════════════════════╝"));
|
|
21
|
-
console.log("");
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* 清屏并显示横幅
|
|
25
|
-
*/
|
|
26
|
-
export function clearScreenWithBanner() {
|
|
27
|
-
console.clear();
|
|
28
|
-
showBanner();
|
|
29
|
-
}
|
|
1
|
+
import chalk from"chalk";import inquirer from"inquirer";export async function pauseToContinue(){await inquirer.prompt([{type:"input",name:"continue",message:"按 Enter 键返回..."}])}export function showBanner(){console.log(""),console.log(chalk.cyan("╔════════════════════════════════════╗")),console.log(chalk.cyan("║")+" "+chalk.white.bold("EdgeOne CLI")+" "+chalk.cyan("║")),console.log(chalk.cyan("║")+" "+chalk.gray("本地化 EdgeOne 服务管理工具")+" "+chalk.cyan("║")),console.log(chalk.cyan("╚════════════════════════════════════╝")),console.log("")}export function clearScreenWithBanner(){console.clear(),showBanner()}
|
package/dist/repl/zone-menu.js
CHANGED
|
@@ -1,219 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 站点状态菜单
|
|
3
|
-
*/
|
|
4
|
-
import chalk from "chalk";
|
|
5
|
-
import inquirer from "inquirer";
|
|
6
|
-
import { EdgeOneClient } from "../api/client.js";
|
|
7
|
-
import { pauseToContinue } from "./ui.js";
|
|
8
|
-
/**
|
|
9
|
-
* 站点状态菜单
|
|
10
|
-
*/
|
|
11
|
-
export async function zoneStatusMenu(config) {
|
|
12
|
-
// 检查是否配置了站点列表
|
|
13
|
-
if (!config.domainIdList || config.domainIdList.length === 0) {
|
|
14
|
-
console.log(chalk.yellow("\n⚠️ 未配置站点列表,请先在配置中添加站点\n"));
|
|
15
|
-
await pauseToContinue();
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const answers = await inquirer.prompt([
|
|
19
|
-
{
|
|
20
|
-
type: "list",
|
|
21
|
-
name: "action",
|
|
22
|
-
message: "站点状态管理:",
|
|
23
|
-
choices: [
|
|
24
|
-
{ name: "🔍 查看站点状态", value: "view" },
|
|
25
|
-
{ name: "🔘 修改站点状态", value: "modify" },
|
|
26
|
-
new inquirer.Separator(),
|
|
27
|
-
{ name: "← 返回", value: "back" },
|
|
28
|
-
],
|
|
29
|
-
},
|
|
30
|
-
]);
|
|
31
|
-
if (answers.action === "back")
|
|
32
|
-
return;
|
|
33
|
-
if (answers.action === "view") {
|
|
34
|
-
if (config.domainIdList) {
|
|
35
|
-
await viewZoneStatus({ ...config, domainIdList: config.domainIdList });
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
else if (answers.action === "modify") {
|
|
39
|
-
if (config.domainIdList) {
|
|
40
|
-
await modifyZoneStatus({ ...config, domainIdList: config.domainIdList });
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* 选择站点
|
|
46
|
-
*/
|
|
47
|
-
async function selectZone(config, message) {
|
|
48
|
-
const zoneChoices = config.domainIdList.map((zone) => ({
|
|
49
|
-
name: zone.name || zone.id,
|
|
50
|
-
value: zone.id,
|
|
51
|
-
}));
|
|
52
|
-
const zoneAnswers = await inquirer.prompt([
|
|
53
|
-
{
|
|
54
|
-
type: "list",
|
|
55
|
-
name: "zone",
|
|
56
|
-
message,
|
|
57
|
-
choices: [...zoneChoices, new inquirer.Separator(), { name: "← 返回", value: "back" }],
|
|
58
|
-
},
|
|
59
|
-
]);
|
|
60
|
-
if (zoneAnswers.zone === "back")
|
|
61
|
-
return null;
|
|
62
|
-
return zoneAnswers.zone;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* 查看站点状态
|
|
66
|
-
*/
|
|
67
|
-
async function viewZoneStatus(config) {
|
|
68
|
-
const selectedZoneId = await selectZone(config, "选择要查看的站点:");
|
|
69
|
-
if (!selectedZoneId)
|
|
70
|
-
return;
|
|
71
|
-
const selectedZone = config.domainIdList.find(z => z.id === selectedZoneId);
|
|
72
|
-
const zoneDisplay = selectedZone?.name || selectedZoneId;
|
|
73
|
-
const client = new EdgeOneClient(config.secretId, config.secretKey, config.endpoint || "teo.tencentcloudapi.com", "ap-guangzhou", config.mode);
|
|
74
|
-
const isDebug = config.mode === "debug";
|
|
75
|
-
if (isDebug) {
|
|
76
|
-
console.log(chalk.cyan("\n🔍 查看站点状态\n"));
|
|
77
|
-
console.log(chalk.gray("API 参数:"));
|
|
78
|
-
console.log(` Action: ${chalk.green("DescribeZones")}`);
|
|
79
|
-
console.log(` ZoneIds: ${chalk.green([selectedZoneId])}`);
|
|
80
|
-
console.log("");
|
|
81
|
-
}
|
|
82
|
-
try {
|
|
83
|
-
const result = await client.describeZoneStatus({ zoneId: selectedZoneId });
|
|
84
|
-
if ("Error" in result.Response) {
|
|
85
|
-
const error = result.Response.Error;
|
|
86
|
-
console.log(chalk.red("\n❌ 请求失败:"));
|
|
87
|
-
console.log(` 错误码: ${chalk.yellow(error.Code)}`);
|
|
88
|
-
console.log(` 错误信息: ${chalk.yellow(error.Message)}`);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
console.log(chalk.green("\n✅ 查询成功!"));
|
|
92
|
-
console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);
|
|
93
|
-
// 显示站点状态信息
|
|
94
|
-
const zones = result.Response.Zones || [];
|
|
95
|
-
if (zones.length > 0) {
|
|
96
|
-
const zone = zones[0];
|
|
97
|
-
const paused = zone.Paused;
|
|
98
|
-
const statusText = paused ? "关闭" : "开启";
|
|
99
|
-
const statusColor = paused ? chalk.red : chalk.green;
|
|
100
|
-
// 获取接入方式
|
|
101
|
-
let accessType = "未知";
|
|
102
|
-
if (zone.NSDetail && !zone.CNAMEDetail && !zone.DNSPodDetail) {
|
|
103
|
-
accessType = "NS";
|
|
104
|
-
}
|
|
105
|
-
else if (zone.CNAMEDetail && !zone.NSDetail && !zone.DNSPodDetail) {
|
|
106
|
-
accessType = "CNAME";
|
|
107
|
-
}
|
|
108
|
-
else if (zone.DNSPodDetail && !zone.NSDetail && !zone.CNAMEDetail) {
|
|
109
|
-
accessType = "DNSPod";
|
|
110
|
-
}
|
|
111
|
-
// 获取 DNS 服务器
|
|
112
|
-
const nameServers = zone.NameServers || [];
|
|
113
|
-
const dnsServers = nameServers.length > 0 ? nameServers.join(", ") : "无";
|
|
114
|
-
// 获取加速区域
|
|
115
|
-
const areaMap = {
|
|
116
|
-
global: "全球加速",
|
|
117
|
-
mainland: "中国大陆",
|
|
118
|
-
overseas: "境外",
|
|
119
|
-
};
|
|
120
|
-
const area = areaMap[zone.Area] || zone.Area || "未知";
|
|
121
|
-
console.log(chalk.cyan("\n📋 站点状态:\n"));
|
|
122
|
-
console.log(chalk.gray("─".repeat(40)));
|
|
123
|
-
console.log(` 站点名称: ${chalk.yellow(zoneDisplay)}`);
|
|
124
|
-
console.log(` 站点ID: ${chalk.yellow(selectedZoneId)}`);
|
|
125
|
-
console.log(` 状态: ${statusColor(statusText)} (${paused})`);
|
|
126
|
-
console.log(chalk.gray("─".repeat(40)));
|
|
127
|
-
console.log(` 接入方式: ${chalk.yellow(accessType)}`);
|
|
128
|
-
console.log(` DNS服务器: ${chalk.yellow(dnsServers)}`);
|
|
129
|
-
console.log(` 加速区域: ${chalk.yellow(area)}`);
|
|
130
|
-
console.log(chalk.gray("─".repeat(40)));
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
console.log(chalk.gray("\n 未找到站点信息\n"));
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
139
|
-
console.log(chalk.red("\n❌ 请求异常:"));
|
|
140
|
-
console.log(` ${errMsg}`);
|
|
141
|
-
}
|
|
142
|
-
console.log("");
|
|
143
|
-
await pauseToContinue();
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* 修改站点状态
|
|
147
|
-
*/
|
|
148
|
-
async function modifyZoneStatus(config) {
|
|
149
|
-
const selectedZoneId = await selectZone(config, "选择要修改的站点:");
|
|
150
|
-
if (!selectedZoneId)
|
|
151
|
-
return;
|
|
152
|
-
const selectedZone = config.domainIdList.find(z => z.id === selectedZoneId);
|
|
153
|
-
const zoneDisplay = selectedZone?.name || selectedZoneId;
|
|
154
|
-
// 选择状态
|
|
155
|
-
const statusAnswers = await inquirer.prompt([
|
|
156
|
-
{
|
|
157
|
-
type: "list",
|
|
158
|
-
name: "paused",
|
|
159
|
-
message: `选择站点状态 (${zoneDisplay}):`,
|
|
160
|
-
choices: [
|
|
161
|
-
{ name: "开启 (Paused: false)", value: false },
|
|
162
|
-
{ name: "关闭 (Paused: true)", value: true },
|
|
163
|
-
new inquirer.Separator(),
|
|
164
|
-
{ name: "← 返回", value: "back" },
|
|
165
|
-
],
|
|
166
|
-
},
|
|
167
|
-
]);
|
|
168
|
-
if (statusAnswers.paused === "back")
|
|
169
|
-
return;
|
|
170
|
-
const paused = statusAnswers.paused;
|
|
171
|
-
const statusText = paused ? "关闭" : "开启";
|
|
172
|
-
// 确认
|
|
173
|
-
const confirmAnswers = await inquirer.prompt([
|
|
174
|
-
{ type: "confirm", name: "confirm", message: `确认将站点 ${zoneDisplay} 设置为 ${statusText}?`, default: true },
|
|
175
|
-
]);
|
|
176
|
-
if (!confirmAnswers.confirm) {
|
|
177
|
-
console.log(chalk.gray("\n❌️ 已取消"));
|
|
178
|
-
await pauseToContinue();
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
// 执行状态切换
|
|
182
|
-
await executeZoneStatusChange(config, selectedZoneId, paused, statusText);
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* 执行站点状态切换
|
|
186
|
-
*/
|
|
187
|
-
async function executeZoneStatusChange(config, zoneId, paused, statusText) {
|
|
188
|
-
const client = new EdgeOneClient(config.secretId, config.secretKey, config.endpoint || "teo.tencentcloudapi.com", "ap-guangzhou", config.mode);
|
|
189
|
-
const isDebug = config.mode === "debug";
|
|
190
|
-
if (isDebug) {
|
|
191
|
-
console.log(chalk.cyan("\n🔘 修改站点状态\n"));
|
|
192
|
-
console.log(chalk.gray("API 参数:"));
|
|
193
|
-
console.log(` Action: ${chalk.green("ModifyZoneStatus")}`);
|
|
194
|
-
console.log(` ZoneId: ${chalk.green(zoneId)}`);
|
|
195
|
-
console.log(` Paused: ${chalk.green(paused)}`);
|
|
196
|
-
console.log("");
|
|
197
|
-
}
|
|
198
|
-
try {
|
|
199
|
-
const result = await client.modifyZoneStatus({ zoneId, paused });
|
|
200
|
-
if ("Error" in result.Response) {
|
|
201
|
-
const error = result.Response.Error;
|
|
202
|
-
console.log(chalk.red("\n❌ 请求失败:"));
|
|
203
|
-
console.log(` 错误码: ${chalk.yellow(error.Code)}`);
|
|
204
|
-
console.log(` 错误信息: ${chalk.yellow(error.Message)}`);
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
console.log(chalk.green("\n✅ 站点状态已更新!"));
|
|
208
|
-
console.log(` 状态: ${chalk.yellow(statusText)}`);
|
|
209
|
-
console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
catch (error) {
|
|
213
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
214
|
-
console.log(chalk.red("\n❌ 请求异常:"));
|
|
215
|
-
console.log(` ${errMsg}`);
|
|
216
|
-
}
|
|
217
|
-
console.log("");
|
|
218
|
-
await pauseToContinue();
|
|
219
|
-
}
|
|
1
|
+
import chalk from"chalk";import inquirer from"inquirer";import{EdgeOneClient}from"../api/client.js";import{pauseToContinue}from"./ui.js";export async function zoneStatusMenu(config){if(!config.domainIdList||0===config.domainIdList.length)return console.log(chalk.yellow("\n⚠️ 未配置站点列表,请先在配置中添加站点\n")),void await pauseToContinue();const answers=await inquirer.prompt([{type:"list",name:"action",message:"站点状态管理:",choices:[{name:"🔍 查看站点状态",value:"view"},{name:"🔘 修改站点状态",value:"modify"},new inquirer.Separator,{name:"← 返回",value:"back"}]}]);"back"!==answers.action&&("view"===answers.action?config.domainIdList&&await async function(config){const selectedZoneId=await selectZone(config,"选择要查看的站点:");if(!selectedZoneId)return;const selectedZone=config.domainIdList.find(z=>z.id===selectedZoneId),zoneDisplay=selectedZone?.name||selectedZoneId,client=new EdgeOneClient(config.secretId,config.secretKey,config.endpoint||"teo.tencentcloudapi.com","ap-guangzhou",config.mode),isDebug="debug"===config.mode;isDebug&&(console.log(chalk.cyan("\n🔍 查看站点状态\n")),console.log(chalk.gray("API 参数:")),console.log(` Action: ${chalk.green("DescribeZones")}`),console.log(` ZoneIds: ${chalk.green([selectedZoneId])}`),console.log(""));try{const result=await client.describeZoneStatus({zoneId:selectedZoneId});if("Error"in result.Response){const error=result.Response.Error;console.log(chalk.red("\n❌ 请求失败:")),console.log(` 错误码: ${chalk.yellow(error.Code)}`),console.log(` 错误信息: ${chalk.yellow(error.Message)}`)}else{console.log(chalk.green("\n✅ 查询成功!")),console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`);const zones=result.Response.Zones||[];if(zones.length>0){const zone=zones[0],paused=zone.Paused,statusText=paused?"关闭":"开启",statusColor=paused?chalk.red:chalk.green;let accessType="未知";!zone.NSDetail||zone.CNAMEDetail||zone.DNSPodDetail?!zone.CNAMEDetail||zone.NSDetail||zone.DNSPodDetail?!zone.DNSPodDetail||zone.NSDetail||zone.CNAMEDetail||(accessType="DNSPod"):accessType="CNAME":accessType="NS";const nameServers=zone.NameServers||[],dnsServers=nameServers.length>0?nameServers.join(", "):"无",area={global:"全球加速",mainland:"中国大陆",overseas:"境外"}[zone.Area]||zone.Area||"未知";console.log(chalk.cyan("\n📋 站点状态:\n")),console.log(chalk.gray("─".repeat(40))),console.log(` 站点名称: ${chalk.yellow(zoneDisplay)}`),console.log(` 站点ID: ${chalk.yellow(selectedZoneId)}`),console.log(` 状态: ${statusColor(statusText)} (${paused})`),console.log(chalk.gray("─".repeat(40))),console.log(` 接入方式: ${chalk.yellow(accessType)}`),console.log(` DNS服务器: ${chalk.yellow(dnsServers)}`),console.log(` 加速区域: ${chalk.yellow(area)}`),console.log(chalk.gray("─".repeat(40)))}else console.log(chalk.gray("\n 未找到站点信息\n"))}}catch(error){const errMsg=error instanceof Error?error.message:String(error);console.log(chalk.red("\n❌ 请求异常:")),console.log(` ${errMsg}`)}console.log(""),await pauseToContinue()}({...config,domainIdList:config.domainIdList}):"modify"===answers.action&&config.domainIdList&&await async function(config){const selectedZoneId=await selectZone(config,"选择要修改的站点:");if(!selectedZoneId)return;const selectedZone=config.domainIdList.find(z=>z.id===selectedZoneId),zoneDisplay=selectedZone?.name||selectedZoneId,statusAnswers=await inquirer.prompt([{type:"list",name:"paused",message:`选择站点状态 (${zoneDisplay}):`,choices:[{name:"开启 (Paused: false)",value:!1},{name:"关闭 (Paused: true)",value:!0},new inquirer.Separator,{name:"← 返回",value:"back"}]}]);if("back"===statusAnswers.paused)return;const paused=statusAnswers.paused,statusText=paused?"关闭":"开启";if(!(await inquirer.prompt([{type:"confirm",name:"confirm",message:`确认将站点 ${zoneDisplay} 设置为 ${statusText}?`,default:!0}])).confirm)return console.log(chalk.gray("\n❌️ 已取消")),void await pauseToContinue();await async function(config,zoneId,paused,statusText){const client=new EdgeOneClient(config.secretId,config.secretKey,config.endpoint||"teo.tencentcloudapi.com","ap-guangzhou",config.mode),isDebug="debug"===config.mode;isDebug&&(console.log(chalk.cyan("\n🔘 修改站点状态\n")),console.log(chalk.gray("API 参数:")),console.log(` Action: ${chalk.green("ModifyZoneStatus")}`),console.log(` ZoneId: ${chalk.green(zoneId)}`),console.log(` Paused: ${chalk.green(paused)}`),console.log(""));try{const result=await client.modifyZoneStatus({zoneId,paused});if("Error"in result.Response){const error=result.Response.Error;console.log(chalk.red("\n❌ 请求失败:")),console.log(` 错误码: ${chalk.yellow(error.Code)}`),console.log(` 错误信息: ${chalk.yellow(error.Message)}`)}else console.log(chalk.green("\n✅ 站点状态已更新!")),console.log(` 状态: ${chalk.yellow(statusText)}`),console.log(` RequestId: ${chalk.yellow(result.Response.RequestId)}`)}catch(error){const errMsg=error instanceof Error?error.message:String(error);console.log(chalk.red("\n❌ 请求异常:")),console.log(` ${errMsg}`)}console.log(""),await pauseToContinue()}(config,selectedZoneId,paused,statusText)}({...config,domainIdList:config.domainIdList}))}async function selectZone(config,message){const zoneChoices=config.domainIdList.map(zone=>({name:zone.name||zone.id,value:zone.id})),zoneAnswers=await inquirer.prompt([{type:"list",name:"zone",message,choices:[...zoneChoices,new inquirer.Separator,{name:"← 返回",value:"back"}]}]);return"back"===zoneAnswers.zone?null:zoneAnswers.zone}
|
package/dist/types/index.js
CHANGED
package/dist/utils/crypto.js
CHANGED
|
@@ -1,85 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 加密工具模块
|
|
3
|
-
* 使用 AES-256-GCM 加密敏感信息
|
|
4
|
-
*/
|
|
5
|
-
import crypto from 'crypto';
|
|
6
|
-
import os from 'os';
|
|
7
|
-
const ALGORITHM = 'aes-256-gcm';
|
|
8
|
-
const KEY_LENGTH = 32;
|
|
9
|
-
const IV_LENGTH = 16;
|
|
10
|
-
const SALT_LENGTH = 64;
|
|
11
|
-
const TAG_LENGTH = 16;
|
|
12
|
-
/**
|
|
13
|
-
* 获取机器标识(用于生成加密密钥)
|
|
14
|
-
*/
|
|
15
|
-
function getMachineId() {
|
|
16
|
-
const platform = os.platform();
|
|
17
|
-
const arch = os.arch();
|
|
18
|
-
const hostname = os.hostname();
|
|
19
|
-
const cpus = os.cpus();
|
|
20
|
-
const cpuModel = cpus.length > 0 ? cpus[0].model : '';
|
|
21
|
-
// 组合多个机器特征生成唯一标识
|
|
22
|
-
const machineInfo = `${platform}-${arch}-${hostname}-${cpuModel}`;
|
|
23
|
-
return crypto.createHash('sha256').update(machineInfo).digest('hex');
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* 生成加密密钥
|
|
27
|
-
*/
|
|
28
|
-
function deriveKey(password, salt) {
|
|
29
|
-
return crypto.pbkdf2Sync(password, salt, 100000, KEY_LENGTH, 'sha256');
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* 加密文本
|
|
33
|
-
*/
|
|
34
|
-
export function encrypt(text) {
|
|
35
|
-
const machineId = getMachineId();
|
|
36
|
-
const salt = crypto.randomBytes(SALT_LENGTH);
|
|
37
|
-
const key = deriveKey(machineId, salt);
|
|
38
|
-
const iv = crypto.randomBytes(IV_LENGTH);
|
|
39
|
-
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
|
|
40
|
-
let encrypted = cipher.update(text, 'utf8', 'hex');
|
|
41
|
-
encrypted += cipher.final('hex');
|
|
42
|
-
const tag = cipher.getAuthTag();
|
|
43
|
-
// 格式: salt(128) + iv(32) + tag(32) + encrypted
|
|
44
|
-
const combined = Buffer.concat([
|
|
45
|
-
salt,
|
|
46
|
-
iv,
|
|
47
|
-
tag,
|
|
48
|
-
Buffer.from(encrypted, 'hex')
|
|
49
|
-
]);
|
|
50
|
-
return combined.toString('base64');
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* 解密文本
|
|
54
|
-
*/
|
|
55
|
-
export function decrypt(encryptedText) {
|
|
56
|
-
try {
|
|
57
|
-
const combined = Buffer.from(encryptedText, 'base64');
|
|
58
|
-
const salt = combined.subarray(0, SALT_LENGTH);
|
|
59
|
-
const iv = combined.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);
|
|
60
|
-
const tag = combined.subarray(SALT_LENGTH + IV_LENGTH, SALT_LENGTH + IV_LENGTH + TAG_LENGTH);
|
|
61
|
-
const encrypted = combined.subarray(SALT_LENGTH + IV_LENGTH + TAG_LENGTH);
|
|
62
|
-
const machineId = getMachineId();
|
|
63
|
-
const key = deriveKey(machineId, salt);
|
|
64
|
-
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
|
|
65
|
-
decipher.setAuthTag(tag);
|
|
66
|
-
let decrypted = decipher.update(encrypted);
|
|
67
|
-
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
68
|
-
return decrypted.toString('utf8');
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
throw new Error('解密失败,配置文件可能已损坏或在其他机器上生成');
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* 检查文本是否为加密格式
|
|
76
|
-
*/
|
|
77
|
-
export function isEncrypted(text) {
|
|
78
|
-
try {
|
|
79
|
-
const combined = Buffer.from(text, 'base64');
|
|
80
|
-
return combined.length >= SALT_LENGTH + IV_LENGTH + TAG_LENGTH;
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
1
|
+
import crypto from"crypto";import os from"os";function getMachineId(){const platform=os.platform(),arch=os.arch(),hostname=os.hostname(),cpus=os.cpus(),machineInfo=`${platform}-${arch}-${hostname}-${cpus.length>0?cpus[0].model:""}`;return crypto.createHash("sha256").update(machineInfo).digest("hex")}function deriveKey(password,salt){return crypto.pbkdf2Sync(password,salt,1e5,32,"sha256")}export function encrypt(text){const machineId=getMachineId(),salt=crypto.randomBytes(64),key=deriveKey(machineId,salt),iv=crypto.randomBytes(16),cipher=crypto.createCipheriv("aes-256-gcm",key,iv);let encrypted=cipher.update(text,"utf8","hex");encrypted+=cipher.final("hex");const tag=cipher.getAuthTag();return Buffer.concat([salt,iv,tag,Buffer.from(encrypted,"hex")]).toString("base64")}export function decrypt(encryptedText){try{const combined=Buffer.from(encryptedText,"base64"),salt=combined.subarray(0,64),iv=combined.subarray(64,80),tag=combined.subarray(80,96),encrypted=combined.subarray(96),key=deriveKey(getMachineId(),salt),decipher=crypto.createDecipheriv("aes-256-gcm",key,iv);decipher.setAuthTag(tag);let decrypted=decipher.update(encrypted);return decrypted=Buffer.concat([decrypted,decipher.final()]),decrypted.toString("utf8")}catch(error){throw new Error("解密失败,配置文件可能已损坏或在其他机器上生成")}}export function isEncrypted(text){try{return Buffer.from(text,"base64").length>=96}catch{return!1}}
|
package/dist/utils/date.js
CHANGED
|
@@ -1,52 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* 日期时间工具函数
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* 将 UTC 时间转换为北京时间 (UTC+8)
|
|
6
|
-
* @param utcTime UTC 时间字符串,格式如 "2026-03-11T10:46:33Z"
|
|
7
|
-
* @returns 格式化后的北京时间字符串,格式如 "2026-03-11 18:46:33"
|
|
8
|
-
*/
|
|
9
|
-
export function utcToBeijingTime(utcTime) {
|
|
10
|
-
if (!utcTime)
|
|
11
|
-
return "";
|
|
12
|
-
const date = new Date(utcTime);
|
|
13
|
-
// 转换为北京时间(UTC+8)
|
|
14
|
-
const beijingTime = new Date(date.getTime() + 8 * 60 * 60 * 1000);
|
|
15
|
-
const year = beijingTime.getUTCFullYear();
|
|
16
|
-
const month = String(beijingTime.getUTCMonth() + 1).padStart(2, "0");
|
|
17
|
-
const day = String(beijingTime.getUTCDate()).padStart(2, "0");
|
|
18
|
-
const hours = String(beijingTime.getUTCHours()).padStart(2, "0");
|
|
19
|
-
const minutes = String(beijingTime.getUTCMinutes()).padStart(2, "0");
|
|
20
|
-
const seconds = String(beijingTime.getUTCSeconds()).padStart(2, "0");
|
|
21
|
-
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* 格式化为 ISO 8601 格式,时区为 +08:00
|
|
25
|
-
* @param date 日期对象
|
|
26
|
-
* @returns ISO 8601 格式字符串,如 "2026-03-11T18:46:33+08:00"
|
|
27
|
-
*/
|
|
28
|
-
export function toISOStringWithTimezone(date) {
|
|
29
|
-
const year = date.getFullYear();
|
|
30
|
-
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
31
|
-
const day = String(date.getDate()).padStart(2, "0");
|
|
32
|
-
const hours = String(date.getHours()).padStart(2, "0");
|
|
33
|
-
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
34
|
-
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
35
|
-
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}+08:00`;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* 获取当前时间一周前的日期
|
|
39
|
-
* @returns 一周前的 Date 对象
|
|
40
|
-
*/
|
|
41
|
-
export function getOneWeekAgo() {
|
|
42
|
-
const now = new Date();
|
|
43
|
-
return new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* 获取当前时间一月前的日期
|
|
47
|
-
* @returns 一月前的 Date 对象
|
|
48
|
-
*/
|
|
49
|
-
export function getOneMonthAgo() {
|
|
50
|
-
const now = new Date();
|
|
51
|
-
return new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
52
|
-
}
|
|
1
|
+
export function utcToBeijingTime(utcTime){if(!utcTime)return"";const date=new Date(utcTime),beijingTime=new Date(date.getTime()+288e5);return`${beijingTime.getUTCFullYear()}-${String(beijingTime.getUTCMonth()+1).padStart(2,"0")}-${String(beijingTime.getUTCDate()).padStart(2,"0")} ${String(beijingTime.getUTCHours()).padStart(2,"0")}:${String(beijingTime.getUTCMinutes()).padStart(2,"0")}:${String(beijingTime.getUTCSeconds()).padStart(2,"0")}`}export function toISOStringWithTimezone(date){return`${date.getFullYear()}-${String(date.getMonth()+1).padStart(2,"0")}-${String(date.getDate()).padStart(2,"0")}T${String(date.getHours()).padStart(2,"0")}:${String(date.getMinutes()).padStart(2,"0")}:${String(date.getSeconds()).padStart(2,"0")}+08:00`}export function getOneWeekAgo(){const now=new Date;return new Date(now.getTime()-6048e5)}export function getOneMonthAgo(){const now=new Date;return new Date(now.getTime()-2592e6)}
|