add:vue-i18n,admin add file size

This commit is contained in:
lan
2023-09-06 11:06:18 +08:00
parent f0b2e4a8b2
commit 4e79991f82
40 changed files with 770 additions and 427 deletions
+2 -3
View File
@@ -10,7 +10,7 @@ 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
from core.response import APIResponse from core.response import APIResponse
from core.settings import default_value, settings from core.settings import settings
from core.storage import file_storage from core.storage import file_storage
admin_api = APIRouter( admin_api = APIRouter(
@@ -34,11 +34,10 @@ async def file_delete(data: IDData):
@admin_api.get('/file/list', dependencies=[Depends(admin_required)]) @admin_api.get('/file/list', dependencies=[Depends(admin_required)])
async def file_list(page: float = 1, size: int = 10): async def file_list(page: float = 1, size: int = 10):
data = await FileCodes.all().limit(size).offset((math.ceil(page) - 1) * size)
return APIResponse(detail={ return APIResponse(detail={
'page': page, 'page': page,
'size': size, 'size': size,
'data': data, 'data': await FileCodes.all().limit(size).offset((math.ceil(page) - 1) * size),
'total': await FileCodes.all().count(), 'total': await FileCodes.all().count(),
}) })
+4 -2
View File
@@ -39,7 +39,8 @@ async def get_now():
datetime.timezone(datetime.timedelta(hours=8)) datetime.timezone(datetime.timedelta(hours=8))
) )
async def get_select_token(code: int):
async def get_select_token(code: str):
""" """
获取下载token 获取下载token
:param code: :param code:
@@ -48,7 +49,8 @@ async def get_select_token(code: int):
token = "123456" token = "123456"
return hashlib.sha256(f"{code}{int(time.time() / 1000)}000{token}".encode()).hexdigest() return hashlib.sha256(f"{code}{int(time.time() / 1000)}000{token}".encode()).hexdigest()
async def get_file_url(code: int):
async def get_file_url(code: str):
""" """
对于需要通过服务器中转下载的服务,获取文件下载地址 对于需要通过服务器中转下载的服务,获取文件下载地址
:param code: :param code:
-1
View File
@@ -1 +0,0 @@
import{aq as t,o,D as s,E as e,I as a}from"./index-128af1be.js";const c={},n={style:{"text-align":"center"}},r=e("span",null,[a("本项目开源于Github "),e("em",null,[e("a",{style:{color:"#333"},href:"https://github.com/vastsa/FileCodeBox"},"FileCodeBox")])],-1),l=[r];function _(i,d){return o(),s("main",n,l)}const u=t(c,[["render",_]]);export{u as default};
+1
View File
@@ -0,0 +1 @@
import{d as a,X as n,D as c,E as e,I as r,F as o,u as s,o as u}from"./index-50add468.js";const i={style:{"text-align":"center"}},l={style:{color:"#333"},href:"https://github.com/vastsa/FileCodeBox"},f=a({__name:"AboutView",setup(_){const{t}=n();return(m,d)=>(u(),c("main",i,[e("span",null,[r(o(s(t)("admin.about.source1"))+" ",1),e("em",null,[e("a",l,o(s(t)("admin.about.source2")),1)])])]))}});export{f as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as T,k as F,e as j,o as C,s as _,b as N,g as v,p as K,q as E,m as R,r as p,t as u,v as B,j as q,f as H,l as W,n as Y,S as J,w as Q}from"./el-popper-d1605fe2.js";import{ag as m,ai as M,ad as V,ah as X,aH as Z}from"./request-e1d079d2.js";function z(t,e){for(var n=-1,o=t==null?0:t.length;++n<o&&e(t[n],n,t)!==!1;);return t}function k(t,e){return t&&T(e,F(e),t)}function tt(t,e){return t&&T(e,j(e),t)}function et(t,e){return T(t,C(t),e)}var rt=Object.getOwnPropertySymbols,nt=rt?function(t){for(var e=[];t;)N(e,C(t)),t=v(t);return e}:_;const x=nt;function at(t,e){return T(t,x(t),e)}function ot(t){return K(t,j,x)}var st=Object.prototype,ct=st.hasOwnProperty;function it(t){var e=t.length,n=new t.constructor(e);return e&&typeof t[0]=="string"&&ct.call(t,"index")&&(n.index=t.index,n.input=t.input),n}function gt(t,e){var n=e?E(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.byteLength)}var ft=/\w*$/;function bt(t){var e=new t.constructor(t.source,ft.exec(t));return e.lastIndex=t.lastIndex,e}var w=m?m.prototype:void 0,I=w?w.valueOf:void 0;function yt(t){return I?Object(I.call(t)):{}}var ut="[object Boolean]",Tt="[object Date]",lt="[object Map]",jt="[object Number]",pt="[object RegExp]",At="[object Set]",dt="[object String]",$t="[object Symbol]",St="[object ArrayBuffer]",mt="[object DataView]",wt="[object Float32Array]",It="[object Float64Array]",Ot="[object Int8Array]",ht="[object Int16Array]",Ft="[object Int32Array]",Ct="[object Uint8Array]",Et="[object Uint8ClampedArray]",Bt="[object Uint16Array]",Mt="[object Uint32Array]";function xt(t,e,n){var o=t.constructor;switch(e){case St:return E(t);case ut:case Tt:return new o(+t);case mt:return gt(t,n);case wt:case It:case Ot:case ht:case Ft:case Ct:case Et:case Bt:case Mt:return R(t,n);case lt:return new o;case jt:case dt:return new o(t);case pt:return bt(t);case At:return new o;case $t:return yt(t)}}var Lt="[object Map]";function Ut(t){return M(t)&&p(t)==Lt}var O=u&&u.isMap,Pt=O?B(O):Ut;const Dt=Pt;var Gt="[object Set]";function _t(t){return M(t)&&p(t)==Gt}var h=u&&u.isSet,Nt=h?B(h):_t;const vt=Nt;var Kt=1,Rt=2,qt=4,L="[object Arguments]",Ht="[object Array]",Wt="[object Boolean]",Yt="[object Date]",Jt="[object Error]",U="[object Function]",Qt="[object GeneratorFunction]",Vt="[object Map]",Xt="[object Number]",P="[object Object]",Zt="[object RegExp]",zt="[object Set]",kt="[object String]",te="[object Symbol]",ee="[object WeakMap]",re="[object ArrayBuffer]",ne="[object DataView]",ae="[object Float32Array]",oe="[object Float64Array]",se="[object Int8Array]",ce="[object Int16Array]",ie="[object Int32Array]",ge="[object Uint8Array]",fe="[object Uint8ClampedArray]",be="[object Uint16Array]",ye="[object Uint32Array]",r={};r[L]=r[Ht]=r[re]=r[ne]=r[Wt]=r[Yt]=r[ae]=r[oe]=r[se]=r[ce]=r[ie]=r[Vt]=r[Xt]=r[P]=r[Zt]=r[zt]=r[kt]=r[te]=r[ge]=r[fe]=r[be]=r[ye]=!0;r[Jt]=r[U]=r[ee]=!1;function l(t,e,n,o,f,s){var a,b=e&Kt,y=e&Rt,D=e&qt;if(n&&(a=f?n(t,o,f,s):n(t)),a!==void 0)return a;if(!V(t))return t;var A=X(t);if(A){if(a=it(t),!b)return q(t,a)}else{var g=p(t),d=g==U||g==Qt;if(H(t))return W(t,b);if(g==P||g==L||d&&!f){if(a=y||d?{}:Y(t),!b)return y?at(t,tt(a,t)):et(t,k(a,t))}else{if(!r[g])return f?t:{};a=xt(t,g,b)}}s||(s=new J);var $=s.get(t);if($)return $;s.set(t,a),vt(t)?t.forEach(function(c){a.add(l(c,e,n,c,t,s))}):Dt(t)&&t.forEach(function(c,i){a.set(i,l(c,e,n,i,t,s))});var G=D?y?ot:Q:y?j:F,S=A?void 0:G(t);return z(S||t,function(c,i){S&&(i=c,c=t[i]),Z(a,i,l(c,e,n,i,t,s))}),a}export{l as b}; import{d as T,k as F,e as j,o as C,s as _,b as N,g as v,p as K,q as E,m as R,r as p,t as u,v as B,j as q,f as H,l as W,n as Y,S as J,w as Q}from"./el-popper-d7593e54.js";import{ag as m,ai as M,ad as V,ah as X,aH as Z}from"./request-99bfbb00.js";function z(t,e){for(var n=-1,o=t==null?0:t.length;++n<o&&e(t[n],n,t)!==!1;);return t}function k(t,e){return t&&T(e,F(e),t)}function tt(t,e){return t&&T(e,j(e),t)}function et(t,e){return T(t,C(t),e)}var rt=Object.getOwnPropertySymbols,nt=rt?function(t){for(var e=[];t;)N(e,C(t)),t=v(t);return e}:_;const x=nt;function at(t,e){return T(t,x(t),e)}function ot(t){return K(t,j,x)}var st=Object.prototype,ct=st.hasOwnProperty;function it(t){var e=t.length,n=new t.constructor(e);return e&&typeof t[0]=="string"&&ct.call(t,"index")&&(n.index=t.index,n.input=t.input),n}function gt(t,e){var n=e?E(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.byteLength)}var ft=/\w*$/;function bt(t){var e=new t.constructor(t.source,ft.exec(t));return e.lastIndex=t.lastIndex,e}var w=m?m.prototype:void 0,I=w?w.valueOf:void 0;function yt(t){return I?Object(I.call(t)):{}}var ut="[object Boolean]",Tt="[object Date]",lt="[object Map]",jt="[object Number]",pt="[object RegExp]",At="[object Set]",dt="[object String]",$t="[object Symbol]",St="[object ArrayBuffer]",mt="[object DataView]",wt="[object Float32Array]",It="[object Float64Array]",Ot="[object Int8Array]",ht="[object Int16Array]",Ft="[object Int32Array]",Ct="[object Uint8Array]",Et="[object Uint8ClampedArray]",Bt="[object Uint16Array]",Mt="[object Uint32Array]";function xt(t,e,n){var o=t.constructor;switch(e){case St:return E(t);case ut:case Tt:return new o(+t);case mt:return gt(t,n);case wt:case It:case Ot:case ht:case Ft:case Ct:case Et:case Bt:case Mt:return R(t,n);case lt:return new o;case jt:case dt:return new o(t);case pt:return bt(t);case At:return new o;case $t:return yt(t)}}var Lt="[object Map]";function Ut(t){return M(t)&&p(t)==Lt}var O=u&&u.isMap,Pt=O?B(O):Ut;const Dt=Pt;var Gt="[object Set]";function _t(t){return M(t)&&p(t)==Gt}var h=u&&u.isSet,Nt=h?B(h):_t;const vt=Nt;var Kt=1,Rt=2,qt=4,L="[object Arguments]",Ht="[object Array]",Wt="[object Boolean]",Yt="[object Date]",Jt="[object Error]",U="[object Function]",Qt="[object GeneratorFunction]",Vt="[object Map]",Xt="[object Number]",P="[object Object]",Zt="[object RegExp]",zt="[object Set]",kt="[object String]",te="[object Symbol]",ee="[object WeakMap]",re="[object ArrayBuffer]",ne="[object DataView]",ae="[object Float32Array]",oe="[object Float64Array]",se="[object Int8Array]",ce="[object Int16Array]",ie="[object Int32Array]",ge="[object Uint8Array]",fe="[object Uint8ClampedArray]",be="[object Uint16Array]",ye="[object Uint32Array]",r={};r[L]=r[Ht]=r[re]=r[ne]=r[Wt]=r[Yt]=r[ae]=r[oe]=r[se]=r[ce]=r[ie]=r[Vt]=r[Xt]=r[P]=r[Zt]=r[zt]=r[kt]=r[te]=r[ge]=r[fe]=r[be]=r[ye]=!0;r[Jt]=r[U]=r[ee]=!1;function l(t,e,n,o,f,s){var a,b=e&Kt,y=e&Rt,D=e&qt;if(n&&(a=f?n(t,o,f,s):n(t)),a!==void 0)return a;if(!V(t))return t;var A=X(t);if(A){if(a=it(t),!b)return q(t,a)}else{var g=p(t),d=g==U||g==Qt;if(H(t))return W(t,b);if(g==P||g==L||d&&!f){if(a=y||d?{}:Y(t),!b)return y?at(t,tt(a,t)):et(t,k(a,t))}else{if(!r[g])return f?t:{};a=xt(t,g,b)}}s||(s=new J);var $=s.get(t);if($)return $;s.set(t,a),vt(t)?t.forEach(function(c){a.add(l(c,e,n,c,t,s))}):Dt(t)&&t.forEach(function(c,i){a.set(i,l(c,e,n,i,t,s))});var G=D?y?ot:Q:y?j:F,S=A?void 0:G(t);return z(S||t,function(c,i){S&&(i=c,c=t[i]),Z(a,i,l(c,e,n,i,t,s))}),a}export{l as b};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{c as _,b as N,au as P,n as W,u as H,H as k,B as v,_ as M,w as V}from"./request-e1d079d2.js";import{d as B,c as $,o as d,D as I,E as m,r as y,n as i,u as l,a as h,w as g,m as b,K as C,M as w,b as T,T as K}from"./index-128af1be.js";let f;const J=s=>{var a;if(!_)return 0;if(f!==void 0)return f;const o=document.createElement("div");o.className=`${s}-scrollbar__wrap`,o.style.visibility="hidden",o.style.width="100px",o.style.position="absolute",o.style.top="-9999px",document.body.appendChild(o);const n=o.offsetWidth;o.style.overflow="scroll";const e=document.createElement("div");e.style.width="100%",o.appendChild(e);const c=e.offsetWidth;return(a=o.parentNode)==null||a.removeChild(o),f=n-c,f};function L(s,a){if(!_)return;if(!a){s.scrollTop=0;return}const o=[];let n=a.offsetParent;for(;n!==null&&s!==n&&s.contains(n);)o.push(n),n=n.offsetParent;const e=a.offsetTop+o.reduce((t,p)=>t+p.offsetTop,0),c=e+a.offsetHeight,r=s.scrollTop,u=r+s.clientHeight;e<r?s.scrollTop=e:c>u&&(s.scrollTop=c-s.clientHeight)}const R=N({type:{type:String,values:["success","info","warning","danger",""],default:""},closable:Boolean,disableTransitions:Boolean,hit:Boolean,color:{type:String,default:""},size:{type:String,values:P,default:""},effect:{type:String,values:["dark","light","plain"],default:"light"},round:Boolean}),D={close:s=>s instanceof MouseEvent,click:s=>s instanceof MouseEvent},F=B({name:"ElTag"}),j=B({...F,props:R,emits:D,setup(s,{emit:a}){const o=s,n=W(),e=H("tag"),c=$(()=>{const{type:t,hit:p,effect:S,closable:E,round:z}=o;return[e.b(),e.is("closable",E),e.m(t),e.m(n.value),e.m(S),e.is("hit",p),e.is("round",z)]}),r=t=>{a("close",t)},u=t=>{a("click",t)};return(t,p)=>t.disableTransitions?(d(),I("span",{key:0,class:i(l(c)),style:T({backgroundColor:t.color}),onClick:u},[m("span",{class:i(l(e).e("content"))},[y(t.$slots,"default")],2),t.closable?(d(),h(l(v),{key:0,class:i(l(e).e("close")),onClick:C(r,["stop"])},{default:g(()=>[b(l(k))]),_:1},8,["class","onClick"])):w("v-if",!0)],6)):(d(),h(K,{key:1,name:`${l(e).namespace.value}-zoom-in-center`,appear:""},{default:g(()=>[m("span",{class:i(l(c)),style:T({backgroundColor:t.color}),onClick:u},[m("span",{class:i(l(e).e("content"))},[y(t.$slots,"default")],2),t.closable?(d(),h(l(v),{key:0,class:i(l(e).e("close")),onClick:C(r,["stop"])},{default:g(()=>[b(l(k))]),_:1},8,["class","onClick"])):w("v-if",!0)],6)]),_:3},8,["name"]))}});var q=M(j,[["__file","/home/runner/work/element-plus/element-plus/packages/components/tag/src/tag.vue"]]);const O=V(q);export{O as E,J as g,L as s,R as t}; import{c as _,b as N,au as P,n as W,u as H,H as k,B as v,_ as M,w as V}from"./request-99bfbb00.js";import{d as B,c as $,o as d,D as I,E as m,r as y,n as i,u as l,a as h,w as g,m as b,K as C,M as w,b as T,T as K}from"./index-50add468.js";let f;const J=s=>{var a;if(!_)return 0;if(f!==void 0)return f;const o=document.createElement("div");o.className=`${s}-scrollbar__wrap`,o.style.visibility="hidden",o.style.width="100px",o.style.position="absolute",o.style.top="-9999px",document.body.appendChild(o);const n=o.offsetWidth;o.style.overflow="scroll";const e=document.createElement("div");e.style.width="100%",o.appendChild(e);const c=e.offsetWidth;return(a=o.parentNode)==null||a.removeChild(o),f=n-c,f};function L(s,a){if(!_)return;if(!a){s.scrollTop=0;return}const o=[];let n=a.offsetParent;for(;n!==null&&s!==n&&s.contains(n);)o.push(n),n=n.offsetParent;const e=a.offsetTop+o.reduce((t,p)=>t+p.offsetTop,0),c=e+a.offsetHeight,r=s.scrollTop,u=r+s.clientHeight;e<r?s.scrollTop=e:c>u&&(s.scrollTop=c-s.clientHeight)}const R=N({type:{type:String,values:["success","info","warning","danger",""],default:""},closable:Boolean,disableTransitions:Boolean,hit:Boolean,color:{type:String,default:""},size:{type:String,values:P,default:""},effect:{type:String,values:["dark","light","plain"],default:"light"},round:Boolean}),D={close:s=>s instanceof MouseEvent,click:s=>s instanceof MouseEvent},F=B({name:"ElTag"}),j=B({...F,props:R,emits:D,setup(s,{emit:a}){const o=s,n=W(),e=H("tag"),c=$(()=>{const{type:t,hit:p,effect:S,closable:E,round:z}=o;return[e.b(),e.is("closable",E),e.m(t),e.m(n.value),e.m(S),e.is("hit",p),e.is("round",z)]}),r=t=>{a("close",t)},u=t=>{a("click",t)};return(t,p)=>t.disableTransitions?(d(),I("span",{key:0,class:i(l(c)),style:T({backgroundColor:t.color}),onClick:u},[m("span",{class:i(l(e).e("content"))},[y(t.$slots,"default")],2),t.closable?(d(),h(l(v),{key:0,class:i(l(e).e("close")),onClick:C(r,["stop"])},{default:g(()=>[b(l(k))]),_:1},8,["class","onClick"])):w("v-if",!0)],6)):(d(),h(K,{key:1,name:`${l(e).namespace.value}-zoom-in-center`,appear:""},{default:g(()=>[m("span",{class:i(l(c)),style:T({backgroundColor:t.color}),onClick:u},[m("span",{class:i(l(e).e("content"))},[y(t.$slots,"default")],2),t.closable?(d(),h(l(v),{key:0,class:i(l(e).e("close")),onClick:C(r,["stop"])},{default:g(()=>[b(l(k))]),_:1},8,["class","onClick"])):w("v-if",!0)],6)]),_:3},8,["name"]))}});var q=M(j,[["__file","/home/runner/work/element-plus/element-plus/packages/components/tag/src/tag.vue"]]);const O=V(q);export{O as E,J as g,L as s,R as t};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{P as A,a6 as N}from"./index-128af1be.js";var o=(E=>(E[E.TEXT=1]="TEXT",E[E.CLASS=2]="CLASS",E[E.STYLE=4]="STYLE",E[E.PROPS=8]="PROPS",E[E.FULL_PROPS=16]="FULL_PROPS",E[E.HYDRATE_EVENTS=32]="HYDRATE_EVENTS",E[E.STABLE_FRAGMENT=64]="STABLE_FRAGMENT",E[E.KEYED_FRAGMENT=128]="KEYED_FRAGMENT",E[E.UNKEYED_FRAGMENT=256]="UNKEYED_FRAGMENT",E[E.NEED_PATCH=512]="NEED_PATCH",E[E.DYNAMIC_SLOTS=1024]="DYNAMIC_SLOTS",E[E.HOISTED=-1]="HOISTED",E[E.BAIL=-2]="BAIL",E))(o||{});const e=E=>{const _=A(E)?E:[E],S=[];return _.forEach(T=>{var r;A(T)?S.push(...e(T)):N(T)&&A(T.children)?S.push(...e(T.children)):(S.push(T),N(T)&&((r=T.component)!=null&&r.subTree)&&S.push(...e(T.component.subTree)))}),S};export{o as P,e as f}; import{P as A,a7 as N}from"./index-50add468.js";var o=(E=>(E[E.TEXT=1]="TEXT",E[E.CLASS=2]="CLASS",E[E.STYLE=4]="STYLE",E[E.PROPS=8]="PROPS",E[E.FULL_PROPS=16]="FULL_PROPS",E[E.HYDRATE_EVENTS=32]="HYDRATE_EVENTS",E[E.STABLE_FRAGMENT=64]="STABLE_FRAGMENT",E[E.KEYED_FRAGMENT=128]="KEYED_FRAGMENT",E[E.UNKEYED_FRAGMENT=256]="UNKEYED_FRAGMENT",E[E.NEED_PATCH=512]="NEED_PATCH",E[E.DYNAMIC_SLOTS=1024]="DYNAMIC_SLOTS",E[E.HOISTED=-1]="HOISTED",E[E.BAIL=-2]="BAIL",E))(o||{});const e=E=>{const _=A(E)?E:[E],S=[];return _.forEach(T=>{var r;A(T)?S.push(...e(T)):N(T)&&A(T.children)?S.push(...e(T.children)):(S.push(T),N(T)&&((r=T.component)!=null&&r.subTree)&&S.push(...e(T.component.subTree)))}),S};export{o as P,e as f};
+1 -1
View File
@@ -8,7 +8,7 @@
<meta name="keywords" content="{{keywords}}" /> <meta name="keywords" content="{{keywords}}" />
<meta name="generator" content="FileCodeBox2.0" /> <meta name="generator" content="FileCodeBox2.0" />
<title>{{title}}</title> <title>{{title}}</title>
<script type="module" crossorigin src="/assets/index-128af1be.js"></script> <script type="module" crossorigin src="/assets/index-50add468.js"></script>
<link rel="stylesheet" href="/assets/index-b9599089.css"> <link rel="stylesheet" href="/assets/index-b9599089.css">
</head> </head>
<body style="background: url('{{background}}') no-repeat center center fixed;background-size: cover;"> <body style="background: url('{{background}}') no-repeat center center fixed;background-size: cover;">
+1
View File
@@ -27,6 +27,7 @@
"unplugin-auto-import": "^0.16.6", "unplugin-auto-import": "^0.16.6",
"unplugin-vue-components": "^0.25.1", "unplugin-vue-components": "^0.25.1",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-i18n": "^9.3.0",
"vue-router": "^4.2.4" "vue-router": "^4.2.4"
}, },
"devDependencies": { "devDependencies": {
+15 -11
View File
@@ -11,6 +11,10 @@ const fileBoxStore = useFileBoxStore();
import QrcodeVue from "qrcode.vue"; import QrcodeVue from "qrcode.vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { ref } from "vue"; import { ref } from "vue";
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
const openUrl = (url: string) => { const openUrl = (url: string) => {
if (url.startsWith('/')) { if (url.startsWith('/')) {
@@ -21,7 +25,7 @@ const openUrl = (url: string) => {
const route = useRoute(); const route = useRoute();
const copyText = (text: any, style = 0) => { const copyText = (text: any, style = 0) => {
ElMessage.success('复制成功') ElMessage.success(t('fileBox.copySuccess'));
if (style === 1) { if (style === 1) {
text = window.location.origin + '/#/?code=' + text; text = window.location.origin + '/#/?code=' + text;
} }
@@ -62,29 +66,29 @@ function renderMarkdown(message: string) {
<el-drawer :append-to-body="true" v-model="fileBoxStore.showFileBox" direction="btt" style="max-width: 1080px;margin: auto;" <el-drawer :append-to-body="true" v-model="fileBoxStore.showFileBox" direction="btt" style="max-width: 1080px;margin: auto;"
size="400"> size="400">
<template #header> <template #header>
<h4>文件箱</h4> <h4>{{t('fileBox.fileBox')}}</h4>
</template> </template>
<template #default> <template #default>
<div v-if="route.name=='home'" style="display: flex;flex-wrap: wrap;justify-content: center"> <div v-if="route.name=='home'" style="display: flex;flex-wrap: wrap;justify-content: center">
<el-dialog <el-dialog
append-to-body append-to-body
align-center align-center
title="文本详情" :title="t('fileBox.textDetail')"
width="70%" width="70%"
style="height: 70%;overflow-y: scroll" style="height: 70%;overflow-y: scroll"
v-model="showTextDetailVisible" v-model="showTextDetailVisible"
> >
<div style="max-width: 100%;overflow-y: scroll" v-html="renderMarkdown(nowText)"></div> <div style="max-width: 100%;overflow-y: scroll" v-html="renderMarkdown(nowText)"></div>
<template #footer> <template #footer>
<el-button type="success" @click="copyText(nowText);showTextDetailVisible = false"> </el-button> <el-button type="success" @click="copyText(nowText);showTextDetailVisible = false">{{t('fileBox.copy')}}</el-button>
<el-button type="primary" @click="showTextDetailVisible = false"> </el-button> <el-button type="primary" @click="showTextDetailVisible = false">{{ t('fileBox.close') }}</el-button>
</template> </template>
</el-dialog> </el-dialog>
<el-card v-for="(value,index) in fileStore.receiveData" :key="index" style="margin: 0.5rem"> <el-card v-for="(value,index) in fileStore.receiveData" :key="index" style="margin: 0.5rem">
<template #header> <template #header>
<div style="display: flex;justify-content: space-between"> <div style="display: flex;justify-content: space-between">
<h4 style="width: 6rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{{ value.name }}</h4> <h4 style="width: 6rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{{ value.name }}</h4>
<el-button size="small" type="danger" @click="fileStore.deleteReceiveData(index)">删除</el-button> <el-button size="small" type="danger" @click="fileStore.deleteReceiveData(index)">{{ t('fileBox.delete') }}</el-button>
</div> </div>
</template> </template>
<div style="width: 200px;"> <div style="width: 200px;">
@@ -94,9 +98,9 @@ function renderMarkdown(message: string) {
<div style="display: flex;flex-direction: column;justify-content: space-around"> <div style="display: flex;flex-direction: column;justify-content: space-around">
<el-tag size="large" style="cursor: pointer" @click="copyText(value.code)">{{ value.code }}</el-tag> <el-tag size="large" style="cursor: pointer" @click="copyText(value.code)">{{ value.code }}</el-tag>
<el-tag v-if="value.name!=='文本分享'" size="large" type="success" style="cursor: pointer" @click="openUrl(value.text);"> <el-tag v-if="value.name!=='文本分享'" size="large" type="success" style="cursor: pointer" @click="openUrl(value.text);">
点击下载 {{ t('fileBox.download') }}
</el-tag> </el-tag>
<el-tag v-else size="large" type="success" style="cursor: pointer" @click="showTextDetail(value.text);">查看详情</el-tag> <el-tag v-else size="large" type="success" style="cursor: pointer" @click="showTextDetail(value.text);">{{ t('fileBox.detail') }}</el-tag>
</div> </div>
</div> </div>
</div> </div>
@@ -107,17 +111,17 @@ function renderMarkdown(message: string) {
<template #header> <template #header>
<div style="display: flex;justify-content: space-between"> <div style="display: flex;justify-content: space-between">
<h4 style="width: 6rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{{ value.name }}</h4> <h4 style="width: 6rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{{ value.name }}</h4>
<el-button size="small" type="danger" @click="fileStore.deleteShareData(index)">删除</el-button> <el-button size="small" type="danger" @click="fileStore.deleteShareData(index)">{{ t('fileBox.delete') }}</el-button>
</div> </div>
</template> </template>
<div style="width: 200px;"> <div style="width: 200px;">
<el-progress v-if="value.status!='success' && value.status!='fail'" striped :percentage="value.percentage" :text-inside="true" <el-progress v-if="value.status!='success' && value.status!='fail'" striped :percentage="value.percentage" :text-inside="true"
:stroke-width="20"></el-progress> :stroke-width="20"></el-progress>
<div style="display: flex;justify-content: space-between"> <div v-else style="display: flex;justify-content: space-between">
<qrcode-vue :value="value.text" :size="100"></qrcode-vue> <qrcode-vue :value="value.text" :size="100"></qrcode-vue>
<div style="display: flex;flex-direction: column;justify-content: space-around"> <div style="display: flex;flex-direction: column;justify-content: space-around">
<el-tag size="large" style="cursor: pointer" @click="copyText(value.code)">{{ value.code }}</el-tag> <el-tag size="large" style="cursor: pointer" @click="copyText(value.code)">{{ value.code }}</el-tag>
<el-tag size="large" type="success" style="cursor: pointer" @click="copyText(value.code,1);">复制链接 <el-tag size="large" type="success" style="cursor: pointer" @click="copyText(value.code,1);">{{ t('fileBox.copyLink') }}
</el-tag> </el-tag>
</div> </div>
</div> </div>
+5 -3
View File
@@ -4,7 +4,9 @@ import { ref, onMounted, onUnmounted } from 'vue'
import { request } from "@/utils/request"; import { request } from "@/utils/request";
import { useFileDataStore } from "@/stores/fileData"; import { useFileDataStore } from "@/stores/fileData";
import { useFileBoxStore } from "@/stores/fileBox"; import { useFileBoxStore } from "@/stores/fileBox";
import { ElMessage } from "element-plus"; import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const fileBoxStore = useFileBoxStore(); const fileBoxStore = useFileBoxStore();
const fileStore = useFileDataStore(); const fileStore = useFileDataStore();
const props = defineProps({ const props = defineProps({
@@ -131,9 +133,9 @@ onMounted(()=>{
<upload-filled/> <upload-filled/>
</el-icon> </el-icon>
<div class="el-upload__text"> <div class="el-upload__text">
将文字文件拖粘贴到此处 <em>点击上传</em> {{t('send.prompt1')}}<em>{{t('send.clickUpload')}}</em>
</div> </div>
<div class="el-upload__text" style="font-size: 10px;">天数&lt;7或限制次数24h后删除</div> <div class="el-upload__text" style="font-size: 10px;">{{t('send.prompt2')}}</div>
<template #tip> <template #tip>
<div class="el-upload__tip"> <div class="el-upload__tip">
</div> </div>
+8 -4
View File
@@ -5,6 +5,10 @@ const shareText = ref('')
import { useFileDataStore } from "@/stores/fileData"; import { useFileDataStore } from "@/stores/fileData";
import { useFileBoxStore } from "@/stores/fileBox"; import { useFileBoxStore } from "@/stores/fileBox";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const fileBoxStore = useFileBoxStore(); const fileBoxStore = useFileBoxStore();
const fileStore = useFileDataStore(); const fileStore = useFileDataStore();
const props = defineProps({ const props = defineProps({
@@ -20,7 +24,7 @@ const props = defineProps({
}) })
const handleSubmitShareText = ()=>{ const handleSubmitShareText = ()=>{
if (shareText.value === '') { if (shareText.value === '') {
ElMessage.warning('请输入您要分享的文本'); ElMessage.warning(t('send.prompt3'));
} else { } else {
const formData = new FormData(); const formData = new FormData();
formData.append('text', shareText.value); formData.append('text', shareText.value);
@@ -34,7 +38,7 @@ const handleSubmitShareText = ()=>{
const data = res.detail; const data = res.detail;
fileBoxStore.showFileBox = true; fileBoxStore.showFileBox = true;
fileStore.addShareData({ fileStore.addShareData({
'name': '文本分享', 'name': t('send.textShare'),
'text': data.text, 'text': data.text,
'code': data.code, 'code': data.code,
'status': 'success', 'status': 'success',
@@ -51,14 +55,14 @@ const handleSubmitShareText = ()=>{
<template> <template>
<div style="position: relative"> <div style="position: relative">
<el-input <el-input
placeholder="请输入您要寄出的文本" :placeholder="t('send.prompt3')"
v-model="shareText" v-model="shareText"
type="textarea" type="textarea"
:rows="9" :rows="9"
:input-style="{'border-radius':'20px','border':'1px dashed var(--el-border-color)','box-shadow':'none'}" :input-style="{'border-radius':'20px','border':'1px dashed var(--el-border-color)','box-shadow':'none'}"
> >
</el-input> </el-input>
<el-button @click="handleSubmitShareText" style="position: absolute;right: 0;top: 0;border-radius: 0 20px 0 20px;margin: 1px;background: rgba(255,255,255,0.2)" size="large">分享</el-button> <el-button @click="handleSubmitShareText" style="position: absolute;right: 0;top: 0;border-radius: 0 20px 0 20px;margin: 1px;background: rgba(255,255,255,0.2)" size="large">{{t('send.share')}}</el-button>
</div> </div>
</template> </template>
+102
View File
@@ -0,0 +1,102 @@
export default {
send: {
'prompt1': 'Drag and drop text or files here, or ',
'prompt2': 'Days <7 or limited times (deleted after 24h)',
'prompt3':'Please enter the text you want to send',
'share':'Share',
'textShare':'Text Share',
'clickUpload': 'Click to upload',
'pleaseInputExpireValue': 'Please enter expiration value',
'expireStyle': 'Expiration style',
'expireData':{
'day': 'Days',
'hour': 'Hours',
'forever': 'Forever',
'minute': 'Minutes',
'count': 'Times'
},
'expireValue':{
'day': 'Days',
'hour': 'Hours',
'minute': 'Minutes',
'count': 'Times'
},
'fileType':{
'file': 'File',
'text': 'Text'
}
},
fileBox: {
copySuccess: 'Copied successfully',
fileBox: 'File Box',
textDetail: 'Text Detail',
copy: 'Copy',
close: 'Close',
delete: 'Delete',
download: 'Click to download',
detail: 'View details',
copyLink: 'Copy link',
},
admin:{
about:{
'source1':'This project is open source on Github: ',
'source2':'FileCodeBox'
},
settings: {
name: 'Website Name',
description: 'Website Description',
keywords: 'Keywords',
background: 'Background Image',
admin_token: 'Admin Password',
uploadSize: 'File Size',
uploadSizeNote: 'Maximum file size, unit: (bit), 1mb = 1 * 1024 * 1024',
openUpload: {
'title': 'Enable Upload',
'open': 'Enable Guest Upload',
'close': 'Disable Guest Upload',
'note': 'After disabling, login to the backend is required for uploading.',
},
file_storage: {
'title': 'Storage Engine',
'local': 'Local Storage',
's3': 'S3 Storage',
'note': 'FileCodeBox needs to be restarted after updating.',
},
mei: 'Every',
minute: 'Minutes',
upload: 'Upload',
files: 'Files',
allow: 'Allow',
errors: 'Errors',
save: 'Save',
saveSuccess: 'Saved successfully',
},
fileView: {
code: 'Access Code',
prefix: 'File Prefix',
suffix: 'File Suffix',
text: 'Text',
used_count: 'Used Count',
expired_count: 'Available Count',
size: 'File Size',
expired_at: 'Expiration Time',
file_path: 'File Path',
action: 'Action',
delete: 'Delete',
},
'menu': {
'fileManage': 'File Management',
'systemSetting': 'System Settings',
'about': 'About Us',
'color': 'Color Mode',
'signout': 'Sign Out',
},
login: {
'managePassword': 'Admin Password',
'passwordNotEmpty': 'Password cannot be empty',
'login': 'Login',
'loginSuccess': 'Login successful',
'loginError': 'Login failed',
}
}
}
+17
View File
@@ -0,0 +1,17 @@
import { createI18n } from 'vue-i18n' //引入vue-i18n组件
import messages from './index'
const language = (
navigator.language || 'zh'
).toLowerCase();
const lang = localStorage.getItem('language') || language
const i18n = createI18n({
silentTranslationWarn: true,
globalInjection: true,
legacy: false,
locale: lang,
messages,
});
export default i18n
+8
View File
@@ -0,0 +1,8 @@
import zh from './zh'
import en from './en'
export default {
zh,
en
}
+102
View File
@@ -0,0 +1,102 @@
export default {
send: {
'prompt1': '将文字、文件拖、粘贴到此处,或 ',
'prompt2': '天数<7或限制次数(24h后删除)',
'prompt3':'请输入您要寄出的文本',
'share':'分享',
'textShare':'文本分享',
'clickUpload': '点击上传',
'pleaseInputExpireValue': '请输入有效期',
'expireStyle': '过期方式',
'expireData':{
'day': '天数',
'hour': '小时',
'forever': '永久',
'minute': '分钟',
'count': '次数'
},
'expireValue':{
'day': '天',
'hour': '时',
'minute': '分',
'count': '次'
},
'fileType':{
'file': '文件',
'text': '文本'
}
},
fileBox: {
copySuccess: '复制成功',
fileBox: '文件箱',
textDetail: '文本详情',
copy: '复 制',
close: '关 闭',
delete: '删 除',
download: '点 击 下 载',
detail: '查 看 详 情',
copyLink: '复制链接',
},
admin:{
about:{
'source1':'本项目开源于Github',
'source2':'FileCodeBox'
},
settings: {
name: '网站名称',
description: '网站描述',
keywords: '关键词',
background: '背景图片',
admin_token: '管理密码',
uploadSize: '文件大小',
uploadSizeNote: '最大文件大小,单位:bit),1mb=1 * 1024 * 1024',
openUpload: {
'title': '开启上传',
'open': '开启游客上传',
'close': '关闭游客上传',
'note': '关闭之后需要登录后台方可上传',
},
file_storage: {
'title': '存储引擎',
'local': '本地存储',
's3': 'S3存储',
'note': '更新后需要重启FileCodeBox',
},
mei: '每',
minute: '分钟',
upload: '上传',
files: '个文件',
allow: '允许',
errors: '次错误',
save: '保存',
saveSuccess: '保存成功',
},
fileView: {
code: '取件码',
prefix: '文件前缀',
suffix: '文件后缀',
text: '文本',
used_count: '已使用次数',
expired_count: '可用次数',
size: '文件大小',
expired_at: '过期时间',
file_path: '文件路径',
action: '操作',
delete: '删除',
},
'menu': {
'fileManage': '文件管理',
'systemSetting': '系统设置',
'about': '关于我们',
'color': '颜色模式',
'signout': '退出登录',
},
login: {
'managePassword': '管理密码',
'passwordNotEmpty': '密码不能为空',
'login': '登 录',
'loginSuccess': '登录成功',
'loginError': '登录失败',
}
}
}
+2
View File
@@ -5,9 +5,11 @@ import { createApp } from 'vue'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import i18n from "./locals/i18n";
const app = createApp(App) const app = createApp(App)
app.use(createPinia()) app.use(createPinia())
app.use(i18n)
app.use(router) app.use(router)
app.mount('#app') app.mount('#app')
+5 -2
View File
@@ -1,12 +1,15 @@
<template> <template>
<main style="text-align: center"> <main style="text-align: center">
<span>本项目开源于Github <span>{{ t('admin.about.source1') }}
<em> <em>
<a style="color: #333" href="https://github.com/vastsa/FileCodeBox">FileCodeBox</a> <a style="color: #333" href="https://github.com/vastsa/FileCodeBox">{{ t('admin.about.source2') }}</a>
</em> </em>
</span> </span>
</main> </main>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script> </script>
+13 -10
View File
@@ -3,8 +3,8 @@
<el-header> <el-header>
<el-menu mode="horizontal" router :default-active="route.path"> <el-menu mode="horizontal" router :default-active="route.path">
<el-menu-item v-for="menu in menus" :index="menu.path" :key="menu.path">{{menu.name}}</el-menu-item> <el-menu-item v-for="menu in menus" :index="menu.path" :key="menu.path">{{menu.name}}</el-menu-item>
<el-menu-item style="float: right" @click="toggleDark(!isDark)">颜色模式</el-menu-item> <el-menu-item style="float: right" @click="toggleDark(!isDark)">{{ t('admin.menu.color') }}</el-menu-item>
<el-menu-item style="float: right" @click="adminData.updateAdminPwd('');isLogin=false">注销登录</el-menu-item> <el-menu-item style="float: right" @click="adminData.updateAdminPwd('');isLogin=false">{{ t('admin.menu.signout') }}</el-menu-item>
</el-menu> </el-menu>
</el-header> </el-header>
<el-main> <el-main>
@@ -12,14 +12,14 @@
</el-main> </el-main>
</el-container> </el-container>
<el-form size="large" v-else> <el-form size="large" v-else>
<el-form-item label="管理密码"> <el-form-item :label="t('admin.managePassword')">
<el-input <el-input
v-model="adminData.adminPassword" v-model="adminData.adminPassword"
placeholder="请输入密码!" :placeholder="t('admin.passwordNotEmpty')"
type="password" type="password"
> >
<template #append> <template #append>
<el-button @click="refreshLoginStatus">登录</el-button> <el-button @click="refreshLoginStatus">{{ t('admin.login') }}</el-button>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@@ -36,19 +36,22 @@ import { useAdminData } from "@/stores/adminData";
import { request } from "@/utils/request"; import { request } from "@/utils/request";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const adminData = useAdminData(); const adminData = useAdminData();
const route = useRoute(); const route = useRoute();
const menus = ref([ const menus = ref([
{ {
name: '文件管理', name: t('admin.menu.fileManage'),
path: '/admin', path: '/admin',
}, },
{ {
name: '系统设置', name: t('admin.menu.systemSetting'),
path: '/admin/setting', path: '/admin/setting',
}, },
{ {
name: '关于我们', name: t('admin.menu.about'),
path: '/admin/about', path: '/admin/about',
} }
]); ]);
@@ -60,9 +63,9 @@ const refreshLoginStatus = () => {
}).then((res: any) => { }).then((res: any) => {
if (res.code === 200) { if (res.code === 200) {
isLogin.value = true; isLogin.value = true;
ElMessage.success('登录成功!'); ElMessage.success(t('admin.loginSuccess'));
} else { } else {
ElMessage.error(res.detail); ElMessage.error(t('admin.loginError'));
} }
}); });
}; };
+23 -11
View File
@@ -1,24 +1,33 @@
<template> <template>
<main> <main>
<el-table size="large" stripe :data="tableData" style="width: 100%"> <el-table size="large" stripe :data="tableData" style="width: 100%">
<el-table-column prop="code" label="取件码" /> <el-table-column prop="code" :label="t('admin.fileView.code')" />
<el-table-column prop="prefix" label="文件前缀" /> <el-table-column prop="prefix" :label="t('admin.fileView.prefix')" />
<el-table-column prop="suffix" label="后缀" /> <el-table-column prop="suffix" :label="t('admin.fileView.suffix')" />
<el-table-column prop="text" label="文本"> <el-table-column prop="text" :label="t('admin.fileView.text')">
<template #default="scope"> <template #default="scope">
<span style="width: 6rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{{ scope.row.text }}</span> <span style="width: 6rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{{ scope.row.text }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="used_count" label="已用次数" /> <el-table-column prop="used_count" :label="t('admin.fileView.used_count')" />
<el-table-column prop="expired_count" label="可用次数" /> <el-table-column prop="expired_count" :label="t('admin.fileView.expired_count')" />
<el-table-column prop="expired_at" label="到期时间" /> <el-table-column prop="size" :label="t('admin.fileView.size')">
<el-table-column prop="file_path" label="文件路径" /> <template #default="scope">
<span>{{ Math.round(scope.row.size/1024/1024*100)/100 }}MB</span>
</template>
</el-table-column>
<el-table-column prop="expired_at" :label="t('admin.fileView.expired_at')">
<template #default="scope">
<span>{{ scope.row.expired_at ? scope.row.expired_at : '永久有效' }}</span>
</template>
</el-table-column>
<el-table-column prop="file_path" :label="t('admin.fileView.file_path')" />
<el-table-column> <el-table-column>
<template #header> <template #header>
操作 {{ t('admin.fileView.action')}}
</template> </template>
<template #default="scope"> <template #default="scope">
<el-button type="danger" size="small" @click="deleteFile(scope.row.id)">删除</el-button> <el-button type="danger" size="small" @click="deleteFile(scope.row.id)">{{ t('admin.fileView.delete') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -29,8 +38,11 @@
import { request } from "@/utils/request"; import { request } from "@/utils/request";
import { ref } from "vue"; import { ref } from "vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
const tableData = ref([]); const tableData = ref([]);
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const params = ref({ const params = ref({
page: 1, page: 1,
size: 10, size: 10,
+31 -27
View File
@@ -1,38 +1,38 @@
<template> <template>
<el-form> <el-form>
<el-form-item size="large" label="网站名称"> <el-form-item size="large" :label="t('admin.settings.name')">
<el-input v-model="config.name" /> <el-input v-model="config.name" />
</el-form-item> </el-form-item>
<el-form-item size="large" label="网站描述"> <el-form-item size="large" :label="t('admin.settings.description')">
<el-input v-model="config.description" /> <el-input v-model="config.description" />
</el-form-item> </el-form-item>
<el-form-item size="large" label="关键词" style="letter-spacing: 0.3rem"> <el-form-item size="large" :label="t('admin.settings.keywords')" style="letter-spacing: 0.3rem">
<el-input v-model="config.keywords" /> <el-input v-model="config.keywords" />
</el-form-item> </el-form-item>
<el-form-item size="large" label="背景图片"> <el-form-item size="large" :label="t('admin.settings.background')">
<el-input v-model="config.background" /> <el-input v-model="config.background" />
</el-form-item> </el-form-item>
<el-form-item size="large" label="后台密码"> <el-form-item size="large" :label="t('admin.settings.admin_token')">
<el-input type="password" v-model="config.admin_token" /> <el-input type="password" v-model="config.admin_token" />
</el-form-item> </el-form-item>
<el-form-item size="large" label="文件大小"> <el-form-item size="large" :label="t('admin.settings.uploadSize')">
<el-input type="number" v-model="config.uploadSize" /> <el-input type="number" v-model="config.uploadSize" />
<template #append>Bit</template> <template #append>Bit</template>
<small>最大文件大小单位:bit),1mb=1 * 1024 * 1024</small> <small>{{ t('admin.settings.uploadSizeNote') }}</small>
</el-form-item> </el-form-item>
<el-form-item size="large" label="开启上传"> <el-form-item size="large" :label="t('admin.settings.openUpload.title')">
<el-select v-model="config.openUpload"> <el-select v-model="config.openUpload">
<el-option label="开启游客上传" :value="1" /> <el-option :label="t('admin.settings.openUpload.open')" :value="1" />
<el-option label="关闭游客上传" :value="0" /> <el-option :label="t('admin.settings.openUpload.close')" :value="0" />
</el-select> </el-select>
<small style="margin-left: 0.4rem">关闭之后需要登录后台方可上传</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="存储引擎"> <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">
<el-option label="本地存储" value="local" /> <el-option :label="t('admin.settings.file_storage.local')" value="local" />
<el-option label="S3存储" value="s3" /> <el-option :label="t('admin.settings.file_storage.s3')" value="s3" />
</el-select> </el-select>
<small style="margin-left: 0.4rem">更新后需要重启FileCodeBox</small> <small style="margin-left: 0.4rem">{{ t('admin.settings.file_storage.note') }}</small>
</el-form-item> </el-form-item>
<div v-if="config.file_storage==='s3'"> <div v-if="config.file_storage==='s3'">
<el-form-item size="large" label="S3 AccessKeyId"> <el-form-item size="large" label="S3 AccessKeyId">
@@ -48,32 +48,32 @@
<el-input v-model="config.s3_endpoint_url" /> <el-input v-model="config.s3_endpoint_url" />
</el-form-item> </el-form-item>
</div> </div>
<el-form-item size="large" label="上传限制"> <el-form-item size="large" :label="t('admin.settings.name')">
<span style="display: flex;height: 38px"> <span style="display: flex;height: 38px">
<span style="margin-right: 0.4rem"></span> <span style="margin-right: 0.4rem">{{ t('admin.settings.mei') }}</span>
<el-input type="number" v-model="config.uploadMinute" /> <el-input type="number" v-model="config.uploadMinute" />
<span style="width: 200px;margin-left: 0.4rem">分钟</span> <span style="width: 200px;margin-left: 0.4rem">{{ t('admin.settings.minute') }}</span>
</span> </span>
<span style="display: flex;height: 38px"> <span style="display: flex;height: 38px">
<span style="width:3rem;margin-right: 0.4rem">上传</span> <span style="width:3rem;margin-right: 0.4rem">{{ t('admin.settings.upload') }}</span>
<el-input type="number" v-model="config.uploadCount" /> <el-input type="number" v-model="config.uploadCount" />
<span style="width: 200px;margin-left: 0.4rem">个文件</span> <span style="width: 200px;margin-left: 0.4rem">{{ t('admin.settings.files') }}</span>
</span> </span>
</el-form-item> </el-form-item>
<el-form-item size="large" label="错误限制"> <el-form-item size="large" :label="t('admin.settings.name')">
<span style="display: flex;height: 38px"> <span style="display: flex;height: 38px">
<span style="margin-right: 0.4rem"></span> <span style="margin-right: 0.4rem">{{ t('admin.settings.mei') }}</span>
<el-input type="number" v-model="config.errorMinute" /> <el-input type="number" v-model="config.errorMinute" />
<span style="width: 200px;margin-left: 0.4rem">分钟</span> <span style="width: 200px;margin-left: 0.4rem">{{ t('admin.settings.minute') }}</span>
</span> </span>
<span style="display: flex;height: 38px"> <span style="display: flex;height: 38px">
<span style="width:3rem;margin-right: 0.4rem">允许</span> <span style="width:3rem;margin-right: 0.4rem">{{ t('admin.settings.allow') }}</span>
<el-input type="number" v-model="config.errorCount" /> <el-input type="number" v-model="config.errorCount" />
<span style="width: 200px;margin-left: 0.4rem">次错误</span> <span style="width: 200px;margin-left: 0.4rem">{{ t('admin.settings.errors') }}</span>
</span> </span>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="submitSave" type="primary" style="margin: auto">保存</el-button> <el-button @click="submitSave" type="primary" style="margin: auto">{{ t('admin.settings.save') }}</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
@@ -82,6 +82,10 @@ import {ref} from "vue";
import { request } from "@/utils/request"; import { request } from "@/utils/request";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const config = ref({ const config = ref({
name: '', name: '',
description: '', description: '',
@@ -116,7 +120,7 @@ const submitSave = () => {
data: config.value data: config.value
}).then((res: any) => { }).then((res: any) => {
if (res.code == 200) { if (res.code == 200) {
ElMessage.success('保存成功'); ElMessage.success(t('admin.settings.saveSuccess'));
} else { } else {
ElMessage.error(res.message); ElMessage.error(res.message);
} }
+21 -13
View File
@@ -3,6 +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'
const { t } = useI18n()
const shareData = ref({ const shareData = ref({
expireValue: 1, expireValue: 1,
expireStyle: 'day', expireStyle: 'day',
@@ -19,29 +23,33 @@ const shareData = ref({
<el-input <el-input
v-model="shareData.expireValue" v-model="shareData.expireValue"
style="width: 200px" style="width: 200px"
placeholder="请输入值" :placeholder="t('send.pleaseInputExpireValue')"
> >
<template #prepend> <template #prepend>
<el-select v-model="shareData.expireStyle" placeholder="过期方式" style="width: 75px"> <el-select v-model="shareData.expireStyle" :placeholder="t('send.expireStyle')" style="width: 75px">
<el-option label="天数" value="day" /> <el-option :label="t('send.expireData.day')" value="day" />
<el-option label="小时" value="hour" /> <el-option :label="t('send.expireData.hour')" value="hour" />
<el-option label="分钟" value="minute" /> <el-option :label="t('send.expireData.minute')" value="minute" />
<el-option label="永久" value="forever" /> <el-option :label="t('send.expireData.forever')" value="forever" />
<el-option label="次数" value="count" /> <el-option :label="t('send.expireData.count')" value="count" />
</el-select> </el-select>
</template> </template>
<template #append> <template #append>
<span v-if="shareData.expireStyle=='day'"></span> <span v-if="shareData.expireStyle=='day'">{{t('send.expireValue.day')}}</span>
<span v-else-if="shareData.expireStyle=='hour'"></span> <span v-else-if="shareData.expireStyle=='hour'">{{t('send.expireValue.hour')}}</span>
<span v-else-if="shareData.expireStyle=='minute'"></span> <span v-else-if="shareData.expireStyle=='minute'">{{t('send.expireValue.minute')}}</span>
<span v-else-if="shareData.expireStyle=='forever'">👌</span> <span v-else-if="shareData.expireStyle=='forever'">👌</span>
<span v-else-if="shareData.expireStyle=='count'"></span> <span v-else-if="shareData.expireStyle=='count'">{{t('send.expireValue.count')}}</span>
</template> </template>
</el-input> </el-input>
</div> </div>
<el-radio-group v-model="shareData.targetType" style="margin-left: 1rem;"> <el-radio-group v-model="shareData.targetType" style="margin-left: 1rem;">
<el-radio label="file">文件</el-radio> <el-radio label="file">
<el-radio label="text">文本</el-radio> {{t('send.fileType.file')}}
</el-radio>
<el-radio label="text">
{{t('send.fileType.text')}}
</el-radio>
</el-radio-group> </el-radio-group>
</div> </div>
<div style="margin-top: 1rem"> <div style="margin-top: 1rem">
+48
View File
@@ -208,6 +208,44 @@
resolved "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" resolved "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@intlify/core-base@9.3.0":
version "9.3.0"
resolved "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.3.0.tgz#fa42e32f89f06d421772fcedeec7dfba845ba98f"
integrity sha512-SRzn8TMnPZ6MY8OFrgouRq4DGaf01SHcJEF6FglYFYvRkgPzziEcQe+v2PD+O5lUp/rJafP4dabm1CmsVAA7rA==
dependencies:
"@intlify/devtools-if" "9.3.0"
"@intlify/message-compiler" "9.3.0"
"@intlify/shared" "9.3.0"
"@intlify/vue-devtools" "9.3.0"
"@intlify/devtools-if@9.3.0":
version "9.3.0"
resolved "https://registry.npmmirror.com/@intlify/devtools-if/-/devtools-if-9.3.0.tgz#ae5a4d3577e05577e65bb6abbb0506d8af9309f6"
integrity sha512-5aKZnqj0Ff4dfwBX2Oo+MheVs00CBnC0RzWK26aT2M4AF0cxdFLOJAs51/eHT01jmzrxSvfBMjdArUWHwgetfg==
dependencies:
"@intlify/shared" "9.3.0"
"@intlify/message-compiler@9.3.0":
version "9.3.0"
resolved "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.3.0.tgz#203366fe7448255731e951507c4d79093bf898b1"
integrity sha512-D8tSJEhTCSFcCzkThjE4Sbk1tIdvzkYa1FaVIzUtZ8hKPATvokNrOiDw1i/h671m8A80l9Ywq594i/LPTB6EJA==
dependencies:
"@intlify/shared" "9.3.0"
source-map-js "^1.0.2"
"@intlify/shared@9.3.0":
version "9.3.0"
resolved "https://registry.npmmirror.com/@intlify/shared/-/shared-9.3.0.tgz#8875120f1e6826be0e99b623e2618167402bfe41"
integrity sha512-MMGRz6zWxtz7rHtxIIdnyb8SYOIaaseN1IvUhAEs9tOW4u77RD4DFp4qgPXesp2Gxo/5QitH9kwSs0jnxGUNEw==
"@intlify/vue-devtools@9.3.0":
version "9.3.0"
resolved "https://registry.npmmirror.com/@intlify/vue-devtools/-/vue-devtools-9.3.0.tgz#f3137319fadaa92686de11be5ef28209dc828455"
integrity sha512-kEaxIz1VEgsz2q5RhoS+fBGTkXr/4+pxmK9mN14+speVGb82HPRntKBmz0GO18I1JisD4Z0vAva+KCTHGeAqbQ==
dependencies:
"@intlify/core-base" "9.3.0"
"@intlify/shared" "9.3.0"
"@jridgewell/sourcemap-codec@^1.4.15": "@jridgewell/sourcemap-codec@^1.4.15":
version "1.4.15" version "1.4.15"
resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
@@ -2805,6 +2843,16 @@ vue-eslint-parser@^9.1.1, vue-eslint-parser@^9.3.1:
lodash "^4.17.21" lodash "^4.17.21"
semver "^7.3.6" semver "^7.3.6"
vue-i18n@^9.3.0:
version "9.3.0"
resolved "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.3.0.tgz#d85551098ab377e4237a101c77bfc05fd4887ff5"
integrity sha512-+2L+ae/e4+fixhjym3lgzGCGQG8wVGlGrDHzjfdgUudheHvbVHu5i6tn6FF+buH75UFA7T5ZO2ZO7zrh6CzuaA==
dependencies:
"@intlify/core-base" "9.3.0"
"@intlify/shared" "9.3.0"
"@intlify/vue-devtools" "9.3.0"
"@vue/devtools-api" "^6.5.0"
vue-router@^4.2.4: vue-router@^4.2.4:
version "4.2.4" version "4.2.4"
resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.2.4.tgz#382467a7e2923e6a85f015d081e1508052c191b9" resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.2.4.tgz#382467a7e2923e6a85f015d081e1508052c191b9"