lan
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
import datetime
|
||||
import uuid
|
||||
import random
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI, Depends, UploadFile, Form, File, HTTPException
|
||||
from starlette.responses import HTMLResponse, FileResponse
|
||||
from starlette.staticfiles import StaticFiles
|
||||
|
||||
from sqlalchemy import or_, select, update, delete
|
||||
from sqlalchemy.ext.asyncio.session import AsyncSession
|
||||
|
||||
import settings
|
||||
from database import get_session, Codes, init_models, engine
|
||||
from storage import STORAGE_ENGINE
|
||||
from depends import admin_required, IPRateLimit
|
||||
|
||||
app = FastAPI(debug=settings.DEBUG)
|
||||
|
||||
DATA_ROOT = Path(settings.DATA_ROOT)
|
||||
if not DATA_ROOT.exists():
|
||||
DATA_ROOT.mkdir(parents=True)
|
||||
|
||||
STATIC_URL = settings.STATIC_URL
|
||||
app.mount(STATIC_URL, StaticFiles(directory=DATA_ROOT), name="static")
|
||||
|
||||
storage = STORAGE_ENGINE[settings.STORAGE_ENGINE]()
|
||||
|
||||
|
||||
@app.on_event('startup')
|
||||
async def startup():
|
||||
await init_models()
|
||||
asyncio.create_task(delete_expire_files())
|
||||
|
||||
|
||||
index_html = open('templates/index.html', 'r', encoding='utf-8').read() \
|
||||
.replace('{{title}}', settings.TITLE) \
|
||||
.replace('{{description}}', settings.DESCRIPTION) \
|
||||
.replace('{{keywords}}', settings.KEYWORDS)
|
||||
admin_html = open('templates/admin.html', 'r', encoding='utf-8').read() \
|
||||
.replace('{{title}}', settings.TITLE) \
|
||||
.replace('{{description}}', settings.DESCRIPTION) \
|
||||
.replace('{{keywords}}', settings.KEYWORDS)
|
||||
|
||||
ip_limit = IPRateLimit()
|
||||
|
||||
|
||||
async def delete_expire_files():
|
||||
while True:
|
||||
async with AsyncSession(engine, expire_on_commit=False) as s:
|
||||
query = select(Codes).where(or_(Codes.exp_time < datetime.datetime.now(), Codes.count == 0))
|
||||
exps = (await s.execute(query)).scalars().all()
|
||||
files = [{'type': old.type, 'text': old.text} for old in exps]
|
||||
await storage.delete_files(files)
|
||||
exps_ids = [exp.id for exp in exps]
|
||||
query = delete(Codes).where(Codes.id.in_(exps_ids))
|
||||
await s.execute(query)
|
||||
await s.commit()
|
||||
await asyncio.sleep(random.randint(60, 300))
|
||||
|
||||
|
||||
async def get_code(s: AsyncSession):
|
||||
code = random.randint(10000, 99999)
|
||||
while (await s.execute(select(Codes.id).where(Codes.code == code))).scalar():
|
||||
code = random.randint(10000, 99999)
|
||||
return str(code)
|
||||
|
||||
|
||||
@app.get(f'/{settings.ADMIN_ADDRESS}')
|
||||
async def admin():
|
||||
return HTMLResponse(admin_html)
|
||||
|
||||
|
||||
@app.post(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)])
|
||||
async def admin_post(s: AsyncSession = Depends(get_session)):
|
||||
query = select(Codes)
|
||||
codes = (await s.execute(query)).scalars().all()
|
||||
return {'detail': '查询成功', 'data': codes}
|
||||
|
||||
|
||||
@app.delete(f'/{settings.ADMIN_ADDRESS}', dependencies=[Depends(admin_required)])
|
||||
async def admin_delete(code: str, s: AsyncSession = Depends(get_session)):
|
||||
query = select(Codes).where(Codes.code == code)
|
||||
file = (await s.execute(query)).scalars().first()
|
||||
await storage.delete_file({'type': file.type, 'text': file.text})
|
||||
await s.delete(file)
|
||||
await s.commit()
|
||||
return {'detail': '删除成功'}
|
||||
|
||||
|
||||
@app.get('/')
|
||||
async def index():
|
||||
return HTMLResponse(index_html)
|
||||
|
||||
|
||||
@app.get('/select')
|
||||
async def get_file(code: str, s: AsyncSession = Depends(get_session)):
|
||||
query = select(Codes).where(Codes.code == code)
|
||||
info = (await s.execute(query)).scalars().first()
|
||||
if not info:
|
||||
raise HTTPException(status_code=404, detail="口令不存在")
|
||||
if info.type == 'text':
|
||||
return {'detail': '查询成功', 'data': info.text}
|
||||
else:
|
||||
filepath = await storage.get_filepath(info.text)
|
||||
return FileResponse(filepath, filename=info.name)
|
||||
|
||||
|
||||
@app.post('/')
|
||||
async def index(code: str, ip: str = Depends(ip_limit), s: AsyncSession = Depends(get_session)):
|
||||
query = select(Codes).where(Codes.code == code)
|
||||
info = (await s.execute(query)).scalars().first()
|
||||
if not info:
|
||||
error_count = settings.ERROR_COUNT - ip_limit.add_ip(ip)
|
||||
raise HTTPException(status_code=404, detail=f"取件码错误,错误{error_count}次将被禁止10分钟")
|
||||
if info.exp_time < datetime.datetime.now() or info.count == 0:
|
||||
await storage.delete_file({'type': info.type, 'text': info.text})
|
||||
await s.delete(info)
|
||||
await s.commit()
|
||||
raise HTTPException(status_code=404, detail="取件码已过期,请联系寄件人")
|
||||
await s.execute(update(Codes).where(Codes.id == info.id).values(count=info.count - 1))
|
||||
await s.commit()
|
||||
if info.type != 'text':
|
||||
info.text = f'/select?code={code}'
|
||||
return {
|
||||
'detail': '取件成功,请点击"取"查看',
|
||||
'data': {'type': info.type, 'text': info.text, 'name': info.name, 'code': info.code}
|
||||
}
|
||||
|
||||
|
||||
@app.post('/share')
|
||||
async def share(text: str = Form(default=None), style: str = Form(default='2'), value: int = Form(default=1),
|
||||
file: UploadFile = File(default=None), s: AsyncSession = Depends(get_session)):
|
||||
code = await get_code(s)
|
||||
if style == '2':
|
||||
if value > 7:
|
||||
raise HTTPException(status_code=400, detail="最大有效天数为7天")
|
||||
exp_time = datetime.datetime.now() + datetime.timedelta(days=value)
|
||||
exp_count = -1
|
||||
elif style == '1':
|
||||
if value < 1:
|
||||
raise HTTPException(status_code=400, detail="最小有效次数为1次")
|
||||
exp_time = datetime.datetime.now() + datetime.timedelta(days=1)
|
||||
exp_count = value
|
||||
else:
|
||||
exp_time = datetime.datetime.now() + datetime.timedelta(days=1)
|
||||
exp_count = -1
|
||||
key = uuid.uuid4().hex
|
||||
if file:
|
||||
file_bytes = await file.read()
|
||||
size = len(file_bytes)
|
||||
if size > settings.FILE_SIZE_LIMIT:
|
||||
raise HTTPException(status_code=400, detail="文件过大")
|
||||
_text, _type, name = await storage.save_file(file, file_bytes, key), file.content_type, file.filename
|
||||
else:
|
||||
size, _text, _type, name = len(text), text, 'text', '文本分享'
|
||||
info = Codes(
|
||||
code=code,
|
||||
text=_text,
|
||||
size=size,
|
||||
type=_type,
|
||||
name=name,
|
||||
count=exp_count,
|
||||
exp_time=exp_time,
|
||||
key=key
|
||||
)
|
||||
s.add(info)
|
||||
await s.commit()
|
||||
return {
|
||||
'detail': '分享成功,请点击文件箱查看取件码',
|
||||
'data': {'code': code, 'key': key, 'name': name, 'text': _text}
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run('main:app', host='0.0.0.0', port=settings.PORT, debug=settings.DEBUG)
|
||||
@@ -0,0 +1,111 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<link rel="stylesheet" href="/static/assert/index.css">
|
||||
<link rel="shortcut icon" href="/static/assert/favicon.ico" type="image/x-icon"/>
|
||||
<title>后台管理-{{title}}</title>
|
||||
<meta name="description" content="{{description}}"/>
|
||||
<meta name="keywords" content="{{keywords}}"/>
|
||||
<meta name="generator" content="FileCodeBox"/>
|
||||
<meta name="template" content="Lan"/>
|
||||
<script src="/static/assert/vue.min.js"></script>
|
||||
<script src="/static/assert/index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<el-row v-if="login" :gutter="10">
|
||||
<el-col :xs="0" :sm="4" :md="4" :lg="4" :xl="4">
|
||||
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16">
|
||||
<el-card>
|
||||
<el-empty v-if="files.length===0" description="暂时还没有文件"></el-empty>
|
||||
<el-card v-for="file in files" :key="file.code">
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<div style="cursor: pointer;text-align: left">
|
||||
<div>取件码:${ file.code }</div>
|
||||
<div>文件名:${ file.name }</div>
|
||||
<div>次 数:${ file.count }</div>
|
||||
<div>到 期:${ file.exp_time.slice(0,19) }</div>
|
||||
<div v-if="file.name==='分享文本'">
|
||||
<span>内 容:${ file.text }</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>链 接:</span>
|
||||
<a :href="file.text" target="_blank"
|
||||
style="color: #1E9FFF;text-underline: none"
|
||||
type="primary">点击下载</a>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-button type="danger" @click="deleteFile(file.code)">删除</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :xs="0" :sm="4" :md="4" :lg="4" :xl="4"> </el-col>
|
||||
</el-row>
|
||||
<div v-else style="width: 250px;text-align: center;margin: 40vh auto">
|
||||
<el-input v-model="pwd" placeholder="请输入登录密码">
|
||||
<el-button slot="append" type="primary" @click="loginAdmin">登录</el-button>
|
||||
</el-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<script src="/static/assert/axios.min.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
delimiters: ['${', '}'],
|
||||
data: function () {
|
||||
return {
|
||||
login: false,
|
||||
pwd: '',
|
||||
files: [],
|
||||
config: {
|
||||
error_count: 0,
|
||||
file_size: 0,
|
||||
admin_pwd: 'admin'
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
const pwd = localStorage.getItem('pwd');
|
||||
if (pwd) {
|
||||
login = true;
|
||||
this.pwd = pwd;
|
||||
this.loginAdmin();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loginAdmin: function () {
|
||||
axios.post('', {}, {'headers': {'pwd': this.pwd}}).then(res => {
|
||||
this.files = res.data.data;
|
||||
this.login = true;
|
||||
localStorage.setItem('pwd', this.pwd);
|
||||
}).catch(e => {
|
||||
localStorage.clear()
|
||||
this.$message({'message': e.response.data.detail, 'type': 'error'});
|
||||
});
|
||||
},
|
||||
deleteFile: function (code) {
|
||||
axios.delete('?code=' + code, {'headers': {'pwd': this.pwd}}).then(res => {
|
||||
this.files = this.files.filter(item => item.code !== code)
|
||||
this.$message({
|
||||
message: res.data.detail,
|
||||
type: 'success'
|
||||
});
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</html>
|
||||
@@ -0,0 +1,318 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<link rel="stylesheet" href="/static/assert/index.css">
|
||||
<link rel="shortcut icon" href="/static/assert/favicon.ico" type="image/x-icon"/>
|
||||
<title>{{title}}</title>
|
||||
<meta name="description" content="{{description}}"/>
|
||||
<meta name="keywords" content="{{keywords}}"/>
|
||||
<meta name="generator" content="FileCodeBox"/>
|
||||
<meta name="template" content="Lan-V1.5.1"/>
|
||||
<style>
|
||||
.qu .el-button {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: 0.2rem;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.qu .el-input__inner {
|
||||
height: 100px;
|
||||
margin: 1rem 0;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="/static/assert/vue.min.js"></script>
|
||||
<script src="/static/assert/index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" style="text-align: center">
|
||||
<el-row v-if="pageNum === 0" class="qu" style="width:400px;margin: 6vh auto 0 auto">
|
||||
<el-card style="padding-bottom: 1rem">
|
||||
<el-col :span="24">
|
||||
<el-input autofocus @input="listenInput" clearable v-model:value="code" maxlength="5"
|
||||
:disabled="inputDisable" placeholder="请输入五位取件码">
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('1')">1</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('2')">2</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('3')">3</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('4')">4</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('5')">5</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('6')">6</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('7')">7</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('8')">8</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('9')">9</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="pageNum=1">寄</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="listenInput('0')">0</el-button>
|
||||
</el-col>
|
||||
<el-col :span=8>
|
||||
<el-button @click="quDrawer=true">取</el-button>
|
||||
</el-col>
|
||||
</el-card>
|
||||
</el-row>
|
||||
<el-row v-else style="width:400px;margin: 20vh auto 0 auto">
|
||||
<el-col :span="24" style="margin: 1rem 0">
|
||||
<el-card>
|
||||
<el-input style="width: 200px" placeholder="数量" v-model="uploadData.value"
|
||||
class="input-with-select">
|
||||
<el-select style="width: 75px" v-model="uploadData.style" slot="prepend" placeholder="请选择">
|
||||
<el-option label="天数" value="2"></el-option>
|
||||
<el-option label="次数" value="1"></el-option>
|
||||
</el-select>
|
||||
<el-button v-if="uploadData.style === '1'" slot="append" disabled>次</el-button>
|
||||
<el-button v-else slot="append" disabled>天</el-button>
|
||||
</el-input>
|
||||
<el-radio-group v-model="uploadData.type" style="margin-left: 18px">
|
||||
<el-radio label="1">文件</el-radio>
|
||||
<el-radio label="2">文本</el-radio>
|
||||
</el-radio-group>
|
||||
<el-upload
|
||||
v-if="uploadData.type === '1'"
|
||||
drag
|
||||
action="/share"
|
||||
multiple
|
||||
style="margin: 1rem 0;"
|
||||
:data="uploadData"
|
||||
:on-success="successUpload"
|
||||
:on-error="errorUpload"
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文字、文件拖、粘贴到此处,或<em>点击上传</em></div>
|
||||
<div class="el-upload__text" style="font-size: 10px">天数<7或限制次数(24h后删除)</div>
|
||||
</el-upload>
|
||||
<el-input
|
||||
v-else
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 8}"
|
||||
style="margin: 1rem 0"
|
||||
placeholder="请输入内容,完成之后点击下方寄出去"
|
||||
v-model="uploadData.text">
|
||||
</el-input>
|
||||
<div class="el-upload__tip">
|
||||
<el-button @click="pageNum=0">去取件</el-button>
|
||||
<el-button @click="cunDrawer=true">取件码</el-button>
|
||||
<el-button v-if="uploadData.type === '2'" @click="toUploadData">寄出去</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-drawer
|
||||
title="文件箱"
|
||||
:visible.sync="quDrawer"
|
||||
:direction="direction"
|
||||
size="50%"
|
||||
>
|
||||
<el-card v-for="(file,index) in files" :key="index" class="box-card">
|
||||
<div style="cursor: pointer;text-align: left">
|
||||
<div>取件码:${ file.code }</div>
|
||||
<div>文件名:${ file.name }</div>
|
||||
<div v-if="file.name==='文本分享'">
|
||||
<span>内 容:${ file.text }</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>链 接:</span>
|
||||
<a :href="file.text" target="_blank"
|
||||
style="color: #1E9FFF;text-underline: none"
|
||||
type="primary">点击下载</a>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-empty v-if="files.length===0" description="请输入取件码,收取文件"></el-empty>
|
||||
</el-drawer>
|
||||
<el-drawer
|
||||
title="文件箱"
|
||||
:visible.sync="jiDrawer"
|
||||
:direction="direction"
|
||||
size="50%">
|
||||
<el-card>
|
||||
<el-empty v-if="files.length===0" description="请上传文件"></el-empty>
|
||||
<el-card style="margin-top: 0.2rem" v-for="(file,index) in files" :key="index">
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-row>
|
||||
<el-col :span="24" style="line-height: 45px">
|
||||
${ file.name }
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
取件码:<h1 style="margin: 0;display: inline">${ file.code }</h1>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<img style="width: 80px;height: 80px;"
|
||||
:src="qrcodeUrl(file)" alt="二维码" :alt="file.code">
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-card>
|
||||
</el-drawer>
|
||||
<div style="text-align: center; margin-top: 1rem;color: #606266">
|
||||
<a style="text-decoration: none;color: #606266" target="_blank" href="https://github.com/vastsa/FileCodeBox">FileCodeBox</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="/static/assert/axios.min.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
delimiters: ['${', '}'],
|
||||
data: function () {
|
||||
return {
|
||||
code: '',
|
||||
quDrawer: false,
|
||||
jiDrawer: false,
|
||||
direction: 'btt',
|
||||
files: [],
|
||||
pageNum: 0,
|
||||
inputDisable: false,
|
||||
uploadData: {
|
||||
style: '2',
|
||||
type: '1',
|
||||
value: 1,
|
||||
file: null,
|
||||
text: ''
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
// 进入网站时,判断Get是否有code参数,有则直接进行取件操作
|
||||
let code = window.location.search.substring('code=='.length)
|
||||
if (code) {
|
||||
this.code = code
|
||||
this.getFile()
|
||||
}
|
||||
// 剪切板监听
|
||||
const that = this
|
||||
document.addEventListener('paste', function (event) {
|
||||
if (that.pageNum === 1) {
|
||||
const items = event.clipboardData && event.clipboardData.items;
|
||||
if (items && items.length) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].kind === 'string') {
|
||||
if (items[i].type.match(/^text\/plain/) && that.uploadData.type !== '2') {
|
||||
that.$message('剪切板文字正在上传,请稍等');
|
||||
items[i].getAsString(function (str) {
|
||||
that.uploadData.text = str;
|
||||
that.toUploadData();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const file = items[i].getAsFile();
|
||||
that.$message('剪切板文件正在上传,请稍等');
|
||||
that.uploadData.file = file
|
||||
that.toUploadData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
http: function (method, url, data = {}, config = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios({
|
||||
method: method,
|
||||
url: url,
|
||||
data: data,
|
||||
...config
|
||||
}).then(res => {
|
||||
this.$message({
|
||||
message: res.data.detail,
|
||||
type: 'success'
|
||||
});
|
||||
resolve(res.data)
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
message: err.response.data.detail,
|
||||
type: 'error'
|
||||
});
|
||||
})
|
||||
})
|
||||
},
|
||||
getFile: function () {
|
||||
const that = this;
|
||||
this.http('post', `?code=${that.code}`).then(res => {
|
||||
that.quDrawer = true;
|
||||
that.files.unshift(res.data);
|
||||
})
|
||||
that.code = '';
|
||||
that.input_disable = false
|
||||
},
|
||||
qrcodeUrl(file) {
|
||||
return 'https://api.qrserver.com/v1/create-qr-code/?data=' + window.location.origin + '/?code=' + file.code
|
||||
},
|
||||
listenInput: function (value) {
|
||||
if (this.code.length < 5) {
|
||||
this.code += value;
|
||||
}
|
||||
if (this.code.length === 5) {
|
||||
this.inout_disable = true;
|
||||
this.getFile();
|
||||
}
|
||||
},
|
||||
toUploadData: function () {
|
||||
if (this.uploadData.text === '' && this.uploadData.file === null) {
|
||||
this.$message({
|
||||
message: '请先粘贴文字或者上传文件',
|
||||
type: 'error'
|
||||
});
|
||||
} else {
|
||||
this.http('post', '/share', this.uploadData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
}).then(res => {
|
||||
this.files.unshift(res.data);
|
||||
this.jiDrawer = true;
|
||||
this.uploadData.text = '';
|
||||
this.uploadData.file = null;
|
||||
});
|
||||
}
|
||||
},
|
||||
successUpload(response, file, fileList) {
|
||||
this.$message({
|
||||
message: response.msg,
|
||||
type: 'success'
|
||||
});
|
||||
this.files.unshift(response.data);
|
||||
},
|
||||
errorUpload(error, file, fileList) {
|
||||
error = JSON.parse(error.message)
|
||||
this.$message({
|
||||
message: error.detail,
|
||||
type: 'error'
|
||||
});
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user