移动 & 提权.

This commit is contained in:
lijiahang
2024-02-20 11:43:18 +08:00
parent 585cf3c8a6
commit f7ca8f0bf1
7 changed files with 236 additions and 35 deletions

View File

@@ -104,6 +104,9 @@ export function downloadFile(res: any, fileName: string) {
* 10进制权限 转 字符串权限
*/
export function permission10toString(permission: number) {
if (permission === undefined) {
return '---';
}
const ps = (permission + '');
let res = '';
for (let i = 0; i < ps.length; i++) {
@@ -124,6 +127,11 @@ export function permission10toString(permission: number) {
res += 'x';
}
}
if (res.length <= 9) {
res = res.padEnd(9, '-');
} else {
res = res.substring(0, 9);
}
return res;
}

View File

@@ -1,5 +1,43 @@
<template>
<div></div>
<a-modal v-model:visible="visible"
body-class="modal-form"
title-align="start"
title="修改权限"
:align-center="false"
:mask-closable="false"
:unmount-on-close="true"
:on-before-ok="handlerOk">
<a-form :model="formModel"
ref="formRef"
label-align="right"
:style="{ width: '460px' }"
:label-col-props="{ span: 6 }"
:wrapper-col-props="{ span: 18 }">
<!-- 文件路径 -->
<a-form-item field="path"
disabled
label="文件路径">
<a-input v-model="formModel.path"
placeholder="原始路径" />
</a-form-item>
<!-- 文件权限 -->
<a-form-item field="mod"
label="文件权限"
:rules="[{ required: true, message: '请输入文件权限' }]">
<div class="mod-wrapper">
<!-- 权限输入框 -->
<a-input-number ref="modRef"
class="mod-input"
v-model="formModel.mod"
placeholder="请输入文件权限"
hide-button
@input="updatePreview" />
<!-- 权限预览 -->
<span class="mod-preview">{{ formModel.permission }}</span>
</div>
</a-form-item>
</a-form>
</a-modal>
</template>
<script lang="ts">
@@ -9,9 +47,79 @@
</script>
<script lang="ts" setup>
import useVisible from '@/hooks/visible';
import { nextTick, ref } from 'vue';
import { useTerminalStore } from '@/store';
import SftpSession from '../../handler/sftp-session';
import { permission10toString } from '@/utils/file';
const { visible, setVisible } = useVisible();
const { sessionManager } = useTerminalStore();
const sessionId = ref();
const modRef = ref();
const formRef = ref();
const formModel = ref({
path: '',
mod: 0,
permission: ''
});
// 修改预览
const updatePreview = (v: number) => {
formModel.value.permission = permission10toString(v);
};
// 打开新增
const open = (session: string, path: string, permission: number) => {
sessionId.value = session;
formModel.value.path = path;
formModel.value.mod = permission;
formModel.value.permission = permission10toString(permission);
setVisible(true);
// 自动聚焦
nextTick(() => {
modRef.value?.focus();
});
};
defineExpose({ open });
// 确定
const handlerOk = async () => {
try {
// 验证参数
const error = await formRef.value.validate();
if (error) {
return false;
}
// 获取会话
const session = sessionManager.getSession(sessionId.value);
if (session instanceof SftpSession) {
session.chmod(formModel.value.path, formModel.value.mod);
}
} catch (e) {
return false;
}
};
</script>
<style lang="less" scoped>
.mod-wrapper {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.mod-input {
width: 65%;
}
.mod-preview {
width: 30%;
display: flex;
justify-content: flex-end;
}
}
</style>

View File

@@ -6,12 +6,10 @@
:align-center="false"
:mask-closable="false"
:unmount-on-close="true"
:on-before-ok="handlerOk"
@close="handleClose">
:on-before-ok="handlerOk">
<a-form :model="formModel"
ref="formRef"
label-align="right"
layout="horizontal"
:style="{ width: '460px' }"
:label-col-props="{ span: 6 }"
:wrapper-col-props="{ span: 18 }">
@@ -35,13 +33,11 @@
<script lang="ts" setup>
import useVisible from '@/hooks/visible';
import useLoading from '@/hooks/loading';
import { nextTick, ref } from 'vue';
import { useTerminalStore } from '@/store';
import SftpSession from '../../handler/sftp-session';
const { visible, setVisible } = useVisible();
const { loading, setLoading } = useLoading();
const { sessionManager } = useTerminalStore();
const sessionId = ref();
@@ -68,7 +64,6 @@
// 确定
const handlerOk = async () => {
setLoading(true);
try {
// 验证参数
const error = await formRef.value.validate();
@@ -86,25 +81,11 @@
session.mkdir(formModel.value.path);
}
}
// 清空
handlerClear();
} catch (e) {
return false;
} finally {
setLoading(false);
}
};
// 关闭
const handleClose = () => {
handlerClear();
};
// 清空
const handlerClear = () => {
setLoading(false);
};
</script>
<style lang="less" scoped>

View File

@@ -1,5 +1,36 @@
<template>
<div></div>
<a-modal v-model:visible="visible"
body-class="modal-form"
title-align="start"
title="移动文件"
:align-center="false"
:mask-closable="false"
:unmount-on-close="true"
:on-before-ok="handlerOk">
<a-form :model="formModel"
ref="formRef"
label-align="right"
:style="{ width: '460px' }"
:label-col-props="{ span: 6 }"
:wrapper-col-props="{ span: 18 }">
<!-- 原始路径 -->
<a-form-item field="path"
disabled
label="原始路径">
<a-input v-model="formModel.path"
placeholder="原始路径" />
</a-form-item>
<!-- 目标路径 -->
<a-form-item field="target"
label="目标路径"
extra="目标路径可以是绝对路径/相对路径/名称 (可以包含 ./ ../)"
:rules="[{ required: true, message: '请输入目标路径' }]">
<a-input ref="targetRef"
v-model="formModel.target"
placeholder="请输入目标路径" />
</a-form-item>
</a-form>
</a-modal>
</template>
<script lang="ts">
@@ -9,6 +40,53 @@
</script>
<script lang="ts" setup>
import useVisible from '@/hooks/visible';
import { nextTick, ref } from 'vue';
import { useTerminalStore } from '@/store';
import SftpSession from '../../handler/sftp-session';
const { visible, setVisible } = useVisible();
const { sessionManager } = useTerminalStore();
const sessionId = ref();
const targetRef = ref();
const formRef = ref();
const formModel = ref({
path: '',
target: ''
});
// 打开新增
const open = (session: string, path: string) => {
sessionId.value = session;
formModel.value.path = path;
formModel.value.target = path;
setVisible(true);
// 自动聚焦
nextTick(() => {
targetRef.value?.focus();
});
};
defineExpose({ open });
// 确定
const handlerOk = async () => {
try {
// 验证参数
const error = await formRef.value.validate();
if (error) {
return false;
}
// 获取会话
const session = sessionManager.getSession(sessionId.value);
if (session instanceof SftpSession) {
session.move(formModel.value.path, formModel.value.target);
}
} catch (e) {
return false;
}
};
</script>

View File

@@ -125,7 +125,7 @@
arrow-class="terminal-tooltip-content"
content="提权">
<span class="click-icon-wrapper row-action-icon"
@click="chmodFile(record.path, record.attr)">
@click="chmodFile(record.path, record.permission)">
<icon-user-group />
</span>
</a-tooltip>
@@ -144,13 +144,13 @@
import type { TableData } from '@arco-design/web-vue/es/table/interface';
import type { SftpFile, ISftpSession } from '../../types/terminal.type';
import type { VNodeRef } from 'vue';
import { ref, computed, watch } from 'vue';
import { ref, computed, watch, inject } from 'vue';
import { useRowSelection } from '@/types/table';
import { dateFormat } from '@/utils';
import { setAutoFocus } from '@/utils/dom';
import useCopy from '@/hooks/copy';
import columns from './types/table.columns';
import { FILE_TYPE } from '../../types/terminal.const';
import { setAutoFocus } from '@/utils/dom';
import { FILE_TYPE, openSftpChmodModalKey, openSftpMoveModalKey } from '../../types/terminal.const';
const props = defineProps<{
session: ISftpSession | undefined;
@@ -161,6 +161,9 @@
const emits = defineEmits(['update:selectedFiles', 'loadFile']);
const openSftpMoveModal = inject(openSftpMoveModalKey) as (sessionId: string, path: string) => void;
const openSftpChmodModal = inject(openSftpChmodModalKey) as (sessionId: string, path: string, permission: number) => void;
const rowSelection = useRowSelection({ width: 40 });
const { copy } = useCopy();
@@ -211,6 +214,8 @@
if (FILE_TYPE.DIRECTORY.value === formatFileType(record.attr).value) {
// 进入文件夹
emits('loadFile', record.path);
} else {
copy(record.name, '名称已复制');
}
};
@@ -232,15 +237,12 @@
// 移动文件
const moveFile = (path: string) => {
// TODO openModal('path')
console.log(path);
openSftpMoveModal(props.session?.sessionId as string, path);
};
// 文件提权
const chmodFile = (path: string, attr: string) => {
// TODO openModal('path','mod')
console.log(path, attr);
const chmodFile = (path: string, permission: number) => {
openSftpChmodModal(props.session?.sessionId as string, path, permission);
};
// 格式化文件类型

View File

@@ -30,6 +30,10 @@
</a-split>
<!-- 创建文件模态框 -->
<sftp-create-modal ref="createModal" />
<!-- 移动文件模态框 -->
<sftp-move-modal ref="moveModal" />
<!-- 文件提权模态框 -->
<sftp-chmod-modal ref="chmodModal" />
</div>
</template>
@@ -45,10 +49,12 @@
import { useTerminalStore } from '@/store';
import { Message } from '@arco-design/web-vue';
import useLoading from '@/hooks/loading';
import { openSftpCreateModalKey } from '../../types/terminal.const';
import { openSftpCreateModalKey, openSftpMoveModalKey, openSftpChmodModalKey } from '../../types/terminal.const';
import SftpTable from './sftp-table.vue';
import SftpTableHeader from './sftp-table-header.vue';
import SftpCreateModal from './sftp-create-modal.vue';
import SftpMoveModal from './sftp-move-modal.vue';
import SftpChmodModal from './sftp-chmod-modal.vue';
const props = defineProps<{
tab: TerminalTabItem
@@ -58,18 +64,30 @@
const { loading: tableLoading, setLoading: setTableLoading } = useLoading(true);
const session = ref<ISftpSession>();
const createModal = ref();
const currentPath = ref<string>('');
const fileList = ref<Array<SftpFile>>([]);
const selectFiles = ref<Array<string>>([]);
const splitSize = ref(1);
const editView = ref(true);
const createModal = ref();
const moveModal = ref();
const chmodModal = ref();
// 暴露打开创建方法
// 暴露打开创建模态框
provide(openSftpCreateModalKey, (sessionId: string, path: string, isTouch: boolean) => {
createModal.value?.open(sessionId, path, isTouch);
});
// 暴露打开移动模态框
provide(openSftpMoveModalKey, (sessionId: string, path: string) => {
moveModal.value?.open(sessionId, path);
});
// 暴露打开提权模态框
provide(openSftpChmodModalKey, (sessionId: string, path: string, permission: number) => {
chmodModal.value?.open(sessionId, path, permission);
});
// 连接成功回调
const connectCallback = () => {
loadFiles(undefined);

View File

@@ -287,6 +287,12 @@ export const openSshSettingModalKey = Symbol();
// 打开 sftpCreateModal key
export const openSftpCreateModalKey = Symbol();
// 打开 sftpMoveModal key
export const openSftpMoveModalKey = Symbol();
// 打开 sftpChmodModal key
export const openSftpChmodModalKey = Symbol();
// 字体后缀 兜底
export const fontFamilySuffix = ',courier-new, courier, monospace';