mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-07 21:46:12 +08:00
完善编排的文件操作模块
This commit is contained in:
parent
3cec2f94f2
commit
9bcea1e575
@ -126,6 +126,4 @@ async function archive(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = archive;
|
||||||
archive,
|
|
||||||
};
|
|
||||||
|
@ -7,23 +7,22 @@ const path = require("path");
|
|||||||
* @param {string} config.filePath 文件路径
|
* @param {string} config.filePath 文件路径
|
||||||
* @param {string} config.encoding 编码方式
|
* @param {string} config.encoding 编码方式
|
||||||
* @param {string} config.readMode 读取模式
|
* @param {string} config.readMode 读取模式
|
||||||
* @param {string} config.flag 读取标志
|
|
||||||
* @param {number} [config.start] 起始位置
|
* @param {number} [config.start] 起始位置
|
||||||
* @param {number} [config.length] 读取长度
|
* @param {number} [config.length] 读取长度
|
||||||
* @returns {Promise<string|Buffer>} 文件内容
|
* @returns {Promise<string|Buffer>} 文件内容
|
||||||
*/
|
*/
|
||||||
async function read(config) {
|
async function read(config) {
|
||||||
const { filePath, encoding, readMode, flag, start, length } = config;
|
const { filePath, encoding, readMode, start, length } = config;
|
||||||
|
|
||||||
if (readMode === "all") {
|
if (readMode === "all") {
|
||||||
return await fs.readFile(filePath, { encoding, flag });
|
return await fs.readFile(filePath, { encoding });
|
||||||
} else if (
|
} else if (
|
||||||
readMode === "start" &&
|
readMode === "start" &&
|
||||||
typeof start === "number" &&
|
typeof start === "number" &&
|
||||||
typeof length === "number"
|
typeof length === "number"
|
||||||
) {
|
) {
|
||||||
// 指定位置读取
|
// 指定位置读取
|
||||||
const fileHandle = await fs.open(filePath, flag || "r");
|
const fileHandle = await fs.open(filePath, "r");
|
||||||
try {
|
try {
|
||||||
const buffer = Buffer.alloc(length);
|
const buffer = Buffer.alloc(length);
|
||||||
const { bytesRead } = await fileHandle.read(buffer, 0, length, start);
|
const { bytesRead } = await fileHandle.read(buffer, 0, length, start);
|
||||||
@ -39,12 +38,11 @@ async function read(config) {
|
|||||||
// 按行读取,暂时使用全部读取然后分行的方式
|
// 按行读取,暂时使用全部读取然后分行的方式
|
||||||
const content = await fs.readFile(filePath, {
|
const content = await fs.readFile(filePath, {
|
||||||
encoding: encoding || "utf8",
|
encoding: encoding || "utf8",
|
||||||
flag,
|
|
||||||
});
|
});
|
||||||
return content.split(/\r?\n/);
|
return content.split(/\r?\n/);
|
||||||
} else {
|
} else {
|
||||||
// 默认使用全部读取
|
// 默认使用全部读取
|
||||||
return await fs.readFile(filePath, { encoding, flag });
|
return await fs.readFile(filePath, { encoding });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,20 +83,12 @@ async function write(config) {
|
|||||||
* 文件删除操作
|
* 文件删除操作
|
||||||
*/
|
*/
|
||||||
async function remove(config) {
|
async function remove(config) {
|
||||||
const { filePath, recursive, force, targetType } = config;
|
const { filePath, recursive, force } = config;
|
||||||
|
|
||||||
// 检查文件是否存在
|
// 检查文件是否存在
|
||||||
try {
|
try {
|
||||||
const stats = await fs.lstat(filePath);
|
const stats = await fs.lstat(filePath);
|
||||||
|
|
||||||
// 检查目标类型
|
|
||||||
if (targetType === "file" && !stats.isFile()) {
|
|
||||||
throw new Error("目标不是文件");
|
|
||||||
}
|
|
||||||
if (targetType === "directory" && !stats.isDirectory()) {
|
|
||||||
throw new Error("目标不是目录");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行删除操作
|
// 执行删除操作
|
||||||
if (stats.isDirectory()) {
|
if (stats.isDirectory()) {
|
||||||
await fs.rm(filePath, { recursive, force });
|
await fs.rm(filePath, { recursive, force });
|
||||||
@ -115,39 +105,16 @@ async function remove(config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件管理操作
|
* 文件权限操作
|
||||||
*/
|
*/
|
||||||
async function manage(config) {
|
async function permission(config) {
|
||||||
const {
|
const { filePath, operationType, mode, uid, gid, recursive } = config;
|
||||||
filePath,
|
|
||||||
manageOperation,
|
|
||||||
newPath,
|
|
||||||
mode,
|
|
||||||
uid,
|
|
||||||
gid,
|
|
||||||
recursive,
|
|
||||||
targetType,
|
|
||||||
} = config;
|
|
||||||
|
|
||||||
|
try {
|
||||||
// 检查文件是否存在
|
// 检查文件是否存在
|
||||||
const stats = await fs.lstat(filePath);
|
const stats = await fs.lstat(filePath);
|
||||||
|
|
||||||
// 检查目标类型
|
if (operationType === "chmod") {
|
||||||
if (targetType === "file" && !stats.isFile()) {
|
|
||||||
throw new Error("目标不是文件");
|
|
||||||
}
|
|
||||||
if (targetType === "directory" && !stats.isDirectory()) {
|
|
||||||
throw new Error("目标不是目录");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (manageOperation) {
|
|
||||||
case "rename":
|
|
||||||
// 确保目标目录存在
|
|
||||||
await fs.mkdir(path.dirname(newPath), { recursive: true });
|
|
||||||
await fs.rename(filePath, newPath);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "chmod":
|
|
||||||
if (recursive && stats.isDirectory()) {
|
if (recursive && stats.isDirectory()) {
|
||||||
const walk = async (dir) => {
|
const walk = async (dir) => {
|
||||||
const files = await fs.readdir(dir);
|
const files = await fs.readdir(dir);
|
||||||
@ -166,9 +133,7 @@ async function manage(config) {
|
|||||||
} else {
|
} else {
|
||||||
await fs.chmod(filePath, parseInt(mode, 8));
|
await fs.chmod(filePath, parseInt(mode, 8));
|
||||||
}
|
}
|
||||||
break;
|
} else if (operationType === "chown") {
|
||||||
|
|
||||||
case "chown":
|
|
||||||
if (recursive && stats.isDirectory()) {
|
if (recursive && stats.isDirectory()) {
|
||||||
await fs.chown(filePath, uid, gid);
|
await fs.chown(filePath, uid, gid);
|
||||||
const walk = async (dir) => {
|
const walk = async (dir) => {
|
||||||
@ -188,10 +153,71 @@ async function manage(config) {
|
|||||||
} else {
|
} else {
|
||||||
await fs.chown(filePath, uid, gid);
|
await fs.chown(filePath, uid, gid);
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
|
throw new Error(`不支持的操作类型: ${operationType}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code === "ENOENT") {
|
||||||
|
throw new Error("文件或目录不存在");
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
/**
|
||||||
throw new Error(`不支持的操作类型: ${manageOperation}`);
|
* 文件复制移动操作
|
||||||
|
*/
|
||||||
|
async function transfer(config) {
|
||||||
|
const { filePath, transferOperation, newPath } = config;
|
||||||
|
|
||||||
|
// 检查文件是否存在
|
||||||
|
try {
|
||||||
|
const stats = await fs.lstat(filePath);
|
||||||
|
|
||||||
|
// 确保目标目录存在
|
||||||
|
await fs.mkdir(path.dirname(newPath), { recursive: true });
|
||||||
|
if (transferOperation === "copy") {
|
||||||
|
const processBar = await quickcommand.showProcessBar({
|
||||||
|
text: "复制中...",
|
||||||
|
});
|
||||||
|
if (stats.isDirectory()) {
|
||||||
|
// 复制目录
|
||||||
|
const copyDir = async (src, dest) => {
|
||||||
|
await fs.mkdir(dest, { recursive: true });
|
||||||
|
const entries = await fs.readdir(src);
|
||||||
|
for (const entry of entries) {
|
||||||
|
const srcPath = path.join(src, entry);
|
||||||
|
const destPath = path.join(dest, entry);
|
||||||
|
const entryStat = await fs.lstat(srcPath);
|
||||||
|
if (entryStat.isDirectory()) {
|
||||||
|
await copyDir(srcPath, destPath);
|
||||||
|
} else {
|
||||||
|
await fs.copyFile(srcPath, destPath);
|
||||||
|
}
|
||||||
|
quickcommand.updateProcessBar({ text: entry }, processBar);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await copyDir(filePath, newPath);
|
||||||
|
} else {
|
||||||
|
// 复制文件
|
||||||
|
await fs.copyFile(filePath, newPath);
|
||||||
|
}
|
||||||
|
processBar.close();
|
||||||
|
} else if (transferOperation === "rename") {
|
||||||
|
const processBar = await quickcommand.showProcessBar({
|
||||||
|
text: "处理中...",
|
||||||
|
});
|
||||||
|
await fs.rename(filePath, newPath);
|
||||||
|
processBar.close();
|
||||||
|
} else {
|
||||||
|
throw new Error(`不支持的操作类型: ${transferOperation}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
processBar?.close();
|
||||||
|
if (error.code === "ENOENT") {
|
||||||
|
throw new Error("文件或目录不存在");
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,69 +272,49 @@ async function list(config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化文件大小
|
||||||
|
* @param {number} bytes 字节数
|
||||||
|
* @returns {string} 格式化后的文件大小
|
||||||
|
*/
|
||||||
|
function formatBytes(bytes) {
|
||||||
|
const units = ["B", "KB", "MB", "GB", "TB"];
|
||||||
|
let unitIndex = 0;
|
||||||
|
while (bytes >= 1024 && unitIndex < units.length - 1) {
|
||||||
|
bytes /= 1024;
|
||||||
|
unitIndex++;
|
||||||
|
}
|
||||||
|
return `${bytes.toFixed(2)} ${units[unitIndex]}`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取文件或目录状态
|
* 获取文件或目录状态
|
||||||
* @param {Object} config 配置对象
|
* @param {Object} config 配置对象
|
||||||
* @param {string} config.filePath 路径
|
* @param {string} config.filePath 路径
|
||||||
* @param {string} config.targetType 目标类型
|
|
||||||
* @param {string} config.statMode 检查类型
|
|
||||||
* @param {boolean} [config.followSymlinks] 是否跟随符号链接
|
* @param {boolean} [config.followSymlinks] 是否跟随符号链接
|
||||||
* @returns {Promise<Object>} 状态信息
|
* @returns {Promise<Object>} 状态信息
|
||||||
*/
|
*/
|
||||||
async function stat(config) {
|
async function stat(config) {
|
||||||
const { filePath, targetType, statMode, followSymlinks } = config;
|
const { filePath, followSymlinks } = config;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const statFn = followSymlinks ? fs.stat : fs.lstat;
|
const statFn = followSymlinks ? fs.stat : fs.lstat;
|
||||||
const stats = await statFn(filePath);
|
const stats = await statFn(filePath);
|
||||||
|
|
||||||
// 检查目标类型是否匹配
|
|
||||||
if (targetType === "file" && !stats.isFile()) {
|
|
||||||
throw new Error("目标不是文件");
|
|
||||||
}
|
|
||||||
if (targetType === "directory" && !stats.isDirectory()) {
|
|
||||||
throw new Error("目标不是目录");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据检查类型返回不同的信息
|
|
||||||
if (statMode === "exists") {
|
|
||||||
return {
|
|
||||||
exists: true,
|
|
||||||
isFile: stats.isFile(),
|
|
||||||
isDirectory: stats.isDirectory(),
|
|
||||||
};
|
|
||||||
} else if (statMode === "status") {
|
|
||||||
return {
|
return {
|
||||||
exists: true,
|
exists: true,
|
||||||
isFile: stats.isFile(),
|
isFile: stats.isFile(),
|
||||||
isDirectory: stats.isDirectory(),
|
isDirectory: stats.isDirectory(),
|
||||||
isSymbolicLink: stats.isSymbolicLink(),
|
isSymbolicLink: stats.isSymbolicLink(),
|
||||||
size: stats.size,
|
humanReadSize: formatBytes(stats.size),
|
||||||
mode: stats.mode,
|
...stats,
|
||||||
uid: stats.uid,
|
|
||||||
gid: stats.gid,
|
|
||||||
accessTime: stats.atime,
|
|
||||||
modifyTime: stats.mtime,
|
|
||||||
changeTime: stats.ctime,
|
|
||||||
birthTime: stats.birthtime,
|
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
// 默认返回基本信息
|
|
||||||
return {
|
|
||||||
exists: true,
|
|
||||||
isFile: stats.isFile(),
|
|
||||||
isDirectory: stats.isDirectory(),
|
|
||||||
isSymbolicLink: stats.isSymbolicLink(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === "ENOENT") {
|
if (error.code === "ENOENT") {
|
||||||
return {
|
return {
|
||||||
exists: false,
|
exists: false,
|
||||||
...(statMode === "exists" && {
|
|
||||||
isFile: false,
|
isFile: false,
|
||||||
isDirectory: false,
|
isDirectory: false,
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
@ -319,39 +325,28 @@ async function stat(config) {
|
|||||||
* 统一的文件操作入口
|
* 统一的文件操作入口
|
||||||
*/
|
*/
|
||||||
async function operation(config) {
|
async function operation(config) {
|
||||||
if (!config || typeof config !== "object") {
|
const { operation: op } = config;
|
||||||
throw new Error("配置参数必须是一个对象");
|
|
||||||
}
|
|
||||||
|
|
||||||
const { operation } = config;
|
switch (op) {
|
||||||
if (!operation) {
|
|
||||||
throw new Error("缺少必要的 operation 参数");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (operation) {
|
|
||||||
case "read":
|
case "read":
|
||||||
return await read(config);
|
return await read(config);
|
||||||
case "write":
|
case "write":
|
||||||
return await write(config);
|
return await write(config);
|
||||||
case "list":
|
case "list":
|
||||||
return await list(config);
|
return await list(config);
|
||||||
case "stat":
|
|
||||||
return await stat(config);
|
|
||||||
case "delete":
|
case "delete":
|
||||||
return await remove(config);
|
return await remove(config);
|
||||||
case "manage":
|
case "stat":
|
||||||
return await manage(config);
|
return await stat(config);
|
||||||
|
case "permission":
|
||||||
|
return await permission(config);
|
||||||
|
case "transfer":
|
||||||
|
return await transfer(config);
|
||||||
default:
|
default:
|
||||||
throw new Error(`不支持的操作类型: ${operation}`);
|
throw new Error(`不支持的操作类型: ${op}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
read,
|
|
||||||
write,
|
|
||||||
list,
|
|
||||||
stat,
|
|
||||||
remove,
|
|
||||||
manage,
|
|
||||||
operation,
|
operation,
|
||||||
};
|
};
|
||||||
|
@ -43,10 +43,16 @@
|
|||||||
<div class="q-ml-xs">删除</div>
|
<div class="q-ml-xs">删除</div>
|
||||||
</div>
|
</div>
|
||||||
</q-tab>
|
</q-tab>
|
||||||
<q-tab name="manage" no-caps>
|
<q-tab name="transfer" no-caps>
|
||||||
<div class="row items-center no-wrap">
|
<div class="row items-center no-wrap">
|
||||||
<q-icon name="settings" size="16px" />
|
<q-icon name="drive_file_move" size="16px" />
|
||||||
<div class="q-ml-xs">管理</div>
|
<div class="q-ml-xs">复制移动</div>
|
||||||
|
</div>
|
||||||
|
</q-tab>
|
||||||
|
<q-tab name="permission" no-caps>
|
||||||
|
<div class="row items-center no-wrap">
|
||||||
|
<q-icon name="security" size="16px" />
|
||||||
|
<div class="q-ml-xs">权限</div>
|
||||||
</div>
|
</div>
|
||||||
</q-tab>
|
</q-tab>
|
||||||
</q-tabs>
|
</q-tabs>
|
||||||
@ -64,10 +70,7 @@
|
|||||||
dialog: {
|
dialog: {
|
||||||
options: {
|
options: {
|
||||||
title: '选择文件',
|
title: '选择文件',
|
||||||
properties: [
|
properties: ['openDirectory', 'openFile', 'showHiddenFiles'],
|
||||||
shouldSelectDirectory ? 'openDirectory' : 'openFile',
|
|
||||||
'showHiddenFiles',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}"
|
}"
|
||||||
@ -100,25 +103,13 @@
|
|||||||
map-options
|
map-options
|
||||||
@update:model-value="updateArgvs('readMode', $event)"
|
@update:model-value="updateArgvs('readMode', $event)"
|
||||||
/>
|
/>
|
||||||
<q-select
|
|
||||||
v-model="argvs.readFlag"
|
|
||||||
:options="readFlagOptions"
|
|
||||||
label="读取标志"
|
|
||||||
dense
|
|
||||||
options-dense
|
|
||||||
filled
|
|
||||||
class="col-grow"
|
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
@update:model-value="updateArgvs('readFlag', $event)"
|
|
||||||
/>
|
|
||||||
<NumberInput
|
<NumberInput
|
||||||
v-if="argvs.readMode === 'start'"
|
v-if="argvs.readMode === 'start'"
|
||||||
:model-value="argvs.start"
|
:model-value="argvs.start"
|
||||||
@update:model-value="updateArgvs('start', $event)"
|
@update:model-value="updateArgvs('start', $event)"
|
||||||
label="起始位置"
|
label="起始位置"
|
||||||
icon="first_page"
|
icon="first_page"
|
||||||
class="col-grow"
|
class="col"
|
||||||
/>
|
/>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
v-if="argvs.readMode === 'start'"
|
v-if="argvs.readMode === 'start'"
|
||||||
@ -126,7 +117,7 @@
|
|||||||
@update:model-value="updateArgvs('length', $event)"
|
@update:model-value="updateArgvs('length', $event)"
|
||||||
label="读取长度"
|
label="读取长度"
|
||||||
icon="last_page"
|
icon="last_page"
|
||||||
class="col-grow"
|
class="col"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -186,7 +177,7 @@
|
|||||||
@update:model-value="updateArgvs('content', $event)"
|
@update:model-value="updateArgvs('content', $event)"
|
||||||
label="写入内容"
|
label="写入内容"
|
||||||
icon="edit"
|
icon="edit"
|
||||||
class="col-12"
|
class="col-grow"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -194,80 +185,87 @@
|
|||||||
<!-- 删除操作配置 -->
|
<!-- 删除操作配置 -->
|
||||||
<template v-if="argvs.operation === 'delete'">
|
<template v-if="argvs.operation === 'delete'">
|
||||||
<div class="row q-gutter-sm">
|
<div class="row q-gutter-sm">
|
||||||
<q-select
|
<CheckButton
|
||||||
v-model="argvs.targetType"
|
|
||||||
:options="targetTypeOptions"
|
|
||||||
label="目标类型"
|
|
||||||
dense
|
|
||||||
filled
|
|
||||||
options-dense
|
|
||||||
class="col-grow"
|
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
@update:model-value="updateArgvs('targetType', $event)"
|
|
||||||
/>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="argvs.recursive"
|
v-model="argvs.recursive"
|
||||||
label="递归删除"
|
label="递归删除"
|
||||||
v-if="argvs.targetType === 'directory'"
|
class="col"
|
||||||
dense
|
|
||||||
class="col-grow"
|
|
||||||
@update:model-value="updateArgvs('recursive', $event)"
|
@update:model-value="updateArgvs('recursive', $event)"
|
||||||
/>
|
/>
|
||||||
<q-checkbox
|
<CheckButton
|
||||||
v-model="argvs.force"
|
v-model="argvs.force"
|
||||||
label="强制删除"
|
label="强制删除"
|
||||||
dense
|
class="col"
|
||||||
class="col-grow"
|
|
||||||
@update:model-value="updateArgvs('force', $event)"
|
@update:model-value="updateArgvs('force', $event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 管理操作配置 -->
|
<!-- 列目录操作配置 -->
|
||||||
<template v-if="argvs.operation === 'manage'">
|
<template v-if="argvs.operation === 'list'">
|
||||||
<div class="row q-gutter-sm">
|
<div class="row q-gutter-sm">
|
||||||
<q-select
|
<CheckButton
|
||||||
v-model="argvs.targetType"
|
v-model="argvs.recursive"
|
||||||
:options="targetTypeOptions"
|
label="递归列出子目录"
|
||||||
label="目标类型"
|
class="col"
|
||||||
dense
|
@update:model-value="updateArgvs('recursive', $event)"
|
||||||
options-dense
|
|
||||||
filled
|
|
||||||
class="col-grow"
|
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
@update:model-value="updateArgvs('targetType', $event)"
|
|
||||||
/>
|
/>
|
||||||
<q-select
|
<CheckButton
|
||||||
v-model="argvs.manageOperation"
|
v-model="argvs.showHidden"
|
||||||
:options="manageOperationOptions"
|
label="显示隐藏文件"
|
||||||
label="管理操作"
|
class="col"
|
||||||
dense
|
@update:model-value="updateArgvs('showHidden', $event)"
|
||||||
options-dense
|
|
||||||
filled
|
|
||||||
class="col-grow"
|
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
@update:model-value="updateArgvs('manageOperation', $event)"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- 重命名操作 -->
|
<!-- 状态操作配置 -->
|
||||||
<template v-if="argvs.manageOperation === 'rename'">
|
<template v-if="argvs.operation === 'stat'">
|
||||||
<div class="row q-gutter-sm">
|
<div class="row q-gutter-sm">
|
||||||
<VariableInput
|
<CheckButton
|
||||||
:model-value="argvs.newPath"
|
v-model="argvs.followSymlinks"
|
||||||
@update:model-value="updateArgvs('newPath', $event)"
|
label="跟随符号链接"
|
||||||
label="新路径"
|
@update:model-value="updateArgvs('followSymlinks', $event)"
|
||||||
icon="drive_file_rename_outline"
|
|
||||||
class="col-grow"
|
class="col-grow"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- 复制移动操作配置 -->
|
||||||
|
<template v-if="argvs.operation === 'transfer'">
|
||||||
|
<div class="row q-gutter-sm">
|
||||||
|
<div class="col-6">
|
||||||
|
<VariableInput
|
||||||
|
:model-value="argvs.newPath"
|
||||||
|
@update:model-value="updateArgvs('newPath', $event)"
|
||||||
|
label="目标路径"
|
||||||
|
icon="drive_file_rename_outline"
|
||||||
|
class="col-6"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<ButtonGroup
|
||||||
|
v-model="argvs.transferOperation"
|
||||||
|
:options="transferOperationOptions"
|
||||||
|
height="36px"
|
||||||
|
@update:model-value="updateArgvs('transferOperation', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 权限操作配置 -->
|
||||||
|
<template v-if="argvs.operation === 'permission'">
|
||||||
|
<div class="row q-gutter-sm">
|
||||||
|
<ButtonGroup
|
||||||
|
v-model="argvs.operationType"
|
||||||
|
class="col"
|
||||||
|
:options="operationTypeOptions"
|
||||||
|
@update:model-value="updateArgvs('operationType', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 修改权限操作 -->
|
<!-- 修改权限操作 -->
|
||||||
<template v-if="argvs.manageOperation === 'chmod'">
|
<template v-if="argvs.operationType === 'chmod'">
|
||||||
<div class="row q-gutter-sm">
|
<div class="row q-gutter-sm">
|
||||||
<q-select
|
<q-select
|
||||||
v-model="argvs.mode"
|
v-model="argvs.mode"
|
||||||
@ -290,11 +288,9 @@
|
|||||||
</q-item>
|
</q-item>
|
||||||
</template>
|
</template>
|
||||||
</q-select>
|
</q-select>
|
||||||
<q-checkbox
|
<CheckButton
|
||||||
v-model="argvs.recursive"
|
v-model="argvs.recursive"
|
||||||
label="递归修改"
|
label="递归修改"
|
||||||
v-if="argvs.targetType === 'directory'"
|
|
||||||
dense
|
|
||||||
class="col-grow"
|
class="col-grow"
|
||||||
@update:model-value="updateArgvs('recursive', $event)"
|
@update:model-value="updateArgvs('recursive', $event)"
|
||||||
/>
|
/>
|
||||||
@ -302,7 +298,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 修改所有者操作 -->
|
<!-- 修改所有者操作 -->
|
||||||
<template v-if="argvs.manageOperation === 'chown'">
|
<template v-if="argvs.operationType === 'chown'">
|
||||||
<div class="row q-gutter-sm">
|
<div class="row q-gutter-sm">
|
||||||
<NumberInput
|
<NumberInput
|
||||||
:model-value="argvs.uid"
|
:model-value="argvs.uid"
|
||||||
@ -318,75 +314,15 @@
|
|||||||
icon="group"
|
icon="group"
|
||||||
class="col-grow"
|
class="col-grow"
|
||||||
/>
|
/>
|
||||||
<q-checkbox
|
<CheckButton
|
||||||
v-model="argvs.recursive"
|
v-model="argvs.recursive"
|
||||||
label="递归修改"
|
label="递归修改"
|
||||||
v-if="argvs.targetType === 'directory'"
|
|
||||||
dense
|
|
||||||
class="col-grow"
|
class="col-grow"
|
||||||
@update:model-value="updateArgvs('recursive', $event)"
|
@update:model-value="updateArgvs('recursive', $event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 列目录操作配置 -->
|
|
||||||
<template v-if="argvs.operation === 'list'">
|
|
||||||
<div class="row q-gutter-sm q-px-xs">
|
|
||||||
<q-checkbox
|
|
||||||
v-model="argvs.recursive"
|
|
||||||
label="递归列出子目录"
|
|
||||||
dense
|
|
||||||
class="col-grow"
|
|
||||||
@update:model-value="updateArgvs('recursive', $event)"
|
|
||||||
/>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="argvs.showHidden"
|
|
||||||
label="显示隐藏文件"
|
|
||||||
dense
|
|
||||||
class="col-grow"
|
|
||||||
@update:model-value="updateArgvs('showHidden', $event)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 状态操作配置 -->
|
|
||||||
<template v-if="argvs.operation === 'stat'">
|
|
||||||
<div class="row q-gutter-sm">
|
|
||||||
<q-select
|
|
||||||
v-model="argvs.targetType"
|
|
||||||
:options="targetTypeOptions"
|
|
||||||
label="目标类型"
|
|
||||||
dense
|
|
||||||
filled
|
|
||||||
options-dense
|
|
||||||
class="col-grow"
|
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
@update:model-value="updateArgvs('targetType', $event)"
|
|
||||||
/>
|
|
||||||
<q-select
|
|
||||||
v-model="argvs.statMode"
|
|
||||||
:options="statModeOptions"
|
|
||||||
label="检查类型"
|
|
||||||
dense
|
|
||||||
filled
|
|
||||||
options-dense
|
|
||||||
class="col-grow"
|
|
||||||
emit-value
|
|
||||||
map-options
|
|
||||||
@update:model-value="updateArgvs('statMode', $event)"
|
|
||||||
/>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="argvs.followSymlinks"
|
|
||||||
label="跟随符号链接"
|
|
||||||
v-if="argvs.statMode === 'status'"
|
|
||||||
@update:model-value="updateArgvs('followSymlinks', $event)"
|
|
||||||
dense
|
|
||||||
class="col-grow"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -394,7 +330,9 @@
|
|||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import VariableInput from "components/composer/common/VariableInput.vue";
|
import VariableInput from "components/composer/common/VariableInput.vue";
|
||||||
import NumberInput from "components/composer/common/NumberInput.vue";
|
import NumberInput from "components/composer/common/NumberInput.vue";
|
||||||
import { stringifyArgv, parseFunction } from "js/composer/formatString";
|
import ButtonGroup from "components/composer/common/ButtonGroup.vue";
|
||||||
|
import CheckButton from "components/composer/common/CheckButton.vue";
|
||||||
|
import { stringifyArgv } from "js/composer/formatString";
|
||||||
import { newVarInputVal } from "js/composer/varInputValManager";
|
import { newVarInputVal } from "js/composer/varInputValManager";
|
||||||
|
|
||||||
// 静态选项数据
|
// 静态选项数据
|
||||||
@ -418,11 +356,6 @@ const READ_MODE_OPTIONS = [
|
|||||||
{ label: "按行读取", value: "line" },
|
{ label: "按行读取", value: "line" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const READ_FLAG_OPTIONS = [
|
|
||||||
{ label: "同步读取", value: "sync" },
|
|
||||||
{ label: "异步读取", value: "async" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const WRITE_MODE_OPTIONS = [
|
const WRITE_MODE_OPTIONS = [
|
||||||
{ label: "覆盖写入", value: "write" },
|
{ label: "覆盖写入", value: "write" },
|
||||||
{ label: "追加写入", value: "append" },
|
{ label: "追加写入", value: "append" },
|
||||||
@ -435,20 +368,19 @@ const WRITE_FLAG_OPTIONS = [
|
|||||||
{ label: "777", value: "777", hint: "所有人读写执行" },
|
{ label: "777", value: "777", hint: "所有人读写执行" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const STAT_MODE_OPTIONS = [
|
|
||||||
{ label: "检查存在", value: "exists" },
|
|
||||||
{ label: "完整状态", value: "status" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const TARGET_TYPE_OPTIONS = [
|
const TARGET_TYPE_OPTIONS = [
|
||||||
{ label: "文件", value: "file" },
|
{ label: "文件", value: "file" },
|
||||||
{ label: "目录", value: "directory" },
|
{ label: "目录", value: "directory" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const MANAGE_OPERATION_OPTIONS = [
|
const OPERATION_TYPE_OPTIONS = [
|
||||||
{ label: "重命名", value: "rename" },
|
{ label: "修改权限", value: "chmod", icon: "lock" },
|
||||||
{ label: "修改权限", value: "chmod" },
|
{ label: "修改所有者", value: "chown", icon: "person" },
|
||||||
{ label: "修改所有者", value: "chown" },
|
];
|
||||||
|
|
||||||
|
const TRANSFER_OPERATION_OPTIONS = [
|
||||||
|
{ label: "移动/重命名", value: "rename", icon: "drive_file_rename_outline" },
|
||||||
|
{ label: "复制", value: "copy", icon: "content_copy" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@ -456,6 +388,8 @@ export default defineComponent({
|
|||||||
components: {
|
components: {
|
||||||
VariableInput,
|
VariableInput,
|
||||||
NumberInput,
|
NumberInput,
|
||||||
|
ButtonGroup,
|
||||||
|
CheckButton,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
@ -468,44 +402,34 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
encodingOptions: ENCODING_OPTIONS,
|
encodingOptions: ENCODING_OPTIONS,
|
||||||
readModeOptions: READ_MODE_OPTIONS,
|
readModeOptions: READ_MODE_OPTIONS,
|
||||||
readFlagOptions: READ_FLAG_OPTIONS,
|
|
||||||
writeModeOptions: WRITE_MODE_OPTIONS,
|
writeModeOptions: WRITE_MODE_OPTIONS,
|
||||||
writeFlagOptions: WRITE_FLAG_OPTIONS,
|
writeFlagOptions: WRITE_FLAG_OPTIONS,
|
||||||
statModeOptions: STAT_MODE_OPTIONS,
|
|
||||||
targetTypeOptions: TARGET_TYPE_OPTIONS,
|
targetTypeOptions: TARGET_TYPE_OPTIONS,
|
||||||
manageOperationOptions: MANAGE_OPERATION_OPTIONS,
|
operationTypeOptions: OPERATION_TYPE_OPTIONS,
|
||||||
|
transferOperationOptions: TRANSFER_OPERATION_OPTIONS,
|
||||||
defaultArgvs: {
|
defaultArgvs: {
|
||||||
operation: "read",
|
operation: "read",
|
||||||
filePath: newVarInputVal("str"),
|
filePath: newVarInputVal("str"),
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
readMode: "all",
|
readMode: "all",
|
||||||
readFlag: "async",
|
|
||||||
start: 0,
|
start: 0,
|
||||||
length: 100,
|
length: 100,
|
||||||
targetType: "file",
|
targetType: "file",
|
||||||
writeMode: "write",
|
writeMode: "write",
|
||||||
writeFlag: "644",
|
writeFlag: "644",
|
||||||
statMode: "exists",
|
followSymlinks: true,
|
||||||
followSymlinks: false,
|
mode: "644",
|
||||||
recursive: false,
|
recursive: false,
|
||||||
force: false,
|
force: false,
|
||||||
showHidden: false,
|
showHidden: false,
|
||||||
manageOperation: "rename",
|
operationType: "chmod",
|
||||||
|
transferOperation: "rename",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
argvs() {
|
argvs() {
|
||||||
return (
|
return this.modelValue.argvs || this.defaultArgvs;
|
||||||
this.modelValue.argvs || this.parseCodeToArgvs(this.modelValue.code)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
shouldSelectDirectory() {
|
|
||||||
return (
|
|
||||||
this.argvs.operation === "list" ||
|
|
||||||
(this.argvs.targetType === "directory" &&
|
|
||||||
["delete", "manage", "stat"].includes(this.argvs.operation))
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -519,7 +443,6 @@ export default defineComponent({
|
|||||||
switch (argvs.operation) {
|
switch (argvs.operation) {
|
||||||
case "read":
|
case "read":
|
||||||
params.encoding = argvs.encoding;
|
params.encoding = argvs.encoding;
|
||||||
params.readFlag = argvs.readFlag;
|
|
||||||
params.readMode = argvs.readMode;
|
params.readMode = argvs.readMode;
|
||||||
if (argvs.readMode === "start") {
|
if (argvs.readMode === "start") {
|
||||||
params.start = Number(argvs.start) || 0;
|
params.start = Number(argvs.start) || 0;
|
||||||
@ -537,32 +460,33 @@ export default defineComponent({
|
|||||||
case "list":
|
case "list":
|
||||||
params.targetType = "directory";
|
params.targetType = "directory";
|
||||||
params.recursive = argvs.recursive;
|
params.recursive = argvs.recursive;
|
||||||
|
params.showHidden = argvs.showHidden;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "delete":
|
case "delete":
|
||||||
params.targetType = argvs.targetType;
|
|
||||||
params.force = argvs.force;
|
params.force = argvs.force;
|
||||||
params.recursive =
|
params.recursive = argvs.recursive;
|
||||||
argvs.recursive && argvs.targetType === "directory";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "manage":
|
|
||||||
params.targetType = argvs.targetType;
|
|
||||||
params.manageOperation = argvs.manageOperation;
|
|
||||||
if (argvs.manageOperation === "rename") {
|
|
||||||
params.newPath = argvs.newPath;
|
|
||||||
} else {
|
|
||||||
if (argvs.mode) params.mode = argvs.mode;
|
|
||||||
if (argvs.uid) params.uid = argvs.uid;
|
|
||||||
if (argvs.gid) params.gid = argvs.gid;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "stat":
|
case "stat":
|
||||||
params.targetType = argvs.targetType;
|
|
||||||
params.statMode = argvs.statMode;
|
|
||||||
params.followSymlinks = argvs.followSymlinks;
|
params.followSymlinks = argvs.followSymlinks;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "permission":
|
||||||
|
params.operationType = argvs.operationType;
|
||||||
|
if (argvs.operationType === "chmod") {
|
||||||
|
params.mode = argvs.mode;
|
||||||
|
} else {
|
||||||
|
params.uid = argvs.uid;
|
||||||
|
params.gid = argvs.gid;
|
||||||
|
}
|
||||||
|
params.recursive = argvs.recursive;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "transfer":
|
||||||
|
params.transferOperation = argvs.transferOperation;
|
||||||
|
params.newPath = argvs.newPath;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${this.modelValue.value}(${stringifyArgv(params)})`;
|
return `${this.modelValue.value}(${stringifyArgv(params)})`;
|
||||||
@ -610,52 +534,6 @@ export default defineComponent({
|
|||||||
this.argvs.mode = `${ownerValue}${groupValue}${otherValue}`;
|
this.argvs.mode = `${ownerValue}${groupValue}${otherValue}`;
|
||||||
this.updateArgvs();
|
this.updateArgvs();
|
||||||
},
|
},
|
||||||
parseCodeToArgvs(code) {
|
|
||||||
const argvs = window.lodashM.cloneDeep(this.defaultArgvs);
|
|
||||||
if (!code) return argvs;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const variableFormatPaths = [
|
|
||||||
"arg0.filePath",
|
|
||||||
"arg0.content",
|
|
||||||
"arg0.newPath",
|
|
||||||
];
|
|
||||||
const result = parseFunction(code, { variableFormatPaths });
|
|
||||||
let params = result.argvs[0];
|
|
||||||
|
|
||||||
// 根据不同操作类型处理特定参数
|
|
||||||
switch (params.operation) {
|
|
||||||
case "read":
|
|
||||||
if (params.readMode === "start") {
|
|
||||||
params.start = Number(params.start) || 0;
|
|
||||||
params.length = Number(params.length) || 100;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "write":
|
|
||||||
// 将 flag 转换回 writeMode
|
|
||||||
params.writeMode = params.flag === "a" ? "append" : "write";
|
|
||||||
// 将 mode 转换回 writeFlag
|
|
||||||
params.writeFlag = params.mode;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "list":
|
|
||||||
params.targetType = "directory";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "delete":
|
|
||||||
case "manage":
|
|
||||||
case "stat":
|
|
||||||
// 这些操作的参数可以直接使用
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return params;
|
|
||||||
} catch (e) {
|
|
||||||
console.error("解析文件操作参数失败:", e);
|
|
||||||
}
|
|
||||||
return argvs;
|
|
||||||
},
|
|
||||||
updateModelValue(argvs) {
|
updateModelValue(argvs) {
|
||||||
this.$emit("update:modelValue", {
|
this.$emit("update:modelValue", {
|
||||||
...this.modelValue,
|
...this.modelValue,
|
||||||
@ -670,19 +548,11 @@ export default defineComponent({
|
|||||||
write: "写入",
|
write: "写入",
|
||||||
list: "列目录",
|
list: "列目录",
|
||||||
delete: "删除",
|
delete: "删除",
|
||||||
manage: "管理",
|
stat: "获取状态",
|
||||||
stat: "状态",
|
transfer: "复制移动",
|
||||||
|
permission: "设置权限",
|
||||||
};
|
};
|
||||||
const findOptionsLabel = (options, value) => {
|
let operationInfo = operationDict[argvs.operation] + " ";
|
||||||
return options.find((option) => option.value === value)?.label || value;
|
|
||||||
};
|
|
||||||
let operationInfo =
|
|
||||||
argvs.operation === "manage"
|
|
||||||
? findOptionsLabel(MANAGE_OPERATION_OPTIONS, argvs.manageOperation) +
|
|
||||||
" "
|
|
||||||
: argvs.operation === "stat"
|
|
||||||
? findOptionsLabel(STAT_MODE_OPTIONS, argvs.statMode) + " "
|
|
||||||
: operationDict[argvs.operation] + " ";
|
|
||||||
return operationInfo + argvs.filePath.value;
|
return operationInfo + argvs.filePath.value;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -382,7 +382,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
argvs() {
|
argvs() {
|
||||||
return this.modelValue.argvs;
|
return this.modelValue.argvs || this.defaultArgvs;
|
||||||
},
|
},
|
||||||
hasRequestData() {
|
hasRequestData() {
|
||||||
return ["PUT", "POST", "PATCH"].includes(this.argvs.method);
|
return ["PUT", "POST", "PATCH"].includes(this.argvs.method);
|
||||||
|
103
src/plugins/monaco/types/quickcomposer.d.ts
vendored
103
src/plugins/monaco/types/quickcomposer.d.ts
vendored
@ -507,89 +507,58 @@ interface quickcomposerApi {
|
|||||||
file: {
|
file: {
|
||||||
/**
|
/**
|
||||||
* 文件操作
|
* 文件操作
|
||||||
*/
|
|
||||||
operation: {
|
|
||||||
/**
|
|
||||||
* 统一的文件操作入口
|
|
||||||
* @param config 操作配置
|
* @param config 操作配置
|
||||||
*/
|
*/
|
||||||
operation(config: {
|
operation(config: {
|
||||||
/** 操作类型:read-读取,write-写入,list-列表,stat-状态,delete-删除,manage-管理 */
|
/** 操作类型:read-读取,write-写入,list-列表,stat-状态,delete-删除,permission-权限,transfer-复制移动 */
|
||||||
operation: "read" | "write" | "list" | "stat" | "delete" | "manage";
|
operation:
|
||||||
|
| "read"
|
||||||
|
| "write"
|
||||||
|
| "list"
|
||||||
|
| "stat"
|
||||||
|
| "delete"
|
||||||
|
| "permission"
|
||||||
|
| "transfer";
|
||||||
/** 文件路径 */
|
/** 文件路径 */
|
||||||
filePath: string;
|
filePath: string;
|
||||||
/** 读取操作配置 */
|
/** 读取操作配置 */
|
||||||
readOptions?: {
|
|
||||||
/** 编码方式 */
|
|
||||||
encoding?: BufferEncoding;
|
encoding?: BufferEncoding;
|
||||||
/** 起始位置 */
|
readMode?: "all" | "start" | "line";
|
||||||
start?: number;
|
start?: number;
|
||||||
/** 结束位置 */
|
length?: number;
|
||||||
end?: number;
|
|
||||||
};
|
|
||||||
/** 写入操作配置 */
|
/** 写入操作配置 */
|
||||||
writeOptions?: {
|
content?: string;
|
||||||
/** 写入内容 */
|
flag?: "w" | "a";
|
||||||
content: string;
|
|
||||||
/** 编码方式 */
|
|
||||||
encoding?: BufferEncoding;
|
|
||||||
/** 写入模式:overwrite-覆盖,append-追加 */
|
|
||||||
writeMode?: "overwrite" | "append";
|
|
||||||
/** 文件权限 */
|
|
||||||
writeFlag?: string;
|
|
||||||
};
|
|
||||||
/** 列表操作配置 */
|
|
||||||
listOptions?: {
|
|
||||||
/** 是否递归 */
|
|
||||||
recursive?: boolean;
|
|
||||||
/** 是否包含隐藏文件 */
|
|
||||||
includeHidden?: boolean;
|
|
||||||
};
|
|
||||||
/** 管理操作配置 */
|
|
||||||
manageOptions?: {
|
|
||||||
/** 目标类型:file-文件,directory-目录 */
|
|
||||||
targetType?: "file" | "directory";
|
|
||||||
/** 管理操作类型:rename-重命名,chmod-修改权限,chown-修改所有者 */
|
|
||||||
manageOperation?: "rename" | "chmod" | "chown";
|
|
||||||
/** 新路径(重命名时使用) */
|
|
||||||
newPath?: string;
|
|
||||||
/** 权限模式(chmod时使用) */
|
|
||||||
mode?: string | number;
|
mode?: string | number;
|
||||||
/** 用户ID(chown时使用) */
|
/** 列表操作配置 */
|
||||||
uid?: number;
|
|
||||||
/** 组ID(chown时使用) */
|
|
||||||
gid?: number;
|
|
||||||
/** 是否递归操作 */
|
|
||||||
recursive?: boolean;
|
recursive?: boolean;
|
||||||
};
|
showHidden?: boolean;
|
||||||
|
/** 权限操作配置 */
|
||||||
|
operationType?: "chmod" | "chown";
|
||||||
|
uid?: number;
|
||||||
|
gid?: number;
|
||||||
|
/** 复制移动操作配置 */
|
||||||
|
transferOperation?: "copy" | "rename";
|
||||||
|
newPath?: string;
|
||||||
|
/** 删除操作配置 */
|
||||||
|
force?: boolean;
|
||||||
|
/** 状态操作配置 */
|
||||||
|
followSymlinks?: boolean;
|
||||||
}): Promise<any>;
|
}): Promise<any>;
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件归档
|
|
||||||
*/
|
|
||||||
archive: {
|
|
||||||
/**
|
/**
|
||||||
* 文件归档操作
|
* 文件归档操作
|
||||||
* @param config 归档配置
|
* @param operation 操作类型:compress-压缩,extract-解压
|
||||||
|
* @param format 归档格式:zip, tar, gzip
|
||||||
|
* @param source 源文件/文件夹路径
|
||||||
|
* @param destination 目标路径
|
||||||
*/
|
*/
|
||||||
archive(config: {
|
archive(
|
||||||
/** 操作类型:compress-压缩,extract-解压 */
|
operation: "compress" | "extract",
|
||||||
operation: "compress" | "extract";
|
format: "zip" | "tar" | "gzip",
|
||||||
/** 归档格式:zip, tar, gzip */
|
source: string | string[],
|
||||||
format: "zip" | "tar" | "gzip";
|
destination: string
|
||||||
/** 源文件/文件夹路径 */
|
): Promise<void>;
|
||||||
sourcePath: string | string[];
|
|
||||||
/** 目标路径 */
|
|
||||||
targetPath: string;
|
|
||||||
/** 压缩级别(1-9) */
|
|
||||||
level?: number;
|
|
||||||
/** 是否保持目录结构 */
|
|
||||||
preserveStructure?: boolean;
|
|
||||||
/** 密码保护(仅zip格式支持) */
|
|
||||||
password?: string;
|
|
||||||
}): Promise<void>;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
system: {
|
system: {
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user