mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-01-24 15:14:01 +08:00
Feat: refactoring FileManager & modify file permissions
This commit is contained in:
parent
2ad6ab4f4f
commit
f4e5079542
2
frontend/components.d.ts
vendored
2
frontend/components.d.ts
vendored
@ -10,6 +10,8 @@ declare module 'vue' {
|
||||
ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb']
|
||||
ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem']
|
||||
AButton: typeof import('ant-design-vue/es')['Button']
|
||||
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
|
||||
ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
|
||||
ACol: typeof import('ant-design-vue/es')['Col']
|
||||
ActionButton: typeof import('./src/components/ActionButton.vue')['default']
|
||||
ADatePicker: typeof import('ant-design-vue/es')['DatePicker']
|
||||
|
@ -5,6 +5,21 @@
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flex-around {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.flex-evenly {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.flex-warp {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { h, ref, createVNode, type Ref } from "vue";
|
||||
import { h, ref, createVNode, type Ref, reactive } from "vue";
|
||||
import { t } from "@/lang/i18n";
|
||||
import type { TableProps, UploadProps } from "ant-design-vue";
|
||||
|
||||
import { LoadingOutlined, ExclamationCircleOutlined } from "@ant-design/icons-vue";
|
||||
|
||||
import { parseForwardAddress } from "@/tools/protocol";
|
||||
|
||||
import { number2permission, permission2number } from "@/tools/permission";
|
||||
import {
|
||||
fileList as getFileListApi,
|
||||
getFileStatus as getFileStatusApi,
|
||||
@ -17,12 +17,19 @@ import {
|
||||
compressFile as compressFileApi,
|
||||
uploadAddress,
|
||||
uploadFile as uploadFileApi,
|
||||
downloadAddress
|
||||
downloadAddress,
|
||||
changePermission as changePermissionApi
|
||||
} from "@/services/apis/fileManager";
|
||||
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
|
||||
import type { DataType, OperationForm, Breadcrumb, FileStatus } from "@/types/fileManager";
|
||||
import type {
|
||||
DataType,
|
||||
OperationForm,
|
||||
Breadcrumb,
|
||||
FileStatus,
|
||||
Permission
|
||||
} from "@/types/fileManager";
|
||||
|
||||
export const useFileManager = (
|
||||
instanceId: string | undefined,
|
||||
@ -78,6 +85,9 @@ export const useFileManager = (
|
||||
if (mode == "unzip") {
|
||||
dialog.value.mode = "unzip";
|
||||
}
|
||||
if (mode == "permission") {
|
||||
dialog.value.mode = "permission";
|
||||
}
|
||||
|
||||
dialog.value.title = title;
|
||||
dialog.value.info = info;
|
||||
@ -88,7 +98,11 @@ export const useFileManager = (
|
||||
|
||||
return new Promise((resolve) => {
|
||||
dialog.value.ok = () => {
|
||||
if (dialog.value.value == "" && dialog.value.mode != "unzip") {
|
||||
if (
|
||||
dialog.value.value == "" &&
|
||||
dialog.value.mode != "unzip" &&
|
||||
dialog.value.mode != "permission"
|
||||
) {
|
||||
return message.error(t("请输入内容"));
|
||||
}
|
||||
resolve(dialog.value.value);
|
||||
@ -430,6 +444,46 @@ export const useFileManager = (
|
||||
}
|
||||
};
|
||||
|
||||
const permission = reactive<Permission>({
|
||||
data: {
|
||||
owner: [],
|
||||
usergroup: [],
|
||||
everyone: []
|
||||
},
|
||||
deep: false,
|
||||
loading: false
|
||||
});
|
||||
const changePermission = async (name: string, mode: number) => {
|
||||
permission.loading = true;
|
||||
permission.data = number2permission(mode);
|
||||
permission.loading = false;
|
||||
await openDialog(t("更改权限"), "", "", "permission");
|
||||
const { execute } = changePermissionApi();
|
||||
try {
|
||||
await execute({
|
||||
params: {
|
||||
remote_uuid: daemonId || "",
|
||||
uuid: instanceId || ""
|
||||
},
|
||||
data: {
|
||||
chmod: permission2number(
|
||||
permission.data.owner,
|
||||
permission.data.usergroup,
|
||||
permission.data.everyone
|
||||
),
|
||||
deep: permission.deep,
|
||||
target: breadcrumbs[breadcrumbs.length - 1].path + name
|
||||
}
|
||||
});
|
||||
|
||||
message.success(t("更改权限成功"));
|
||||
await getFileList();
|
||||
} catch (err: any) {
|
||||
return message.error(err.message);
|
||||
}
|
||||
permission.deep = false;
|
||||
};
|
||||
|
||||
return {
|
||||
fileStatus,
|
||||
indicator,
|
||||
@ -437,6 +491,7 @@ export const useFileManager = (
|
||||
percentComplete,
|
||||
spinning,
|
||||
rowSelection,
|
||||
permission,
|
||||
openDialog,
|
||||
getFileList,
|
||||
touchFile,
|
||||
@ -453,6 +508,7 @@ export const useFileManager = (
|
||||
downloadFile,
|
||||
handleChangeDir,
|
||||
handleTableChange,
|
||||
getFileStatus
|
||||
getFileStatus,
|
||||
changePermission
|
||||
};
|
||||
};
|
||||
|
@ -221,3 +221,22 @@ export const fileContent = useDefineApi<
|
||||
url: "/api/files",
|
||||
method: "PUT"
|
||||
});
|
||||
|
||||
// 修改权限
|
||||
export const changePermission = useDefineApi<
|
||||
{
|
||||
params: {
|
||||
remote_uuid: string;
|
||||
uuid: string;
|
||||
};
|
||||
data: {
|
||||
chmod: number;
|
||||
deep: boolean;
|
||||
target: string;
|
||||
};
|
||||
},
|
||||
boolean
|
||||
>({
|
||||
url: "/api/files/chmod",
|
||||
method: "PUT"
|
||||
});
|
||||
|
35
frontend/src/tools/permission.ts
Normal file
35
frontend/src/tools/permission.ts
Normal file
@ -0,0 +1,35 @@
|
||||
export const permission2number = (
|
||||
owner: string[],
|
||||
usergroup: string[],
|
||||
everyone: string[]
|
||||
): number => {
|
||||
const calculate = (arr: string[]): number => {
|
||||
return arr.reduce((acc, cur) => acc + parseInt(cur), 0);
|
||||
};
|
||||
return parseInt(`${calculate(owner)}${calculate(usergroup)}${calculate(everyone)}`);
|
||||
};
|
||||
|
||||
export const number2permission = (permission: number) => {
|
||||
const calculate = (num: number): string[] => {
|
||||
const arr: string[] = [];
|
||||
if (num - 4 >= 0) {
|
||||
arr.push("4");
|
||||
num -= 4;
|
||||
}
|
||||
if (num - 2 >= 0) {
|
||||
arr.push("2");
|
||||
num -= 2;
|
||||
}
|
||||
if (num - 1 >= 0) {
|
||||
arr.push("1");
|
||||
num -= 1;
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
const str = permission.toString().padStart(3, "0");
|
||||
return {
|
||||
owner: calculate(parseInt(str[0])),
|
||||
usergroup: calculate(parseInt(str[1])),
|
||||
everyone: calculate(parseInt(str[2]))
|
||||
};
|
||||
};
|
@ -26,3 +26,13 @@ export interface FileStatus {
|
||||
isGlobalInstance: boolean;
|
||||
dist: string[];
|
||||
}
|
||||
|
||||
export interface Permission {
|
||||
data: {
|
||||
owner: string[];
|
||||
usergroup: string[];
|
||||
everyone: string[];
|
||||
};
|
||||
deep: boolean;
|
||||
loading: boolean;
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ const {
|
||||
rowSelection,
|
||||
spinning,
|
||||
fileStatus,
|
||||
permission,
|
||||
getFileList,
|
||||
touchFile,
|
||||
reloadList,
|
||||
@ -131,7 +132,8 @@ const {
|
||||
handleChangeDir,
|
||||
rowClickTable,
|
||||
handleTableChange,
|
||||
getFileStatus
|
||||
getFileStatus,
|
||||
changePermission
|
||||
} = useFileManager(
|
||||
instanceId,
|
||||
daemonId,
|
||||
@ -331,7 +333,11 @@ onMounted(() => {
|
||||
<a-dropdown>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item v-if="fileStatus?.platform != 'win32'" key="1">
|
||||
<a-menu-item
|
||||
v-if="fileStatus?.platform != 'win32'"
|
||||
key="1"
|
||||
@click="changePermission(record.name, record.mode)"
|
||||
>
|
||||
{{ t("TXT_CODE_16853efe") }}
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
@ -434,6 +440,59 @@ onMounted(() => {
|
||||
<a-radio-button value="big5">big5</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-space>
|
||||
|
||||
<a-space v-if="dialog.mode == 'permission'" direction="vertical" class="w-100">
|
||||
<a-spin :spinning="permission.loading" :indicator="indicator" size="small">
|
||||
<div class="flex-around permission">
|
||||
<a-checkbox-group v-model:value="permission.data.owner">
|
||||
<a-row class="direction-column son">
|
||||
<h3 class="m-0">所有者</h3>
|
||||
<a-col class="m-5 options">
|
||||
<a-checkbox value="4">读取</a-checkbox>
|
||||
</a-col>
|
||||
<a-col class="m-5 options">
|
||||
<a-checkbox value="2">写入</a-checkbox>
|
||||
</a-col>
|
||||
<a-col class="m-5 options">
|
||||
<a-checkbox value="1">执行</a-checkbox>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-checkbox-group>
|
||||
|
||||
<a-checkbox-group v-model:value="permission.data.usergroup">
|
||||
<a-row class="direction-column son">
|
||||
<h3 class="m-0">用户组</h3>
|
||||
<a-col class="m-5 options">
|
||||
<a-checkbox value="4">读取</a-checkbox>
|
||||
</a-col>
|
||||
<a-col class="m-5 options">
|
||||
<a-checkbox value="2">写入</a-checkbox>
|
||||
</a-col>
|
||||
<a-col class="m-5 options">
|
||||
<a-checkbox value="1">执行</a-checkbox>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-checkbox-group>
|
||||
|
||||
<a-checkbox-group v-model:value="permission.data.everyone">
|
||||
<a-row class="direction-column son">
|
||||
<h3 class="m-0">任何人</h3>
|
||||
<a-col class="m-5 options">
|
||||
<a-checkbox value="4">读取</a-checkbox>
|
||||
</a-col>
|
||||
<a-col class="m-5 options">
|
||||
<a-checkbox value="2">写入</a-checkbox>
|
||||
</a-col>
|
||||
<a-col class="m-5 options">
|
||||
<a-checkbox value="1">执行</a-checkbox>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
|
||||
<a-checkbox v-model:checked="permission.deep">应用到子目录</a-checkbox>
|
||||
</a-spin>
|
||||
</a-space>
|
||||
</a-modal>
|
||||
|
||||
<FileEditor ref="FileEditorDialog" />
|
||||
@ -482,4 +541,22 @@ onMounted(() => {
|
||||
background-color: var(--color-gray-4);
|
||||
}
|
||||
}
|
||||
|
||||
.permission {
|
||||
.son {
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 10px;
|
||||
padding: 10px 20px;
|
||||
box-shadow: inset 0 0 0 1px #00000010;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 350px) {
|
||||
.permission {
|
||||
flex-direction: column;
|
||||
.son {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user