修改DNS组件

This commit is contained in:
fofolee 2025-01-07 18:19:25 +08:00
parent a13580d53f
commit 807da38e2e
7 changed files with 221 additions and 251 deletions

View File

@ -13,9 +13,9 @@ const resolveCname = promisify(dns.resolveCname);
const reverse = promisify(dns.reverse);
// 解析主机名
async function lookupHost(hostname, options = {}) {
async function lookupHost(hostname, family = 0, all = false) {
try {
return await lookup(hostname, options);
return await lookup(hostname, { family, all });
} catch (error) {
throw new Error(`DNS查询失败: ${error.message}`);
}

View File

@ -36,9 +36,15 @@ export default defineComponent({
},
//
commonConfig() {
return this.modelValue.config || [];
return (
// , excludeConfig[]
this.modelValue.config?.filter(
(_, index) =>
!this.getSelectFunction()?.excludeConfig?.includes(index)
) || []
);
},
//
// configconfig
functionConfig() {
return this.getSelectFunction()?.config || [];
},

View File

@ -1,241 +0,0 @@
<template>
<div class="dns-editor">
<!-- 操作类型选择 -->
<OperationCard
:model-value="argvs.operation"
@update:model-value="(val) => updateArgvs('operation', val)"
:options="operations"
/>
<!-- 操作配置 -->
<div class="operation-options">
<div class="options-container row">
<!-- 主机名输入 -->
<VariableInput
:model-value="argvs.hostname"
@update:model-value="(val) => updateArgvs('hostname', val)"
label="主机名"
icon="dns"
class="col"
/>
<!-- IP地址输入 -->
<VariableInput
:model-value="argvs.ip"
@update:model-value="(val) => updateArgvs('ip', val)"
label="IP地址"
icon="router"
v-if="argvs.operation === 'reverseResolve'"
/>
<!-- lookup 选项 -->
<div
class="row items-center col-5"
v-if="argvs.operation === 'lookupHost'"
>
<div class="col-6">
<q-select
:model-value="argvs.options.family"
@update:model-value="(val) => updateArgvs('options.family', val)"
:options="families"
label="IP版本"
dense
filled
emit-value
map-options
options-dense
/>
</div>
<div class="col-6 q-px-sm">
<q-toggle
:model-value="argvs.options.all"
@update:model-value="(val) => updateArgvs('options.all', val)"
label="返回所有地址"
dense
/>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { defineComponent } from "vue";
import { stringifyArgv, parseFunction } from "js/composer/formatString";
import VariableInput from "components/composer/common/VariableInput.vue";
import OperationCard from "components/composer/common/OperationCard.vue";
export default defineComponent({
name: "DnsEditor",
components: {
VariableInput,
OperationCard,
},
props: {
modelValue: {
type: Object,
required: true,
},
},
emits: ["update:modelValue"],
data() {
return {
operations: [
{ value: "lookupHost", label: "DNS查询", icon: "search" },
{ value: "resolveAll", label: "解析所有记录", icon: "all_inclusive" },
{ value: "resolveIpv4", label: "解析IPv4", icon: "filter_4" },
{ value: "resolveIpv6", label: "解析IPv6", icon: "filter_6" },
{ value: "resolveMxRecords", label: "解析MX记录", icon: "mail" },
{
value: "resolveTxtRecords",
label: "解析TXT记录",
icon: "text_fields",
},
{ value: "resolveNsRecords", label: "解析NS记录", icon: "dns" },
{ value: "resolveCnameRecords", label: "解析CNAME记录", icon: "link" },
{ value: "reverseResolve", label: "反向解析", icon: "swap_horiz" },
],
families: [
{ label: "自动", value: 0 },
{ label: "IPv4", value: 4 },
{ label: "IPv6", value: 6 },
],
defaultArgvs: {
operation: "lookupHost",
hostname: {
value: "",
isString: true,
__varInputVal__: true,
},
ip: {
value: "",
isString: true,
__varInputVal__: true,
},
options: {
family: 0,
all: false,
},
},
};
},
computed: {
argvs: {
get() {
return (
this.modelValue.argvs ||
this.parseCodeToArgvs(this.modelValue.code) || {
...this.defaultArgvs,
}
);
},
set(value) {
this.updateModelValue(value);
},
},
needsHostname() {
return this.argvs.operation !== "reverseResolve";
},
},
methods: {
generateCode(argvs = this.argvs) {
switch (argvs.operation) {
case "lookupHost":
return `${this.modelValue.value}.${argvs.operation}(${stringifyArgv(
argvs.hostname
)}, ${stringifyArgv(argvs.options)})`;
case "reverseResolve":
return `${this.modelValue.value}.${argvs.operation}(${stringifyArgv(
argvs.ip
)})`;
default:
return `${this.modelValue.value}.${argvs.operation}(${stringifyArgv(
argvs.hostname
)})`;
}
},
parseCodeToArgvs(code) {
if (!code) return null;
try {
// 使variable
const variableFormatPaths = [
"arg0", // /IP
"arg1.**", // options
];
// 使 parseFunction
const result = parseFunction(code, { variableFormatPaths });
if (!result) return this.defaultArgvs;
const operation = result.name.split(".").pop();
const [firstArg, secondArg] = result.argvs;
const newArgvs = {
...this.defaultArgvs,
operation,
};
if (operation === "reverseResolve") {
newArgvs.ip = firstArg;
} else {
newArgvs.hostname = firstArg;
if (operation === "lookupHost" && secondArg) {
newArgvs.options = {
family: secondArg.family ?? this.defaultArgvs.options.family,
all: secondArg.all ?? this.defaultArgvs.options.all,
};
}
}
return newArgvs;
} catch (e) {
console.error("解析DNS参数失败:", e);
return this.defaultArgvs;
}
},
updateArgvs(key, value) {
this.argvs = {
...this.argvs,
[key]: value,
};
},
getSummary(argvs) {
const op = this.operations.find(
(op) => op.value === argvs.operation
)?.label;
return op === "反向解析"
? "反向解析 " + argvs.ip.value
: op + " " + argvs.hostname.value;
},
updateModelValue(argvs) {
this.$emit("update:modelValue", {
...this.modelValue,
summary: this.getSummary(argvs),
argvs,
code: this.generateCode(argvs),
});
},
},
mounted() {
if (!this.modelValue.argvs && !this.modelValue.code) {
this.updateModelValue(this.defaultArgvs);
}
},
});
</script>
<style scoped>
.dns-editor {
display: flex;
flex-direction: column;
}
.options-container {
min-height: 32px;
gap: 8px;
padding-top: 8px;
}
</style>

View File

@ -73,9 +73,6 @@ export const ZlibEditor = defineAsyncComponent(() =>
export const UrlEditor = defineAsyncComponent(() =>
import("components/composer/network/UrlEditor.vue")
);
export const DnsEditor = defineAsyncComponent(() =>
import("components/composer/network/DnsEditor.vue")
);
export const BufferEditor = defineAsyncComponent(() =>
import("src/components/composer/data/BufferEditor.vue")
);

View File

@ -54,12 +54,94 @@ export const networkCommands = {
icon: "link",
},
{
value: "quickcomposer.network.dns",
value: "quickcomposer.network.dns.lookupHost",
label: "DNS操作",
desc: "DNS解析和查询",
component: "DnsEditor",
icon: "dns",
isAsync: true,
config: [
{
label: "要查询的域名",
icon: "dns",
type: "varInput",
width: "auto",
},
],
functionSelector: [
{
label: "DNS查询",
value: "quickcomposer.network.dns.lookupHost",
icon: "search",
config: [
{
label: "IP版本",
icon: "settings_ethernet",
type: "select",
options: [
{ label: "自动", value: 0 },
{ label: "IPv4", value: 4 },
{ label: "IPv6", value: 6 },
],
defaultValue: 0,
width: 2.5,
},
{
label: "返回所有地址",
type: "checkbox",
defaultValue: false,
width: 2.5,
},
],
},
{
value: "quickcomposer.network.dns.resolveAll",
label: "解析所有记录",
icon: "all_inclusive",
},
{
value: "quickcomposer.network.dns.resolveIpv4",
label: "解析IPv4",
icon: "filter_4",
},
{
value: "quickcomposer.network.dns.resolveIpv6",
label: "解析IPv6",
icon: "filter_6",
},
{
value: "quickcomposer.network.dns.resolveMxRecords",
label: "解析MX记录",
icon: "mail",
},
{
value: "quickcomposer.network.dns.resolveTxtRecords",
label: "解析TXT记录",
icon: "text_fields",
},
{
value: "quickcomposer.network.dns.resolveNsRecords",
label: "解析NS记录",
icon: "dns",
},
{
value: "quickcomposer.network.dns.resolveCnameRecords",
label: "解析CNAME记录",
icon: "link",
},
{
value: "quickcomposer.network.dns.reverseResolve",
label: "反向解析",
icon: "swap_horiz",
excludeConfig: [0],
config: [
{
label: "IP地址",
icon: "router",
type: "varInput",
},
],
},
],
},
],
};

View File

@ -0,0 +1,127 @@
/**
* Common Component Creation Guide
* 通用组件创建指南 - 使用 MultiParams 组件
*/
const commonComponentGuide = {
description: "创建使用 MultiParams 组件的命令的完整流程",
important: "创建过程中严禁删除、修改任何已有的函数或对象",
steps: {
"1. Backend Interface": {
location: "plugin/lib/quickcomposer/xxx/yyy.js",
description: "创建具体功能实现",
requirements: {
functionDefinition: "使用独立函数而非对象方法",
asyncHandling: "使用 async/await 处理异步操作",
errorHandling: "合理的错误捕获和提示",
paramValidation: "检查必要参数是否存在",
},
},
"2. Interface Export": {
location: "plugin/lib/quickcomposer/xxx/index.js",
description: "导出接口给quickcomposer使用",
examples: {
singleFunction: "module.exports = { operation }",
multipleFunctions: "module.exports = { ...encoder, ...hash }",
},
},
"3. Interface Registration": {
location: "plugin/lib/quickcomposer.js",
description: "将接口注册到quickcomposer对象",
format: "quickcomposer.xxx = require('./quickcomposer/xxx')",
},
"4. Command Configuration": {
location: "src/js/composer/commands/xxxCommands.js",
description: "配置命令参数,使用 MultiParams 组件",
requiredFields: {
value: "必选,生成代码时使用的函数名,如 quickcomposer.xxx.yyy",
label: "必选,命令的显示名称",
config: {
description: "必选,通用参数配置数组,每个元素是一个对象",
properties: {
label: "必选,参数标签",
type: "必选,参数类型(varInput/numInput/select/checkbox等)",
icon: "必选,参数图标",
width: "可选,参数占用宽度(1-12或auto)",
defaultValue: "可选,参数默认值",
options: "可选select等类型的选项",
},
example: `
config: [
{
label: "域名",
type: "varInput",
icon: "dns",
width: "auto"
}
]
`,
},
functionSelector: {
description:
"可选,函数选择器配置,用于一个命令包含多个相关函数的情况",
properties: {
value: "必选,函数名",
label: "必选,显示名称",
icon: "可选,图标",
config: "可选函数特有的参数配置格式同通用config",
excludeConfig: "可选,要排除的通用参数索引数组",
},
example: `
functionSelector: [
{
label: "DNS查询",
value: "quickcomposer.network.dns.lookupHost",
icon: "search",
config: [
{
label: "IP版本",
type: "select",
options: [
{ label: "自动", value: 0 },
{ label: "IPv4", value: 4 }
],
defaultValue: 0
}
]
},
{
value: "quickcomposer.network.dns.reverseResolve",
label: "反向解析",
icon: "swap_horiz",
excludeConfig: [0], // 排除第一个通用参数
config: [
{
label: "IP地址",
type: "varInput",
icon: "router"
}
]
}
]
`,
},
},
optionalFields: {
desc: "命令描述",
isAsync: "是否异步命令",
icon: "命令图标",
},
},
},
notes: {
bestPractices: {
description: "最佳实践",
tips: [
"合理使用 width 属性布局参数",
"相关参数尽量放在同一行",
"使用 excludeConfig 禁用掉不需要的参数配置",
"合理设置 defaultValue",
"使用语义化的图标",
"保持参数标签简洁明了",
],
},
},
examples: {
multiFunctionCommand: "多函数命令如DNS操作",
},
};

View File

@ -272,7 +272,6 @@ const customComponentGuide = {
desc: "命令描述",
isAsync: "是否异步命令",
isControlFlow: "是否控制流命令",
allowEmptyArgv: "是否允许空参数",
},
},
},