mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-09 23:16:18 +08:00
272 lines
7.1 KiB
Vue
272 lines
7.1 KiB
Vue
<template>
|
|
<div class="dns-editor">
|
|
<!-- 操作类型选择 -->
|
|
<div class="operation-cards">
|
|
<div
|
|
v-for="op in operations"
|
|
:key="op.name"
|
|
:class="['operation-card', { active: argvs.operation === op.name }]"
|
|
@click="updateArgvs('operation', op.name)"
|
|
:data-value="op.name"
|
|
>
|
|
<q-icon
|
|
:name="op.icon"
|
|
size="16px"
|
|
:color="argvs.operation === op.name ? 'primary' : 'grey'"
|
|
/>
|
|
<div class="text-caption">{{ op.label }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 操作配置 -->
|
|
<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/ui/VariableInput.vue";
|
|
|
|
export default defineComponent({
|
|
name: "DnsEditor",
|
|
components: {
|
|
VariableInput,
|
|
},
|
|
props: {
|
|
modelValue: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
},
|
|
emits: ["update:modelValue"],
|
|
data() {
|
|
return {
|
|
operations: [
|
|
{ name: "lookupHost", label: "DNS查询", icon: "search" },
|
|
{ name: "resolveAll", label: "解析所有记录", icon: "all_inclusive" },
|
|
{ name: "resolveIpv4", label: "解析IPv4", icon: "filter_4" },
|
|
{ name: "resolveIpv6", label: "解析IPv6", icon: "filter_6" },
|
|
{ name: "resolveMxRecords", label: "解析MX记录", icon: "mail" },
|
|
{
|
|
name: "resolveTxtRecords",
|
|
label: "解析TXT记录",
|
|
icon: "text_fields",
|
|
},
|
|
{ name: "resolveNsRecords", label: "解析NS记录", icon: "dns" },
|
|
{ name: "resolveCnameRecords", label: "解析CNAME记录", icon: "link" },
|
|
{ name: "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.args;
|
|
|
|
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.name === 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);
|
|
}
|
|
},
|
|
watch: {
|
|
"argvs.operation": {
|
|
immediate: true,
|
|
handler(newVal) {
|
|
this.$nextTick(() => {
|
|
document
|
|
.querySelector(`.operation-card[data-value="${newVal}"]`)
|
|
?.scrollIntoView({
|
|
behavior: "smooth",
|
|
block: "nearest",
|
|
inline: "nearest",
|
|
});
|
|
});
|
|
},
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.dns-editor {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.options-container {
|
|
min-height: 32px;
|
|
gap: 8px;
|
|
padding-top: 8px;
|
|
}
|
|
|
|
.command-composer .operation-card {
|
|
min-width: 95px;
|
|
}
|
|
</style>
|