增加定时清理回收站文件
This commit is contained in:
9
web-vue/package-lock.json
generated
9
web-vue/package-lock.json
generated
@@ -886,7 +886,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz",
|
||||
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
@@ -1422,15 +1421,13 @@
|
||||
"version": "4.17.23",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.23",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz",
|
||||
"integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash-unified": {
|
||||
"version": "1.0.3",
|
||||
@@ -1637,7 +1634,6 @@
|
||||
"integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
"postcss": "^8.4.43",
|
||||
@@ -1697,7 +1693,6 @@
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.31.tgz",
|
||||
"integrity": "sha512-iV/sU9SzOlmA/0tygSmjkEN6Jbs3nPoIPFhCMLD2STrjgOU8DX7ZtzMhg4ahVwf5Rp9KoFzcXeB1ZrVbLBp5/Q==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.31",
|
||||
"@vue/compiler-sfc": "3.5.31",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
const request = axios.create({
|
||||
baseURL: '/api',
|
||||
timeout: 300000
|
||||
timeout: 0 // 不限制超时,大文件上传需要
|
||||
})
|
||||
|
||||
request.interceptors.request.use(
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import request from './request'
|
||||
|
||||
export const getUsers = () => request.get('/users')
|
||||
|
||||
export const getSystemConfig = () => request.get('/users/config')
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<div class="file-list-footer">
|
||||
<span>共 {{ fileList.length }} 个文件,总大小:{{ formatSize(totalSize) }}</span>
|
||||
<span v-if="isOverLimit" class="warning-text">(超出剩余空间)</span>
|
||||
<span v-if="isOverSizeLimit" class="warning-text">(单次上传不能超过500MB)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -52,7 +53,7 @@
|
||||
<el-icon><Close /></el-icon>
|
||||
<span style="margin-left: 4px">取消</span>
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleUpload" :loading="uploading" :disabled="isOverLimit">
|
||||
<el-button type="primary" @click="handleUpload" :loading="uploading" :disabled="isOverLimit || isOverSizeLimit">
|
||||
<el-icon><Upload /></el-icon>
|
||||
<span style="margin-left: 4px">开始上传</span>
|
||||
</el-button>
|
||||
@@ -90,6 +91,12 @@ const isOverLimit = computed(() => {
|
||||
return totalSize.value > props.remainingStorage
|
||||
})
|
||||
|
||||
// 是否超过500MB限制
|
||||
const MAX_UPLOAD_SIZE = 500 * 1024 * 1024 // 500MB
|
||||
const isOverSizeLimit = computed(() => {
|
||||
return totalSize.value > MAX_UPLOAD_SIZE
|
||||
})
|
||||
|
||||
const handleChange = (file, list) => {
|
||||
if (list.length > 10) {
|
||||
ElMessage.warning('最多一次上传10个文件')
|
||||
@@ -124,6 +131,11 @@ const handleUpload = () => {
|
||||
return
|
||||
}
|
||||
|
||||
if (isOverSizeLimit.value) {
|
||||
ElMessage.warning('单次上传总大小不能超过500MB')
|
||||
return
|
||||
}
|
||||
|
||||
emit('upload', fileList.value.map(f => f.raw))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { getSystemConfig } from '@/api/user'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const token = ref(localStorage.getItem('token') || '')
|
||||
@@ -11,7 +12,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
const phone = ref(localStorage.getItem('phone') || '')
|
||||
const email = ref(localStorage.getItem('email') || '')
|
||||
const storageUsed = ref(Number(localStorage.getItem('storageUsed')) || 0)
|
||||
const storageLimit = ref(Number(localStorage.getItem('storageLimit')) || 20 * 1024 * 1024 * 1024)
|
||||
const storageLimit = ref(Number(localStorage.getItem('storageLimit')) || 0)
|
||||
|
||||
const isLoggedIn = computed(() => !!token.value)
|
||||
|
||||
@@ -54,11 +55,23 @@ export const useUserStore = defineStore('user', () => {
|
||||
localStorage.setItem('storageUsed', storageUsed.value)
|
||||
}
|
||||
if (user.storageLimit !== undefined) {
|
||||
storageLimit.value = Number(user.storageLimit) || 20 * 1024 * 1024 * 1024
|
||||
storageLimit.value = Number(user.storageLimit) || 0
|
||||
localStorage.setItem('storageLimit', storageLimit.value)
|
||||
}
|
||||
}
|
||||
|
||||
const fetchStorageLimit = async () => {
|
||||
try {
|
||||
const res = await getSystemConfig()
|
||||
if (res.data?.storageLimitBytes) {
|
||||
storageLimit.value = res.data.storageLimitBytes
|
||||
localStorage.setItem('storageLimit', storageLimit.value)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取存储配额失败', e)
|
||||
}
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
token.value = ''
|
||||
username.value = ''
|
||||
@@ -69,7 +82,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
phone.value = ''
|
||||
email.value = ''
|
||||
storageUsed.value = 0
|
||||
storageLimit.value = 20 * 1024 * 1024 * 1024
|
||||
storageLimit.value = 0
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('username')
|
||||
localStorage.removeItem('userId')
|
||||
@@ -82,5 +95,5 @@ export const useUserStore = defineStore('user', () => {
|
||||
localStorage.removeItem('storageLimit')
|
||||
}
|
||||
|
||||
return { token, username, userId, nickname, signature, avatar, phone, email, storageUsed, storageLimit, isLoggedIn, setToken, setUser, logout }
|
||||
return { token, username, userId, nickname, signature, avatar, phone, email, storageUsed, storageLimit, isLoggedIn, setToken, setUser, fetchStorageLimit, logout }
|
||||
})
|
||||
|
||||
@@ -225,7 +225,7 @@ const movableFolders = ref([])
|
||||
|
||||
// 存储 —— 真实数据
|
||||
const storagePercent = computed(() => {
|
||||
const limit = userStore.storageLimit || 20 * 1024 * 1024 * 1024
|
||||
const limit = userStore.storageLimit || 0
|
||||
const used = userStore.storageUsed || 0
|
||||
if (limit <= 0) return 0
|
||||
return Math.min(Math.round((used / limit) * 100), 100)
|
||||
@@ -237,13 +237,14 @@ const usedStorage = computed(() => {
|
||||
: (used / (1024 * 1024)).toFixed(2) + ' MB'
|
||||
})
|
||||
const totalStorage = computed(() => {
|
||||
const limit = userStore.storageLimit || 20 * 1024 * 1024 * 1024
|
||||
const limit = userStore.storageLimit || 0
|
||||
if (limit <= 0) return '—'
|
||||
return (limit / (1024 * 1024 * 1024)).toFixed(0) + ' GB'
|
||||
})
|
||||
|
||||
// 剩余存储空间(字节)
|
||||
const remainingStorage = computed(() => {
|
||||
const limit = userStore.storageLimit || 20 * 1024 * 1024 * 1024
|
||||
const limit = userStore.storageLimit || 0
|
||||
const used = userStore.storageUsed || 0
|
||||
return Math.max(0, limit - used)
|
||||
})
|
||||
@@ -251,12 +252,14 @@ const remainingStorage = computed(() => {
|
||||
// 刷新存储数据(从后端精确重算)
|
||||
const refreshStorage = async () => {
|
||||
try {
|
||||
// 先获取系统配置(存储配额)
|
||||
await userStore.fetchStorageLimit()
|
||||
// 再获取用户当前用量
|
||||
const res = await getCurrentUser()
|
||||
const data = res.data
|
||||
if (data) {
|
||||
userStore.setUser({
|
||||
storageUsed: data.storageUsed ?? 0,
|
||||
storageLimit: data.storageLimit ?? 20 * 1024 * 1024 * 1024
|
||||
storageUsed: data.storageUsed ?? 0
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class="feature-list">
|
||||
<div class="feature-item">
|
||||
<el-icon><Check /></el-icon>
|
||||
<span>20GB 超大存储空间</span>
|
||||
<span>{{ storageLimitText }} 存储空间</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<el-icon><Check /></el-icon>
|
||||
@@ -58,17 +58,40 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { FolderOpened, Check } from '@element-plus/icons-vue'
|
||||
import LoginForm from './LoginForm.vue'
|
||||
import RegisterForm from './RegisterForm.vue'
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { getSystemConfig } from '@/api/user'
|
||||
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const isLogin = ref(true)
|
||||
const storageLimitGb = ref(50)
|
||||
|
||||
const storageLimitText = computed(() => {
|
||||
return storageLimitGb.value >= 1024
|
||||
? (storageLimitGb.value / 1024).toFixed(1) + 'TB'
|
||||
: storageLimitGb.value + 'GB'
|
||||
})
|
||||
|
||||
const fetchConfig = async () => {
|
||||
try {
|
||||
const res = await getSystemConfig()
|
||||
if (res.data?.storageLimitGb) {
|
||||
storageLimitGb.value = res.data.storageLimitGb
|
||||
}
|
||||
} catch (e) {
|
||||
// 使用默认值
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchConfig()
|
||||
})
|
||||
|
||||
const toggleMode = () => {
|
||||
isLogin.value = !isLogin.value
|
||||
|
||||
Reference in New Issue
Block a user