This commit is contained in:
MoYi 2023-11-18 19:59:12 +08:00
parent f08bf44c8e
commit 653ce5a677
10 changed files with 1433 additions and 1087 deletions

20
.eslintrc.json Normal file
View File

@ -0,0 +1,20 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-essential"
],
"parserOptions": {
"ecmaVersion": "latest",
"parser": "@typescript-eslint/parser"
},
"plugins": [
"@typescript-eslint",
"vue"
],
"rules": {}
}

3
.gitignore vendored
View File

@ -14,7 +14,6 @@ dist-ssr
# Editor directories and files
.vscode/*
.vscode
!.vscode/extensions.json
.idea
.DS_Store
@ -23,5 +22,3 @@ dist-ssr
*.njsproj
*.sln
*.sw?
keys/

3
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
</head>
<body style="margin: 0">
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>

2088
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{
"name": "fileshareui",
"name": "file",
"private": true,
"version": "0.0.0",
"type": "module",
@ -9,18 +9,16 @@
"preview": "vite preview"
},
"dependencies": {
"element-plus": "^2.4.2",
"fs": "^0.0.1-security",
"vant": "^4.7.3",
"vue": "^3.3.4"
},
"devDependencies": {
"@types/node": "^20.9.1",
"@vant/auto-import-resolver": "^1.0.2",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"@vitejs/plugin-vue": "^4.2.3",
"eslint": "^8.54.0",
"eslint-plugin-vue": "^9.18.1",
"typescript": "^5.0.2",
"unplugin-vue-components": "^0.25.2",
"vite": "^5.0.0",
"vite": "^4.4.5",
"vue-tsc": "^1.8.5"
}
}

View File

@ -1,267 +1,13 @@
<template>
<div class="Home">
<!-- 主页顶部部分 -->
<el-row class="HomeHead">
<el-col :span="24">
<div>
<!-- 搜索输入框 -->
<el-input class="InputText" v-model="searchInput" placeholder="请输入你要搜索的文件名称">
<!-- 搜索按钮 -->
<template #append>
<el-button @click="handleSearch">搜索</el-button>
</template>
</el-input>
</div>
<div class="HomeHeadAvatar">
<!-- 用户头像 -->
<el-avatar class="Avatar" shape="square" :size="35" @click="showPopup">头像</el-avatar>
<!-- 用户登录弹出框 -->
<van-popup v-model:show='show' round position="top" :style="{ height: '30%' }">
<div class="HomeHeadUserLogin">
<h4>账号:</h4>
<!-- 用户名输入框 -->
<el-input v-model="username" placeholder="请输入账号"/>
<h4>密码:</h4>
<!-- 密码输入框 -->
<el-input v-model="userPassword" show-password placeholder="请输入密码"/>
<!-- 登录按钮 -->
<el-button @click="userLogin" type="primary" class="UserLoginButton">登录</el-button>
</div>
</van-popup>
</div>
</el-col>
</el-row>
<!-- 主页左右布局 -->
<el-row>
<el-col :span="leftColumnSpan" class="Left">
<!-- 文件列表表格 -->
<el-table :data="pagedTableData" style="width: 100%" :empty-text="'暂无数据'">
<el-table-column prop="id" label="ID" width="50"/>
<el-table-column prop="fileName" label="文件名" width="150"/>
<el-table-column prop="format" label="文件格式" width="100"/>
<el-table-column prop="fileSize" label="文件大小" width="100"/>
<el-table-column prop="uploader" label="上传者" width="100"/>
<el-table-column fixed="right" label="操作" width="100">
<template #default="scope">
<!-- 下载按钮 -->
<el-button link type="primary" size="small" @click="handleDownload(scope.row)">下载</el-button>
<!-- 详细信息按钮 -->
<el-button link type="info" size="small" @click="handleAbout(scope.row)">详细</el-button>
<!-- 删除按钮 (管理员权限 TODO) -->
<!-- <el-button link type="danger" size="small" @click="handleDelete(scope.row)" >删除</el-button> -->
</template>
</el-table-column>
</el-table>
<van-popup v-model:show="showAbout" round position="bottom" :style="{ height: '30%' }">
<div class="BoxFileAbout">
<h4>文件名: {{ selectedRow ? selectedRow.fileName : '' }}</h4>
<h4>文件格式: {{ selectedRow ? selectedRow.format : '' }}</h4>
<h4>文件大小: {{ selectedRow ? selectedRow.fileSize : '' }}</h4>
<h4>上传者: {{ selectedRow ? selectedRow.uploader : '' }}</h4>
</div>
</van-popup>
<!-- 分页 -->
<div class="LeftAndRightContainer">
<el-pagination
:page-size="pageSize"
:pager-count="pagerCount"
layout="prev, pager, next"
:total="totalItems"
@current-change="handlePageChange"
/>
</div>
</el-col>
<el-col :span="rightColumnSpan" class="Right">
Right
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import {ref, onMounted, watch, computed} from 'vue'; // Vue 3
import {useWindowSize} from '@vueuse/core'; //
//
const leftColumnSpan = ref(18); // 18
//
const rightColumnSpan = ref(6); // 6
const {width} = useWindowSize(); // 使useWindowSize()
const searchInput = ref(''); //
//
const originalTableData: TableRow[] = []; //
const randomDataRowCount = 1000; //
for (let i = 1; i < randomDataRowCount; i++) {
originalTableData.push({
id: i,
fileName: "测试文件" + i,
format: 'ttf',
fileSize: (Math.random() * 1023).toFixed(0) + "kb",
uploader: "MoYiJiangNan",
md5: (Math.random() * 1000) + "md5test",
uploadTime: "2023年" + Math.floor(Math.random() * 12) + "月" + Math.floor(Math.random() * 30) + "日" + Math.floor(Math.random() * 24) + "时" + Math.floor(Math.random() * 60) + "分" + Math.floor(Math.random() * 60) + "秒"
});
}
//
const tableData = ref(originalTableData); //
//
const pageSize = ref(15); //
const pagerCount = ref(7); //
const totalItems = ref(tableData.value.length); //
const currentPage = ref(1); //
//
const pagedTableData = computed(() => {
const startIndex = (currentPage.value - 1) * pageSize.value; //
const endIndex = startIndex + pageSize.value; //
return tableData.value.slice(startIndex, endIndex); //
});
const username = ref(); //
const userPassword = ref(); //
//
const handlePageChange = (page: number) => {
currentPage.value = page; //
};
//
const handleSearch = () => {
const query = searchInput.value.trim().toLowerCase(); //
if (!query) {
//
tableData.value = originalTableData;
} else {
//
tableData.value = originalTableData.filter((item) => {
return item.fileName.toLowerCase().includes(query);
});
}
currentPage.value = 1; //
totalItems.value = tableData.value.length; //
};
//
const updateLeftColumnSpan = () => {
if (width.value <= 768) {
leftColumnSpan.value = 24; // 768px
rightColumnSpan.value = 0; //
} else {
leftColumnSpan.value = 18; // 768px18
rightColumnSpan.value = 6; // 6
}
};
onMounted(updateLeftColumnSpan); // updateLeftColumnSpan
watch(width, updateLeftColumnSpan); // updateLeftColumnSpan
// row
interface TableRow {
id: number;
fileName: string;
format: string;
fileSize: string;
uploader: string;
md5: string;
uploadTime: string;
}
//
const handleDownload = (row: TableRow) => {
console.log('点击下载按钮', row);
alert('下载功能暂未实现' + row.id);
};
//
const showAbout = ref<boolean>(false);
const selectedRow = ref<TableRow | null>(null); // //
const handleAbout = (row: TableRow) => {
console.log('点击详细信息按钮', row);
selectedRow.value = row; // selectedRow
showAbout.value = true;
};
const userLogin = () => {
console.log(username.value, userPassword.value);
};
const show = ref(false); //
const showPopup = () => {
show.value = true; //
};
</script>
<style scoped>
/* 样式作用范围被限制在当前组件内 */
/* 主页顶部部分样式 */
.HomeHead {
width: calc(100% - 20px); /* 宽度为屏幕宽度减去20像素 */
height: 5ch; /* 高度为5字符高度 */
margin: 10px 10px 10px 10px; /* 外边距上右下左均为10像素 */
display: flex; /* 使用Flex布局 */
justify-content: center; /* 水平居中对齐 */
align-items: center; /* 垂直居中对齐 */
text-align: center; /* 文本水平居中对齐 */
}
/* 左右容器样式 */
.LeftAndRightContainer {
display: flex; /* 使用Flex布局 */
flex-direction: column; /* 垂直方向排列子元素 */
justify-content: center; /* 水平居中对齐 */
align-items: center; /* 垂直居中对齐 */
text-align: center; /* 文本水平居中对齐 */
}
/* 左侧栏样式 */
.Left {
flex: 0 0 calc(75% - 5px); /* 占用75%的宽度不可伸缩减去5像素的间隔 */
margin: 0 10px 0 0; /* 外边距上右下左分别为0 10px 0 0 */
}
/* 右侧栏样式 */
.Right {
flex: 0 0 calc(25% - 5px); /* 占用25%的宽度不可伸缩减去5像素的间隔 */
background-color: green; /* 背景颜色为绿色 */
}
/* 媒体查询,用于移动屏幕 */
@media (max-width: 768px) {
.Right {
display: none; /* 隐藏右侧栏 */
}
.Left {
flex: 0 0 100%; /* 左侧栏占满整个宽度 */
margin: 0; /* 调整外边距 */
}
/* 您可以在这里为移动屏幕添加更多样式调整 */
}
/* 用户头像样式 */
.Avatar {
float: right; /* 右浮动 */
margin: 0 5px 0 0; /* 外边距上右下左分别为0 5px 0 0 */
}
/* 搜索输入框样式 */
.InputText {
float: left; /* 左浮动 */
margin: 0 0 0 5px; /* 外边距上右下左分别为0 0 0 5px */
width: 80%; /* 宽度占80% */
}
/* 用户登录框样式 */
.HomeHeadUserLogin {
margin: 10px 30px 0 30px; /* 外边距上右下左分别为10px 30px 0 30px */
text-align: left; /* 文本左对齐 */
}
/* 用户登录按钮样式 */
.UserLoginButton {
width: 80%; /* 宽度占80% */
margin: 20px; /* 外边距上下均为20px */
}
.BoxFileAbout {
margin: 30px;
}
</style>

View File

@ -1,11 +1,5 @@
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import 'vant/lib/index.css';
import './style.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
createApp(App).mount('#app')

View File

@ -1,13 +1,80 @@
.el-table .cell {
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
word-break: break-all;
/* 行高 */
line-height: 30px;
padding: 0 0;
/* 字体大小 */
font-size: 15px;
margin-left: 15px;
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

View File

@ -1,18 +1,7 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import {readFileSync} from "fs"
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from '@vant/auto-import-resolver';
// https://vitejs.dev/config/
export default defineConfig({
server: {
host: "0.0.0.0",
port: 5173,
https: {
key: readFileSync("./keys/agent2-key.pem"),
cert: readFileSync("./keys/agent2-cert.pem"),
},
},
plugins: [vue(), Components({resolvers: [VantResolver()]})],
plugins: [vue()],
})