Browse Source

feat: 文件管理页面

pull/18/head^2
zhengkunwang223 2 years ago
parent
commit
07af78758f
  1. 10462
      frontend/package-lock.json
  2. 4
      frontend/package.json
  3. 16
      frontend/src/api/interface/file.ts
  4. 26
      frontend/src/api/interface/files.json
  5. 7
      frontend/src/api/modules/files.ts
  6. 7
      frontend/src/components/svg-icon/svg-icon.vue
  7. 24
      frontend/src/lang/modules/zh.ts
  8. 2
      frontend/src/layout/layout-content.vue
  9. 5
      frontend/src/main.ts
  10. 14
      frontend/src/styles/element-dark.scss
  11. 2
      frontend/src/styles/element.scss
  12. 189
      frontend/src/views/file-management/index.vue
  13. 45
      frontend/vite.config.ts

10462
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

4
frontend/package.json

@ -25,9 +25,9 @@
"axios": "^0.27.2",
"echarts": "^5.3.0",
"echarts-liquidfill": "^3.1.0",
"element-plus": "^2.2.6",
"fit2cloud-ui-plus": "^0.0.1-beta.12",
"js-base64": "^3.7.2",
"element-plus": "^2.2.13",
"fit2cloud-ui-plus": "^0.0.1-beta.15",
"js-md5": "^0.7.3",
"nprogress": "^0.2.0",
"pinia": "^2.0.12",

16
frontend/src/api/interface/file.ts

@ -0,0 +1,16 @@
import { CommonModel } from '.';
export namespace File {
export interface File extends CommonModel {
name: string;
mode: number;
user: string;
group: string;
updateDate: string;
isDir: boolean;
isLink: boolean;
path: string;
size: number;
accessTime: string;
changeTime: string;
}
}

26
frontend/src/api/interface/files.json

@ -0,0 +1,26 @@
{
"code": 200,
"data": {
"items": [
{
"name": "var",
"isDir": true,
"mode": 775,
"user": "root",
"group": "root",
"size": 2048,
"updateTime": "2022-08-11T11:05:22.001+08:00"
},
{
"name": "test.txt",
"isDir": false,
"mode": 775,
"user": "root",
"group": "root",
"size": 4096,
"updateTime": "2022-08-11T11:05:22.001+08:00"
}
],
"total": 2
}
}

7
frontend/src/api/modules/files.ts

@ -0,0 +1,7 @@
// import { File } from '@/api/interface/file';
import files from '@/api/interface/files.json';
export const GetFilesList = () => {
// return http.post<Login.ResLogin>(`/auth/login`, params);
return files;
};

7
frontend/src/components/svg-icon/svg-icon.vue

@ -43,4 +43,11 @@ const svgClass = computed(() => {
padding-left: 0.3em;
padding-right: 0.3em;
}
.table-icon {
width: 1.5em;
height: 1.5em;
position: relative;
fill: currentColor;
vertical-align: middle;
}
</style>

24
frontend/src/lang/modules/zh.ts

@ -1,6 +1,7 @@
export default {
commons: {
button: {
create: '新建',
create: '创建',
add: '添加',
delete: '删除',
@ -151,4 +152,27 @@ export default {
request: '请求',
response: '响应',
},
file: {
dir: '文件夹',
upload: '上传',
download: '下载',
fileName: '文件名',
search: '查找',
mode: '权限',
owner: '所有者',
file: '文件',
remoteFile: '远程下载',
share: '分享',
sync: '数据同步',
size: '大小',
updateTime: '修改时间',
open: '打开',
rename: '重命名',
role: '权限',
info: '属性',
linkFile: '软连接文件',
terminal: '终端',
shareList: '分享列表',
zip: '压缩',
},
};

2
frontend/src/layout/layout-content.vue

@ -9,7 +9,7 @@
:header="header"
v-if="showBack"
></back-button>
{{ header }}
<span v-else> {{ header }}</span>
</slot>
</div>
<div class="content-container__toolbar" v-if="slots.toolbar">

5
frontend/src/main.ts

@ -7,10 +7,11 @@ import '@/assets/iconfont/iconfont.js';
import ElementPlus from 'element-plus';
import Fit2CloudPlus from 'fit2cloud-ui-plus';
import * as Icons from '@element-plus/icons-vue';
import 'element-plus/dist/index.css';
import 'element-plus/theme-chalk/dark/css-vars.css';
import '@/styles/element-dark.scss';
import '@/styles/element.scss';
import 'element-plus/dist/index.css';
import 'element-plus/theme-chalk/dark/css-vars.css';
import 'fit2cloud-ui-plus/src/styles/index.scss';
import directives from '@/directives/index';
import router from '@/routers/index';
import I18n from '@/lang/index';

14
frontend/src/styles/element-dark.scss

@ -140,6 +140,20 @@ html.dark {
}
}
.el-table {
--el-table-border-color: #696969;
//fit2cloud-ui 自定义
--el-table-text-color: #cfcfcf;
// $table-header-bgColor: #f5f6f7 !default;
.fu-table-header th {
border-top: 1px solid var(--el-table-border-color);
font-weight: 500 !important;
color: var(--el-text-color-regular) !important;
background-color: var(--el-bg-color) !important;
}
}
// el-drawer
.el-drawer {
.el-drawer__header {

2
frontend/src/styles/element.scss

@ -189,4 +189,4 @@
margin-right: 20px;
border: 0;
// box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
}
}

189
frontend/src/views/file-management/index.vue

@ -1,5 +1,190 @@
<template>
<LayoutContent></LayoutContent>
<LayoutContent :header="$t('menu.files')">
<el-row :gutter="20">
<el-col :span="6">
<el-tree :data="dataSource" show-checkbox node-key="id">
<template #default="{ node }">
<el-icon v-if="node.data.isDir && node.expanded"><FolderOpened /></el-icon>
<el-icon v-if="node.data.isDir && !node.expanded"><Folder /></el-icon>
<el-icon v-if="!node.data.isDir"><Document /></el-icon>
<span class="custom-tree-node">
<span>{{ node.data.label }}</span>
</span>
</template>
</el-tree>
</el-col>
<el-col :span="18">
<div class="path">
<el-breadcrumb class="child" :separator-icon="ArrowRight">
<el-breadcrumb-item>root</el-breadcrumb-item>
<el-breadcrumb-item>var</el-breadcrumb-item>
<el-breadcrumb-item>log</el-breadcrumb-item>
</el-breadcrumb>
</div>
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data">
<template #toolbar>
<el-dropdown split-button type="primary">
{{ $t('commons.button.create') }}
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>
<svg-icon iconName="p-file-folder"></svg-icon>{{ $t('file.dir') }}
</el-dropdown-item>
<el-dropdown-item>
<svg-icon iconName="p-file-normal"></svg-icon>{{ $t('file.file') }}
</el-dropdown-item>
<el-dropdown-item>
<svg-icon iconName="p-file-normal"></svg-icon>{{ $t('file.linkFile') }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button type="primary" plain> {{ $t('file.upload') }}</el-button>
<el-button type="primary" plain> {{ $t('file.search') }}</el-button>
<el-button type="primary" plain> {{ $t('file.remoteFile') }}</el-button>
<el-button type="primary" plain> {{ $t('file.sync') }}</el-button>
<el-button type="primary" plain> {{ $t('file.terminal') }}</el-button>
<el-button type="primary" plain> {{ $t('file.shareList') }}</el-button>
</template>
<el-table-column :label="$t('commons.table.name')" min-width="120" fix>
<template #default="{ row }">
<svg-icon v-if="row.isDir" className="table-icon" iconName="p-file-folder"></svg-icon>
<svg-icon v-else className="table-icon" iconName="p-file-normal"></svg-icon>
<el-link :underline="false">{{ row.name }}</el-link>
</template>
</el-table-column>
<el-table-column :label="$t('file.mode')" prop="mode"> </el-table-column>
<el-table-column :label="$t('file.owner')" prop="user"> </el-table-column>
<el-table-column :label="$t('file.size')" prop="size"> </el-table-column>
<el-table-column :label="$t('file.updateTime')" prop="updateTime" :formatter="dateFromat">
</el-table-column>
<fu-table-operations
min-width="300"
:ellipsis="4"
:buttons="buttons"
:label="$t('commons.table.operate')"
fixed="right"
fix
/>
</ComplexTable>
</el-col>
</el-row>
</LayoutContent>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import { onMounted, reactive, ref } from '@vue/runtime-core';
import LayoutContent from '@/layout/layout-content.vue';
import ComplexTable from '@/components/complex-table/index.vue';
import i18n from '@/lang';
import { GetFilesList } from '@/api/modules/files';
import { dateFromat } from '@/utils/util';
import { ArrowRight } from '@element-plus/icons-vue';
interface Tree {
id: number;
label: string;
isDir: Boolean;
children?: Tree[];
}
let data = ref();
let selects = ref<any>([]);
const paginationConfig = reactive({
page: 1,
pageSize: 5,
total: 0,
});
const buttons = [
{
label: i18n.global.t('file.open'),
},
{
label: i18n.global.t('file.mode'),
},
{
label: i18n.global.t('file.zip'),
},
{
label: i18n.global.t('file.rename'),
},
{
label: i18n.global.t('commons.button.delete'),
},
{
label: i18n.global.t('file.info'),
},
];
const search = async () => {
const res = await GetFilesList();
data.value = res.data.items;
paginationConfig.total = res.data.total;
};
const dataSource = ref<Tree[]>([
{
id: 1,
label: 'var',
isDir: true,
children: [
{
id: 4,
label: 'log',
isDir: true,
children: [
{
id: 9,
isDir: false,
label: 'ko.log',
},
{
id: 10,
isDir: false,
label: 'kubepi.log',
},
],
},
],
},
{
id: 2,
label: 'opt',
isDir: true,
children: [
{
id: 5,
isDir: false,
label: 'app.conf',
},
{
id: 6,
isDir: false,
label: 'test.txt',
},
],
},
]);
onMounted(() => {
search();
});
</script>
<style>
.path {
margin-top: -50px;
height: 30px;
width: 800px;
background-color: #f1f1f1;
margin-bottom: 5px;
border: 1px solid #e8e8e8;
}
.child {
position: relative;
top: 50%;
transform: translateY(-50%);
width: 80%;
}
</style>

45
frontend/vite.config.ts

@ -8,10 +8,7 @@ import viteCompression from 'vite-plugin-compression';
import VueSetupExtend from 'vite-plugin-vue-setup-extend';
import eslintPlugin from 'vite-plugin-eslint';
import vueJsx from '@vitejs/plugin-vue-jsx';
import importToCDN from 'vite-plugin-cdn-import';
// import AutoImport from "unplugin-auto-import/vite";
// import Components from "unplugin-vue-components/vite";
// import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import DefineOptions from 'unplugin-vue-define-options/vite';
// @see: https://vitejs.dev/config/
@ -59,37 +56,14 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
}),
DefineOptions(),
// * EsLint 报错信息显示在浏览器界面上
eslintPlugin(),
eslintPlugin({
exclude: ['**/*.js'],
}),
// * vite 可以使用 jsx/tsx 语法
vueJsx(),
// * name 可以写在 script 标签上
VueSetupExtend(),
// * demand import element(如果使用了cdn引入,没必要使用element自动导入了)
// AutoImport({
// resolvers: [ElementPlusResolver()]
// }),
// Components({
// resolvers: [ElementPlusResolver()]
// }),
// * cdn 引入(vue、element-plus)
importToCDN({
modules: [
// vue按需引入会导致依赖vue的插件出现问题(列如:pinia/vuex)
// {
// name: "vue",
// var: "Vue",
// path: "https://unpkg.com/vue@next"
// },
// 使用cdn引入element-plus时,开发环境还是需要在main.js中引入element-plus,可以不用引入css
// {
// name: "element-plus",
// var: "ElementPlus",
// path: "https://unpkg.com/element-plus",
// css: "https://unpkg.com/element-plus/dist/index.css"
// }
],
}),
// * 是否生成包预览
viteEnv.VITE_REPORT && visualizer(),
// * gzip compress
viteEnv.VITE_BUILD_GZIP &&
@ -104,18 +78,9 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
esbuild: {
pure: viteEnv.VITE_DROP_CONSOLE ? ['console.log', 'debugger'] : [],
},
// build configure
build: {
outDir: 'dist',
// esbuild 打包更快,但是不能去除 console.log
minify: 'esbuild',
// minify: "terser",
// terserOptions: {
// compress: {
// drop_console: viteEnv.VITE_DROP_CONSOLE,
// drop_debugger: true
// }
// },
rollupOptions: {
output: {
// Static resource classification and packaging

Loading…
Cancel
Save