mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-08 14:34:13 +08:00
编排添加解析路径功能
This commit is contained in:
parent
00ddba20ec
commit
923fc9e4de
@ -1,5 +1,5 @@
|
|||||||
const quickcomposer = {
|
const quickcomposer = {
|
||||||
textProcessor: require("./quickcomposer/textProcessor"),
|
text: require("./quickcomposer/text"),
|
||||||
simulate: require("./quickcomposer/simulate"),
|
simulate: require("./quickcomposer/simulate"),
|
||||||
file: require("./quickcomposer/file"),
|
file: require("./quickcomposer/file"),
|
||||||
system: require("./quickcomposer/system"),
|
system: require("./quickcomposer/system"),
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
const { execSync } = require("child_process");
|
const { exec: execAsync } = require("child_process");
|
||||||
const iconv = require("iconv-lite");
|
const iconv = require("iconv-lite");
|
||||||
const os = require("os");
|
const os = require("os");
|
||||||
|
const util = require("util");
|
||||||
|
|
||||||
|
// 将 exec 转换为 Promise 版本
|
||||||
|
const execPromise = util.promisify(execAsync);
|
||||||
|
|
||||||
function getSystemEncoding() {
|
function getSystemEncoding() {
|
||||||
// Windows 默认使用 GBK/GB2312,其他系统默认 UTF-8
|
// Windows 默认使用 GBK/GB2312,其他系统默认 UTF-8
|
||||||
return os.platform() === "win32" ? "gbk" : "utf8";
|
return os.platform() === "win32" ? "gbk" : "utf8";
|
||||||
}
|
}
|
||||||
|
|
||||||
function exec(command, options = {}) {
|
async function exec(command, options = {}) {
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
autoEncoding = true,
|
autoEncoding = true,
|
||||||
@ -17,7 +21,7 @@ function exec(command, options = {}) {
|
|||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
// 执行命令,总是使用 buffer 获取原始输出
|
// 执行命令,总是使用 buffer 获取原始输出
|
||||||
const output = execSync(command, {
|
const { stdout: output } = await execPromise(command, {
|
||||||
...execOptions,
|
...execOptions,
|
||||||
encoding: "buffer",
|
encoding: "buffer",
|
||||||
windowsHide,
|
windowsHide,
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
const exec = require("./exec");
|
const exec = require("./exec");
|
||||||
const os = require("./os");
|
const os = require("./os");
|
||||||
|
const path = require("./path");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
exec,
|
exec,
|
||||||
os,
|
os,
|
||||||
|
path,
|
||||||
};
|
};
|
||||||
|
150
plugin/lib/quickcomposer/system/path.js
Normal file
150
plugin/lib/quickcomposer/system/path.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 规范化路径
|
||||||
|
* @param {string} p 要规范化的路径
|
||||||
|
* @returns {string} 规范化后的路径
|
||||||
|
*/
|
||||||
|
async function normalize(p) {
|
||||||
|
try {
|
||||||
|
return path.normalize(p);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`路径规范化失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接路径片段
|
||||||
|
* @param {...string} paths 路径片段
|
||||||
|
* @returns {string} 连接后的路径
|
||||||
|
*/
|
||||||
|
async function join(...paths) {
|
||||||
|
try {
|
||||||
|
return path.join(...paths);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`路径连接失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析路径
|
||||||
|
* @param {string} p 要解析的路径
|
||||||
|
* @returns {Object} 解析结果,包含 root, dir, base, ext, name
|
||||||
|
*/
|
||||||
|
async function parse(p) {
|
||||||
|
try {
|
||||||
|
return path.parse(p);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`路径解析失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取路径的目录名
|
||||||
|
* @param {string} p 路径
|
||||||
|
* @returns {string} 目录名
|
||||||
|
*/
|
||||||
|
async function dirname(p) {
|
||||||
|
try {
|
||||||
|
return path.dirname(p);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`获取目录名失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取路径的文件名
|
||||||
|
* @param {string} p 路径
|
||||||
|
* @param {string} [ext] 可选的扩展名,如果提供则从结果中移除
|
||||||
|
* @returns {string} 文件名
|
||||||
|
*/
|
||||||
|
async function basename(p, ext) {
|
||||||
|
try {
|
||||||
|
return path.basename(p, ext);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`获取文件名失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取路径的扩展名
|
||||||
|
* @param {string} p 路径
|
||||||
|
* @returns {string} 扩展名
|
||||||
|
*/
|
||||||
|
async function extname(p) {
|
||||||
|
try {
|
||||||
|
return path.extname(p);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`获取扩展名失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断路径是否为绝对路径
|
||||||
|
* @param {string} p 路径
|
||||||
|
* @returns {boolean} 是否为绝对路径
|
||||||
|
*/
|
||||||
|
async function isAbsolute(p) {
|
||||||
|
try {
|
||||||
|
return path.isAbsolute(p);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`判断绝对路径失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算相对路径
|
||||||
|
* @param {string} from 起始路径
|
||||||
|
* @param {string} to 目标路径
|
||||||
|
* @returns {string} 相对路径
|
||||||
|
*/
|
||||||
|
async function relative(from, to) {
|
||||||
|
try {
|
||||||
|
return path.relative(from, to);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`计算相对路径失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将路径解析为绝对路径
|
||||||
|
* @param {...string} paths 路径片段
|
||||||
|
* @returns {string} 解析后的绝对路径
|
||||||
|
*/
|
||||||
|
async function resolve(...paths) {
|
||||||
|
try {
|
||||||
|
return path.resolve(...paths);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`解析绝对路径失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化路径对象为路径字符串
|
||||||
|
* @param {Object} pathObject 路径对象,包含 dir, root, base, name, ext
|
||||||
|
* @returns {string} 格式化后的路径
|
||||||
|
*/
|
||||||
|
async function format(pathObject) {
|
||||||
|
try {
|
||||||
|
return path.format(pathObject);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`格式化路径失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
normalize,
|
||||||
|
join,
|
||||||
|
parse,
|
||||||
|
dirname,
|
||||||
|
basename,
|
||||||
|
extname,
|
||||||
|
isAbsolute,
|
||||||
|
relative,
|
||||||
|
resolve,
|
||||||
|
format,
|
||||||
|
sep: path.sep,
|
||||||
|
delimiter: path.delimiter,
|
||||||
|
win32: path.win32,
|
||||||
|
posix: path.posix,
|
||||||
|
};
|
472
src/components/composer/system/PathEditor.vue
Normal file
472
src/components/composer/system/PathEditor.vue
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
<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)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="row items-center justify-center q-gutter-x-xs q-px-sm q-py-xs"
|
||||||
|
>
|
||||||
|
<q-icon
|
||||||
|
:name="op.icon"
|
||||||
|
size="16px"
|
||||||
|
:color="argvs.operation === op.name ? 'primary' : 'grey'"
|
||||||
|
/>
|
||||||
|
<div class="text-caption">{{ op.label }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作配置 -->
|
||||||
|
<div class="operation-options q-mt-sm">
|
||||||
|
<!-- 通用路径输入 -->
|
||||||
|
<div class="options-container">
|
||||||
|
<template
|
||||||
|
v-if="
|
||||||
|
[
|
||||||
|
'normalize',
|
||||||
|
'parse',
|
||||||
|
'dirname',
|
||||||
|
'basename',
|
||||||
|
'extname',
|
||||||
|
'isAbsolute',
|
||||||
|
].includes(argvs.operation)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.path"
|
||||||
|
@update:model-value="(val) => updateArgvs('path', val)"
|
||||||
|
label="路径"
|
||||||
|
icon="folder"
|
||||||
|
/>
|
||||||
|
<!-- basename 的扩展名参数 -->
|
||||||
|
<div v-if="argvs.operation === 'basename'" class="q-mt-sm">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.ext"
|
||||||
|
@update:model-value="(val) => updateArgvs('ext', val)"
|
||||||
|
label="要移除的扩展名(可选)"
|
||||||
|
icon="extension"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- join 和 resolve 的多路径输入 -->
|
||||||
|
<template v-if="['join', 'resolve'].includes(argvs.operation)">
|
||||||
|
<div
|
||||||
|
v-for="(path, index) in argvs.paths"
|
||||||
|
:key="index"
|
||||||
|
class="q-mb-sm"
|
||||||
|
>
|
||||||
|
<div class="row items-center q-gutter-sm">
|
||||||
|
<div class="col">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="path"
|
||||||
|
@update:model-value="(val) => updatePathAtIndex(index, val)"
|
||||||
|
:label="'路径片段 ' + (index + 1)"
|
||||||
|
icon="folder"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<q-btn
|
||||||
|
v-if="index === argvs.paths.length - 1"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
icon="add"
|
||||||
|
size="sm"
|
||||||
|
color="primary"
|
||||||
|
@click="addPath"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
v-if="argvs.paths.length > 1"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
icon="remove"
|
||||||
|
color="negative"
|
||||||
|
size="sm"
|
||||||
|
@click="removePath(index)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- relative 的起始和目标路径 -->
|
||||||
|
<template v-if="argvs.operation === 'relative'">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.from"
|
||||||
|
@update:model-value="(val) => updateArgvs('from', val)"
|
||||||
|
label="起始路径"
|
||||||
|
icon="folder"
|
||||||
|
/>
|
||||||
|
<div class="q-mt-sm">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.to"
|
||||||
|
@update:model-value="(val) => updateArgvs('to', val)"
|
||||||
|
label="目标路径"
|
||||||
|
icon="folder"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- format 的路径对象 -->
|
||||||
|
<template v-if="argvs.operation === 'format'">
|
||||||
|
<div class="row q-col-gutter-sm">
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.pathObject.root"
|
||||||
|
@update:model-value="(val) => updatePathObject('root', val)"
|
||||||
|
label="根路径"
|
||||||
|
icon="folder"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.pathObject.dir"
|
||||||
|
@update:model-value="(val) => updatePathObject('dir', val)"
|
||||||
|
label="目录"
|
||||||
|
icon="folder"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.pathObject.base"
|
||||||
|
@update:model-value="(val) => updatePathObject('base', val)"
|
||||||
|
label="基本名称"
|
||||||
|
icon="description"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.pathObject.name"
|
||||||
|
@update:model-value="(val) => updatePathObject('name', val)"
|
||||||
|
label="文件名"
|
||||||
|
icon="insert_drive_file"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.pathObject.ext"
|
||||||
|
@update:model-value="(val) => updatePathObject('ext', val)"
|
||||||
|
label="扩展名"
|
||||||
|
icon="extension"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import { stringifyObject, parseFunction } from "js/composer/formatString";
|
||||||
|
import VariableInput from "components/composer/ui/VariableInput.vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "PathEditor",
|
||||||
|
components: {
|
||||||
|
VariableInput,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ["update:modelValue"],
|
||||||
|
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" },
|
||||||
|
],
|
||||||
|
defaultArgvs: {
|
||||||
|
operation: "normalize",
|
||||||
|
path: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
paths: [
|
||||||
|
{
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
from: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
ext: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
pathObject: {
|
||||||
|
root: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
dir: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
base: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
ext: {
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
argvs: {
|
||||||
|
get() {
|
||||||
|
return (
|
||||||
|
this.modelValue.argvs ||
|
||||||
|
this.parseCodeToArgvs(this.modelValue.code) || {
|
||||||
|
...this.defaultArgvs,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.$emit("update:modelValue", {
|
||||||
|
...this.modelValue,
|
||||||
|
code: this.generateCode(value),
|
||||||
|
argvs: value,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pointerStyle() {
|
||||||
|
const activeIndex = this.operations.findIndex(
|
||||||
|
(op) => op.name === this.argvs.operation
|
||||||
|
);
|
||||||
|
if (activeIndex === -1) return {};
|
||||||
|
|
||||||
|
const cardWidth = 80;
|
||||||
|
const gap = 4;
|
||||||
|
const pointerWidth = 12;
|
||||||
|
const leftOffset =
|
||||||
|
(cardWidth + gap) * activeIndex + cardWidth / 2 - pointerWidth / 2;
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: `${leftOffset}px`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
generateCode(argvs = this.argvs) {
|
||||||
|
switch (argvs.operation) {
|
||||||
|
case "normalize":
|
||||||
|
case "parse":
|
||||||
|
case "dirname":
|
||||||
|
case "extname":
|
||||||
|
case "isAbsolute":
|
||||||
|
return `${this.modelValue.value}.${argvs.operation}(${stringifyObject(
|
||||||
|
argvs.path
|
||||||
|
)})`;
|
||||||
|
|
||||||
|
case "basename":
|
||||||
|
if (argvs.ext && argvs.ext.value) {
|
||||||
|
return `${this.modelValue.value}.${
|
||||||
|
argvs.operation
|
||||||
|
}(${stringifyObject(argvs.path)}, ${stringifyObject(argvs.ext)})`;
|
||||||
|
}
|
||||||
|
return `${this.modelValue.value}.${argvs.operation}(${stringifyObject(
|
||||||
|
argvs.path
|
||||||
|
)})`;
|
||||||
|
|
||||||
|
case "join":
|
||||||
|
case "resolve":
|
||||||
|
return `${this.modelValue.value}.${argvs.operation}(${argvs.paths
|
||||||
|
.map((p) => stringifyObject(p))
|
||||||
|
.join(", ")})`;
|
||||||
|
|
||||||
|
case "relative":
|
||||||
|
return `${this.modelValue.value}.${argvs.operation}(${stringifyObject(
|
||||||
|
argvs.from
|
||||||
|
)}, ${stringifyObject(argvs.to)})`;
|
||||||
|
|
||||||
|
case "format":
|
||||||
|
return `${this.modelValue.value}.${argvs.operation}(${stringifyObject(
|
||||||
|
argvs.pathObject
|
||||||
|
)})`;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return `${this.modelValue.value}.${argvs.operation}()`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
parseCodeToArgvs(code) {
|
||||||
|
if (!code) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 定义需要使用variable格式的路径
|
||||||
|
const variableFormatPaths = [
|
||||||
|
"arg*", // 所有参数
|
||||||
|
"arg*.**", // 所有参数的所有嵌套属性
|
||||||
|
];
|
||||||
|
|
||||||
|
// 使用 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (operation) {
|
||||||
|
case "normalize":
|
||||||
|
case "parse":
|
||||||
|
case "dirname":
|
||||||
|
case "extname":
|
||||||
|
case "isAbsolute":
|
||||||
|
newArgvs.path = firstArg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "basename":
|
||||||
|
newArgvs.path = firstArg;
|
||||||
|
if (secondArg) {
|
||||||
|
newArgvs.ext = secondArg;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "join":
|
||||||
|
case "resolve":
|
||||||
|
newArgvs.paths = result.args.map((arg) => arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "relative":
|
||||||
|
newArgvs.from = firstArg;
|
||||||
|
newArgvs.to = secondArg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "format":
|
||||||
|
newArgvs.pathObject = firstArg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newArgvs;
|
||||||
|
} catch (e) {
|
||||||
|
console.error("解析Path参数失败:", e);
|
||||||
|
return this.defaultArgvs;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateArgvs(key, value) {
|
||||||
|
this.argvs = {
|
||||||
|
...this.argvs,
|
||||||
|
[key]: value,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
updatePathAtIndex(index, value) {
|
||||||
|
const newPaths = [...this.argvs.paths];
|
||||||
|
newPaths[index] = value;
|
||||||
|
this.updateArgvs("paths", newPaths);
|
||||||
|
},
|
||||||
|
updatePathObject(key, value) {
|
||||||
|
this.updateArgvs("pathObject", {
|
||||||
|
...this.argvs.pathObject,
|
||||||
|
[key]: value,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addPath() {
|
||||||
|
this.updateArgvs("paths", [
|
||||||
|
...this.argvs.paths,
|
||||||
|
{
|
||||||
|
value: "",
|
||||||
|
isString: true,
|
||||||
|
__varInputVal__: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
removePath(index) {
|
||||||
|
const newPaths = [...this.argvs.paths];
|
||||||
|
newPaths.splice(index, 1);
|
||||||
|
this.updateArgvs("paths", newPaths);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (!this.modelValue.argvs && !this.modelValue.code) {
|
||||||
|
this.$emit("update:modelValue", {
|
||||||
|
...this.modelValue,
|
||||||
|
code: this.generateCode(this.defaultArgvs),
|
||||||
|
argvs: { ...this.defaultArgvs },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.path-editor {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operation-cards {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 4px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operation-card {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
min-width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operation-card:hover {
|
||||||
|
background: var(--q-primary-opacity-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.operation-card.active {
|
||||||
|
border-color: var(--q-primary);
|
||||||
|
background: var(--q-primary-opacity-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.options-container {
|
||||||
|
min-height: 32px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
@ -48,12 +48,12 @@
|
|||||||
v-if="variables.length"
|
v-if="variables.length"
|
||||||
>
|
>
|
||||||
<q-list class="variable-list">
|
<q-list class="variable-list">
|
||||||
<q-item-label header class="text-subtitle2">
|
<q-item-label header class="variable-label">
|
||||||
<q-icon name="functions" size="16px" class="q-mr-sm" />
|
<q-icon name="functions" size="15px" />
|
||||||
选择变量
|
选择变量
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
|
|
||||||
<q-separator />
|
<q-separator class="q-my-xs" />
|
||||||
|
|
||||||
<template v-if="variables.length">
|
<template v-if="variables.length">
|
||||||
<q-item
|
<q-item
|
||||||
@ -216,21 +216,29 @@ export default defineComponent({
|
|||||||
|
|
||||||
.variable-item {
|
.variable-item {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin: 2px 0;
|
padding: 0px 16px;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
min-height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.variable-item:hover {
|
.variable-item:hover {
|
||||||
background: var(--q-primary-opacity-10);
|
background: var(--q-primary-opacity-10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.variable-label {
|
||||||
|
padding: 4px 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.variable-name {
|
.variable-name {
|
||||||
font-size: 13px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.variable-source {
|
.variable-source {
|
||||||
font-size: 12px;
|
font-size: 11px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,3 +63,7 @@ export const SystemCommandEditor = defineAsyncComponent(() =>
|
|||||||
export const OsEditor = defineAsyncComponent(() =>
|
export const OsEditor = defineAsyncComponent(() =>
|
||||||
import("components/composer/system/OsEditor.vue")
|
import("components/composer/system/OsEditor.vue")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const PathEditor = defineAsyncComponent(() =>
|
||||||
|
import("src/components/composer/system/PathEditor.vue")
|
||||||
|
);
|
||||||
|
@ -2,7 +2,7 @@ import { fileCommands } from "./fileCommands";
|
|||||||
import { networkCommands } from "./networkCommands";
|
import { networkCommands } from "./networkCommands";
|
||||||
import { systemCommands } from "./systemCommands";
|
import { systemCommands } from "./systemCommands";
|
||||||
import { notifyCommands } from "./notifyCommands";
|
import { notifyCommands } from "./notifyCommands";
|
||||||
import { textProcessorCommands } from "./textProcessorCommands";
|
import { textCommands } from "./textCommands";
|
||||||
import { otherCommands } from "./otherCommands";
|
import { otherCommands } from "./otherCommands";
|
||||||
import { simulateCommands } from "./simulateCommands";
|
import { simulateCommands } from "./simulateCommands";
|
||||||
import { controlCommands } from "./controlCommands";
|
import { controlCommands } from "./controlCommands";
|
||||||
@ -12,7 +12,7 @@ export const commandCategories = [
|
|||||||
networkCommands,
|
networkCommands,
|
||||||
systemCommands,
|
systemCommands,
|
||||||
notifyCommands,
|
notifyCommands,
|
||||||
textProcessorCommands,
|
textCommands,
|
||||||
controlCommands,
|
controlCommands,
|
||||||
otherCommands,
|
otherCommands,
|
||||||
simulateCommands,
|
simulateCommands,
|
||||||
|
@ -27,6 +27,7 @@ export const systemCommands = {
|
|||||||
desc: "执行系统命令并返回输出结果",
|
desc: "执行系统命令并返回输出结果",
|
||||||
component: "SystemCommandEditor",
|
component: "SystemCommandEditor",
|
||||||
icon: "terminal",
|
icon: "terminal",
|
||||||
|
isAsync: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.system.os",
|
value: "quickcomposer.system.os",
|
||||||
@ -34,6 +35,15 @@ export const systemCommands = {
|
|||||||
desc: "获取操作系统相关信息",
|
desc: "获取操作系统相关信息",
|
||||||
component: "OsEditor",
|
component: "OsEditor",
|
||||||
icon: "computer",
|
icon: "computer",
|
||||||
|
isAsync: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "quickcomposer.system.path",
|
||||||
|
label: "路径操作",
|
||||||
|
desc: "路径操作",
|
||||||
|
component: "PathEditor",
|
||||||
|
icon: "folder_path",
|
||||||
|
isAsync: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
export const textProcessorCommands = {
|
export const textCommands = {
|
||||||
label: "文本处理",
|
label: "文本处理",
|
||||||
icon: "code",
|
icon: "code",
|
||||||
defaultOpened: false,
|
defaultOpened: false,
|
||||||
commands: [
|
commands: [
|
||||||
{
|
{
|
||||||
value: "quickcomposer.textProcessor",
|
value: "quickcomposer.text",
|
||||||
label: "编解码",
|
label: "编解码",
|
||||||
desc: "文本编解码",
|
desc: "文本编解码",
|
||||||
icon: "code",
|
icon: "code",
|
||||||
@ -21,46 +21,46 @@ export const textProcessorCommands = {
|
|||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: "Base64编码",
|
label: "Base64编码",
|
||||||
value: "quickcomposer.textProcessor.base64Encode",
|
value: "quickcomposer.text.base64Encode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Base64解码",
|
label: "Base64解码",
|
||||||
value: "quickcomposer.textProcessor.base64Decode",
|
value: "quickcomposer.text.base64Decode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "十六进制编码",
|
label: "十六进制编码",
|
||||||
value: "quickcomposer.textProcessor.hexEncode",
|
value: "quickcomposer.text.hexEncode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "十六进制解码",
|
label: "十六进制解码",
|
||||||
value: "quickcomposer.textProcessor.hexDecode",
|
value: "quickcomposer.text.hexDecode",
|
||||||
},
|
},
|
||||||
{ label: "URL编码", value: "quickcomposer.textProcessor.urlEncode" },
|
{ label: "URL编码", value: "quickcomposer.text.urlEncode" },
|
||||||
{ label: "URL解码", value: "quickcomposer.textProcessor.urlDecode" },
|
{ label: "URL解码", value: "quickcomposer.text.urlDecode" },
|
||||||
{
|
{
|
||||||
label: "HTML编码",
|
label: "HTML编码",
|
||||||
value: "quickcomposer.textProcessor.htmlEncode",
|
value: "quickcomposer.text.htmlEncode",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "HTML解码",
|
label: "HTML解码",
|
||||||
value: "quickcomposer.textProcessor.htmlDecode",
|
value: "quickcomposer.text.htmlDecode",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
width: 3,
|
width: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.textProcessor.symmetricCrypto",
|
value: "quickcomposer.text.symmetricCrypto",
|
||||||
label: "对称加解密",
|
label: "对称加解密",
|
||||||
component: "SymmetricCryptoEditor",
|
component: "SymmetricCryptoEditor",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.textProcessor.asymmetricCrypto",
|
value: "quickcomposer.text.asymmetricCrypto",
|
||||||
label: "非对称加解密",
|
label: "非对称加解密",
|
||||||
component: "AsymmetricCryptoEditor",
|
component: "AsymmetricCryptoEditor",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.textProcessor",
|
value: "quickcomposer.text",
|
||||||
label: "哈希计算",
|
label: "哈希计算",
|
||||||
desc: "计算文本的哈希值",
|
desc: "计算文本的哈希值",
|
||||||
icon: "enhanced_encryption",
|
icon: "enhanced_encryption",
|
||||||
@ -75,17 +75,17 @@ export const textProcessorCommands = {
|
|||||||
functionSelector: {
|
functionSelector: {
|
||||||
selectLabel: "哈希算法",
|
selectLabel: "哈希算法",
|
||||||
options: [
|
options: [
|
||||||
{ label: "MD5", value: "quickcomposer.textProcessor.md5Hash" },
|
{ label: "MD5", value: "quickcomposer.text.md5Hash" },
|
||||||
{ label: "SHA1", value: "quickcomposer.textProcessor.sha1Hash" },
|
{ label: "SHA1", value: "quickcomposer.text.sha1Hash" },
|
||||||
{ label: "SHA256", value: "quickcomposer.textProcessor.sha256Hash" },
|
{ label: "SHA256", value: "quickcomposer.text.sha256Hash" },
|
||||||
{ label: "SHA512", value: "quickcomposer.textProcessor.sha512Hash" },
|
{ label: "SHA512", value: "quickcomposer.text.sha512Hash" },
|
||||||
{ label: "SM3", value: "quickcomposer.textProcessor.sm3Hash" },
|
{ label: "SM3", value: "quickcomposer.text.sm3Hash" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
width: 3,
|
width: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.textProcessor.reverseString",
|
value: "quickcomposer.text.reverseString",
|
||||||
label: "字符串反转",
|
label: "字符串反转",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -97,7 +97,7 @@ export const textProcessorCommands = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.textProcessor.replaceString",
|
value: "quickcomposer.text.replaceString",
|
||||||
label: "字符串替换",
|
label: "字符串替换",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -124,7 +124,7 @@ export const textProcessorCommands = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.textProcessor.substring",
|
value: "quickcomposer.text.substring",
|
||||||
label: "字符串截取",
|
label: "字符串截取",
|
||||||
config: [
|
config: [
|
||||||
{
|
{
|
||||||
@ -151,7 +151,7 @@ export const textProcessorCommands = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "quickcomposer.textProcessor.regexTransform",
|
value: "quickcomposer.text.regexTransform",
|
||||||
label: "正则提取/替换",
|
label: "正则提取/替换",
|
||||||
component: "RegexEditor",
|
component: "RegexEditor",
|
||||||
componentProps: {
|
componentProps: {
|
Loading…
x
Reference in New Issue
Block a user