Skip to content

Commit b6c0bc0

Browse files
committed
fix:admin
1 parent a8052c6 commit b6c0bc0

5 files changed

Lines changed: 79 additions & 82 deletions

File tree

core/database.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
from sqlalchemy.ext.declarative import declarative_base
55
from sqlalchemy.ext.asyncio import create_async_engine
66
from sqlalchemy.ext.asyncio.session import AsyncSession
7+
78
from settings import settings
89

910
engine = create_async_engine(settings.DATABASE_URL)
10-
1111
Base = declarative_base()
1212

1313

@@ -33,14 +33,20 @@ class Codes(Base):
3333
exp_time = Column(DateTime, nullable=True)
3434

3535

36-
async def init_models():
36+
async def init_models(s):
3737
async with engine.begin() as conn:
3838
await conn.run_sync(Base.metadata.create_all)
3939
if await conn.scalar(select(Options).filter(Options.key == 'INSTALL')) is None:
4040
# 如果没有存在install,则清空表,并插入默认数据
4141
await conn.execute(delete(table=Options))
4242
await conn.execute(insert(table=Options, values=[
4343
{'key': 'INSTALL', 'value': settings.VERSION},
44+
{'key': 'DEBUG', 'value': settings.DEBUG},
45+
{'key': 'DATABASE_FILE', 'value': settings.DATABASE_FILE},
46+
{'key': 'PORT', 'value': settings.PORT},
47+
{'key': 'DATA_ROOT', 'value': settings.DATA_ROOT},
48+
{'key': 'LOCAL_ROOT', 'value': settings.LOCAL_ROOT},
49+
{'key': 'STATIC_URL', 'value': settings.STATIC_URL},
4450
{'key': 'BANNERS', 'value': settings.BANNERS},
4551
{'key': 'ENABLE_UPLOAD', 'value': settings.ENABLE_UPLOAD},
4652
{'key': 'MAX_DAYS', 'value': settings.MAX_DAYS},
@@ -66,9 +72,12 @@ async def init_models():
6672
f'请尽快修改后台信息!\n'
6773
f'FileCodeBox https://github.com/vastsa/FileCodeBox'
6874
)
69-
else:
70-
# 从数据库更新缓存中的setting
71-
await settings.updates(await conn.execute(select(Options).filter()))
75+
await settings.updates(await conn.execute(select(Options).filter()))
76+
77+
78+
async def get_config(key):
79+
async with engine.begin() as conn:
80+
return await conn.scalar(select(Options.value).filter(Options.key == key))
7281

7382

7483
async def get_session():

core/storage.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ async def save_file(self, file: UploadFile, remote_filepath: str):
5858
upload_filepath = settings.DATA_ROOT + str(now)
5959
await asyncio.to_thread(self._save, upload_filepath, file.file)
6060
self.upload_file(upload_filepath, remote_filepath)
61+
remote_filepath = remote_filepath.strip(f"https://{settings.BUCKET_NAME}.{settings.OSS_ENDPOINT}/")
62+
self.upload_file(upload_filepath, remote_filepath)
6163
await asyncio.to_thread(os.remove, upload_filepath)
6264

6365
async def delete_files(self, texts):

main.py

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import asyncio
12
import datetime
23
import uuid
34
from pathlib import Path
@@ -6,16 +7,25 @@
67
from starlette.requests import Request
78
from starlette.responses import HTMLResponse, FileResponse
89
from starlette.staticfiles import StaticFiles
9-
import os, shutil
10-
from core.utils import error_ip_limit, upload_ip_limit, get_code, storage
10+
import os
11+
import shutil
12+
from core.utils import error_ip_limit, upload_ip_limit, get_code, storage, delete_expire_files
1113
from core.depends import admin_required
12-
from settings import settings
1314
from fastapi import FastAPI, Depends, UploadFile, Form, File, HTTPException, BackgroundTasks
14-
1515
from core.database import init_models, Options, Codes, get_session
16+
from settings import settings
1617

1718
# 实例化FastAPI
18-
app = FastAPI(debug=settings.DEBUG, docs_url=None, redoc_url=None)
19+
app = FastAPI(debug=settings.DEBUG, redoc_url=None, )
20+
21+
22+
@app.on_event('startup')
23+
async def startup(s: AsyncSession = Depends(get_session)):
24+
# 初始化数据库
25+
await init_models(s)
26+
# 启动后台任务,不定时删除过期文件
27+
asyncio.create_task(delete_expire_files())
28+
1929

2030
# 数据存储文件夹
2131
DATA_ROOT = Path(settings.DATA_ROOT)
@@ -28,34 +38,27 @@
2838

2939
# 静态文件夹,这个固定就行了,静态资源都放在这里
3040
app.mount('/static', StaticFiles(directory='./static'), name="static")
41+
3142
# 首页页面
32-
index_html = open('templates/index.html', 'r', encoding='utf-8').read() \
33-
.replace('{{title}}', settings.TITLE) \
34-
.replace('{{description}}', settings.DESCRIPTION) \
35-
.replace('{{keywords}}', settings.KEYWORDS) \
36-
.replace("'{{fileSizeLimit}}'", str(settings.FILE_SIZE_LIMIT))
43+
index_html = open('templates/index.html', 'r', encoding='utf-8').read()
3744
# 管理页面
38-
admin_html = open('templates/admin.html', 'r', encoding='utf-8').read() \
39-
.replace('{{title}}', settings.TITLE) \
40-
.replace('{{description}}', settings.DESCRIPTION) \
41-
.replace('{{admin_address}}', settings.ADMIN_ADDRESS) \
42-
.replace('{{keywords}}', settings.KEYWORDS)
43-
44-
45-
@app.on_event('startup')
46-
async def startup():
47-
# 初始化数据库
48-
await init_models()
45+
admin_html = open('templates/admin.html', 'r', encoding='utf-8').read()
4946

5047

5148
@app.get('/')
5249
async def index():
53-
return HTMLResponse(index_html)
50+
return HTMLResponse(
51+
index_html.replace('{{title}}', settings.TITLE).replace('{{description}}', settings.DESCRIPTION).replace(
52+
'{{keywords}}', settings.KEYWORDS).replace("'{{fileSizeLimit}}'", str(settings.FILE_SIZE_LIMIT))
53+
)
5454

5555

5656
@app.get(f'/{settings.ADMIN_ADDRESS}', description='管理页面')
5757
async def admin():
58-
return HTMLResponse(admin_html)
58+
return HTMLResponse(
59+
admin_html.replace('{{title}}', settings.TITLE).replace('{{description}}', settings.DESCRIPTION).replace(
60+
'{{admin_address}}', settings.ADMIN_ADDRESS).replace('{{keywords}}', settings.KEYWORDS)
61+
)
5962

6063

6164
@app.get(f'/{settings.ADMIN_ADDRESS}/files', dependencies=[Depends(admin_required)])
@@ -150,14 +153,10 @@ async def admin_patch(request: Request, s: AsyncSession = Depends(get_session)):
150153
await s.execute(update(Options).where(Options.key == key).values(value=value))
151154
await settings.update(key, value)
152155
await s.commit()
156+
await settings.updates([[i.id, i.key, i.value] for i in (await s.execute(select(Options))).scalars().all()])
153157
return {'detail': '修改成功'}
154158

155159

156-
@app.get('/')
157-
async def index():
158-
return HTMLResponse(index_html)
159-
160-
161160
@app.post('/')
162161
async def index(code: str, ip: str = Depends(error_ip_limit), s: AsyncSession = Depends(get_session)):
163162
query = select(Codes).where(Codes.code == code)

settings.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import uuid
2+
23
from starlette.config import Config
34

4-
# 配置文件.env
5-
# 请将.env移动至data目录,方便docker部署
5+
# 配置文件.env,存放为data/.env
66
config = Config("data/.env")
77

88

@@ -65,14 +65,25 @@ class Settings:
6565
}]
6666
int_dict = {'PORT', 'MAX_DAYS', 'ERROR_COUNT', 'ERROR_MINUTE', 'UPLOAD_COUNT', 'UPLOAD_MINUTE',
6767
'DELETE_EXPIRE_FILES_INTERVAL', 'FILE_SIZE_LIMIT'}
68+
bool_dict = {'DEBUG', 'ENABLE_UPLOAD'}
6869

6970
async def update(self, key, value) -> None:
7071
if hasattr(self, key):
71-
setattr(self, key, int(value) if key in self.int_dict else value)
72+
if key in self.int_dict:
73+
value = int(value)
74+
elif key in self.bool_dict:
75+
value = value == 'true'
76+
setattr(self, key, value)
7277

7378
async def updates(self, options) -> None:
74-
for i, key, value in options:
75-
await self.update(key, value)
79+
with open('data/.env', 'w', encoding='utf-8') as f:
80+
for i, key, value in options:
81+
print(i, key, value)
82+
# 更新env文件
83+
f.write(f"{key}={value}\n")
84+
# 更新配置
85+
await self.update(key, value)
86+
f.flush()
7687

7788

7889
settings = Settings()

templates/admin.html

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,6 @@
2222
body {
2323
background: #f5f5f5;
2424
}
25-
26-
@media (prefers-color-scheme: dark) {
27-
28-
body {
29-
background-color: #18181c;
30-
}
31-
32-
.el-card, .el-textarea__inner, .el-upload-dragger {
33-
border-radius: 20px;
34-
border: 1px solid transparent;
35-
background-color: rgba(255, 255, 255, 0.1);
36-
box-shadow: 5px 5px 0 0 rgba(0, 0, 0, 0.2);
37-
}
38-
39-
#app * {
40-
color: #ccc !important;
41-
}
42-
43-
.el-input-group__prepend, .el-menu, .el-menu-item, .el-input__inner, .el-input-group__append, .el-empty__description, .el-select-dropdown, .el-button {
44-
border: 1px solid transparent;
45-
background-color: rgba(0, 0, 0, 0.2);
46-
}
47-
48-
.el-drawer, #el-drawer__title, .el-drawer__body, .el-drawer__wrapper {
49-
background-color: rgba(0, 0, 0, 0.5);
50-
border: 1px solid transparent;
51-
}
52-
}
5325
</style>
5426
</head>
5527
<body>
@@ -74,7 +46,7 @@
7446
<div>次&nbsp;&nbsp; 数:${ file.count }</div>
7547
<div>到&nbsp;&nbsp; 期:${ file.exp_time.slice(0,19) }</div>
7648
<div v-if="file.type==='text'">
77-
<span>内&nbsp;&nbsp; 容:${ file.text }</span>
49+
<span style="white-space: pre-line">内&nbsp;&nbsp; 容:${ file.text }</span>
7850
</div>
7951
<div v-else>
8052
<span>链&nbsp;&nbsp; 接:</span>
@@ -121,12 +93,12 @@
12193
</el-col>
12294
<el-col v-if="activeIndex === '4'">
12395
<el-row>
124-
<el-col :span="5" style="height: 88vh;overflow: scroll" :gutter="10">
96+
<el-col :span="4" style="height: 88vh;overflow: scroll;text-align: center" :gutter="10">
12597
<el-card v-for="menu in menus" :key="menu.key">
12698
<div style="cursor: pointer;" @click="updateTab=menu.key">${menu.name}</div>
12799
</el-card>
128100
</el-col>
129-
<el-col :span="19">
101+
<el-col :span="20">
130102
<el-card style="height: 88vh;overflow: scroll">
131103
<div v-if="updateTab=='INSTALL'">
132104
<div>
@@ -158,13 +130,8 @@ <h2>Github:<a target="_blank"
158130
<div v-else-if="updateTab=='WEBSITE'">
159131
<el-form ref="form" style="margin:1rem auto" :model="config" label-width="200px">
160132
<el-form-item label="后台密码">
161-
<el-input type="password" v-model="config.ADMIN_PASSWORD" placeholder="网站名称"></el-input>
162-
</el-form-item>
163-
<el-form-item>
164-
<el-alert
165-
title="下列信息修改后需要手动重启系统"
166-
type="warning">
167-
</el-alert>
133+
<el-input type="password" v-model="config.ADMIN_PASSWORD"
134+
placeholder="网站名称"></el-input>
168135
</el-form-item>
169136
<el-form-item label="网站名称">
170137
<el-input v-model="config.TITLE" placeholder="网站名称"></el-input>
@@ -175,6 +142,12 @@ <h2>Github:<a target="_blank"
175142
<el-form-item label="网站关键词">
176143
<el-input v-model="config.KEYWORDS" placeholder="网站关键词"></el-input>
177144
</el-form-item>
145+
<el-form-item>
146+
<el-alert
147+
title="下列信息修改后需要手动重启系统"
148+
type="warning">
149+
</el-alert>
150+
</el-form-item>
178151
<el-form-item label="后台地址">
179152
<el-input v-model="config.ADMIN_ADDRESS" placeholder="后台地址"></el-input>
180153
</el-form-item>
@@ -272,19 +245,21 @@ <h2>Github:<a target="_blank"
272245
if (pwd) {
273246
login = true;
274247
this.pwd = pwd;
248+
this.loginAdmin();
249+
this.getLocalFiles();
250+
}
251+
},
252+
methods: {
253+
getConfig: function () {
275254
axios.get(window.location.href + '/config', {
276255
headers: {
277-
pwd: pwd
256+
pwd: this.pwd
278257
}
279258
}).then(res => {
280259
this.config = res.data.data;
281260
this.menus = res.data.menus;
282261
});
283-
this.loginAdmin();
284-
this.getLocalFiles();
285-
}
286-
},
287-
methods: {
262+
},
288263
updateSize: function (value) {
289264
this.paginate.size = value;
290265
this.loginAdmin();
@@ -327,6 +302,7 @@ <h2>Github:<a target="_blank"
327302
this.files = res.data.data
328303
this.login = true;
329304
localStorage.setItem('pwd', this.pwd);
305+
this.getConfig();
330306
}).catch(e => {
331307
localStorage.clear()
332308
this.$message({'message': e.response.data.detail, 'type': 'error'});

0 commit comments

Comments
 (0)