mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-08 22:51:25 +08:00
新增operationcard组件
This commit is contained in:
parent
516e6c2d16
commit
25be7f4926
@ -1,27 +1,11 @@
|
||||
<template>
|
||||
<div class="flex-container">
|
||||
<div
|
||||
<OperationCard
|
||||
v-if="hasFunctionSelector"
|
||||
class="flex-item"
|
||||
:style="{ flex: localCommand.functionSelector.width || 3 }"
|
||||
>
|
||||
<div class="operation-cards">
|
||||
<div
|
||||
v-for="option in localCommand.functionSelector?.options"
|
||||
:key="option.value"
|
||||
:class="['operation-card', { active: funcName === option.value }]"
|
||||
:data-value="option.value"
|
||||
@click="funcName = option.value"
|
||||
>
|
||||
<q-icon
|
||||
:name="option.icon || localCommand.icon || 'functions'"
|
||||
size="16px"
|
||||
:color="funcName === option.value ? 'primary' : 'grey'"
|
||||
/>
|
||||
<div class="text-caption">{{ option.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
:model-value="funcName"
|
||||
@update:model-value="funcName = $event"
|
||||
:options="localCommand.functionSelector?.options"
|
||||
/>
|
||||
<div class="flex-container">
|
||||
<div
|
||||
v-for="(item, index) in localConfig"
|
||||
@ -102,6 +86,7 @@ import VariableInput from "components/composer/common/VariableInput.vue";
|
||||
import NumberInput from "components/composer/common/NumberInput.vue";
|
||||
import ArrayEditor from "components/composer/common/ArrayEditor.vue";
|
||||
import DictEditor from "components/composer/common/DictEditor.vue";
|
||||
import OperationCard from "components/composer/common/OperationCard.vue";
|
||||
import { stringifyArgv, parseFunction } from "js/composer/formatString";
|
||||
|
||||
export default defineComponent({
|
||||
@ -111,6 +96,7 @@ export default defineComponent({
|
||||
NumberInput,
|
||||
ArrayEditor,
|
||||
DictEditor,
|
||||
OperationCard,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
@ -219,23 +205,6 @@ export default defineComponent({
|
||||
this.updateModelValue(this.funcName, this.defaultArgvs);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
funcName: {
|
||||
immediate: true,
|
||||
handler(newVal) {
|
||||
// 当操作卡片改变时,确保它在视图中可见
|
||||
this.$nextTick(() => {
|
||||
document
|
||||
.querySelector(`.operation-card[data-value="${newVal}"]`)
|
||||
?.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "nearest",
|
||||
inline: "nearest",
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
148
src/components/composer/common/OperationCard.vue
Normal file
148
src/components/composer/common/OperationCard.vue
Normal file
@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<div class="operation-cards-container" :style="containerStyle">
|
||||
<div ref="scrollArea" class="scroll-container" @wheel.prevent="handleWheel">
|
||||
<div class="cards-wrapper">
|
||||
<div
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
:class="['operation-card', { active: modelValue === option.value }]"
|
||||
:data-value="option.value"
|
||||
@click="$emit('update:modelValue', option.value)"
|
||||
>
|
||||
<q-icon
|
||||
:name="option.icon || 'functions'"
|
||||
size="16px"
|
||||
:color="modelValue === option.value ? 'primary' : 'grey'"
|
||||
/>
|
||||
<div class="text-caption">{{ option.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: () => this.options[0]?.value,
|
||||
},
|
||||
minWidth: {
|
||||
type: String,
|
||||
default: "80px",
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
containerStyle() {
|
||||
return {
|
||||
"--min-width": this.minWidth,
|
||||
"--total-items": this.options.length,
|
||||
"--total-gap": `${(this.options.length - 1) * 8}px`,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 将滚轮垂直滚动转换为水平滚动
|
||||
handleWheel(e) {
|
||||
const scrollArea = this.$refs.scrollArea;
|
||||
// 同时处理水平和垂直滚动
|
||||
const delta =
|
||||
Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY * 0.8;
|
||||
|
||||
if (scrollArea) {
|
||||
scrollArea.scrollLeft += delta;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue(newVal) {
|
||||
document
|
||||
.querySelector(`.operation-card[data-value="${newVal}"]`)
|
||||
?.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "nearest",
|
||||
inline: "nearest",
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.operation-cards-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.scroll-container {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.scroll-container::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cards-wrapper {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-auto-columns: minmax(
|
||||
var(--min-width),
|
||||
calc((100% - (var(--total-gap, 0px))) / var(--total-items, 1))
|
||||
);
|
||||
gap: 8px;
|
||||
width: fit-content;
|
||||
min-width: 100%;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.operation-card {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 16px;
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
padding: 4px 8px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.operation-card:hover {
|
||||
background: var(--q-primary-opacity-5);
|
||||
transform: translateY(-1px);
|
||||
border: 1px solid var(--q-primary-opacity-5);
|
||||
}
|
||||
|
||||
.operation-card.active {
|
||||
border-color: var(--q-primary);
|
||||
background: var(--q-primary-opacity-5);
|
||||
}
|
||||
|
||||
/* 暗色模式适配 */
|
||||
.body--dark .operation-card {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.body--dark .operation-card:hover {
|
||||
background: var(--q-primary-opacity-5);
|
||||
}
|
||||
|
||||
.body--dark .operation-card.active {
|
||||
border-color: var(--q-primary-opacity-50);
|
||||
background: var(--q-primary-opacity-5);
|
||||
}
|
||||
|
||||
.operation-card .text-caption {
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
line-height: 1.2;
|
||||
}
|
||||
</style>
|
@ -1,23 +1,11 @@
|
||||
<template>
|
||||
<div class="buffer-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>
|
||||
|
||||
<OperationCard
|
||||
:model-value="argvs.operation"
|
||||
@update:model-value="(val) => updateArgvs('operation', val)"
|
||||
:options="operations"
|
||||
/>
|
||||
<!-- 操作配置 -->
|
||||
<div class="operation-options q-mt-sm">
|
||||
<div class="options-container">
|
||||
@ -366,6 +354,7 @@ import { stringifyArgv, parseFunction } from "js/composer/formatString";
|
||||
import VariableInput from "components/composer/common/VariableInput.vue";
|
||||
import NumberInput from "components/composer/common/NumberInput.vue";
|
||||
import ArrayEditor from "components/composer/common/ArrayEditor.vue";
|
||||
import OperationCard from "components/composer/common/OperationCard.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "BufferEditor",
|
||||
@ -373,6 +362,7 @@ export default defineComponent({
|
||||
VariableInput,
|
||||
NumberInput,
|
||||
ArrayEditor,
|
||||
OperationCard,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
@ -384,16 +374,16 @@ export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
operations: [
|
||||
{ name: "from", label: "创建Buffer", icon: "add_box" },
|
||||
{ name: "toString", label: "转换字符串", icon: "text_fields" },
|
||||
{ name: "write", label: "写入数据", icon: "edit" },
|
||||
{ name: "fill", label: "填充数据", icon: "format_color_fill" },
|
||||
{ name: "copy", label: "复制数据", icon: "content_copy" },
|
||||
{ name: "compare", label: "比较数据", icon: "compare" },
|
||||
{ name: "concat", label: "连接Buffer", icon: "merge" },
|
||||
{ name: "indexOf", label: "查找数据", icon: "search" },
|
||||
{ name: "slice", label: "切片数据", icon: "content_cut" },
|
||||
{ name: "swap", label: "交换字节序", icon: "swap_horiz" },
|
||||
{ value: "from", label: "创建Buffer", icon: "add_box" },
|
||||
{ value: "toString", label: "转换字符串", icon: "text_fields" },
|
||||
{ value: "write", label: "写入数据", icon: "edit" },
|
||||
{ value: "fill", label: "填充数据", icon: "format_color_fill" },
|
||||
{ value: "copy", label: "复制数据", icon: "content_copy" },
|
||||
{ value: "compare", label: "比较数据", icon: "compare" },
|
||||
{ value: "concat", label: "连接Buffer", icon: "merge" },
|
||||
{ value: "indexOf", label: "查找数据", icon: "search" },
|
||||
{ value: "slice", label: "切片数据", icon: "content_cut" },
|
||||
{ value: "swap", label: "交换字节序", icon: "swap_horiz" },
|
||||
],
|
||||
encodings: [
|
||||
{ label: "UTF-8", value: "utf8" },
|
||||
@ -669,7 +659,7 @@ export default defineComponent({
|
||||
},
|
||||
getSummary(argvs) {
|
||||
const op = this.operations.find(
|
||||
(op) => op.name === argvs.operation
|
||||
(op) => op.value === argvs.operation
|
||||
)?.label;
|
||||
return op;
|
||||
},
|
||||
@ -687,22 +677,6 @@ export default defineComponent({
|
||||
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>
|
||||
|
||||
|
@ -1,31 +1,18 @@
|
||||
<template>
|
||||
<div class="zlib-editor">
|
||||
<!-- 操作类型选择 -->
|
||||
<div class="row items-center q-gutter-x-xs">
|
||||
<!-- 数据输入 -->
|
||||
<VariableInput
|
||||
:model-value="argvs.data"
|
||||
@update:model-value="(val) => updateArgvs('data', val)"
|
||||
label="要处理的数据"
|
||||
class="col"
|
||||
icon="data_object"
|
||||
/>
|
||||
<div class="col-auto row items-center q-gutter-x-xs">
|
||||
<div
|
||||
v-for="op in operations"
|
||||
:key="op.name"
|
||||
:class="['operation-card', { active: argvs.operation === op.name }]"
|
||||
@click="updateArgvs('operation', 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>
|
||||
<OperationCard
|
||||
:model-value="argvs.operation"
|
||||
@update:model-value="(val) => updateArgvs('operation', val)"
|
||||
:options="operations"
|
||||
/>
|
||||
<!-- 数据输入 -->
|
||||
<VariableInput
|
||||
:model-value="argvs.data"
|
||||
@update:model-value="(val) => updateArgvs('data', val)"
|
||||
label="要处理的数据"
|
||||
icon="data_object"
|
||||
/>
|
||||
<!-- 操作配置 -->
|
||||
<div class="operation-options">
|
||||
<div class="options-container">
|
||||
@ -144,12 +131,13 @@ import { defineComponent } from "vue";
|
||||
import { stringifyArgv, parseFunction } from "js/composer/formatString";
|
||||
import VariableInput from "components/composer/common/VariableInput.vue";
|
||||
import NumberInput from "components/composer/common/NumberInput.vue";
|
||||
|
||||
import OperationCard from "components/composer/common/OperationCard.vue";
|
||||
export default defineComponent({
|
||||
name: "ZlibEditor",
|
||||
components: {
|
||||
VariableInput,
|
||||
NumberInput,
|
||||
OperationCard,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
@ -161,8 +149,8 @@ export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
operations: [
|
||||
{ name: "compressData", label: "压缩", icon: "compress" },
|
||||
{ name: "decompressData", label: "解压", icon: "expand" },
|
||||
{ value: "compressData", label: "压缩", icon: "compress" },
|
||||
{ value: "decompressData", label: "解压", icon: "expand" },
|
||||
],
|
||||
methods: [
|
||||
{ label: "Gzip", value: "gzip" },
|
||||
@ -299,7 +287,7 @@ export default defineComponent({
|
||||
},
|
||||
getSummary(argvs) {
|
||||
const op = this.operations.find(
|
||||
(op) => op.name === argvs.operation
|
||||
(op) => op.value === argvs.operation
|
||||
)?.label;
|
||||
const method = this.methods.find((m) => m.value === argvs.method)?.label;
|
||||
return `${op} (${method})`;
|
||||
|
@ -1,22 +1,11 @@
|
||||
<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>
|
||||
<OperationCard
|
||||
:model-value="argvs.operation"
|
||||
@update:model-value="(val) => updateArgvs('operation', val)"
|
||||
:options="operations"
|
||||
/>
|
||||
|
||||
<!-- 操作配置 -->
|
||||
<div class="operation-options">
|
||||
@ -75,11 +64,12 @@
|
||||
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: {
|
||||
@ -91,19 +81,19 @@ export default defineComponent({
|
||||
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" },
|
||||
{ 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" },
|
||||
{
|
||||
name: "resolveTxtRecords",
|
||||
value: "resolveTxtRecords",
|
||||
label: "解析TXT记录",
|
||||
icon: "text_fields",
|
||||
},
|
||||
{ name: "resolveNsRecords", label: "解析NS记录", icon: "dns" },
|
||||
{ name: "resolveCnameRecords", label: "解析CNAME记录", icon: "link" },
|
||||
{ name: "reverseResolve", label: "反向解析", icon: "swap_horiz" },
|
||||
{ value: "resolveNsRecords", label: "解析NS记录", icon: "dns" },
|
||||
{ value: "resolveCnameRecords", label: "解析CNAME记录", icon: "link" },
|
||||
{ value: "reverseResolve", label: "反向解析", icon: "swap_horiz" },
|
||||
],
|
||||
families: [
|
||||
{ label: "自动", value: 0 },
|
||||
@ -214,7 +204,7 @@ export default defineComponent({
|
||||
},
|
||||
getSummary(argvs) {
|
||||
const op = this.operations.find(
|
||||
(op) => op.name === argvs.operation
|
||||
(op) => op.value === argvs.operation
|
||||
)?.label;
|
||||
return op === "反向解析"
|
||||
? "反向解析 " + argvs.ip.value
|
||||
@ -234,22 +224,6 @@ export default defineComponent({
|
||||
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>
|
||||
|
||||
@ -264,8 +238,4 @@ export default defineComponent({
|
||||
gap: 8px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.command-composer .operation-card {
|
||||
min-width: 95px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,22 +1,11 @@
|
||||
<template>
|
||||
<div class="url-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>
|
||||
<OperationCard
|
||||
:model-value="argvs.operation"
|
||||
@update:model-value="(val) => updateArgvs('operation', val)"
|
||||
:options="operations"
|
||||
/>
|
||||
|
||||
<!-- 操作配置 -->
|
||||
<div class="operation-options q-mt-sm">
|
||||
@ -172,12 +161,14 @@ import { defineComponent } from "vue";
|
||||
import { stringifyArgv, parseFunction } from "js/composer/formatString";
|
||||
import VariableInput from "components/composer/common/VariableInput.vue";
|
||||
import DictEditor from "components/composer/common/DictEditor.vue";
|
||||
import OperationCard from "components/composer/common/OperationCard.vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UrlEditor",
|
||||
components: {
|
||||
VariableInput,
|
||||
DictEditor,
|
||||
OperationCard,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
@ -189,17 +180,17 @@ export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
operations: [
|
||||
{ name: "parse", label: "解析URL", icon: "link_off" },
|
||||
{ name: "format", label: "格式化URL", icon: "link" },
|
||||
{ name: "parseQuery", label: "解析查询字符串", icon: "search" },
|
||||
{ name: "formatQuery", label: "格式化查询字符串", icon: "edit" },
|
||||
{ name: "parsePath", label: "解析路径", icon: "folder_open" },
|
||||
{ name: "parseHost", label: "解析主机名", icon: "dns" },
|
||||
{ name: "getQueryParam", label: "获取参数", icon: "find_in_page" },
|
||||
{ name: "addQueryParam", label: "添加参数", icon: "add_circle" },
|
||||
{ name: "removeQueryParam", label: "移除参数", icon: "remove_circle" },
|
||||
{ name: "isAbsolute", label: "检查绝对URL", icon: "check_circle" },
|
||||
{ name: "parseComponents", label: "解析组成部分", icon: "category" },
|
||||
{ value: "parse", label: "解析URL", icon: "link_off" },
|
||||
{ value: "format", label: "格式化URL", icon: "link" },
|
||||
{ value: "parseQuery", label: "解析查询字符串", icon: "search" },
|
||||
{ value: "formatQuery", label: "格式化查询字符串", icon: "edit" },
|
||||
{ value: "parsePath", label: "解析路径", icon: "folder_open" },
|
||||
{ value: "parseHost", label: "解析主机名", icon: "dns" },
|
||||
{ value: "getQueryParam", label: "获取参数", icon: "find_in_page" },
|
||||
{ value: "addQueryParam", label: "添加参数", icon: "add_circle" },
|
||||
{ value: "removeQueryParam", label: "移除参数", icon: "remove_circle" },
|
||||
{ value: "isAbsolute", label: "检查绝对URL", icon: "check_circle" },
|
||||
{ value: "parseComponents", label: "解析组成部分", icon: "category" },
|
||||
],
|
||||
defaultArgvs: {
|
||||
operation: "parse",
|
||||
@ -428,7 +419,7 @@ export default defineComponent({
|
||||
},
|
||||
getSummary(argvs) {
|
||||
const op = this.operations.find(
|
||||
(op) => op.name === argvs.operation
|
||||
(op) => op.value === argvs.operation
|
||||
)?.label;
|
||||
return op + " " + argvs.url.value;
|
||||
},
|
||||
@ -446,22 +437,6 @@ export default defineComponent({
|
||||
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>
|
||||
|
||||
@ -477,9 +452,4 @@ export default defineComponent({
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* 覆盖command-composer的样式 */
|
||||
.command-composer .operation-card {
|
||||
min-width: 100px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,21 +1,11 @@
|
||||
<template>
|
||||
<div class="os-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)"
|
||||
>
|
||||
<q-icon
|
||||
:name="op.icon"
|
||||
size="16px"
|
||||
:color="argvs.operation === op.name ? 'primary' : 'grey'"
|
||||
/>
|
||||
<div class="text-caption">{{ op.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<OperationCard
|
||||
:model-value="argvs.operation"
|
||||
@update:model-value="(val) => updateArgvs('operation', val)"
|
||||
:options="operations"
|
||||
/>
|
||||
|
||||
<!-- 操作配置 -->
|
||||
<div class="operation-options q-mt-sm" v-if="hasOptions">
|
||||
@ -91,9 +81,12 @@
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { stringifyArgv, parseFunction } from "js/composer/formatString";
|
||||
|
||||
import OperationCard from "components/composer/common/OperationCard.vue";
|
||||
export default defineComponent({
|
||||
name: "OsEditor",
|
||||
components: {
|
||||
OperationCard,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
@ -104,11 +97,11 @@ export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
operations: [
|
||||
{ name: "arch", label: "系统架构", icon: "memory" },
|
||||
{ name: "cpus", label: "CPU信息", icon: "developer_board" },
|
||||
{ name: "memory", label: "内存信息", icon: "storage" },
|
||||
{ name: "network", label: "网络信息", icon: "wifi" },
|
||||
{ name: "platform", label: "平台信息", icon: "computer" },
|
||||
{ value: "arch", label: "系统架构", icon: "memory" },
|
||||
{ value: "cpus", label: "CPU信息", icon: "developer_board" },
|
||||
{ value: "memory", label: "内存信息", icon: "storage" },
|
||||
{ value: "network", label: "网络信息", icon: "wifi" },
|
||||
{ value: "platform", label: "平台信息", icon: "computer" },
|
||||
],
|
||||
formatOptions: [
|
||||
{ label: "完整信息", value: "full" },
|
||||
@ -192,7 +185,7 @@ export default defineComponent({
|
||||
},
|
||||
pointerStyle() {
|
||||
const activeIndex = this.operations.findIndex(
|
||||
(op) => op.name === this.argvs.operation
|
||||
(op) => op.value === this.argvs.operation
|
||||
);
|
||||
if (activeIndex === -1) return {};
|
||||
|
||||
@ -281,7 +274,7 @@ export default defineComponent({
|
||||
};
|
||||
},
|
||||
getSummary(argvs) {
|
||||
return this.operations.find((op) => op.name === argvs.operation).label;
|
||||
return this.operations.find((op) => op.value === argvs.operation).label;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
this.$emit("update:modelValue", {
|
||||
|
@ -1,22 +1,11 @@
|
||||
<template>
|
||||
<div class="path-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>
|
||||
<OperationCard
|
||||
:model-value="argvs.operation"
|
||||
@update:model-value="(val) => updateArgvs('operation', val)"
|
||||
:options="operations"
|
||||
/>
|
||||
|
||||
<!-- 操作配置 -->
|
||||
<div class="operation-options q-mt-sm">
|
||||
@ -163,11 +152,12 @@
|
||||
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: "PathEditor",
|
||||
components: {
|
||||
VariableInput,
|
||||
OperationCard,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
@ -179,16 +169,16 @@ export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
operations: [
|
||||
{ name: "normalize", label: "规范化路径", icon: "straighten" },
|
||||
{ name: "join", label: "连接路径", icon: "add_link" },
|
||||
{ name: "parse", label: "解析路径", icon: "account_tree" },
|
||||
{ name: "dirname", label: "获取目录名", icon: "folder" },
|
||||
{ name: "basename", label: "获取文件名", icon: "description" },
|
||||
{ name: "extname", label: "获取扩展名", icon: "extension" },
|
||||
{ name: "isAbsolute", label: "判断绝对路径", icon: "check_circle" },
|
||||
{ name: "relative", label: "计算相对路径", icon: "compare_arrows" },
|
||||
{ name: "resolve", label: "解析绝对路径", icon: "assistant_direction" },
|
||||
{ name: "format", label: "格式化路径", icon: "format_shapes" },
|
||||
{ value: "normalize", label: "规范化路径", icon: "straighten" },
|
||||
{ value: "join", label: "连接路径", icon: "add_link" },
|
||||
{ value: "parse", label: "解析路径", icon: "account_tree" },
|
||||
{ value: "dirname", label: "获取目录名", icon: "folder" },
|
||||
{ value: "basename", label: "获取文件名", icon: "description" },
|
||||
{ value: "extname", label: "获取扩展名", icon: "extension" },
|
||||
{ value: "isAbsolute", label: "判断绝对路径", icon: "check_circle" },
|
||||
{ value: "relative", label: "计算相对路径", icon: "compare_arrows" },
|
||||
{ value: "resolve", label: "解析绝对路径", icon: "assistant_direction" },
|
||||
{ value: "format", label: "格式化路径", icon: "format_shapes" },
|
||||
],
|
||||
defaultArgvs: {
|
||||
operation: "normalize",
|
||||
@ -265,7 +255,7 @@ export default defineComponent({
|
||||
},
|
||||
pointerStyle() {
|
||||
const activeIndex = this.operations.findIndex(
|
||||
(op) => op.name === this.argvs.operation
|
||||
(op) => op.value === this.argvs.operation
|
||||
);
|
||||
if (activeIndex === -1) return {};
|
||||
|
||||
@ -414,7 +404,7 @@ export default defineComponent({
|
||||
this.updateArgvs("paths", newPaths);
|
||||
},
|
||||
getSummary(argvs) {
|
||||
return this.operations.find((op) => op.name === argvs.operation)?.label;
|
||||
return this.operations.find((op) => op.value === argvs.operation)?.label;
|
||||
},
|
||||
updateModelValue(argvs) {
|
||||
this.$emit("update:modelValue", {
|
||||
@ -430,22 +420,6 @@ export default defineComponent({
|
||||
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>
|
||||
|
||||
|
@ -1,53 +1,3 @@
|
||||
/* 操作卡片样式 */
|
||||
.command-composer .operation-cards {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
white-space: nowrap;
|
||||
padding: 1px;
|
||||
gap: 8px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.command-composer .operation-cards::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.command-composer .operation-card {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border: 1px solid transparent;
|
||||
border-radius: 6px;
|
||||
min-width: 72px;
|
||||
max-height: 36px;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.command-composer .operation-card:hover {
|
||||
background: var(--q-primary-opacity-5);
|
||||
transform: translateY(-1px);
|
||||
border: 1px solid var(--q-primary-opacity-10);
|
||||
}
|
||||
|
||||
.command-composer .operation-card.active {
|
||||
border-color: var(--q-primary);
|
||||
background: var(--q-primary-opacity-5);
|
||||
}
|
||||
|
||||
/* 暗色模式适配 */
|
||||
.body--dark .command-composer .operation-card {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.body--dark .command-composer .operation-card.active {
|
||||
border-color: var(--q-primary-opacity-50);
|
||||
}
|
||||
|
||||
/* 滚动美化 */
|
||||
.command-composer .q-scrollarea__thumb {
|
||||
width: 2px;
|
||||
|
@ -130,7 +130,7 @@ const customComponentGuide = {
|
||||
implementation: {
|
||||
simpleCase: `
|
||||
// 返回操作类型的标签
|
||||
return this.operations.find(op => op.name === argvs.operation).label;
|
||||
return this.operations.find(op => op.value === argvs.operation).label;
|
||||
`,
|
||||
complexCase: `
|
||||
// 返回关键参数的值
|
||||
|
Loading…
x
Reference in New Issue
Block a user