feat: 新增后台选择过期方式

This commit is contained in:
lan
2024-06-15 20:04:48 +08:00
parent 85054fcba3
commit 76038dba68
8 changed files with 45 additions and 39 deletions
+3 -3
View File
@@ -8,7 +8,7 @@ from fastapi import APIRouter, Depends
from apps.admin.depends import admin_required from apps.admin.depends import admin_required
from apps.admin.pydantics import IDData from apps.admin.pydantics import IDData
from apps.base.models import FileCodes from apps.base.models import FileCodes, KeyValue
from core.response import APIResponse from core.response import APIResponse
from core.settings import settings from core.settings import settings
from core.storage import file_storage from core.storage import file_storage
@@ -44,7 +44,7 @@ async def file_list(page: float = 1, size: int = 10):
@admin_api.get('/config/get', dependencies=[Depends(admin_required)]) @admin_api.get('/config/get', dependencies=[Depends(admin_required)])
async def get_config(): async def get_config():
return APIResponse(detail=settings.__dict__) return APIResponse(detail=settings.items())
@admin_api.patch('/config/update', dependencies=[Depends(admin_required)]) @admin_api.patch('/config/update', dependencies=[Depends(admin_required)])
@@ -52,7 +52,7 @@ async def update_config(data: dict):
admin_token = data.get('admin_token') admin_token = data.get('admin_token')
if admin_token is None or admin_token == '': if admin_token is None or admin_token == '':
return APIResponse(code=400, detail='管理员密码不能为空') return APIResponse(code=400, detail='管理员密码不能为空')
await KeyValue.filter(key='settings').update(value=data)
for k, v in data.items(): for k, v in data.items():
settings.__setattr__(k, v) settings.__setattr__(k, v)
return APIResponse() return APIResponse()
+7 -1
View File
@@ -24,7 +24,6 @@ class FileCodes(Model):
expired_at: Optional[datetime] = fields.DatetimeField(null=True, description='过期时间') expired_at: Optional[datetime] = fields.DatetimeField(null=True, description='过期时间')
expired_count: Optional[int] = fields.IntField(description='可用次数', default=0) expired_count: Optional[int] = fields.IntField(description='可用次数', default=0)
used_count: Optional[int] = fields.IntField(description='已用次数', default=0) used_count: Optional[int] = fields.IntField(description='已用次数', default=0)
created_at: Optional[datetime] = fields.DatetimeField(auto_now_add=True, description='创建时间') created_at: Optional[datetime] = fields.DatetimeField(auto_now_add=True, description='创建时间')
async def is_expired(self): async def is_expired(self):
@@ -41,4 +40,11 @@ class FileCodes(Model):
return f"{self.file_path}/{self.uuid_file_name}" return f"{self.file_path}/{self.uuid_file_name}"
class KeyValue(Model):
id: Optional[int] = fields.IntField(pk=True)
key: Optional[str] = fields.CharField(max_length=255, description='', index=True, unique=True)
value: Optional[str] = fields.JSONField(description='', null=True)
created_at: Optional[datetime] = fields.DatetimeField(auto_now_add=True, description='创建时间')
file_codes_pydantic = pydantic_model_creator(FileCodes, name='FileCodes') file_codes_pydantic = pydantic_model_creator(FileCodes, name='FileCodes')
+1
View File
@@ -288,4 +288,5 @@ storages = {
'onedrive': OneDriveFileStorage, 'onedrive': OneDriveFileStorage,
'opendal': OpenDALFileStorage, 'opendal': OpenDALFileStorage,
} }
file_storage: FileStorageInterface = storages[settings.file_storage]() file_storage: FileStorageInterface = storages[settings.file_storage]()
+1 -1
View File
@@ -4,7 +4,7 @@ const language = (
navigator.language || 'zh_cn' navigator.language || 'zh_cn'
).toLowerCase(); ).toLowerCase();
const lang = (localStorage.getItem('language') || language).replace(/-/, '_'); const lang = (localStorage.getItem('language') || language).replace(/-/, '_');
console.log(lang)
const i18n = createI18n({ const i18n = createI18n({
silentTranslationWarn: true, silentTranslationWarn: true,
globalInjection: true, globalInjection: true,
+1
View File
@@ -56,6 +56,7 @@ export default {
background: '背景图片', background: '背景图片',
admin_token: '管理密码', admin_token: '管理密码',
uploadSize: '文件大小', uploadSize: '文件大小',
expireStyle: '过期方式',
uploadSizeNote: '最大文件大小,单位:Bytes),1mb=1 * 1024 * 1024', uploadSizeNote: '最大文件大小,单位:Bytes),1mb=1 * 1024 * 1024',
openUpload: { openUpload: {
title: '开启上传', title: '开启上传',
+17 -3
View File
@@ -23,15 +23,28 @@
<template #append>Bytes</template> <template #append>Bytes</template>
<small>{{ t('admin.settings.uploadSizeNote') }}</small> <small>{{ t('admin.settings.uploadSizeNote') }}</small>
</el-form-item> </el-form-item>
<el-form-item size="large" :label="t('admin.settings.expireStyle')" >
<el-select
v-model="config.expireStyle"
multiple
style="width: 100%"
>
<el-option :label="t('send.expireData.day')" value="day" />
<el-option :label="t('send.expireData.hour')" value="hour" />
<el-option :label="t('send.expireData.minute')" value="minute" />
<el-option :label="t('send.expireData.forever')" value="forever" />
<el-option :label="t('send.expireData.count')" value="count" />
</el-select>
</el-form-item>
<el-form-item size="large" :label="t('admin.settings.openUpload.title')"> <el-form-item size="large" :label="t('admin.settings.openUpload.title')">
<el-select v-model="config.openUpload"> <el-select v-model="config.openUpload" style="width: 80%">
<el-option :label="t('admin.settings.openUpload.open')" :value="1" /> <el-option :label="t('admin.settings.openUpload.open')" :value="1" />
<el-option :label="t('admin.settings.openUpload.close')" :value="0" /> <el-option :label="t('admin.settings.openUpload.close')" :value="0" />
</el-select> </el-select>
<small style="margin-left: 0.4rem">{{ t('admin.settings.openUpload.note') }}</small> <small style="margin-left: 0.4rem">{{ t('admin.settings.openUpload.note') }}</small>
</el-form-item> </el-form-item>
<el-form-item size="large" :label="t('admin.settings.file_storage.title')"> <el-form-item size="large" :label="t('admin.settings.file_storage.title')">
<el-select v-model="config.file_storage"> <el-select v-model="config.file_storage" style="width: 80%">
<el-option :label="t('admin.settings.file_storage.local')" value="local" /> <el-option :label="t('admin.settings.file_storage.local')" value="local" />
<el-option :label="t('admin.settings.file_storage.s3')" value="s3" /> <el-option :label="t('admin.settings.file_storage.s3')" value="s3" />
</el-select> </el-select>
@@ -105,6 +118,7 @@ const config = ref({
name: '', name: '',
description: '', description: '',
file_storage: '', file_storage: '',
expireStyle: [],
admin_token: '', admin_token: '',
keywords: '', keywords: '',
openUpload: 1, openUpload: 1,
@@ -112,7 +126,7 @@ const config = ref({
uploadMinute: 1, uploadMinute: 1,
s3_access_key_id: '', s3_access_key_id: '',
background: '', background: '',
page_explain:'', page_explain: '',
s3_secret_access_key: '', s3_secret_access_key: '',
aws_session_token: '', aws_session_token: '',
s3_signature_version: '', s3_signature_version: '',
+8 -6
View File
@@ -3,8 +3,10 @@ import { ref } from 'vue'
import CardTools from "@/components/CardTools.vue"; import CardTools from "@/components/CardTools.vue";
import UploadFile from "@/components/UploadFile.vue"; import UploadFile from "@/components/UploadFile.vue";
import UploadText from "@/components/UploadText.vue"; import UploadText from "@/components/UploadText.vue";
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useConfigStore } from "@/stores/config";
const { config } = useConfigStore();
const { t } = useI18n() const { t } = useI18n()
const shareData = ref({ const shareData = ref({
@@ -27,11 +29,11 @@ const shareData = ref({
> >
<template #prepend> <template #prepend>
<el-select v-model="shareData.expireStyle" :placeholder="t('send.expireStyle')" style="width: 75px"> <el-select v-model="shareData.expireStyle" :placeholder="t('send.expireStyle')" style="width: 75px">
<el-option :label="t('send.expireData.day')" value="day" /> <el-option v-for="item in config.expireStyle" :key="item" :label="t(`send.expireData.${item}`)" :value="item" />
<el-option :label="t('send.expireData.hour')" value="hour" /> <!-- <el-option :label="t('send.expireData.hour')" value="hour" />-->
<el-option :label="t('send.expireData.minute')" value="minute" /> <!-- <el-option :label="t('send.expireData.minute')" value="minute" />-->
<el-option :label="t('send.expireData.forever')" value="forever" /> <!-- <el-option :label="t('send.expireData.forever')" value="forever" />-->
<el-option :label="t('send.expireData.count')" value="count" /> <!-- <el-option :label="t('send.expireData.count')" value="count" />-->
</el-select> </el-select>
</template> </template>
<template #append> <template #append>
+7 -25
View File
@@ -6,16 +6,16 @@ import asyncio
import re import re
from fastapi import FastAPI from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from starlette.responses import HTMLResponse, FileResponse from fastapi.responses import HTMLResponse
from tortoise.contrib.fastapi import register_tortoise from tortoise.contrib.fastapi import register_tortoise
from apps.base.models import KeyValue
from apps.base.views import share_api from apps.base.views import share_api
from apps.admin.views import admin_api from apps.admin.views import admin_api
from core.response import APIResponse from core.response import APIResponse
from core.settings import data_root, settings, BASE_DIR from core.settings import data_root, settings, BASE_DIR, DEFAULT_CONFIG
from core.tasks import delete_expire_files from core.tasks import delete_expire_files
from core.utils import max_save_times_desc
app = FastAPI() app = FastAPI()
@@ -27,27 +27,6 @@ app.add_middleware(
allow_headers=["*"], allow_headers=["*"],
) )
@app.get('/assets/{file_path:path}')
async def assets(file_path: str):
if settings.max_save_seconds > 0:
if re.match(r'SendView-[\d|a-f|A-F]+\.js', file_path):
with open(BASE_DIR / f'fcb-fronted/dist/assets/{file_path}', 'r', encoding='utf-8') as f:
# 删除永久保存选项
content = f.read()
content = content.replace('_(c,{label:e(r)("send.expireData.forever"),value:"forever"},null,8,["label"]),', '')
return HTMLResponse(content=content, media_type='text/javascript')
if re.match(r'index-[\d|a-f|A-F]+\.js', file_path):
with open(BASE_DIR / f'fcb-fronted/dist/assets/{file_path}', 'r', encoding='utf-8') as f:
# 更改本文描述
desc_zh, desc_en = await max_save_times_desc(settings.max_save_seconds)
content = f.read()
content = content.replace('天数<7', desc_zh)
content = content.replace('Days <7', desc_en)
return HTMLResponse(content=content, media_type='text/javascript')
return FileResponse(f'fcb-fronted/dist/assets/{file_path}')
register_tortoise( register_tortoise(
app, app,
generate_schemas=True, generate_schemas=True,
@@ -75,6 +54,8 @@ app.include_router(admin_api)
async def startup_event(): async def startup_event():
# 启动后台任务,不定时删除过期文件 # 启动后台任务,不定时删除过期文件
asyncio.create_task(delete_expire_files()) asyncio.create_task(delete_expire_files())
user_config, created = await KeyValue.get_or_create(key='settings', defaults={'value': DEFAULT_CONFIG})
settings.user_config = user_config.value
@app.get('/') @app.get('/')
@@ -94,6 +75,7 @@ async def get_config():
return APIResponse(detail={ return APIResponse(detail={
'explain': settings.page_explain, 'explain': settings.page_explain,
'uploadSize': settings.uploadSize, 'uploadSize': settings.uploadSize,
'expireStyle': settings.expireStyle,
}) })