Add support for pinnable search history records

pull/660/head
zanllp 2024-06-22 07:19:38 +08:00
parent 4ce1f8240a
commit b40b838f9c
47 changed files with 402 additions and 67 deletions

View File

@ -13,7 +13,7 @@ Promise.resolve().then(async () => {
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Infinite Image Browsing</title>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-333f4d92.js"></script>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-8120eed9.js"></script>
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-daea5cd8.css">
</head>

View File

@ -198,7 +198,7 @@ def convert_to_bytes(file_size_str):
raise ValueError(f"Invalid file size string '{file_size_str}'")
def get_video_type(file_path):
video_extensions = ['.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.ts']
video_extensions = ['.mp4', '.m4v', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.ts']
file_extension = file_path[file_path.rfind('.'):].lower()
if file_extension in video_extensions:

3
vue/components.d.ts vendored
View File

@ -15,6 +15,7 @@ declare module '@vue/runtime-core' {
ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem']
AButton: typeof import('ant-design-vue/es')['Button']
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
ACol: typeof import('ant-design-vue/es')['Col']
ACollapse: typeof import('ant-design-vue/es')['Collapse']
ACollapsePanel: typeof import('ant-design-vue/es')['CollapsePanel']
ADrawer: typeof import('ant-design-vue/es')['Drawer']
@ -31,6 +32,7 @@ declare module '@vue/runtime-core' {
AModal: typeof import('ant-design-vue/es')['Modal']
ARadioButton: typeof import('ant-design-vue/es')['RadioButton']
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
ARow: typeof import('ant-design-vue/es')['Row']
ASelect: typeof import('ant-design-vue/es')['Select']
ASkeleton: typeof import('ant-design-vue/es')['Skeleton']
ASlider: typeof import('ant-design-vue/es')['Slider']
@ -45,6 +47,7 @@ declare module '@vue/runtime-core' {
ChangeIndicator: typeof import('./src/components/ChangeIndicator.vue')['default']
ContextMenu: typeof import('./src/components/ContextMenu.vue')['default']
FileItem: typeof import('./src/components/FileItem.vue')['default']
HistoryRecord: typeof import('./src/components/HistoryRecord.vue')['default']
MultiSelectKeep: typeof import('./src/components/MultiSelectKeep.vue')['default']
NumInput: typeof import('./src/components/numInput.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']

View File

@ -1 +1 @@
import{d as E,by as $,r as f,k as M,_ as T,a as c,aj as W,h as g,c as v,P as z}from"./index-333f4d92.js";var G=["prefixCls","name","id","type","disabled","readonly","tabindex","autofocus","value","required"],H={prefixCls:String,name:String,id:String,type:String,defaultChecked:{type:[Boolean,Number],default:void 0},checked:{type:[Boolean,Number],default:void 0},disabled:Boolean,tabindex:{type:[Number,String]},readonly:Boolean,autofocus:Boolean,value:z.any,required:Boolean};const L=E({compatConfig:{MODE:3},name:"Checkbox",inheritAttrs:!1,props:$(H,{prefixCls:"rc-checkbox",type:"checkbox",defaultChecked:!1}),emits:["click","change"],setup:function(a,d){var t=d.attrs,h=d.emit,m=d.expose,o=f(a.checked===void 0?a.defaultChecked:a.checked),i=f();M(function(){return a.checked},function(){o.value=a.checked}),m({focus:function(){var e;(e=i.value)===null||e===void 0||e.focus()},blur:function(){var e;(e=i.value)===null||e===void 0||e.blur()}});var l=f(),x=function(e){if(!a.disabled){a.checked===void 0&&(o.value=e.target.checked),e.shiftKey=l.value;var r={target:c(c({},a),{},{checked:e.target.checked}),stopPropagation:function(){e.stopPropagation()},preventDefault:function(){e.preventDefault()},nativeEvent:e};a.checked!==void 0&&(i.value.checked=!!a.checked),h("change",r),l.value=!1}},C=function(e){h("click",e),l.value=e.shiftKey};return function(){var n,e=a.prefixCls,r=a.name,s=a.id,p=a.type,b=a.disabled,K=a.readonly,P=a.tabindex,B=a.autofocus,S=a.value,N=a.required,_=T(a,G),j=t.class,q=t.onFocus,D=t.onBlur,w=t.onKeydown,A=t.onKeypress,F=t.onKeyup,y=c(c({},_),t),O=Object.keys(y).reduce(function(k,u){return(u.substr(0,5)==="aria-"||u.substr(0,5)==="data-"||u==="role")&&(k[u]=y[u]),k},{}),R=W(e,j,(n={},g(n,"".concat(e,"-checked"),o.value),g(n,"".concat(e,"-disabled"),b),n)),V=c(c({name:r,id:s,type:p,readonly:K,disabled:b,tabindex:P,class:"".concat(e,"-input"),checked:!!o.value,autofocus:B,value:S},O),{},{onChange:x,onClick:C,onFocus:q,onBlur:D,onKeydown:w,onKeypress:A,onKeyup:F,required:N});return v("span",{class:R},[v("input",c({ref:i},V),null),v("span",{class:"".concat(e,"-inner")},null)])}}});export{L as V};
import{d as E,bv as $,r as f,k as M,_ as T,a as c,aj as W,h as g,c as v,P as z}from"./index-8120eed9.js";var G=["prefixCls","name","id","type","disabled","readonly","tabindex","autofocus","value","required"],H={prefixCls:String,name:String,id:String,type:String,defaultChecked:{type:[Boolean,Number],default:void 0},checked:{type:[Boolean,Number],default:void 0},disabled:Boolean,tabindex:{type:[Number,String]},readonly:Boolean,autofocus:Boolean,value:z.any,required:Boolean};const L=E({compatConfig:{MODE:3},name:"Checkbox",inheritAttrs:!1,props:$(H,{prefixCls:"rc-checkbox",type:"checkbox",defaultChecked:!1}),emits:["click","change"],setup:function(a,d){var t=d.attrs,h=d.emit,m=d.expose,o=f(a.checked===void 0?a.defaultChecked:a.checked),i=f();M(function(){return a.checked},function(){o.value=a.checked}),m({focus:function(){var e;(e=i.value)===null||e===void 0||e.focus()},blur:function(){var e;(e=i.value)===null||e===void 0||e.blur()}});var l=f(),x=function(e){if(!a.disabled){a.checked===void 0&&(o.value=e.target.checked),e.shiftKey=l.value;var r={target:c(c({},a),{},{checked:e.target.checked}),stopPropagation:function(){e.stopPropagation()},preventDefault:function(){e.preventDefault()},nativeEvent:e};a.checked!==void 0&&(i.value.checked=!!a.checked),h("change",r),l.value=!1}},C=function(e){h("click",e),l.value=e.shiftKey};return function(){var n,e=a.prefixCls,r=a.name,s=a.id,p=a.type,b=a.disabled,K=a.readonly,P=a.tabindex,B=a.autofocus,S=a.value,N=a.required,_=T(a,G),j=t.class,q=t.onFocus,D=t.onBlur,w=t.onKeydown,A=t.onKeypress,F=t.onKeyup,k=c(c({},_),t),O=Object.keys(k).reduce(function(y,u){return(u.substr(0,5)==="aria-"||u.substr(0,5)==="data-"||u==="role")&&(y[u]=k[u]),y},{}),R=W(e,j,(n={},g(n,"".concat(e,"-checked"),o.value),g(n,"".concat(e,"-disabled"),b),n)),V=c(c({name:r,id:s,type:p,readonly:K,disabled:b,tabindex:P,class:"".concat(e,"-input"),checked:!!o.value,autofocus:B,value:S},O),{},{onChange:x,onClick:C,onFocus:q,onBlur:D,onKeydown:w,onKeypress:A,onKeyup:F,required:N});return v("span",{class:R},[v("input",c({ref:i},V),null),v("span",{class:"".concat(e,"-inner")},null)])}}});export{L as V};

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d as a,N as t,O as s,c as n,cA as _,V as o}from"./index-333f4d92.js";const c={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),s("div",c,[n(_,{left:e.left,right:e.right},null,8,["left","right"])]))}});const d=o(i,[["__scopeId","data-v-ae3fb9a8"]]);export{d as default};
import{d as a,N as t,O as s,c as n,cA as _,V as o}from"./index-8120eed9.js";const c={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),s("div",c,[n(_,{left:e.left,right:e.right},null,8,["left","right"])]))}});const d=o(i,[["__scopeId","data-v-ae3fb9a8"]]);export{d as default};

View File

@ -1 +1 @@
import{d as se,k as ne,av as oe,W as ie,N as u,O as I,c as s,Z as e,Y as n,a0 as R,Q as d,E as ae,S as a,R as p,X as V,a9 as de,U as k,aa as D,ac as re,ad as ce,af as z,aI as ue,aJ as me,bU as pe,V as ge}from"./index-333f4d92.js";import{S as ve}from"./index-b9551320.js";import{L as fe,R as Ie,f as ke,M as _e}from"./MultiSelectKeep-0aedd2f1.js";import{c as Ce,d as he,F as we}from"./FileItem-064f25fa.js";import{c as Se,u as xe}from"./hook-4244356f.js";import{a as be}from"./functionalCallableComp-dc2cf08d.js";import"./shortcut-0854cd7e.js";import"./Checkbox-2cca96a3.js";import"./index-267d1f4e.js";/* empty css */const Me=r=>(ue("data-v-479efe51"),r=r(),me(),r),ye={class:"hint"},Ae={class:"action-bar"},Te=Me(()=>d("div",{style:{padding:"16px 0 512px"}},null,-1)),$e={key:1},Fe={class:"no-res-hint"},Re={class:"hint"},Ve={key:2,class:"preview-switch"},De=se({__name:"MatchedImageGrid",props:{tabIdx:{},paneIdx:{},selectedTagIds:{},id:{}},setup(r){const _=r,g=Se(l=>pe(_.selectedTagIds,l)),{queue:B,images:i,onContextMenuClickU:C,stackViewEl:G,previewIdx:c,previewing:h,onPreviewVisibleChange:N,previewImgMove:w,canPreview:S,itemSize:x,gridItems:U,showGenInfo:m,imageGenInfo:b,q:E,multiSelectedIdxs:v,onFileItemClick:J,scroller:M,showMenuIdx:f,onFileDragStart:L,onFileDragEnd:O,cellWidth:P,onScroll:y,saveAllFileAsJson:K,saveLoadedFileAsJson:q}=xe(g);ne(()=>_.selectedTagIds,async()=>{var l;await g.reset(),await oe(),(l=M.value)==null||l.scrollToItem(0),y()},{immediate:!0});const Q=ie(),{onClearAllSelected:W,onSelectAll:X,onReverseSelect:Y}=Ce();return(l,t)=>{const Z=_e,j=re,H=ce,A=z,ee=z,te=ve;return u(),I("div",{class:"container",ref_key:"stackViewEl",ref:G},[s(Z,{show:!!e(v).length||e(Q).keepMultiSelect,onClearAllSelected:e(W),onSelectAll:e(X),onReverseSelect:e(Y)},null,8,["show","onClearAllSelected","onSelectAll","onReverseSelect"]),s(te,{size:"large",spinning:!e(B).isIdle},{default:n(()=>{var T,$;return[s(H,{visible:e(m),"onUpdate:visible":t[1]||(t[1]=o=>R(m)?m.value=o:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=o=>m.value=!1)},{cancelText:n(()=>[]),default:n(()=>[s(j,{active:"",loading:!e(E).isIdle},{default:n(()=>[d("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[0]||(t[0]=o=>e(ae)(e(b)))},[d("div",ye,a(l.$t("doubleClickToCopy")),1),p(" "+a(e(b)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),d("div",Ae,[s(A,{onClick:e(q)},{default:n(()=>[p(a(l.$t("saveLoadedImageAsJson")),1)]),_:1},8,["onClick"]),s(A,{onClick:e(K)},{default:n(()=>[p(a(l.$t("saveAllAsJson")),1)]),_:1},8,["onClick"])]),(T=e(i))!=null&&T.length?(u(),V(e(he),{key:0,ref_key:"scroller",ref:M,class:"file-list",items:e(i),"item-size":e(x).first,"key-field":"fullpath","item-secondary-size":e(x).second,gridItems:e(U),onScroll:e(y)},{after:n(()=>[Te]),default:n(({item:o,index:F})=>[s(we,{idx:F,file:o,"cell-width":e(P),"show-menu-idx":e(f),"onUpdate:showMenuIdx":t[3]||(t[3]=le=>R(f)?f.value=le:null),onDragstart:e(L),onDragend:e(O),onFileItemClick:e(J),"full-screen-preview-image-url":e(i)[e(c)]?e(de)(e(i)[e(c)]):"",selected:e(v).includes(F),onContextMenuClick:e(C),onPreviewVisibleChange:e(N),"is-selected-mutil-files":e(v).length>1},null,8,["idx","file","cell-width","show-menu-idx","onDragstart","onDragend","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onPreviewVisibleChange","is-selected-mutil-files"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"])):e(g).load&&l.selectedTagIds.and_tags.length===1&&!(($=l.selectedTagIds.folder_paths_str)!=null&&$.trim())?(u(),I("div",$e,[d("div",Fe,[d("p",Re,a(l.$t("tagSearchNoResultsMessage")),1),s(ee,{onClick:t[4]||(t[4]=o=>e(be)()),type:"primary"},{default:n(()=>[p(a(l.$t("rebuildImageIndex")),1)]),_:1})])])):k("",!0),e(h)?(u(),I("div",Ve,[s(e(fe),{onClick:t[5]||(t[5]=o=>e(w)("prev")),class:D({disable:!e(S)("prev")})},null,8,["class"]),s(e(Ie),{onClick:t[6]||(t[6]=o=>e(w)("next")),class:D({disable:!e(S)("next")})},null,8,["class"])])):k("",!0)]}),_:1},8,["spinning"]),e(h)&&e(i)&&e(i)[e(c)]?(u(),V(ke,{key:0,file:e(i)[e(c)],idx:e(c),onContextMenuClick:e(C)},null,8,["file","idx","onContextMenuClick"])):k("",!0)],512)}}});const Ke=ge(De,[["__scopeId","data-v-479efe51"]]);export{Ke as default};
import{d as se,k as ne,av as oe,W as ie,N as u,O as I,c as s,Z as e,Y as n,a0 as F,Q as d,E as ae,S as a,R as p,X as V,a9 as de,U as k,aa as D,ac as re,ad as ce,af as z,aI as ue,aJ as me,bR as pe,V as ge}from"./index-8120eed9.js";import{S as ve}from"./index-27c4b040.js";import{L as fe,R as Ie,f as ke,M as _e}from"./MultiSelectKeep-9bfd3b7f.js";import{c as Ce,d as he,F as we}from"./FileItem-ad0bcda2.js";import{c as Se,u as xe}from"./hook-3ec3e8da.js";import{a as be}from"./functionalCallableComp-c2695a1f.js";import"./shortcut-95612d36.js";import"./Checkbox-356e3a33.js";import"./index-a3c1f71f.js";/* empty css */const Me=r=>(ue("data-v-479efe51"),r=r(),me(),r),ye={class:"hint"},Ae={class:"action-bar"},Re=Me(()=>d("div",{style:{padding:"16px 0 512px"}},null,-1)),Te={key:1},$e={class:"no-res-hint"},Fe={class:"hint"},Ve={key:2,class:"preview-switch"},De=se({__name:"MatchedImageGrid",props:{tabIdx:{},paneIdx:{},selectedTagIds:{},id:{}},setup(r){const _=r,g=Se(l=>pe(_.selectedTagIds,l)),{queue:B,images:i,onContextMenuClickU:C,stackViewEl:G,previewIdx:c,previewing:h,onPreviewVisibleChange:N,previewImgMove:w,canPreview:S,itemSize:x,gridItems:E,showGenInfo:m,imageGenInfo:b,q:J,multiSelectedIdxs:v,onFileItemClick:U,scroller:M,showMenuIdx:f,onFileDragStart:L,onFileDragEnd:O,cellWidth:P,onScroll:y,saveAllFileAsJson:K,saveLoadedFileAsJson:q}=xe(g);ne(()=>_.selectedTagIds,async()=>{var l;await g.reset(),await oe(),(l=M.value)==null||l.scrollToItem(0),y()},{immediate:!0});const Q=ie(),{onClearAllSelected:W,onSelectAll:X,onReverseSelect:Y}=Ce();return(l,t)=>{const Z=_e,j=re,H=ce,A=z,ee=z,te=ve;return u(),I("div",{class:"container",ref_key:"stackViewEl",ref:G},[s(Z,{show:!!e(v).length||e(Q).keepMultiSelect,onClearAllSelected:e(W),onSelectAll:e(X),onReverseSelect:e(Y)},null,8,["show","onClearAllSelected","onSelectAll","onReverseSelect"]),s(te,{size:"large",spinning:!e(B).isIdle},{default:n(()=>{var R,T;return[s(H,{visible:e(m),"onUpdate:visible":t[1]||(t[1]=o=>F(m)?m.value=o:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=o=>m.value=!1)},{cancelText:n(()=>[]),default:n(()=>[s(j,{active:"",loading:!e(J).isIdle},{default:n(()=>[d("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[0]||(t[0]=o=>e(ae)(e(b)))},[d("div",ye,a(l.$t("doubleClickToCopy")),1),p(" "+a(e(b)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),d("div",Ae,[s(A,{onClick:e(q)},{default:n(()=>[p(a(l.$t("saveLoadedImageAsJson")),1)]),_:1},8,["onClick"]),s(A,{onClick:e(K)},{default:n(()=>[p(a(l.$t("saveAllAsJson")),1)]),_:1},8,["onClick"])]),(R=e(i))!=null&&R.length?(u(),V(e(he),{key:0,ref_key:"scroller",ref:M,class:"file-list",items:e(i),"item-size":e(x).first,"key-field":"fullpath","item-secondary-size":e(x).second,gridItems:e(E),onScroll:e(y)},{after:n(()=>[Re]),default:n(({item:o,index:$})=>[s(we,{idx:$,file:o,"cell-width":e(P),"show-menu-idx":e(f),"onUpdate:showMenuIdx":t[3]||(t[3]=le=>F(f)?f.value=le:null),onDragstart:e(L),onDragend:e(O),onFileItemClick:e(U),"full-screen-preview-image-url":e(i)[e(c)]?e(de)(e(i)[e(c)]):"",selected:e(v).includes($),onContextMenuClick:e(C),onPreviewVisibleChange:e(N),"is-selected-mutil-files":e(v).length>1},null,8,["idx","file","cell-width","show-menu-idx","onDragstart","onDragend","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onPreviewVisibleChange","is-selected-mutil-files"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"])):e(g).load&&l.selectedTagIds.and_tags.length===1&&!((T=l.selectedTagIds.folder_paths_str)!=null&&T.trim())?(u(),I("div",Te,[d("div",$e,[d("p",Fe,a(l.$t("tagSearchNoResultsMessage")),1),s(ee,{onClick:t[4]||(t[4]=o=>e(be)()),type:"primary"},{default:n(()=>[p(a(l.$t("rebuildImageIndex")),1)]),_:1})])])):k("",!0),e(h)?(u(),I("div",Ve,[s(e(fe),{onClick:t[5]||(t[5]=o=>e(w)("prev")),class:D({disable:!e(S)("prev")})},null,8,["class"]),s(e(Ie),{onClick:t[6]||(t[6]=o=>e(w)("next")),class:D({disable:!e(S)("next")})},null,8,["class"])])):k("",!0)]}),_:1},8,["spinning"]),e(h)&&e(i)&&e(i)[e(c)]?(u(),V(ke,{key:0,file:e(i)[e(c)],idx:e(c),onContextMenuClick:e(C)},null,8,["file","idx","onContextMenuClick"])):k("",!0)],512)}}});const Ke=ge(De,[["__scopeId","data-v-479efe51"]]);export{Ke as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
[data-v-ecedc00a] .float-panel{position:fixed}.regex-icon[data-v-ecedc00a]{user-select:none;padding:4px;margin:0 4px;cursor:pointer;border:1px solid var(--zp-border);border-radius:4px}.regex-icon img[data-v-ecedc00a]{height:1.5em}.regex-icon[data-v-ecedc00a]:hover{background:var(--zp-border)}.regex-icon.selected[data-v-ecedc00a]{background:var(--primary-color-1);border:1px solid var(--primary-color)}.search-bar[data-v-ecedc00a]{padding:8px 8px 0;display:flex}.search-bar.last[data-v-ecedc00a]{padding-bottom:8px}.search-bar .form-name[data-v-ecedc00a]{flex-shrink:0;padding:4px 8px}.search-bar .actions>*[data-v-ecedc00a]{margin-right:4px}.preview-switch[data-v-ecedc00a]{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;z-index:11111;pointer-events:none}.preview-switch>*[data-v-ecedc00a]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-ecedc00a]{opacity:0;pointer-events:none;cursor:none}.container[data-v-ecedc00a]{background:var(--zp-secondary-background);position:relative}.container .file-list[data-v-ecedc00a]{list-style:none;padding:8px;height:100%;overflow:auto;height:var(--pane-max-height);width:100%}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
[data-v-1a34b8ae] .float-panel{position:fixed}.regex-icon[data-v-1a34b8ae]{user-select:none;padding:4px;margin:0 4px;cursor:pointer;border:1px solid var(--zp-border);border-radius:4px}.regex-icon img[data-v-1a34b8ae]{height:1.5em}.regex-icon[data-v-1a34b8ae]:hover{background:var(--zp-border)}.regex-icon.selected[data-v-1a34b8ae]{background:var(--primary-color-1);border:1px solid var(--primary-color)}.search-bar[data-v-1a34b8ae]{padding:8px 8px 0;display:flex}.search-bar.last[data-v-1a34b8ae]{padding-bottom:8px}.search-bar .form-name[data-v-1a34b8ae]{flex-shrink:0;padding:4px 8px}.search-bar .actions>*[data-v-1a34b8ae]{margin-right:4px}.preview-switch[data-v-1a34b8ae]{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;z-index:11111;pointer-events:none}.preview-switch>*[data-v-1a34b8ae]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-1a34b8ae]{opacity:0;pointer-events:none;cursor:none}.container[data-v-1a34b8ae]{background:var(--zp-secondary-background);position:relative}.container .file-list[data-v-1a34b8ae]{list-style:none;padding:8px;height:100%;overflow:auto;height:var(--pane-max-height);width:100%}

1
vue/dist/assets/TagSearch-84615bb3.js vendored Normal file

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

View File

@ -1 +1 @@
import{d as v,cB as C,c2 as I,N as l,O as _,Q as f,c,Y as r,R as h,S as d,Z as e,X as B,a9 as F,cg as z,cC as x,af as R,V as S}from"./index-333f4d92.js";import{u as $,a as V,k as E,F as A,d as N}from"./FileItem-064f25fa.js";import"./functionalCallableComp-dc2cf08d.js";import"./index-267d1f4e.js";/* empty css */const T={class:"actions-panel actions"},L={key:0,class:"file-list"},U={class:"hint"},H=v({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(O){const{stackViewEl:w}=$().toRefs(),{itemSize:p,gridItems:k,cellWidth:y}=V(),i=E(),{selectdFiles:n}=C(i),u=I(),D=async t=>{const s=z(t);s&&i.addFiles(s.nodes)},b=async()=>{u.pushAction(async()=>{const t=await x.value.post("/zip",{paths:n.value.map(o=>o.fullpath)},{responseType:"blob"}),s=window.URL.createObjectURL(new Blob([t.data])),a=document.createElement("a");a.href=s,a.setAttribute("download",`iib_${new Date().toLocaleString()}.zip`),document.body.appendChild(a),a.click()})},g=t=>{n.value.splice(t,1)};return(t,s)=>{const a=R;return l(),_("div",{class:"container",ref_key:"stackViewEl",ref:w,onDrop:D},[f("div",T,[c(a,{onClick:s[0]||(s[0]=o=>e(i).selectdFiles=[])},{default:r(()=>[h(d(t.$t("clear")),1)]),_:1}),c(a,{onClick:b,type:"primary",loading:!e(u).isIdle},{default:r(()=>[h(d(t.$t("zipDownload")),1)]),_:1},8,["loading"])]),e(n).length?(l(),B(e(N),{key:1,ref:"scroller",class:"file-list",items:e(n).slice(),"item-size":e(p).first,"key-field":"fullpath","item-secondary-size":e(p).second,gridItems:e(k)},{default:r(({item:o,index:m})=>[c(A,{idx:m,file:o,"cell-width":e(y),"enable-close-icon":"",onCloseIconClick:Q=>g(m),"full-screen-preview-image-url":e(F)(o),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","onCloseIconClick","full-screen-preview-image-url"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):(l(),_("div",L,[f("p",U,d(t.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const Z=S(H,[["__scopeId","data-v-aab31da2"]]);export{Z as default};
import{d as v,cB as C,b$ as I,N as l,O as _,Q as f,c,Y as r,R as h,S as d,Z as e,X as B,a9 as F,cd as z,cC as $,af as x,V as R}from"./index-8120eed9.js";import{u as S,a as V,k as E,F as A,d as N}from"./FileItem-ad0bcda2.js";import"./functionalCallableComp-c2695a1f.js";import"./index-a3c1f71f.js";/* empty css */const T={class:"actions-panel actions"},L={key:0,class:"file-list"},U={class:"hint"},H=v({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(O){const{stackViewEl:w}=S().toRefs(),{itemSize:p,gridItems:k,cellWidth:b}=V(),i=E(),{selectdFiles:n}=C(i),u=I(),y=async t=>{const s=z(t);s&&i.addFiles(s.nodes)},D=async()=>{u.pushAction(async()=>{const t=await $.value.post("/zip",{paths:n.value.map(o=>o.fullpath)},{responseType:"blob"}),s=window.URL.createObjectURL(new Blob([t.data])),a=document.createElement("a");a.href=s,a.setAttribute("download",`iib_${new Date().toLocaleString()}.zip`),document.body.appendChild(a),a.click()})},g=t=>{n.value.splice(t,1)};return(t,s)=>{const a=x;return l(),_("div",{class:"container",ref_key:"stackViewEl",ref:w,onDrop:y},[f("div",T,[c(a,{onClick:s[0]||(s[0]=o=>e(i).selectdFiles=[])},{default:r(()=>[h(d(t.$t("clear")),1)]),_:1}),c(a,{onClick:D,type:"primary",loading:!e(u).isIdle},{default:r(()=>[h(d(t.$t("zipDownload")),1)]),_:1},8,["loading"])]),e(n).length?(l(),B(e(N),{key:1,ref:"scroller",class:"file-list",items:e(n).slice(),"item-size":e(p).first,"key-field":"fullpath","item-secondary-size":e(p).second,gridItems:e(k)},{default:r(({item:o,index:m})=>[c(A,{idx:m,file:o,"cell-width":e(b),"enable-close-icon":"",onCloseIconClick:Q=>g(m),"full-screen-preview-image-url":e(F)(o),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","onCloseIconClick","full-screen-preview-image-url"])]),_:1},8,["items","item-size","item-secondary-size","gridItems"])):(l(),_("div",L,[f("p",U,d(t.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const Z=R(H,[["__scopeId","data-v-aab31da2"]]);export{Z as default};

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d8 as g,c as o,A as w,cC as i,cr as y,W as h,ad as c,d9 as x,da as O,af as I,cn as F,a9 as S,x as l,db as M,az as N,v as _,r as f,ae as v,q as k,R as D,dc as C}from"./index-333f4d92.js";var p=1/0,P=17976931348623157e292;function A(e){if(!e)return e===0?e:0;if(e=g(e),e===p||e===-p){var t=e<0?-1:1;return t*P}return e===e?e:0}function U(e){var t=e==null?0:e.length;return t?e[t-1]:void 0}var V={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"}}]},name:"download",theme:"outlined"};const j=V;function m(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},a=Object.keys(n);typeof Object.getOwnPropertySymbols=="function"&&(a=a.concat(Object.getOwnPropertySymbols(n).filter(function(s){return Object.getOwnPropertyDescriptor(n,s).enumerable}))),a.forEach(function(s){R(e,s,n[s])})}return e}function R(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var d=function(t,n){var a=m({},t,n.attrs);return o(w,m({},a,{icon:j}),null)};d.displayName="DownloadOutlined";d.inheritAttrs=!1;const T=d,H=async e=>(await i.value.get("/files",{params:{folder_path:e}})).data,W=async e=>(await i.value.post("/delete_files",{file_paths:e})).data,$=async(e,t,n)=>(await i.value.post("/move_files",{file_paths:e,dest:t,create_dest_folder:n})).data,B=async(e,t,n)=>(await i.value.post("/copy_files",{file_paths:e,dest:t,create_dest_folder:n})).data,z=async e=>{await i.value.post("/mkdirs",{dest_folder:e})},G=e=>{const t=f("");return new Promise(n=>{c.confirm({title:l("inputFolderName"),content:()=>o(v,{value:t.value,"onUpdate:value":a=>t.value=a},null),async onOk(){if(!t.value)return;const a=k(e,t.value);await z(a),n()}})})},q=()=>o("p",{style:{background:"var(--zp-secondary-background)",padding:"8px",borderLeft:"4px solid var(--primary-color)"}},[D("Tips: "),l("multiSelectTips")]),L=(e,t)=>{const n=y(),a=h(),s=r=>{var u;return!!((u=n.tagMap.get(e.fullpath))!=null&&u.some(b=>b.id===r))};c.confirm({width:"80vw",title:e.name,icon:null,content:()=>o("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",flexDirection:"column"}},[o("video",{style:{maxHeight:x?"80vh":"60vh",maxWidth:"100%",minWidth:"70%"},src:O(e),controls:!0,autoplay:!0},null),o("div",{style:{marginTop:"4px"}},[a.conf.all_custom_tags.map(r=>o("div",{key:r.id,onClick:()=>t==null?void 0:t(r.id),style:{background:s(r.id)?n.getColor(r.name):"var(--zp-primary-background)",color:s(r.id)?"white":n.getColor(r.name),margin:"2px",padding:"2px 16px","border-radius":"4px",display:"inline-block",cursor:"pointer","font-weight":"bold",transition:".5s all ease",border:`2px solid ${n.getColor(r.name)}`,"user-select":"none"}},[r.name]))]),o("div",{class:"actions",style:{marginTop:"16px"}},[o(I,{onClick:()=>F([S(e,!0)])},{icon:o(T,null,null),default:l("download")})])]),maskClosable:!0,wrapClassName:"hidden-antd-btns-modal"})},X=()=>{c.confirm({title:l("confirmRebuildImageIndex"),onOk:async()=>{await M(),N.emit("searchIndexExpired"),_.success(l("rebuildComplete"))}})},Y=e=>{const t=f(e.split(/[\\/]/).pop()??"");return new Promise(n=>{c.confirm({title:l("rename"),content:()=>o(v,{value:t.value,"onUpdate:value":a=>t.value=a},null),async onOk(){if(!t.value)return;const a=await C({path:e,name:t.value});n(a.new_path)}})})};export{q as M,X as a,Y as b,B as c,W as d,L as e,H as g,U as l,$ as m,G as o,A as t};
import{d8 as g,c as o,A as w,cC as i,co as y,W as h,ad as c,d9 as x,da as O,af as I,ck as F,a9 as S,x as l,db as M,az as N,v as k,r as f,ae as v,q as _,R as D,dc as C}from"./index-8120eed9.js";var p=1/0,P=17976931348623157e292;function A(e){if(!e)return e===0?e:0;if(e=g(e),e===p||e===-p){var t=e<0?-1:1;return t*P}return e===e?e:0}function U(e){var t=e==null?0:e.length;return t?e[t-1]:void 0}var V={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M505.7 661a8 8 0 0012.6 0l112-141.7c4.1-5.2.4-12.9-6.3-12.9h-74.1V168c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v338.3H400c-6.7 0-10.4 7.7-6.3 12.9l112 141.8zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"}}]},name:"download",theme:"outlined"};const j=V;function m(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?Object(arguments[t]):{},a=Object.keys(n);typeof Object.getOwnPropertySymbols=="function"&&(a=a.concat(Object.getOwnPropertySymbols(n).filter(function(r){return Object.getOwnPropertyDescriptor(n,r).enumerable}))),a.forEach(function(r){R(e,r,n[r])})}return e}function R(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var d=function(t,n){var a=m({},t,n.attrs);return o(w,m({},a,{icon:j}),null)};d.displayName="DownloadOutlined";d.inheritAttrs=!1;const T=d,H=async e=>(await i.value.get("/files",{params:{folder_path:e}})).data,W=async e=>(await i.value.post("/delete_files",{file_paths:e})).data,$=async(e,t,n)=>(await i.value.post("/move_files",{file_paths:e,dest:t,create_dest_folder:n})).data,B=async(e,t,n)=>(await i.value.post("/copy_files",{file_paths:e,dest:t,create_dest_folder:n})).data,z=async e=>{await i.value.post("/mkdirs",{dest_folder:e})},G=e=>{const t=f("");return new Promise(n=>{c.confirm({title:l("inputFolderName"),content:()=>o(v,{value:t.value,"onUpdate:value":a=>t.value=a},null),async onOk(){if(!t.value)return;const a=_(e,t.value);await z(a),n()}})})},q=()=>o("p",{style:{background:"var(--zp-secondary-background)",padding:"8px",borderLeft:"4px solid var(--primary-color)"}},[D("Tips: "),l("multiSelectTips")]),L=(e,t)=>{const n=y(),a=h(),r=s=>{var u;return!!((u=n.tagMap.get(e.fullpath))!=null&&u.some(b=>b.id===s))};c.confirm({width:"80vw",title:e.name,icon:null,content:()=>o("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",flexDirection:"column"}},[o("video",{style:{maxHeight:x?"80vh":"60vh",maxWidth:"100%",minWidth:"70%"},src:O(e),controls:!0,autoplay:!0},null),o("div",{style:{marginTop:"4px"}},[a.conf.all_custom_tags.map(s=>o("div",{key:s.id,onClick:()=>t==null?void 0:t(s.id),style:{background:r(s.id)?n.getColor(s.name):"var(--zp-primary-background)",color:r(s.id)?"white":n.getColor(s.name),margin:"2px",padding:"2px 16px","border-radius":"4px",display:"inline-block",cursor:"pointer","font-weight":"bold",transition:".5s all ease",border:`2px solid ${n.getColor(s.name)}`,"user-select":"none"}},[s.name]))]),o("div",{class:"actions",style:{marginTop:"16px"}},[o(I,{onClick:()=>F([S(e,!0)])},{icon:o(T,null,null),default:l("download")})])]),maskClosable:!0,wrapClassName:"hidden-antd-btns-modal"})},X=()=>{c.confirm({title:l("confirmRebuildImageIndex"),onOk:async()=>{await M(),N.emit("searchIndexExpired"),k.success(l("rebuildComplete"))}})},Y=e=>{const t=f(e.split(/[\\/]/).pop()??"");return new Promise(n=>{c.confirm({title:l("rename"),content:()=>o(v,{value:t.value,"onUpdate:value":a=>t.value=a},null),async onOk(){if(!t.value)return;const a=await C({path:e,name:t.value});n(a.new_path)}})})};export{q as M,X as a,Y as b,B as c,W as d,L as e,H as g,U as l,$ as m,G as o,A as t};

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{u as w,a as y,F as k,d as x}from"./FileItem-064f25fa.js";import{d as D,W as F,cr as b,r as h,ba as I,bd as C,N as V,O as E,c,Y as z,Z as e,a9 as S,cg as B,cD as R,V as A}from"./index-333f4d92.js";import"./functionalCallableComp-dc2cf08d.js";import"./index-267d1f4e.js";/* empty css */const K=D({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,d=F(),{stackViewEl:m}=w().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=y(),g=b(),s=h(o.files??[]),_=async a=>{const l=B(a);o.allowDragAndDrop&&l&&(s.value=R([...s.value,...l.nodes]))},v=a=>{s.value.splice(a,1)};return I(()=>{d.pageFuncExportMap.set(o.paneKey,{getFiles:()=>C(s.value),setFiles:a=>s.value=a})}),(a,l)=>(V(),E("div",{class:"container",ref_key:"stackViewEl",ref:m,onDrop:_},[c(e(x),{ref:"scroller",class:"file-list",items:s.value.slice(),"item-size":e(i).first,"key-field":"fullpath","item-secondary-size":e(i).second,gridItems:e(u)},{default:z(({item:t,index:r})=>{var n;return[c(k,{idx:r,file:t,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:N=>v(r),"full-screen-preview-image-url":e(S)(t),"extra-tags":(n=t==null?void 0:t.tags)==null?void 0:n.map(e(g).tagConvert),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","enable-close-icon","onCloseIconClick","full-screen-preview-image-url","extra-tags"])]}),_:1},8,["items","item-size","item-secondary-size","gridItems"])],544))}});const H=A(K,[["__scopeId","data-v-f35f4802"]]);export{H as default};
import{u as w,a as y,F as k,d as x}from"./FileItem-ad0bcda2.js";import{d as D,W as F,co as b,r as h,b6 as I,ba as C,N as V,O as E,c,Y as z,Z as e,a9 as S,cd as B,cD as R,V as A}from"./index-8120eed9.js";import"./functionalCallableComp-c2695a1f.js";import"./index-a3c1f71f.js";/* empty css */const K=D({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,d=F(),{stackViewEl:m}=w().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=y(),g=b(),s=h(o.files??[]),_=async a=>{const l=B(a);o.allowDragAndDrop&&l&&(s.value=R([...s.value,...l.nodes]))},v=a=>{s.value.splice(a,1)};return I(()=>{d.pageFuncExportMap.set(o.paneKey,{getFiles:()=>C(s.value),setFiles:a=>s.value=a})}),(a,l)=>(V(),E("div",{class:"container",ref_key:"stackViewEl",ref:m,onDrop:_},[c(e(x),{ref:"scroller",class:"file-list",items:s.value.slice(),"item-size":e(i).first,"key-field":"fullpath","item-secondary-size":e(i).second,gridItems:e(u)},{default:z(({item:t,index:r})=>{var n;return[c(k,{idx:r,file:t,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:N=>v(r),"full-screen-preview-image-url":e(S)(t),"extra-tags":(n=t==null?void 0:t.tags)==null?void 0:n.map(e(g).tagConvert),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","enable-close-icon","onCloseIconClick","full-screen-preview-image-url","extra-tags"])]}),_:1},8,["items","item-size","item-secondary-size","gridItems"])],544))}});const H=A(K,[["__scopeId","data-v-f35f4802"]]);export{H as default};

1
vue/dist/assets/hook-3ec3e8da.js vendored Normal file
View File

@ -0,0 +1 @@
import{ah as F,r as g,c9 as q,ca as x,H as A,B as D,b$ as N,bj as j,cb as z}from"./index-8120eed9.js";import{u as G,a as H,b as L,e as O}from"./FileItem-ad0bcda2.js";import{a as Q,b as B,c as T}from"./MultiSelectKeep-9bfd3b7f.js";let U=0;const W=()=>++U,$=(o,c,{dataUpdateStrategy:l="replace"}={})=>{const n=F([""]),u=g(!1),t=g(),a=g(!1);let f=g(-1);const v=new Set,w=e=>{var s;l==="replace"?t.value=e:l==="merge"&&(A((Array.isArray(t.value)||typeof t.value>"u")&&Array.isArray(e),"数据更新策略为合并时仅可用于值为数组的情况"),t.value=[...(s=t==null?void 0:t.value)!==null&&s!==void 0?s:[],...e])},d=e=>x(void 0,void 0,void 0,function*(){if(a.value||u.value&&typeof e>"u")return!1;a.value=!0;const s=W();f.value=s;try{let r;if(typeof e=="number"){if(r=n[e],typeof r!="string")return!1}else r=n[n.length-1];const p=yield o(r);if(v.has(s))return v.delete(s),!1;w(c(p));const i=p.cursor;if((e===n.length-1||typeof e!="number")&&(u.value=!i.has_next,i.has_next)){const I=i.next_cursor||i.next;A(typeof I=="string"),n.push(I)}}finally{f.value===s&&(a.value=!1)}return!0}),h=()=>{v.add(f.value),a.value=!1},S=(e=!1)=>x(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&h(),A(!a.value),n.splice(0,n.length,""),a.value=!1,t.value=void 0,u.value=!1,s&&(yield d())}),m=()=>({next:()=>x(void 0,void 0,void 0,function*(){if(a.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return q({abort:h,load:u,next:d,res:t,loading:a,cursorStack:n,reset:S,[Symbol.asyncIterator]:m,iter:{[Symbol.asyncIterator]:m}})},Z=o=>F($(o,c=>c.files,{dataUpdateStrategy:"merge"})),ee=o=>{const c=F(new Set),l=D(()=>(o.res??[]).filter(y=>!c.has(y.fullpath))),n=N(),{stackViewEl:u,multiSelectedIdxs:t,stack:a,scroller:f}=G({images:l}).toRefs(),{itemSize:v,gridItems:w,cellWidth:d,onScroll:h}=H({fetchNext:()=>o.next()}),{showMenuIdx:S}=L(),{onFileDragStart:m,onFileDragEnd:e}=Q(),{showGenInfo:s,imageGenInfo:r,q:p,onContextMenuClick:i,onFileItemClick:I}=B({openNext:j}),{previewIdx:C,previewing:_,onPreviewVisibleChange:E,previewImgMove:M,canPreview:J}=T(),P=async(y,b,R)=>{a.value=[{curr:"",files:l.value}],await i(y,b,R)};O("removeFiles",async({paths:y})=>{y.forEach(b=>c.add(b))});const k=()=>{z(l.value)};return{images:l,scroller:f,queue:n,iter:o,onContextMenuClickU:P,stackViewEl:u,previewIdx:C,previewing:_,onPreviewVisibleChange:E,previewImgMove:M,canPreview:J,itemSize:v,gridItems:w,showGenInfo:s,imageGenInfo:r,q:p,onContextMenuClick:i,onFileItemClick:I,showMenuIdx:S,multiSelectedIdxs:t,onFileDragStart:m,onFileDragEnd:e,cellWidth:d,onScroll:h,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!o.load;)await o.next();k()}}};export{Z as c,ee as u};

View File

@ -1 +0,0 @@
import{ah as F,r as g,cc as q,cd as A,H as b,B as D,c2 as N,bm as z,ce as G}from"./index-333f4d92.js";import{u as H,a as L,b as O,e as Q}from"./FileItem-064f25fa.js";import{a as j,b as B,c as T}from"./MultiSelectKeep-0aedd2f1.js";let U=0;const W=()=>++U,K=(o,c,{dataUpdateStrategy:l="replace"}={})=>{const n=F([""]),u=g(!1),t=g(),a=g(!1);let f=g(-1);const v=new Set,w=e=>{var s;l==="replace"?t.value=e:l==="merge"&&(b((Array.isArray(t.value)||typeof t.value>"u")&&Array.isArray(e),"数据更新策略为合并时仅可用于值为数组的情况"),t.value=[...(s=t==null?void 0:t.value)!==null&&s!==void 0?s:[],...e])},d=e=>A(void 0,void 0,void 0,function*(){if(a.value||u.value&&typeof e>"u")return!1;a.value=!0;const s=W();f.value=s;try{let r;if(typeof e=="number"){if(r=n[e],typeof r!="string")return!1}else r=n[n.length-1];const p=yield o(r);if(v.has(s))return v.delete(s),!1;w(c(p));const i=p.cursor;if((e===n.length-1||typeof e!="number")&&(u.value=!i.has_next,i.has_next)){const I=i.next_cursor||i.next;b(typeof I=="string"),n.push(I)}}finally{f.value===s&&(a.value=!1)}return!0}),m=()=>{v.add(f.value),a.value=!1},S=(e=!1)=>A(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&m(),b(!a.value),n.splice(0,n.length,""),a.value=!1,t.value=void 0,u.value=!1,s&&(yield d())}),h=()=>({next:()=>A(void 0,void 0,void 0,function*(){if(a.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return q({abort:m,load:u,next:d,res:t,loading:a,cursorStack:n,reset:S,[Symbol.asyncIterator]:h,iter:{[Symbol.asyncIterator]:h}})},$=o=>F(K(o,c=>c.files,{dataUpdateStrategy:"merge"})),ee=o=>{const c=F(new Set),l=D(()=>(o.res??[]).filter(y=>!c.has(y.fullpath))),n=N(),{stackViewEl:u,multiSelectedIdxs:t,stack:a,scroller:f}=H({images:l}).toRefs(),{itemSize:v,gridItems:w,cellWidth:d,onScroll:m}=L({fetchNext:()=>o.next()}),{showMenuIdx:S}=O(),{onFileDragStart:h,onFileDragEnd:e}=j(),{showGenInfo:s,imageGenInfo:r,q:p,onContextMenuClick:i,onFileItemClick:I}=B({openNext:z}),{previewIdx:C,previewing:_,onPreviewVisibleChange:E,previewImgMove:M,canPreview:J}=T(),P=async(y,x,R)=>{a.value=[{curr:"",files:l.value}],await i(y,x,R)};Q("removeFiles",async({paths:y})=>{y.forEach(x=>c.add(x))});const k=()=>{G(l.value)};return{images:l,scroller:f,queue:n,iter:o,onContextMenuClickU:P,stackViewEl:u,previewIdx:C,previewing:_,onPreviewVisibleChange:E,previewImgMove:M,canPreview:J,itemSize:v,gridItems:w,showGenInfo:s,imageGenInfo:r,q:p,onContextMenuClick:i,onFileItemClick:I,showMenuIdx:S,multiSelectedIdxs:t,onFileDragStart:h,onFileDragEnd:e,cellWidth:d,onScroll:m,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!o.load;)await o.next();k()}}};export{$ as c,ee as u};

View File

@ -1 +1 @@
import{d as w,by as D,ar as A,cy as j,av as k,l as V,cz as B,ch as m,e as $,c as a,_ as T,h as r,a as P,bI as M,P as b}from"./index-333f4d92.js";var O=["class","style"],W=function(){return{prefixCls:String,spinning:{type:Boolean,default:void 0},size:String,wrapperClassName:String,tip:b.any,delay:Number,indicator:b.any}},p=null;function q(t,n){return!!t&&!!n&&!isNaN(Number(n))}function G(t){var n=t.indicator;p=typeof n=="function"?n:function(){return a(n,null,null)}}const H=w({compatConfig:{MODE:3},name:"ASpin",inheritAttrs:!1,props:D(W(),{size:"default",spinning:!0,wrapperClassName:""}),setup:function(){return{originalUpdateSpinning:null,configProvider:A("configProvider",j)}},data:function(){var n=this.spinning,e=this.delay,i=q(n,e);return{sSpinning:n&&!i}},created:function(){this.originalUpdateSpinning=this.updateSpinning,this.debouncifyUpdateSpinning(this.$props)},mounted:function(){this.updateSpinning()},updated:function(){var n=this;k(function(){n.debouncifyUpdateSpinning(),n.updateSpinning()})},beforeUnmount:function(){this.cancelExistingSpin()},methods:{debouncifyUpdateSpinning:function(n){var e=n||this.$props,i=e.delay;i&&(this.cancelExistingSpin(),this.updateSpinning=V(this.originalUpdateSpinning,i))},updateSpinning:function(){var n=this.spinning,e=this.sSpinning;e!==n&&(this.sSpinning=n)},cancelExistingSpin:function(){var n=this.updateSpinning;n&&n.cancel&&n.cancel()},renderIndicator:function(n){var e="".concat(n,"-dot"),i=B(this,"indicator");return i===null?null:(Array.isArray(i)&&(i=i.length===1?i[0]:i),m(i)?$(i,{class:e}):p&&m(p())?$(p(),{class:e}):a("span",{class:"".concat(e," ").concat(n,"-dot-spin")},[a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null)]))}},render:function(){var n,e,i,o=this.$props,f=o.size,x=o.prefixCls,h=o.tip,d=h===void 0?(n=(e=this.$slots).tip)===null||n===void 0?void 0:n.call(e):h,N=o.wrapperClassName,l=this.$attrs,v=l.class,_=l.style,C=T(l,O),S=this.configProvider,U=S.getPrefixCls,I=S.direction,s=U("spin",x),u=this.sSpinning,z=(i={},r(i,s,!0),r(i,"".concat(s,"-sm"),f==="small"),r(i,"".concat(s,"-lg"),f==="large"),r(i,"".concat(s,"-spinning"),u),r(i,"".concat(s,"-show-text"),!!d),r(i,"".concat(s,"-rtl"),I==="rtl"),r(i,v,!!v),i),y=a("div",P(P({},C),{},{style:_,class:z}),[this.renderIndicator(s),d?a("div",{class:"".concat(s,"-text")},[d]):null]),g=M(this);if(g&&g.length){var c,E=(c={},r(c,"".concat(s,"-container"),!0),r(c,"".concat(s,"-blur"),u),c);return a("div",{class:["".concat(s,"-nested-loading"),N]},[u&&a("div",{key:"loading"},[y]),a("div",{class:E,key:"container"},[g])])}return y}});export{H as S,G as s};
import{d as w,bv as D,ar as A,cy as j,av as k,l as V,cz as B,ce as y,e as $,c as a,_ as T,h as r,a as P,bF as F,P as b}from"./index-8120eed9.js";var M=["class","style"],O=function(){return{prefixCls:String,spinning:{type:Boolean,default:void 0},size:String,wrapperClassName:String,tip:b.any,delay:Number,indicator:b.any}},p=null;function W(t,n){return!!t&&!!n&&!isNaN(Number(n))}function G(t){var n=t.indicator;p=typeof n=="function"?n:function(){return a(n,null,null)}}const H=w({compatConfig:{MODE:3},name:"ASpin",inheritAttrs:!1,props:D(O(),{size:"default",spinning:!0,wrapperClassName:""}),setup:function(){return{originalUpdateSpinning:null,configProvider:A("configProvider",j)}},data:function(){var n=this.spinning,e=this.delay,i=W(n,e);return{sSpinning:n&&!i}},created:function(){this.originalUpdateSpinning=this.updateSpinning,this.debouncifyUpdateSpinning(this.$props)},mounted:function(){this.updateSpinning()},updated:function(){var n=this;k(function(){n.debouncifyUpdateSpinning(),n.updateSpinning()})},beforeUnmount:function(){this.cancelExistingSpin()},methods:{debouncifyUpdateSpinning:function(n){var e=n||this.$props,i=e.delay;i&&(this.cancelExistingSpin(),this.updateSpinning=V(this.originalUpdateSpinning,i))},updateSpinning:function(){var n=this.spinning,e=this.sSpinning;e!==n&&(this.sSpinning=n)},cancelExistingSpin:function(){var n=this.updateSpinning;n&&n.cancel&&n.cancel()},renderIndicator:function(n){var e="".concat(n,"-dot"),i=B(this,"indicator");return i===null?null:(Array.isArray(i)&&(i=i.length===1?i[0]:i),y(i)?$(i,{class:e}):p&&y(p())?$(p(),{class:e}):a("span",{class:"".concat(e," ").concat(n,"-dot-spin")},[a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null)]))}},render:function(){var n,e,i,o=this.$props,f=o.size,x=o.prefixCls,h=o.tip,d=h===void 0?(n=(e=this.$slots).tip)===null||n===void 0?void 0:n.call(e):h,N=o.wrapperClassName,l=this.$attrs,v=l.class,_=l.style,C=T(l,M),S=this.configProvider,U=S.getPrefixCls,z=S.direction,s=U("spin",x),u=this.sSpinning,E=(i={},r(i,s,!0),r(i,"".concat(s,"-sm"),f==="small"),r(i,"".concat(s,"-lg"),f==="large"),r(i,"".concat(s,"-spinning"),u),r(i,"".concat(s,"-show-text"),!!d),r(i,"".concat(s,"-rtl"),z==="rtl"),r(i,v,!!v),i),m=a("div",P(P({},C),{},{style:_,class:E}),[this.renderIndicator(s),d?a("div",{class:"".concat(s,"-text")},[d]):null]),g=F(this);if(g&&g.length){var c,I=(c={},r(c,"".concat(s,"-container"),!0),r(c,"".concat(s,"-blur"),u),c);return a("div",{class:["".concat(s,"-nested-loading"),N]},[u&&a("div",{key:"loading"},[m]),a("div",{class:I,key:"container"},[g])])}return m}});export{H as S,G as s};

File diff suppressed because one or more lines are too long

1
vue/dist/assets/index-9938200e.js vendored Normal file
View File

@ -0,0 +1 @@
import{r as F,o as P,cv as K,ar as L,B as l,at as T,au as I,d as $,u as B,cw as _,b as y,b9 as V,cx as A,aj as E,h as c,c as M,a as G}from"./index-8120eed9.js";const W=function(){var o=F(!1);return P(function(){o.value=K()}),o};var D=Symbol("rowContextKey"),U=function(r){T(D,r)},k=function(){return L(D,{gutter:l(function(){}),wrap:l(function(){}),supportFlexGap:l(function(){})})};I("top","middle","bottom","stretch");I("start","end","center","space-around","space-between");var q=function(){return{align:String,justify:String,prefixCls:String,gutter:{type:[Number,Array,Object],default:0},wrap:{type:Boolean,default:void 0}}},H=$({compatConfig:{MODE:3},name:"ARow",props:q(),setup:function(r,N){var m=N.slots,v=B("row",r),d=v.prefixCls,h=v.direction,j,x=F({xs:!0,sm:!0,md:!0,lg:!0,xl:!0,xxl:!0,xxxl:!0}),w=W();P(function(){j=_.subscribe(function(e){var t=r.gutter||0;(!Array.isArray(t)&&y(t)==="object"||Array.isArray(t)&&(y(t[0])==="object"||y(t[1])==="object"))&&(x.value=e)})}),V(function(){_.unsubscribe(j)});var S=l(function(){var e=[0,0],t=r.gutter,n=t===void 0?0:t,s=Array.isArray(n)?n:[n,0];return s.forEach(function(i,b){if(y(i)==="object")for(var a=0;a<A.length;a++){var p=A[a];if(x.value[p]&&i[p]!==void 0){e[b]=i[p];break}}else e[b]=i||0}),e});U({gutter:S,supportFlexGap:w,wrap:l(function(){return r.wrap})});var R=l(function(){var e;return E(d.value,(e={},c(e,"".concat(d.value,"-no-wrap"),r.wrap===!1),c(e,"".concat(d.value,"-").concat(r.justify),r.justify),c(e,"".concat(d.value,"-").concat(r.align),r.align),c(e,"".concat(d.value,"-rtl"),h.value==="rtl"),e))}),O=l(function(){var e=S.value,t={},n=e[0]>0?"".concat(e[0]/-2,"px"):void 0,s=e[1]>0?"".concat(e[1]/-2,"px"):void 0;return n&&(t.marginLeft=n,t.marginRight=n),w.value?t.rowGap="".concat(e[1],"px"):s&&(t.marginTop=s,t.marginBottom=s),t});return function(){var e;return M("div",{class:R.value,style:O.value},[(e=m.default)===null||e===void 0?void 0:e.call(m)])}}});const Y=H;function J(o){return typeof o=="number"?"".concat(o," ").concat(o," auto"):/^\d+(\.\d+)?(px|em|rem|%)$/.test(o)?"0 0 ".concat(o):o}var Q=function(){return{span:[String,Number],order:[String,Number],offset:[String,Number],push:[String,Number],pull:[String,Number],xs:{type:[String,Number,Object],default:void 0},sm:{type:[String,Number,Object],default:void 0},md:{type:[String,Number,Object],default:void 0},lg:{type:[String,Number,Object],default:void 0},xl:{type:[String,Number,Object],default:void 0},xxl:{type:[String,Number,Object],default:void 0},xxxl:{type:[String,Number,Object],default:void 0},prefixCls:String,flex:[String,Number]}};const Z=$({compatConfig:{MODE:3},name:"ACol",props:Q(),setup:function(r,N){var m=N.slots,v=k(),d=v.gutter,h=v.supportFlexGap,j=v.wrap,x=B("col",r),w=x.prefixCls,S=x.direction,R=l(function(){var e,t=r.span,n=r.order,s=r.offset,i=r.push,b=r.pull,a=w.value,p={};return["xs","sm","md","lg","xl","xxl","xxxl"].forEach(function(g){var f,u={},C=r[g];typeof C=="number"?u.span=C:y(C)==="object"&&(u=C||{}),p=G(G({},p),{},(f={},c(f,"".concat(a,"-").concat(g,"-").concat(u.span),u.span!==void 0),c(f,"".concat(a,"-").concat(g,"-order-").concat(u.order),u.order||u.order===0),c(f,"".concat(a,"-").concat(g,"-offset-").concat(u.offset),u.offset||u.offset===0),c(f,"".concat(a,"-").concat(g,"-push-").concat(u.push),u.push||u.push===0),c(f,"".concat(a,"-").concat(g,"-pull-").concat(u.pull),u.pull||u.pull===0),c(f,"".concat(a,"-rtl"),S.value==="rtl"),f))}),E(a,(e={},c(e,"".concat(a,"-").concat(t),t!==void 0),c(e,"".concat(a,"-order-").concat(n),n),c(e,"".concat(a,"-offset-").concat(s),s),c(e,"".concat(a,"-push-").concat(i),i),c(e,"".concat(a,"-pull-").concat(b),b),e),p)}),O=l(function(){var e=r.flex,t=d.value,n={};if(t&&t[0]>0){var s="".concat(t[0]/2,"px");n.paddingLeft=s,n.paddingRight=s}if(t&&t[1]>0&&!h.value){var i="".concat(t[1]/2,"px");n.paddingTop=i,n.paddingBottom=i}return e&&(n.flex=J(e),j.value===!1&&!n.minWidth&&(n.minWidth=0)),n});return function(){var e;return M("div",{class:R.value,style:O.value},[(e=m.default)===null||e===void 0?void 0:e.call(m)])}}});export{Z as C,Y as R};

File diff suppressed because one or more lines are too long

1
vue/dist/assets/index-abca4c64.css vendored Normal file

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

12
vue/dist/assets/numInput-9bc510bb.js vendored Normal file

File diff suppressed because one or more lines are too long

1
vue/dist/assets/numInput-a72a24b1.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{R as y,C as v}from"./index-9938200e.js";import{bL as f,c as d,A as b,d as w,N as a,O as c,Q as r,T as P,a2 as S,aC as O,Y as R,R as u,S as p,Z as V,af as $,V as L,I as x,cp as _}from"./index-8120eed9.js";const A=f(y),E=f(v);var C={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M878.3 392.1L631.9 145.7c-6.5-6.5-15-9.7-23.5-9.7s-17 3.2-23.5 9.7L423.8 306.9c-12.2-1.4-24.5-2-36.8-2-73.2 0-146.4 24.1-206.5 72.3-15.4 12.3-16.6 35.4-2.7 49.4l181.7 181.7-215.4 215.2a15.8 15.8 0 00-4.6 9.8l-3.4 37.2c-.9 9.4 6.6 17.4 15.9 17.4.5 0 1 0 1.5-.1l37.2-3.4c3.7-.3 7.2-2 9.8-4.6l215.4-215.4 181.7 181.7c6.5 6.5 15 9.7 23.5 9.7 9.7 0 19.3-4.2 25.9-12.4 56.3-70.3 79.7-158.3 70.2-243.4l161.1-161.1c12.9-12.8 12.9-33.8 0-46.8z"}}]},name:"pushpin",theme:"filled"};const H=C;function h(t){for(var e=1;e<arguments.length;e++){var s=arguments[e]!=null?Object(arguments[e]):{},n=Object.keys(s);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(s).filter(function(i){return Object.getOwnPropertyDescriptor(s,i).enumerable}))),n.forEach(function(i){N(t,i,s[i])})}return t}function N(t,e,s){return e in t?Object.defineProperty(t,e,{value:s,enumerable:!0,configurable:!0,writable:!0}):t[e]=s,t}var l=function(e,s){var n=h({},e,s.attrs);return d(b,h({},n,{icon:H}),null)};l.displayName="PushpinFilled";l.inheritAttrs=!1;const z=l,F={class:"record-container"},I={style:{flex:"1"}},k={class:"rec-actions"},B=["onClick"],j=w({__name:"HistoryRecord",props:{records:{}},emits:["reuseRecord"],setup(t){return(e,s)=>{const n=$;return a(),c("div",null,[r("ul",F,[(a(!0),c(P,null,S(e.records.getRecords(),i=>(a(),c("li",{key:i.id,class:"record"},[r("div",I,[O(e.$slots,"default",{record:i},void 0,!0)]),r("div",k,[d(n,{onClick:g=>e.$emit("reuseRecord",i),type:"primary"},{default:R(()=>[u(p(e.$t("restore")),1)]),_:2},1032,["onClick"]),r("div",{class:"pin",onClick:g=>e.records.switchPin(i)},[d(V(z)),u(" "+p(e.records.isPinned(i)?e.$t("unpin"):e.$t("pin")),1)],8,B)])]))),128))])])}}});const T=L(j,[["__scopeId","data-v-fd295bfe"]]);class o{constructor(e=128,s=[],n=[]){this.maxLength=e,this.records=s,this.pinnedValues=n}isPinned(e){return this.pinnedValues.some(s=>s.id===e.id)}add(e){this.records.length>=this.maxLength&&this.records.pop(),this.records.unshift({...e,id:x()+Date.now(),time:new Date().toLocaleString()})}pin(e){const s=this.records.findIndex(n=>n.id===e.id);s!==-1&&this.records.splice(s,1),this.pinnedValues.push(e)}unpin(e){const s=this.pinnedValues.findIndex(n=>n.id===e.id);s!==-1&&this.pinnedValues.splice(s,1),this.records.unshift(e)}switchPin(e){this.isPinned(e)?this.unpin(e):this.pin(e)}getRecords(){return[...this.pinnedValues,...this.records]}}const m="iib://",q=_(`${m}fuzzy-search-HistoryRecord`,new o,{serializer:{read:t=>{const e=JSON.parse(t);return new o(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),M=_(`${m}tag-search-HistoryRecord`,new o,{serializer:{read:t=>{const e=JSON.parse(t);return new o(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}});export{T as H,E as _,A as a,q as f,M as t};

View File

@ -0,0 +1 @@
.record-container[data-v-fd295bfe]{list-style:none;padding:8px;margin:16px;max-height:50vh;overflow:auto}.record[data-v-fd295bfe]{display:flex;flex-direction:row;justify-content:space-between;align-items:center;padding:10px;border-bottom:1px solid var(--zp-tertiary);position:relative;flex-wrap:nowrap;transition:all .3s ease}.record[data-v-fd295bfe]:hover{background:var(--zp-secondary-background)}.record .rec-actions[data-v-fd295bfe]{user-select:none;display:flex;gap:8px}.record .pin[data-v-fd295bfe]{cursor:pointer;padding:4px 8px;border-radius:4px;transition:all .3s ease}.record .pin[data-v-fd295bfe]:hover{background:var(--zp-primary-background)}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
vue/dist/index.html vendored
View File

@ -7,7 +7,7 @@
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Infinite Image Browsing</title>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-333f4d92.js"></script>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-8120eed9.js"></script>
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-daea5cd8.css">
</head>

View File

@ -0,0 +1,74 @@
<template>
<div>
<ul class="record-container">
<li v-for="record in records.getRecords()" :key="record.id" class="record">
<div style="flex: 1">
<slot :record="record"></slot>
</div>
<div class="rec-actions">
<a-button @click="$emit('reuseRecord', record)" type="primary">{{ $t('restore') }}</a-button>
<div class="pin" @click="records.switchPin(record)">
<PushpinFilled /> {{ records.isPinned(record) ? $t('unpin') : $t('pin') }}
</div>
</div>
</li>
</ul>
</div>
</template>
<script lang="ts" setup>
import { PushpinFilled } from '@/icon'
import { HistoryRecord } from '@/util/HistoryRecord'
defineProps<{
records: HistoryRecord<any>
}>()
defineEmits<{
reuseRecord: [record: any]
}>()
</script>
<style scoped lang="scss">
.record-container {
list-style: none;
padding: 8px;
margin: 16px;
max-height: 50vh;
overflow: auto;
}
.record {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid var(--zp-tertiary);
position: relative;
flex-wrap: nowrap;
transition: all .3s ease;
&:hover {
background: var(--zp-secondary-background);
}
.rec-actions {
user-select: none;
display: flex;
gap: 8px;
}
.pin {
cursor: pointer;
padding: 4px 8px;
border-radius: 4px;
transition: all .3s ease;
&:hover {
background: var(--zp-primary-background);
}
}
}
</style>

View File

@ -1,6 +1,14 @@
import type { IIBI18nMap } from '.'
export const en: IIBI18nMap = {
time: 'Time',
pin: 'Pin',
unpin: 'Unpin',
restore: 'Restore',
restoreFromHistory: 'Restore from History',
history: 'History',
historyRecordsSubstr: 'Input Value',
historyRecordsisRegex: 'Is Regex',
walkModeDoc: 'Browse all files in a specified folder without paging, using infinite scrolling to display them. DFS will be used to traverse all files. Note: Sorting is only performed within the same layer in this mode.',
normalModelDoc: 'Similar to the Windows file browser, with high flexibility. But exceptions may occur when accessing cloud storage or similar SMB.',
fixedModeDoc: 'Similar to Normal mode, but with faster initial page speed, better compatibility, and slightly less flexibility. If you encounter an exception in Normal mode, you can try this mode instead.',

View File

@ -1,4 +1,12 @@
export const zhHans = {
time: '时间',
pin: '置顶',
unpin: '取消置顶',
restore: '还原',
restoreFromHistory: '从历史记录中恢复',
history: '历史记录',
historyRecordsSubstr: '输入值',
historyRecordsisRegex: '是否正则',
walkModeDoc: '无需翻页即可浏览指定文件夹下的所有文件使用无限滚动的方式呈现。将会使用DFS的方式遍历所有文件. 注意:该模式下排序仅在同层之间进行',
normalModelDoc: '类似于windows的文件浏览器拥有较高的灵活性. 但在访问云存储或者类似SMB这样的地方时可能会出现异常',
fixedModeDoc: '类似Normal模式但页面初始速度更快兼容性更好灵活性稍差。在Normal模式下出现了异常的话都可以改用这个试试',

View File

@ -1,6 +1,14 @@
import type { IIBI18nMap } from '.'
export const zhHant: Partial<IIBI18nMap> = {
time: '時間',
pin: '置頂',
unpin: '取消置頂',
restore: '還原',
restoreFromHistory: '從歷史記錄中恢復',
history: '歷史記錄',
historyRecordsSubstr: '輸入值',
historyRecordsisRegex: '是否正則',
walkModeDoc: '無需翻頁即可瀏覽指定資料夾下的所有檔案,使用無限捲動的方式呈現。將會使用 DFS 的方式遍歷所有檔案. 注意:該模式下排序僅在同層之間進行',
normalModelDoc: '類似於 Windows 的檔案瀏覽器,擁有較高的靈活性. 但在訪問雲端儲存或者類似 SMB 這樣的地方時可能會出現異常',
fixedModeDoc: '類似 Normal 模式,但頁面初始速度更快,相容性更好,靈活性稍差。在 Normal 模式下出現了異常的話都可以改用這個試試',

View File

@ -15,11 +15,15 @@ import { createImageSearchIter, useImageSearch } from './hook'
import { useKeepMultiSelect } from '../fileTransfer/hook'
import MultiSelectKeep from '@/components/MultiSelectKeep.vue'
import { useGlobalStore } from '@/store/useGlobalStore'
import HistoryRecord from '@/components/HistoryRecord.vue'
import { fuzzySearchHistory, FuzzySearchHistoryRecord } from '@/store/searchHistory'
const props = defineProps<{ tabIdx: number; paneIdx: number, searchScope?: string }>()
const isRegex = ref(false)
const substr = ref('')
const folder_paths_str = ref(props.searchScope ?? '')
const showHistoryRecord = ref(false)
const searchCount = ref(0)
const iter = createImageSearchIter(cursor => {
const req: SearchBySubstrReq = {
cursor,
@ -27,7 +31,7 @@ const iter = createImageSearchIter(cursor => {
surstr: !isRegex.value ? substr.value : '',
folder_paths: (folder_paths_str.value ?? '').split(/,|\n/).map(v => v.trim()).filter(v => v)
}
return getImagesBySubstr(req)
return getImagesBySubstr(req)
})
const {
queue,
@ -77,7 +81,23 @@ const onUpdateBtnClick = makeAsyncFunctionSingle(
return info.value
}).res
)
const reuse = (rec: FuzzySearchHistoryRecord & { id: string; time: string }) => {
substr.value = rec.substr
folder_paths_str.value = rec.folder_paths_str
isRegex.value = rec.isRegex
showHistoryRecord.value = false
query()
}
const query = async () => {
searchCount.value++
fuzzySearchHistory.value.add({
substr: substr.value,
folder_paths_str: folder_paths_str.value,
isRegex: isRegex.value
})
await iter.reset({ refetch: true })
await nextTick()
onScroll()
@ -102,9 +122,35 @@ const g = useGlobalStore()
const { onClearAllSelected, onSelectAll, onReverseSelect } = useKeepMultiSelect()
</script>
<template>
<a-modal v-model:visible="showHistoryRecord" width="70vw" mask-closable @ok="showHistoryRecord = false">
<HistoryRecord :records="fuzzySearchHistory" @reuse-record="reuse">
<template #default="{ record }">
<div style="padding-right: 16px;">
<a-row>
<a-col :span="4">{{ $t('historyRecordsSubstr') }}:</a-col>
<a-col :span="20">{{ record.substr }}</a-col>
</a-row>
<a-row v-if="record.folder_paths_str">
<a-col :span="4">{{ $t('searchScope') }}:</a-col>
<a-col :span="20">{{ record.folder_paths_str }}</a-col>
</a-row>
<a-row>
<a-col :span="4">{{ $t('historyRecordsisRegex') }}:</a-col>
<a-col :span="20">{{ record.isRegex }}</a-col>
</a-row>
<a-row>
<a-col :span="4">{{ $t('time') }}:</a-col>
<a-col :span="20">{{ record.time }}</a-col>
</a-row>
<div>
</div>
</div>
</template>
</HistoryRecord>
</a-modal>
<div class="container" ref="stackViewEl">
<MultiSelectKeep :show="!!multiSelectedIdxs.length || g.keepMultiSelect"
@clear-all-selected="onClearAllSelected" @select-all="onSelectAll" @reverse-select="onReverseSelect"/>
<MultiSelectKeep :show="!!multiSelectedIdxs.length || g.keepMultiSelect" @clear-all-selected="onClearAllSelected"
@select-all="onSelectAll" @reverse-select="onReverseSelect" />
<div class="search-bar" v-if="info" @keydown.stop>
<a-input v-model:value="substr" :placeholder="$t('fuzzy-search-placeholder') + ' ' + $t('regexSearchEnabledHint')"
:disabled="!queue.isIdle" @keydown.enter="query" allow-clear />
@ -112,17 +158,19 @@ const { onClearAllSelected, onSelectAll, onReverseSelect } = useKeepMultiSelect(
title="Use Regular Expression"> <img :src="regex"></div>
<AButton @click="onUpdateBtnClick" :loading="!queue.isIdle" type="primary" v-if="info.expired || !info.img_count">
{{ info.img_count === 0 ? $t('generateIndexHint') : $t('UpdateIndex') }}</AButton>
<AButton v-else type="primary" @click="query" :loading="!queue.isIdle || iter.loading" :disabled="!substr && !folder_paths_str">{{
$t('search') }}
<AButton v-else type="primary" @click="query" :loading="!queue.isIdle || iter.loading"
:disabled="!substr && !folder_paths_str">{{ $t('search') }}
</AButton>
</div>
<div class="search-bar">
<div class="form-name">{{ $t('searchScope') }}</div>
<ATextarea :auto-size="{ maxRows: 8 }" v-model:value="folder_paths_str" :placeholder="$t('specifiedSearchFolder')"/>
<ATextarea :auto-size="{ maxRows: 8 }" v-model:value="folder_paths_str"
:placeholder="$t('specifiedSearchFolder')" />
</div>
<div class="search-bar last actions">
<a-button @click="saveLoadedFileAsJson">{{ $t('saveLoadedImageAsJson') }}</a-button>
<a-button @click="saveAllFileAsJson">{{ $t('saveAllAsJson') }}</a-button>
<a-button @click="showHistoryRecord = true">{{ $t('history') }}</a-button>
</div>
<ASpin size="large" :spinning="!queue.isIdle">
<AModal v-model:visible="showGenInfo" width="70vw" mask-closable @ok="showGenInfo = false">
@ -140,18 +188,48 @@ const { onClearAllSelected, onSelectAll, onReverseSelect } = useKeepMultiSelect(
</div>
</ASkeleton>
</AModal>
<div v-if="searchCount === 0 && !images.length"
style="margin: 64px 16px 32px; padding: 8px; background: var(--zp-secondary-variant-background);border-radius: 16px">
<h2 style="margin: 16px 32px 16px;">
{{ $t('restoreFromHistory') }}
</h2>
<HistoryRecord :records="fuzzySearchHistory" @reuse-record="reuse">
<template #default="{ record }">
<div style="padding-right: 16px;;">
<a-row>
<a-col :span="4">{{ $t('historyRecordsSubstr') }}:</a-col>
<a-col :span="20">{{ record.substr }}</a-col>
</a-row>
<a-row v-if="record.folder_paths_str">
<a-col :span="4">{{ $t('searchScope') }}:</a-col>
<a-col :span="20">{{ record.folder_paths_str }}</a-col>
</a-row>
<a-row>
<a-col :span="4">{{ $t('historyRecordsisRegex') }}:</a-col>
<a-col :span="20">{{ record.isRegex }}</a-col>
</a-row>
<a-row>
<a-col :span="4">{{ $t('time') }}:</a-col>
<a-col :span="20">{{ record.time }}</a-col>
</a-row>
<div>
</div>
</div>
</template>
</HistoryRecord>
</div>
<RecycleScroller ref="scroller" class="file-list" v-if="images" :items="images" :item-size="itemSize.first"
key-field="fullpath" :item-secondary-size="itemSize.second" :gridItems="gridItems" @scroll="onScroll">
<template #after>
<div style="padding: 16px 0 512px;"/>
<div style="padding: 16px 0 512px;" />
</template>
<template v-slot="{ item: file, index: idx }">
<!-- idx 和file有可能丢失 -->
<file-item-cell :idx="idx" :file="file" v-model:show-menu-idx="showMenuIdx" @file-item-click="onFileItemClick"
:full-screen-preview-image-url="images[previewIdx] ? toRawFileUrl(images[previewIdx]) : ''"
:cell-width="cellWidth" :selected="multiSelectedIdxs.includes(idx)" @context-menu-click="onContextMenuClickU"
@dragstart="onFileDragStart" @dragend="onFileDragEnd" :is-selected-mutil-files="multiSelectedIdxs.length > 1"
@preview-visible-change="onPreviewVisibleChange" />
:cell-width="cellWidth" :selected="multiSelectedIdxs.includes(idx)"
@context-menu-click="onContextMenuClickU" @dragstart="onFileDragStart" @dragend="onFileDragEnd"
:is-selected-mutil-files="multiSelectedIdxs.length > 1" @preview-visible-change="onPreviewVisibleChange" />
</template>
</RecycleScroller>
<div v-if="previewing" class="preview-switch">
@ -159,8 +237,8 @@ const { onClearAllSelected, onSelectAll, onReverseSelect } = useKeepMultiSelect(
<RightCircleOutlined @click="previewImgMove('next')" :class="{ disable: !canPreview('next') }" />
</div>
</ASpin>
<fullScreenContextMenu v-if="previewing && images && images[previewIdx]" :file="images[previewIdx]" :idx="previewIdx"
@context-menu-click="onContextMenuClickU" />
<fullScreenContextMenu v-if="previewing && images && images[previewIdx]" :file="images[previewIdx]"
:idx="previewIdx" @context-menu-click="onContextMenuClickU" />
</div>
</template>
<style scoped lang="scss">
@ -169,6 +247,7 @@ const { onClearAllSelected, onSelectAll, onReverseSelect } = useKeepMultiSelect(
position: fixed;
}
}
.regex-icon {
img {
height: 1.5em;
@ -193,16 +272,20 @@ const { onClearAllSelected, onSelectAll, onReverseSelect } = useKeepMultiSelect(
.search-bar {
padding: 8px 8px 0 8px;
&.last {
padding-bottom: 8px;
}
display: flex;
.form-name {
flex-shrink: 0;
padding: 4px 8px;
}
.actions > * {
margin-right: 4px;
.form-name {
flex-shrink: 0;
padding: 4px 8px;
}
.actions>* {
margin-right: 4px;
}
}
@ -235,7 +318,7 @@ const { onClearAllSelected, onSelectAll, onReverseSelect } = useKeepMultiSelect(
.container {
background: var(--zp-secondary-background);
position: relative;
.file-list {
@ -246,4 +329,5 @@ const { onClearAllSelected, onSelectAll, onReverseSelect } = useKeepMultiSelect(
height: var(--pane-max-height);
width: 100%;
}
}</style>
}
</style>

View File

@ -22,13 +22,14 @@ import { makeAsyncFunctionSingle } from '@/util'
import TagSearchItem from './TagSearchItem.vue'
import { reactive, nextTick } from 'vue'
import { watch } from 'vue'
import { tagSearchHistory } from '@/store/searchHistory'
const props = defineProps<{ tabIdx: number; paneIdx: number, searchScope?: string }>()
const global = useGlobalStore()
const queue = createReactiveQueue()
const loading = computed(() => !queue.isIdle)
const info = ref<DataBaseBasicInfo>()
const showHistoryRecord = ref(false)
const matchIds = ref<MatchImageByTagsReq>({ and_tags: [], or_tags: [], not_tags: [], folder_paths_str: props.searchScope })
const tags = computed(() =>
info.value ? info.value.tags.slice().sort((a, b) => b.count - a.count) : []
@ -103,9 +104,16 @@ const onUpdateBtnClick = makeAsyncFunctionSingle(
)
const query = () => {
tagSearchHistory.value.add(matchIds.value)
global.openTagSearchMatchedImageGridInRight(props.tabIdx, pairid, matchIds.value)
}
const reuse = (record: MatchImageByTagsReq) => {
matchIds.value = record
showHistoryRecord.value = false
query()
}
useGlobalEventListen('returnToIIB', async () => {
const res = await queue.pushAction(getExpiredDirs).res
info.value!.expired = res.expired
@ -185,9 +193,44 @@ const tagListFilter = (list: Tag[], name: string) => {
return list.slice(0, max)
}
const tagIdsToString = (tagIds: TagId[]) => {
return tagIds.map((id) => tags.value.find((v) => v.id === id)?.name).join(', ')
}
</script>
<template>
<div class="container">
<a-modal v-model:visible="showHistoryRecord" width="70vw" mask-closable @ok="showHistoryRecord = false">
<HistoryRecord :records="tagSearchHistory" @reuse-record="reuse">
<template #default="{ record }">
<div style="padding-right: 16px;">
<a-row v-if="record.and_tags.length">
<a-col :span="4">{{ $t('exactMatch') }}:</a-col>
<a-col :span="20">{{ tagIdsToString(record.and_tags) }}</a-col>
</a-row>
<a-row v-if="record.or_tags.length">
<a-col :span="4">{{ $t('anyMatch') }}:</a-col>
<a-col :span="20">{{ tagIdsToString(record.or_tags) }}</a-col>
</a-row>
<a-row v-if="record.not_tags.length">
<a-col :span="4">{{ $t('exclude') }}:</a-col>
<a-col :span="20">{{ tagIdsToString(record.not_tags) }}</a-col>
</a-row>
<a-row v-if="record.folder_paths_str">
<a-col :span="4">{{ $t('searchScope') }}:</a-col>
<a-col :span="20">{{ record.folder_paths_str }}</a-col>
</a-row>
<a-row>
<a-col :span="4">{{ $t('time') }}:</a-col>
<a-col :span="20">{{ record.time }}</a-col>
</a-row>
<div>
</div>
</div>
</template>
</HistoryRecord>
</a-modal>
<ASelect v-if="false" />
<template v-if="info">
<div>
@ -206,6 +249,8 @@ const tagListFilter = (list: Tag[], name: string) => {
<div class="form-name">{{ $t('anyMatch') }}</div>
<SearchSelect :conv="conv" mode="multiple" style="width: 100%" :options="tags"
v-model:value="matchIds.or_tags" :disabled="!tags.length" :placeholder="$t('selectAnyMatchTag')" />
<div style="padding-left: 4px"></div>
<AButton @click="showHistoryRecord = true">{{ $t('history') }}</AButton>
</div>
<div class="search-bar">
<div class="form-name">{{ $t('exclude') }}</div>

View File

@ -0,0 +1,31 @@
import { type MatchImageByTagsReq } from '@/api/db'
import { HistoryRecord } from '@/util/HistoryRecord'
import { prefix } from '@/util/const'
import { useLocalStorage } from '@vueuse/core'
import { Ref } from 'vue'
export type FuzzySearchHistoryRecord ={
substr: string,
folder_paths_str: string,
isRegex: boolean
}
export const fuzzySearchHistory = useLocalStorage(`${prefix}fuzzy-search-HistoryRecord`, new HistoryRecord(), {
serializer: {
read: (str) => {
const val = JSON.parse(str)
return new HistoryRecord(val.maxLength, val.records, val.pinnedValues)
},
write: JSON.stringify,
},
}) as Ref<HistoryRecord<FuzzySearchHistoryRecord>>
export const tagSearchHistory = useLocalStorage(`${prefix}tag-search-HistoryRecord`, new HistoryRecord(), {
serializer: {
read: (str) => {
const val = JSON.parse(str)
return new HistoryRecord(val.maxLength, val.records, val.pinnedValues)
},
write: JSON.stringify,
},
}) as Ref<HistoryRecord<MatchImageByTagsReq>>

View File

@ -0,0 +1,57 @@
import { uniqueId } from 'lodash-es'
import { Dict } from '.'
export class HistoryRecord<F extends Dict, T extends { id: string; time: string; } = F & { id: string; time: string; }> {
constructor(
private maxLength: number = 128,
private records: T[] = [],
private pinnedValues: T[] = []) {
}
isPinned (value: T): boolean {
return this.pinnedValues.some(item => item.id === value.id);
}
add (value: F) {
// Remove oldest record if maximum length is reached
if (this.records.length >= this.maxLength) {
this.records.pop()
}
this.records.unshift({ ...value, id: uniqueId() + Date.now(), time: new Date().toLocaleString() } as unknown as T)
}
pin (value: T) {
// Remove value from records if it exists
const index = this.records.findIndex(item => item.id === value.id);
if (index !== -1) {
this.records.splice(index, 1)
}
// Add value to pinned values
this.pinnedValues.push(value)
}
unpin (value: T) {
// Remove value from pinned values if it exists
const index = this.pinnedValues.findIndex(item => item.id === value.id);
if (index !== -1) {
this.pinnedValues.splice(index, 1)
}
// Add value back to records
this.records.unshift(value)
}
switchPin (value: T) {
if (this.isPinned(value)) {
this.unpin(value)
} else {
this.pin(value)
}
}
getRecords (): T[] {
return [...this.pinnedValues, ...this.records]
}
}

View File

@ -50,7 +50,7 @@ export function isVideoFile (filename: string): boolean {
if (typeof filename !== 'string') {
return false
}
const exts = ['.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.ts']
const exts = ['.mp4', '.m4v', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.ts']
const extension = filename.split('.').pop()?.toLowerCase()
return extension !== undefined && exts.includes(`.${extension}`)
}

View File

@ -167,3 +167,17 @@ export const safeJsonParse = <T>(str: string) => {
return null
}
}
export const formatDuration = (duration: number) => {
if (duration >= 3600) {
const hour = Math.floor(duration / 3600);
const min = Math.floor((duration % 3600) / 60);
const sec = duration % 60;
return `${hour}:${min.toString().padStart(2, '0')}:${sec.toFixed(0).padStart(2, '0')}`;
} else {
const min = Math.floor(duration / 60);
const sec = duration % 60;
return `${min}:${sec.toFixed(0).padStart(2, '0')}`;
}
}