Merge pull request #143 from yanlong-li/master
feat: 管理后台文件列表支持下载文件&管理后台文件列表格式化过期时间
This commit is contained in:
@@ -56,3 +56,27 @@ async def update_config(data: dict):
|
|||||||
for k, v in data.items():
|
for k, v in data.items():
|
||||||
settings.__setattr__(k, v)
|
settings.__setattr__(k, v)
|
||||||
return APIResponse()
|
return APIResponse()
|
||||||
|
|
||||||
|
|
||||||
|
# 根据id获取文件
|
||||||
|
async def get_file_by_id(id):
|
||||||
|
# 查询文件
|
||||||
|
file_code = await FileCodes.filter(id=id).first()
|
||||||
|
# 检查文件是否存在
|
||||||
|
if not file_code:
|
||||||
|
return False, '文件不存在'
|
||||||
|
return True, file_code
|
||||||
|
|
||||||
|
|
||||||
|
@admin_api.get('/file/download', dependencies=[Depends(admin_required)])
|
||||||
|
async def file_download(id: int):
|
||||||
|
has, file_code = await get_file_by_id(id)
|
||||||
|
# 检查文件是否存在
|
||||||
|
if not has:
|
||||||
|
# 返回API响应
|
||||||
|
return APIResponse(code=404, detail='文件不存在')
|
||||||
|
# 如果文件是文本,返回文本内容,否则返回文件响应
|
||||||
|
if file_code.text:
|
||||||
|
return APIResponse(detail=file_code.text)
|
||||||
|
else:
|
||||||
|
return await file_storage.get_file_response(file_code)
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
import{d as a,Q as n,F as c,D as e,J as r,H as o,u as s,o as u}from"./index-fd7b9342.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};
|
import{d as a,Q as n,F as c,D as e,J as r,H as o,u as s,o as u}from"./index-bdf811f7.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};
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
-20
File diff suppressed because one or more lines are too long
+20
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -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 J,l as W,n as Y,S as H,w as Q}from"./el-popper-2c6af9ca.js";import{ak as m,am as M,ah as V,al as X,aJ as Z}from"./request-aa27c475.js";function k(t,e){for(var n=-1,o=t==null?0:t.length;++n<o&&e(t[n],n,t)!==!1;);return t}function z(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 ft(t,e){var n=e?E(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.byteLength)}var gt=/\w*$/;function bt(t){var e=new t.constructor(t.source,gt.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 ft(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]",Jt="[object Array]",Wt="[object Boolean]",Yt="[object Date]",Ht="[object Error]",U="[object Function]",Qt="[object GeneratorFunction]",Vt="[object Map]",Xt="[object Number]",P="[object Object]",Zt="[object RegExp]",kt="[object Set]",zt="[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]",fe="[object Uint8Array]",ge="[object Uint8ClampedArray]",be="[object Uint16Array]",ye="[object Uint32Array]",r={};r[L]=r[Jt]=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[kt]=r[zt]=r[te]=r[fe]=r[ge]=r[be]=r[ye]=!0;r[Ht]=r[U]=r[ee]=!1;function l(t,e,n,o,g,s){var a,b=e&Kt,y=e&Rt,D=e&qt;if(n&&(a=g?n(t,o,g,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 f=p(t),d=f==U||f==Qt;if(J(t))return W(t,b);if(f==P||f==L||d&&!g){if(a=y||d?{}:Y(t),!b)return y?at(t,tt(a,t)):et(t,z(a,t))}else{if(!r[f])return g?t:{};a=xt(t,f,b)}}s||(s=new H);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 k(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 J,l as W,n as Y,S as H,w as Q}from"./el-popper-c9bad75e.js";import{ak as m,am as M,ah as V,al as X,aJ as Z}from"./request-e2f6da06.js";function k(t,e){for(var n=-1,o=t==null?0:t.length;++n<o&&e(t[n],n,t)!==!1;);return t}function z(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 ft(t,e){var n=e?E(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.byteLength)}var gt=/\w*$/;function bt(t){var e=new t.constructor(t.source,gt.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 ft(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]",Jt="[object Array]",Wt="[object Boolean]",Yt="[object Date]",Ht="[object Error]",U="[object Function]",Qt="[object GeneratorFunction]",Vt="[object Map]",Xt="[object Number]",P="[object Object]",Zt="[object RegExp]",kt="[object Set]",zt="[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]",fe="[object Uint8Array]",ge="[object Uint8ClampedArray]",be="[object Uint16Array]",ye="[object Uint32Array]",r={};r[L]=r[Jt]=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[kt]=r[zt]=r[te]=r[fe]=r[ge]=r[be]=r[ye]=!0;r[Ht]=r[U]=r[ee]=!1;function l(t,e,n,o,g,s){var a,b=e&Kt,y=e&Rt,D=e&qt;if(n&&(a=g?n(t,o,g,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 f=p(t),d=f==U||f==Qt;if(J(t))return W(t,b);if(f==P||f==L||d&&!g){if(a=y||d?{}:Y(t),!b)return y?at(t,tt(a,t)):et(t,z(a,t))}else{if(!r[f])return g?t:{};a=xt(t,f,b)}}s||(s=new H);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 k(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};
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
import{c as S,ax as _,b as P,y as V,u as W,M as k,k as y,_ as M,w as $}from"./request-aa27c475.js";import{d as B,c as H,o as d,F as I,D as m,r as v,b as i,u as l,a as h,w as g,q as C,E as b,G as w,e as T,T as F}from"./index-fd7b9342.js";let f;const A=s=>{var a;if(!S)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 J(s,a){if(!S)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,u)=>t+u.offsetTop,0),c=e+a.offsetHeight,r=s.scrollTop,p=r+s.clientHeight;e<r?s.scrollTop=e:c>p&&(s.scrollTop=c-s.clientHeight)}const L=s=>["",..._].includes(s),R=P({type:{type:String,values:["success","info","warning","danger",""],default:""},closable:Boolean,disableTransitions:Boolean,hit:Boolean,color:{type:String,default:""},size:{type:String,values:_,default:""},effect:{type:String,values:["dark","light","plain"],default:"light"},round:Boolean}),q={close:s=>s instanceof MouseEvent,click:s=>s instanceof MouseEvent},D=B({name:"ElTag"}),G=B({...D,props:R,emits:q,setup(s,{emit:a}){const o=s,n=V(),e=W("tag"),c=H(()=>{const{type:t,hit:u,effect:E,closable:z,round:N}=o;return[e.b(),e.is("closable",z),e.m(t),e.m(n.value),e.m(E),e.is("hit",u),e.is("round",N)]}),r=t=>{a("close",t)},p=t=>{a("click",t)};return(t,u)=>t.disableTransitions?(d(),I("span",{key:0,class:i(l(c)),style:T({backgroundColor:t.color}),onClick:p},[m("span",{class:i(l(e).e("content"))},[v(t.$slots,"default")],2),t.closable?(d(),h(l(y),{key:0,class:i(l(e).e("close")),onClick:b(r,["stop"])},{default:g(()=>[C(l(k))]),_:1},8,["class","onClick"])):w("v-if",!0)],6)):(d(),h(F,{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:p},[m("span",{class:i(l(e).e("content"))},[v(t.$slots,"default")],2),t.closable?(d(),h(l(y),{key:0,class:i(l(e).e("close")),onClick:b(r,["stop"])},{default:g(()=>[C(l(k))]),_:1},8,["class","onClick"])):w("v-if",!0)],6)]),_:3},8,["name"]))}});var K=M(G,[["__file","/home/runner/work/element-plus/element-plus/packages/components/tag/src/tag.vue"]]);const O=$(K);export{O as E,A as g,L as i,J as s,R as t};
|
import{c as S,ax as _,b as P,y as V,u as W,M as k,k as y,_ as M,w as $}from"./request-e2f6da06.js";import{d as B,c as H,o as d,F as I,D as m,r as v,b as i,u as l,a as h,w as g,q as C,E as b,G as w,e as T,T as F}from"./index-bdf811f7.js";let f;const A=s=>{var a;if(!S)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 J(s,a){if(!S)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,u)=>t+u.offsetTop,0),c=e+a.offsetHeight,r=s.scrollTop,p=r+s.clientHeight;e<r?s.scrollTop=e:c>p&&(s.scrollTop=c-s.clientHeight)}const L=s=>["",..._].includes(s),R=P({type:{type:String,values:["success","info","warning","danger",""],default:""},closable:Boolean,disableTransitions:Boolean,hit:Boolean,color:{type:String,default:""},size:{type:String,values:_,default:""},effect:{type:String,values:["dark","light","plain"],default:"light"},round:Boolean}),q={close:s=>s instanceof MouseEvent,click:s=>s instanceof MouseEvent},D=B({name:"ElTag"}),G=B({...D,props:R,emits:q,setup(s,{emit:a}){const o=s,n=V(),e=W("tag"),c=H(()=>{const{type:t,hit:u,effect:E,closable:z,round:N}=o;return[e.b(),e.is("closable",z),e.m(t),e.m(n.value),e.m(E),e.is("hit",u),e.is("round",N)]}),r=t=>{a("close",t)},p=t=>{a("click",t)};return(t,u)=>t.disableTransitions?(d(),I("span",{key:0,class:i(l(c)),style:T({backgroundColor:t.color}),onClick:p},[m("span",{class:i(l(e).e("content"))},[v(t.$slots,"default")],2),t.closable?(d(),h(l(y),{key:0,class:i(l(e).e("close")),onClick:b(r,["stop"])},{default:g(()=>[C(l(k))]),_:1},8,["class","onClick"])):w("v-if",!0)],6)):(d(),h(F,{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:p},[m("span",{class:i(l(e).e("content"))},[v(t.$slots,"default")],2),t.closable?(d(),h(l(y),{key:0,class:i(l(e).e("close")),onClick:b(r,["stop"])},{default:g(()=>[C(l(k))]),_:1},8,["class","onClick"])):w("v-if",!0)],6)]),_:3},8,["name"]))}});var K=M(G,[["__file","/home/runner/work/element-plus/element-plus/packages/components/tag/src/tag.vue"]]);const O=$(K);export{O as E,A as g,L as i,J as s,R as t};
|
||||||
+2
-2
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
import{X as A,K as N}from"./index-fd7b9342.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{X as A,K as N}from"./index-bdf811f7.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};
|
||||||
Vendored
+1
-1
@@ -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-fd7b9342.js"></script>
|
<script type="module" crossorigin src="/assets/index-bdf811f7.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/index-76720517.css">
|
<link rel="stylesheet" href="/assets/index-76720517.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;">
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
@@ -88,6 +88,11 @@ export default {
|
|||||||
file_path: 'File Path',
|
file_path: 'File Path',
|
||||||
action: 'Action',
|
action: 'Action',
|
||||||
delete: 'Delete',
|
delete: 'Delete',
|
||||||
|
delete_success: 'Delete successful',
|
||||||
|
forever: 'Forever',
|
||||||
|
unlimited_count: 'Unlimited',
|
||||||
|
download: 'Download',
|
||||||
|
download_fail: 'File save failed, please try again later~',
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
fileManage: 'File Management',
|
fileManage: 'File Management',
|
||||||
|
|||||||
@@ -88,6 +88,11 @@ export default {
|
|||||||
file_path: '文件路径',
|
file_path: '文件路径',
|
||||||
action: '操作',
|
action: '操作',
|
||||||
delete: '删除',
|
delete: '删除',
|
||||||
|
delete_success: '删除成功',
|
||||||
|
forever: '永久有效',
|
||||||
|
unlimited_count: '不限次数',
|
||||||
|
download: '下载',
|
||||||
|
download_fail: '文件保存失败,请稍后再试~',
|
||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
fileManage: '文件管理',
|
fileManage: '文件管理',
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ instance.interceptors.request.use(
|
|||||||
});
|
});
|
||||||
instance.interceptors.response.use(
|
instance.interceptors.response.use(
|
||||||
(response:any) => {
|
(response:any) => {
|
||||||
|
if (response.status === 200 && response.config.url === '/admin/file/download') {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
if (response.data.code === 200) {
|
if (response.data.code === 200) {
|
||||||
return response.data;
|
return response.data;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export function formatTimestamp(timestamp: string): string {
|
||||||
|
const date = new Date(timestamp);
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||||
|
const day = date.getDate().toString().padStart(2, '0');
|
||||||
|
const hours = date.getHours().toString().padStart(2, '0');
|
||||||
|
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||||
|
const seconds = date.getSeconds().toString().padStart(2, '0');
|
||||||
|
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<el-table-column prop="used_count" :label="t('admin.fileView.used_count')" />
|
<el-table-column prop="used_count" :label="t('admin.fileView.used_count')" />
|
||||||
<el-table-column prop="expired_count" :label="t('admin.fileView.expired_count')">
|
<el-table-column prop="expired_count" :label="t('admin.fileView.expired_count')">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.expired_count > -1 ? scope.row.expired_count : '不限次数' }}</span>
|
<span>{{ scope.row.expired_count > -1 ? scope.row.expired_count : t('admin.fileView.unlimited_count') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="size" :label="t('admin.fileView.size')">
|
<el-table-column prop="size" :label="t('admin.fileView.size')">
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="expired_at" :label="t('admin.fileView.expired_at')">
|
<el-table-column prop="expired_at" :label="t('admin.fileView.expired_at')">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.expired_at ? scope.row.expired_at : '永久有效' }}</span>
|
<span>{{ scope.row.expired_at ? formatTimestamp(scope.row.expired_at) : t('admin.fileView.forever') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="file_path" :label="t('admin.fileView.file_path')" />
|
<el-table-column prop="file_path" :label="t('admin.fileView.file_path')" />
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button type="danger" size="small" @click="deleteFile(scope.row.id)">{{ t('admin.fileView.delete') }}</el-button>
|
<el-button type="danger" size="small" @click="deleteFile(scope.row.id)">{{ t('admin.fileView.delete') }}</el-button>
|
||||||
|
<el-button type="success" size="small" @click="downloadFile(scope.row.id)" v-if="scope.row.file_path">{{ t('admin.fileView.download') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { request } from "@/utils/request";
|
import { request } from "@/utils/request";
|
||||||
|
import { formatTimestamp } from "@/utils/timestamp-format"
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
const tableData = ref([]);
|
const tableData = ref([]);
|
||||||
@@ -64,10 +66,72 @@ const deleteFile = (id: number) => {
|
|||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
ElMessage.success('删除成功');
|
ElMessage.success(t('admin.fileView.delete_success'));
|
||||||
refreshData();
|
refreshData();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const downloadFile = (id: number) => {
|
||||||
|
|
||||||
|
request({
|
||||||
|
url: '/admin/file/download',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
responseType: 'blob'
|
||||||
|
}).then((response: any) => {
|
||||||
|
const contentDisposition = response.headers['content-disposition'];
|
||||||
|
let filename = 'file';
|
||||||
|
// 使用正则表达式来提取文件名
|
||||||
|
const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
|
||||||
|
if (filenameMatch != null && filenameMatch[1]) {
|
||||||
|
// 去除文件名周围的引号
|
||||||
|
filename = filenameMatch[1].replace(/['"]/g, '');
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
if (window.showSaveFilePicker)
|
||||||
|
saveFileByWebApi(response.data, filename).catch(() => {
|
||||||
|
// ElMessage.error('文件保存函数不支持您的浏览器');
|
||||||
|
saveFileByElementA(response.data, filename).catch(() => {
|
||||||
|
ElMessage.error(t('admin.fileView.download_fail'));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
else
|
||||||
|
saveFileByElementA(response.data, filename).catch(() => {
|
||||||
|
ElMessage.error(t('admin.fileView.download_fail'));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
async function saveFileByElementA(fileBlob: Blob, filename: string) {
|
||||||
|
const downloadUrl = window.URL.createObjectURL(fileBlob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = downloadUrl;
|
||||||
|
link.download = filename; // 设置下载文件名
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
// 清理并释放URL对象
|
||||||
|
window.URL.revokeObjectURL(downloadUrl);
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}
|
||||||
|
async function saveFileByWebApi(fileBlob: Blob, filename: string) {
|
||||||
|
// 创建一个新句柄。
|
||||||
|
// @ts-ignore
|
||||||
|
const newHandle = await window.showSaveFilePicker({
|
||||||
|
suggestedName: filename,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建一个 FileSystemWritableFileStream 用于写入。
|
||||||
|
const writableStream = await newHandle.createWritable();
|
||||||
|
|
||||||
|
// 写入我们的文件。
|
||||||
|
await writableStream.write(fileBlob);
|
||||||
|
|
||||||
|
// 关闭文件并将内容写入磁盘。
|
||||||
|
await writableStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const updatePageSize=(pageSize: number) => {
|
const updatePageSize=(pageSize: number) => {
|
||||||
params.value.size = pageSize;
|
params.value.size = pageSize;
|
||||||
refreshData();
|
refreshData();
|
||||||
|
|||||||
Reference in New Issue
Block a user