Add batch download feature, support collecting selected images from other pages for download and archiving
parent
d3b3599b73
commit
3692b2e6c3
|
|
@ -14,3 +14,4 @@ dist/**/*
|
|||
*.spec
|
||||
out/**/*
|
||||
venv/**/*
|
||||
zip_temp/*.zip
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ 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-23e5bc7c.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-618900f2.css">
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-af270b30.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-90388ea3.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ from scripts.iib.tool import (
|
|||
open_folder,
|
||||
get_img_geninfo_txt_path,
|
||||
unique_by,
|
||||
create_zip_file
|
||||
)
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
|
@ -442,6 +443,10 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
|
|||
def index_bd():
|
||||
return FileResponse(index_html_path)
|
||||
|
||||
|
||||
class PathsReq(BaseModel):
|
||||
paths: List[str]
|
||||
|
||||
class OpenFolderReq(BaseModel):
|
||||
path: str
|
||||
|
||||
|
|
@ -459,6 +464,16 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
|
|||
os.kill(os.getpid(), 9)
|
||||
return {"message": "Application is shutting down."}
|
||||
|
||||
@app.post(pre + "/zip", dependencies=[Depends(get_token)])
|
||||
def zip_files(req: PathsReq):
|
||||
now = datetime.now()
|
||||
timestamp = now.strftime("%Y-%m-%d-%H-%M-%S")
|
||||
zip_temp_dir = os.path.join(cwd, "zip_temp")
|
||||
os.makedirs(zip_temp_dir, exist_ok=True)
|
||||
file_path = os.path.join(zip_temp_dir, f"iib_batch_download_{timestamp}.zip")
|
||||
create_zip_file(req.paths, file_path)
|
||||
return FileResponse(file_path, media_type="application/zip")
|
||||
|
||||
db_pre = pre + "/db"
|
||||
|
||||
@app.get(db_pre + "/basic_info", dependencies=[Depends(get_token)])
|
||||
|
|
@ -532,9 +547,6 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
|
|||
# tags = Tag.get_all_custom_tag()
|
||||
return ImageTag.get_tags_for_image(conn, img.id, type="custom")
|
||||
|
||||
class PathsReq(BaseModel):
|
||||
paths: List[str]
|
||||
|
||||
@app.post(db_pre + "/get_image_tags", dependencies=[Depends(get_token)])
|
||||
async def get_img_tags(req: PathsReq):
|
||||
conn = DataBase.get_conn()
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ import re
|
|||
import tempfile
|
||||
import imghdr
|
||||
import subprocess
|
||||
from typing import Dict
|
||||
from typing import Dict, List
|
||||
import sys
|
||||
import piexif
|
||||
import piexif.helper
|
||||
import json
|
||||
import zipfile
|
||||
|
||||
sd_img_dirs = [
|
||||
"outdir_txt2img_samples",
|
||||
|
|
@ -145,6 +146,28 @@ def is_valid_image_path(path):
|
|||
return True
|
||||
|
||||
|
||||
|
||||
def create_zip_file(file_paths: List[str], zip_file_name: str):
|
||||
"""
|
||||
将文件打包成一个压缩包
|
||||
|
||||
Args:
|
||||
file_paths: 文件路径的列表
|
||||
zip_file_name: 压缩包的文件名
|
||||
|
||||
Returns:
|
||||
无返回值
|
||||
"""
|
||||
with zipfile.ZipFile(zip_file_name, 'w', zipfile.ZIP_DEFLATED) as zip_file:
|
||||
for file_path in file_paths:
|
||||
if os.path.isfile(file_path):
|
||||
zip_file.write(file_path, os.path.basename(file_path))
|
||||
elif os.path.isdir(file_path):
|
||||
for root, _, files in os.walk(file_path):
|
||||
for file in files:
|
||||
full_path = os.path.join(root, file)
|
||||
zip_file.write(full_path, os.path.relpath(full_path, file_path))
|
||||
|
||||
def get_temp_path():
|
||||
"""获取跨平台的临时文件目录路径"""
|
||||
temp_path = None
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ declare module '@vue/runtime-core' {
|
|||
ATabs: typeof import('ant-design-vue/es')['Tabs']
|
||||
ATag: typeof import('ant-design-vue/es')['Tag']
|
||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||
ContextMenu: typeof import('./src/components/ContextMenu.vue')['default']
|
||||
FileItem: typeof import('./src/components/FileItem.vue')['default']
|
||||
NumInput: typeof import('./src/components/numInput.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
import{d as t,o as a,m as r,cI as n}from"./index-23e5bc7c.js";const p=t({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(o){return(e,s)=>(a(),r(n,{left:e.left,right:e.right},null,8,["left","right"]))}});export{p as default};
|
||||
import{d as t,o as a,m as r,b$ as n}from"./index-af270b30.js";const p=t({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(o){return(e,s)=>(a(),r(n,{left:e.left,right:e.right},null,8,["left","right"]))}});export{p as default};
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{d as q,l as Q,ax as W,o as r,y as _,c as s,n as a,r as e,s as h,p as y,t as X,v as b,x as j,m as M,L as H,E as m,N as S,Q as J,R as K,X as Y}from"./index-af270b30.js";import{L as Z,R as ee,f as te,S as ie}from"./fullScreenContextMenu-2284d97e.js";import{g as le,F as se}from"./FileItem-a4055f0b.js";import{g as ne}from"./db-dbaa937e.js";import{u as ae}from"./hook-c56860bd.js";import"./shortcut-c1bb7547.js";const oe={class:"hint"},re={key:1,class:"preview-switch"},de=q({__name:"MatchedImageGrid",props:{tabIdx:{},paneIdx:{},selectedTagIds:{},id:{}},setup(T){const u=T,{queue:p,images:i,onContextMenuClickU:g,stackViewEl:V,previewIdx:n,previewing:v,onPreviewVisibleChange:D,previewImgMove:f,canPreview:w,itemSize:I,gridItems:F,showGenInfo:o,imageGenInfo:k,q:z,multiSelectedIdxs:$,onFileItemClick:B,scroller:x,showMenuIdx:d,onFileDragStart:E,onFileDragEnd:G,cellWidth:N,onScroll:R,updateImageTag:A}=ae();return Q(()=>u.selectedTagIds,async()=>{const{res:c}=p.pushAction(()=>ne(u.selectedTagIds));i.value=await c,await W(),A(),x.value.scrollToItem(0)},{immediate:!0}),(c,t)=>{const P=J,U=K,L=ie;return r(),_("div",{class:"container",ref_key:"stackViewEl",ref:V},[s(L,{size:"large",spinning:!e(p).isIdle},{default:a(()=>[s(U,{visible:e(o),"onUpdate:visible":t[1]||(t[1]=l=>h(o)?o.value=l:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=l=>o.value=!1)},{cancelText:a(()=>[]),default:a(()=>[s(P,{active:"",loading:!e(z).isIdle},{default:a(()=>[y("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[0]||(t[0]=l=>e(X)(e(k)))},[y("div",oe,b(c.$t("doubleClickToCopy")),1),j(" "+b(e(k)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),e(i)?(r(),M(e(le),{key:0,ref_key:"scroller",ref:x,class:"file-list",items:e(i),"item-size":e(I).first,"key-field":"fullpath","item-secondary-size":e(I).second,gridItems:e(F),onScroll:e(R)},{default:a(({item:l,index:C})=>[s(se,{idx:C,file:l,"cell-width":e(N),"show-menu-idx":e(d),"onUpdate:showMenuIdx":t[3]||(t[3]=O=>h(d)?d.value=O:null),onDragstart:e(E),onDragend:e(G),onFileItemClick:e(B),"full-screen-preview-image-url":e(i)[e(n)]?e(H)(e(i)[e(n)]):"",selected:e($).includes(C),onContextMenuClick:e(g),onPreviewVisibleChange:e(D)},null,8,["idx","file","cell-width","show-menu-idx","onDragstart","onDragend","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"])):m("",!0),e(v)?(r(),_("div",re,[s(e(Z),{onClick:t[4]||(t[4]=l=>e(f)("prev")),class:S({disable:!e(w)("prev")})},null,8,["class"]),s(e(ee),{onClick:t[5]||(t[5]=l=>e(f)("next")),class:S({disable:!e(w)("next")})},null,8,["class"])])):m("",!0)]),_:1},8,["spinning"]),e(v)&&e(i)&&e(i)[e(n)]?(r(),M(te,{key:0,file:e(i)[e(n)],idx:e(n),onContextMenuClick:e(g)},null,8,["file","idx","onContextMenuClick"])):m("",!0)],512)}}});const fe=Y(de,[["__scopeId","data-v-d698e678"]]);export{fe as default};
|
||||
|
|
@ -1 +0,0 @@
|
|||
.preview-switch[data-v-3c251729]{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-3c251729]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-3c251729]{opacity:0;pointer-events:none;cursor:none}.container[data-v-3c251729]{background:var(--zp-secondary-background)}.container .file-list[data-v-3c251729]{list-style:none;padding:8px;height:100%;overflow:auto;height:var(--pane-max-height);width:100%}
|
||||
|
|
@ -1 +0,0 @@
|
|||
import{d as q,l as Q,ax as j,o as r,y as _,c as s,n as a,r as e,s as h,p as y,t as W,v as b,x as X,m as M,L as H,E as u,N as S,Q as J,R as K,X as Y}from"./index-23e5bc7c.js";import{h as Z,i as ee,L as te,R as ie,j as le,S as se}from"./fullScreenContextMenu-c5f9ce74.js";import{g as ne}from"./db-52d8ead8.js";import{u as ae}from"./hook-13bccbae.js";import"./shortcut-98354a10.js";const oe={class:"hint"},re={key:1,class:"preview-switch"},de=q({__name:"MatchedImageGrid",props:{tabIdx:{},paneIdx:{},selectedTagIds:{},id:{}},setup(T){const m=T,{queue:p,images:i,onContextMenuClickU:g,stackViewEl:V,previewIdx:n,previewing:v,onPreviewVisibleChange:D,previewImgMove:f,canPreview:w,itemSize:I,gridItems:z,showGenInfo:o,imageGenInfo:k,q:F,multiSelectedIdxs:$,onFileItemClick:B,scroller:x,showMenuIdx:d,onFileDragStart:E,onFileDragEnd:G,cellWidth:N,onScroll:R,updateImageTag:A}=ae();return Q(()=>m.selectedTagIds,async()=>{const{res:c}=p.pushAction(()=>ne(m.selectedTagIds));i.value=await c,await j(),A(),x.value.scrollToItem(0)},{immediate:!0}),(c,t)=>{const P=J,U=K,L=se;return r(),_("div",{class:"container",ref_key:"stackViewEl",ref:V},[s(L,{size:"large",spinning:!e(p).isIdle},{default:a(()=>[s(U,{visible:e(o),"onUpdate:visible":t[1]||(t[1]=l=>h(o)?o.value=l:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=l=>o.value=!1)},{cancelText:a(()=>[]),default:a(()=>[s(P,{active:"",loading:!e(F).isIdle},{default:a(()=>[y("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[0]||(t[0]=l=>e(W)(e(k)))},[y("div",oe,b(c.$t("doubleClickToCopy")),1),X(" "+b(e(k)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),e(i)?(r(),M(e(Z),{key:0,ref_key:"scroller",ref:x,class:"file-list",items:e(i),"item-size":e(I).first,"key-field":"fullpath","item-secondary-size":e(I).second,gridItems:e(z),onScroll:e(R)},{default:a(({item:l,index:C})=>[s(ee,{idx:C,file:l,"cell-width":e(N),"show-menu-idx":e(d),"onUpdate:showMenuIdx":t[3]||(t[3]=O=>h(d)?d.value=O:null),onDragstart:e(E),onDragend:e(G),onFileItemClick:e(B),"full-screen-preview-image-url":e(i)[e(n)]?e(H)(e(i)[e(n)]):"",selected:e($).includes(C),onContextMenuClick:e(g),onPreviewVisibleChange:e(D)},null,8,["idx","file","cell-width","show-menu-idx","onDragstart","onDragend","onFileItemClick","full-screen-preview-image-url","selected","onContextMenuClick","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"])):u("",!0),e(v)?(r(),_("div",re,[s(e(te),{onClick:t[4]||(t[4]=l=>e(f)("prev")),class:S({disable:!e(w)("prev")})},null,8,["class"]),s(e(ie),{onClick:t[5]||(t[5]=l=>e(f)("next")),class:S({disable:!e(w)("next")})},null,8,["class"])])):u("",!0)]),_:1},8,["spinning"]),e(v)&&e(i)&&e(i)[e(n)]?(r(),M(le,{key:0,file:e(i)[e(n)],idx:e(n),onContextMenuClick:e(g)},null,8,["file","idx","onContextMenuClick"])):u("",!0)],512)}}});const ve=Y(de,[["__scopeId","data-v-3c251729"]]);export{ve as default};
|
||||
|
|
@ -0,0 +1 @@
|
|||
.preview-switch[data-v-d698e678]{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-d698e678]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-d698e678]{opacity:0;pointer-events:none;cursor:none}.container[data-v-d698e678]{background:var(--zp-secondary-background)}.container .file-list[data-v-d698e678]{list-style:none;padding:8px;height:100%;overflow:auto;height:var(--pane-max-height);width:100%}
|
||||
|
|
@ -0,0 +1 @@
|
|||
.search-bar[data-v-bb005cb9]{padding:8px;display:flex}.preview-switch[data-v-bb005cb9]{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-bb005cb9]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-bb005cb9]{opacity:0;pointer-events:none;cursor:none}.container[data-v-bb005cb9]{background:var(--zp-secondary-background)}.container .file-list[data-v-bb005cb9]{list-style:none;padding:8px;height:100%;overflow:auto;height:var(--pane-max-height);width:100%}
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{d as Y,$,aw as Z,bQ as ee,bP as B,o,y as k,c as r,r as e,bT as ne,m,n as u,x as w,v,E as g,s as V,p as F,t as te,L as ae,N as A,ax as se,ar as le,ai as ie,U as oe,V as re,Q as ue,R as de,X as ce}from"./index-af270b30.js";import{L as pe,R as me,f as ve,S as ge}from"./fullScreenContextMenu-2284d97e.js";/* empty css */import{g as fe,F as ke}from"./FileItem-a4055f0b.js";import{b as E,c as we,e as be,u as ye}from"./db-dbaa937e.js";import{u as Ie}from"./hook-c56860bd.js";import"./shortcut-c1bb7547.js";const xe={key:0,class:"search-bar"},Ce={class:"hint"},_e={key:1,class:"preview-switch"},he=Y({__name:"SubstrSearch",setup(Se){const{queue:l,images:a,onContextMenuClickU:b,stackViewEl:T,previewIdx:d,previewing:y,onPreviewVisibleChange:U,previewImgMove:I,canPreview:x,itemSize:C,gridItems:R,showGenInfo:c,imageGenInfo:_,q:N,multiSelectedIdxs:P,onFileItemClick:L,scroller:h,showMenuIdx:f,onFileDragStart:q,onFileDragEnd:G,cellWidth:K,onScroll:O,updateImageTag:Q}=Ie(),p=$(""),t=$();Z(async()=>{t.value=await E(),t.value.img_count&&t.value.expired&&S()});const S=ee(()=>l.pushAction(async()=>(await ye(),t.value=await E(),t.value)).res),M=async()=>{a.value=await l.pushAction(()=>be(p.value)).res,await se(),Q(),h.value.scrollToItem(0),a.value.length||le.info(ie("fuzzy-search-noResults"))};return B("returnToIIB",async()=>{const i=await l.pushAction(we).res;t.value.expired=i.expired}),B("searchIndexExpired",()=>t.value&&(t.value.expired=!0)),(i,n)=>{const H=oe,z=re,W=ue,X=de,j=ge;return o(),k("div",{class:"container",ref_key:"stackViewEl",ref:T},[t.value?(o(),k("div",xe,[r(H,{value:p.value,"onUpdate:value":n[0]||(n[0]=s=>p.value=s),placeholder:i.$t("fuzzy-search-placeholder"),disabled:!e(l).isIdle,onKeydown:ne(M,["enter"])},null,8,["value","placeholder","disabled","onKeydown"]),t.value.expired||!t.value.img_count?(o(),m(z,{key:0,onClick:e(S),loading:!e(l).isIdle,type:"primary"},{default:u(()=>[w(v(t.value.img_count===0?i.$t("generateIndexHint"):i.$t("UpdateIndex")),1)]),_:1},8,["onClick","loading"])):(o(),m(z,{key:1,type:"primary",onClick:M,loading:!e(l).isIdle,disabled:!p.value},{default:u(()=>[w(v(i.$t("search")),1)]),_:1},8,["loading","disabled"]))])):g("",!0),r(j,{size:"large",spinning:!e(l).isIdle},{default:u(()=>[r(X,{visible:e(c),"onUpdate:visible":n[2]||(n[2]=s=>V(c)?c.value=s:null),width:"70vw","mask-closable":"",onOk:n[3]||(n[3]=s=>c.value=!1)},{cancelText:u(()=>[]),default:u(()=>[r(W,{active:"",loading:!e(N).isIdle},{default:u(()=>[F("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:n[1]||(n[1]=s=>e(te)(e(_)))},[F("div",Ce,v(i.$t("doubleClickToCopy")),1),w(" "+v(e(_)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),e(a)?(o(),m(e(fe),{key:0,ref_key:"scroller",ref:h,class:"file-list",items:e(a),"item-size":e(C).first,"key-field":"fullpath","item-secondary-size":e(C).second,gridItems:e(R),onScroll:e(O)},{default:u(({item:s,index:D})=>[r(ke,{idx:D,file:s,"show-menu-idx":e(f),"onUpdate:showMenuIdx":n[4]||(n[4]=J=>V(f)?f.value=J:null),onFileItemClick:e(L),"full-screen-preview-image-url":e(a)[e(d)]?e(ae)(e(a)[e(d)]):"","cell-width":e(K),selected:e(P).includes(D),onContextMenuClick:e(b),onDragstart:e(q),onDragend:e(G),onPreviewVisibleChange:e(U)},null,8,["idx","file","show-menu-idx","onFileItemClick","full-screen-preview-image-url","cell-width","selected","onContextMenuClick","onDragstart","onDragend","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"])):g("",!0),e(y)?(o(),k("div",_e,[r(e(pe),{onClick:n[5]||(n[5]=s=>e(I)("prev")),class:A({disable:!e(x)("prev")})},null,8,["class"]),r(e(me),{onClick:n[6]||(n[6]=s=>e(I)("next")),class:A({disable:!e(x)("next")})},null,8,["class"])])):g("",!0)]),_:1},8,["spinning"]),e(y)&&e(a)&&e(a)[e(d)]?(o(),m(ve,{key:1,file:e(a)[e(d)],idx:e(d),onContextMenuClick:e(b)},null,8,["file","idx","onContextMenuClick"])):g("",!0)],512)}}});const Ae=ce(he,[["__scopeId","data-v-bb005cb9"]]);export{Ae as default};
|
||||
|
|
@ -1 +0,0 @@
|
|||
import{d as Y,$,aw as Z,bQ as ee,bP as B,o,y as k,c as r,r as e,bT as ae,m,n as d,x as w,v,E as f,s as V,p as A,t as ne,L as te,N as E,ax as le,ar as se,ai as ie,U as oe,V as re,Q as de,R as ue,X as ce}from"./index-23e5bc7c.js";import{h as pe,i as me,L as ve,R as fe,j as ge,S as ke}from"./fullScreenContextMenu-c5f9ce74.js";/* empty css */import{b as T,c as we,e as ye,u as Ie}from"./db-52d8ead8.js";import{u as xe}from"./hook-13bccbae.js";import"./shortcut-98354a10.js";const be={key:0,class:"search-bar"},Ce={class:"hint"},he={key:1,class:"preview-switch"},_e=Y({__name:"SubstrSearch",setup(Se){const{queue:s,images:t,onContextMenuClickU:y,stackViewEl:U,previewIdx:u,previewing:I,onPreviewVisibleChange:F,previewImgMove:x,canPreview:b,itemSize:C,gridItems:R,showGenInfo:c,imageGenInfo:h,q:N,multiSelectedIdxs:P,onFileItemClick:L,scroller:_,showMenuIdx:g,onFileDragStart:q,onFileDragEnd:G,cellWidth:K,onScroll:O,updateImageTag:Q}=xe(),p=$(""),n=$();Z(async()=>{n.value=await T(),n.value.img_count&&n.value.expired&&S()});const S=ee(()=>s.pushAction(async()=>(await Ie(),n.value=await T(),n.value)).res),M=async()=>{t.value=await s.pushAction(()=>ye(p.value)).res,await le(),Q(),_.value.scrollToItem(0),t.value.length||se.info(ie("fuzzy-search-noResults"))};return B("returnToIIB",async()=>{const i=await s.pushAction(we).res;n.value.expired=i.expired}),B("searchIndexExpired",()=>n.value&&(n.value.expired=!0)),(i,a)=>{const j=oe,z=re,H=de,W=ue,X=ke;return o(),k("div",{class:"container",ref_key:"stackViewEl",ref:U},[n.value?(o(),k("div",be,[r(j,{value:p.value,"onUpdate:value":a[0]||(a[0]=l=>p.value=l),placeholder:i.$t("fuzzy-search-placeholder"),disabled:!e(s).isIdle,onKeydown:ae(M,["enter"])},null,8,["value","placeholder","disabled","onKeydown"]),n.value.expired||!n.value.img_count?(o(),m(z,{key:0,onClick:e(S),loading:!e(s).isIdle,type:"primary"},{default:d(()=>[w(v(n.value.img_count===0?i.$t("generateIndexHint"):i.$t("UpdateIndex")),1)]),_:1},8,["onClick","loading"])):(o(),m(z,{key:1,type:"primary",onClick:M,loading:!e(s).isIdle,disabled:!p.value},{default:d(()=>[w(v(i.$t("search")),1)]),_:1},8,["loading","disabled"]))])):f("",!0),r(X,{size:"large",spinning:!e(s).isIdle},{default:d(()=>[r(W,{visible:e(c),"onUpdate:visible":a[2]||(a[2]=l=>V(c)?c.value=l:null),width:"70vw","mask-closable":"",onOk:a[3]||(a[3]=l=>c.value=!1)},{cancelText:d(()=>[]),default:d(()=>[r(H,{active:"",loading:!e(N).isIdle},{default:d(()=>[A("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:a[1]||(a[1]=l=>e(ne)(e(h)))},[A("div",Ce,v(i.$t("doubleClickToCopy")),1),w(" "+v(e(h)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),e(t)?(o(),m(e(pe),{key:0,ref_key:"scroller",ref:_,class:"file-list",items:e(t),"item-size":e(C).first,"key-field":"fullpath","item-secondary-size":e(C).second,gridItems:e(R),onScroll:e(O)},{default:d(({item:l,index:D})=>[r(me,{idx:D,file:l,"show-menu-idx":e(g),"onUpdate:showMenuIdx":a[4]||(a[4]=J=>V(g)?g.value=J:null),onFileItemClick:e(L),"full-screen-preview-image-url":e(t)[e(u)]?e(te)(e(t)[e(u)]):"","cell-width":e(K),selected:e(P).includes(D),onContextMenuClick:e(y),onDragstart:e(q),onDragend:e(G),onPreviewVisibleChange:e(F)},null,8,["idx","file","show-menu-idx","onFileItemClick","full-screen-preview-image-url","cell-width","selected","onContextMenuClick","onDragstart","onDragend","onPreviewVisibleChange"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"])):f("",!0),e(I)?(o(),k("div",he,[r(e(ve),{onClick:a[5]||(a[5]=l=>e(x)("prev")),class:E({disable:!e(b)("prev")})},null,8,["class"]),r(e(fe),{onClick:a[6]||(a[6]=l=>e(x)("next")),class:E({disable:!e(b)("next")})},null,8,["class"])])):f("",!0)]),_:1},8,["spinning"]),e(I)&&e(t)&&e(t)[e(u)]?(o(),m(ge,{key:1,file:e(t)[e(u)],idx:e(u),onContextMenuClick:e(y)},null,8,["file","idx","onContextMenuClick"])):f("",!0)],512)}}});const Ae=ce(_e,[["__scopeId","data-v-905bf6da"]]);export{Ae as default};
|
||||
|
|
@ -1 +0,0 @@
|
|||
.search-bar[data-v-905bf6da]{padding:8px;display:flex}.preview-switch[data-v-905bf6da]{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-905bf6da]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-905bf6da]{opacity:0;pointer-events:none;cursor:none}.container[data-v-905bf6da]{background:var(--zp-secondary-background)}.container .file-list[data-v-905bf6da]{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
|
|
@ -0,0 +1 @@
|
|||
.container[data-v-aab31da2]{background:var(--zp-secondary-background);height:100%;overflow:auto;display:flex;flex-direction:column}.container .actions-panel[data-v-aab31da2]{padding:8px;background-color:var(--zp-primary-background)}.container .file-list[data-v-aab31da2]{flex:1;list-style:none;padding:8px;height:var(--pane-max-height);width:100%}.container .file-list .hint[data-v-aab31da2]{text-align:center;font-size:2em;padding:30vh 128px 0}
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{d as v,c0 as C,bO as I,o as i,y as _,p as f,c,n as r,x as h,v as d,r as e,m as F,L as x,c1 as z,c2 as B,V as $,X as R}from"./index-af270b30.js";import{u as S,b as V,m as E,F as A,g as L}from"./FileItem-a4055f0b.js";import"./db-dbaa937e.js";import"./shortcut-c1bb7547.js";const T={class:"actions-panel actions"},N={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(),l=E(),{selectdFiles:n}=C(l),m=I(),y=async t=>{const s=z(t);s&&l.addFiles(s.nodes)},D=async()=>{m.pushAction(async()=>{const t=await B.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=$;return i(),_("div",{class:"container",ref_key:"stackViewEl",ref:w,onDrop:y},[f("div",T,[c(a,{onClick:s[0]||(s[0]=o=>e(l).selectdFiles=[])},{default:r(()=>[h(d(t.$t("clear")),1)]),_:1}),c(a,{onClick:D,type:"primary",loading:!e(m).isIdle},{default:r(()=>[h(d(t.$t("zipDownload")),1)]),_:1},8,["loading"])]),e(n).length?(i(),F(e(L),{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:u})=>[c(A,{idx:u,file:o,"cell-width":e(b),"enable-close-icon":"",onCloseIconClick:j=>g(u),"full-screen-preview-image-url":e(x)(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"])):(i(),_("div",N,[f("p",U,d(t.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const G=R(H,[["__scopeId","data-v-aab31da2"]]);export{G as default};
|
||||
|
|
@ -1 +1 @@
|
|||
import{c6 as t}from"./index-23e5bc7c.js";const o=async()=>(await t.value.get("/db/basic_info")).data,c=async()=>(await t.value.get("/db/expired_dirs")).data,r=async()=>{await t.value.post("/db/update_image_data",{},{timeout:1/0})},d=async a=>(await t.value.post("/db/match_images_by_tags",a)).data,g=async a=>(await t.value.post("/db/add_custom_tag",a)).data,u=async a=>(await t.value.post("/db/toggle_custom_tag_to_img",a)).data,p=async a=>{await t.value.post("/db/remove_custom_tag",a)},i=async a=>(await t.value.get("/db/search_by_substr",{params:{substr:a}})).data,e="/db/scanned_paths",m=async a=>{await t.value.post(e,{path:a})},_=async a=>{await t.value.delete(e,{data:{path:a}})},b=async a=>(await t.value.post("/db/get_image_tags",{paths:a})).data;export{m as a,o as b,c,g as d,i as e,b as f,d as g,_ as h,p as r,u as t,r as u};
|
||||
import{c2 as t}from"./index-af270b30.js";const o=async()=>(await t.value.get("/db/basic_info")).data,c=async()=>(await t.value.get("/db/expired_dirs")).data,r=async()=>{await t.value.post("/db/update_image_data",{},{timeout:1/0})},d=async a=>(await t.value.post("/db/match_images_by_tags",a)).data,g=async a=>(await t.value.post("/db/add_custom_tag",a)).data,u=async a=>(await t.value.post("/db/toggle_custom_tag_to_img",a)).data,p=async a=>{await t.value.post("/db/remove_custom_tag",a)},i=async a=>(await t.value.get("/db/search_by_substr",{params:{substr:a}})).data,e="/db/scanned_paths",m=async a=>{await t.value.post(e,{path:a})},_=async a=>{await t.value.delete(e,{data:{path:a}})},b=async a=>(await t.value.post("/db/get_image_tags",{paths:a})).data;export{m as a,o as b,c,g as d,i as e,b as f,d as g,_ as h,p as r,u as t,r as u};
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
.ant-alert{box-sizing:border-box;margin:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;display:flex;align-items:center;padding:8px 15px;word-wrap:break-word;border-radius:2px}.ant-alert-content{flex:1;min-width:0}.ant-alert-icon{margin-right:8px}.ant-alert-description{display:none;font-size:14px;line-height:22px}.ant-alert-success{background-color:#f6ffed;border:1px solid #b7eb8f}.ant-alert-success .ant-alert-icon{color:#52c41a}.ant-alert-info{background-color:#fff1e6;border:1px solid #f7ae83}.ant-alert-info .ant-alert-icon{color:#d03f0a}.ant-alert-warning{background-color:#fffbe6;border:1px solid #ffe58f}.ant-alert-warning .ant-alert-icon{color:#faad14}.ant-alert-error{background-color:#fff2f0;border:1px solid #ffccc7}.ant-alert-error .ant-alert-icon{color:#ff4d4f}.ant-alert-error .ant-alert-description>pre{margin:0;padding:0}.ant-alert-action{margin-left:8px}.ant-alert-close-icon{margin-left:8px;padding:0;overflow:hidden;font-size:12px;line-height:12px;background-color:transparent;border:none;outline:none;cursor:pointer}.ant-alert-close-icon .anticon-close{color:#00000073;transition:color .3s}.ant-alert-close-icon .anticon-close:hover{color:#000000bf}.ant-alert-close-text{color:#00000073;transition:color .3s}.ant-alert-close-text:hover{color:#000000bf}.ant-alert-with-description{align-items:flex-start;padding:15px 15px 15px 24px}.ant-alert-with-description.ant-alert-no-icon{padding:15px}.ant-alert-with-description .ant-alert-icon{margin-right:15px;font-size:24px}.ant-alert-with-description .ant-alert-message{display:block;margin-bottom:4px;color:#000000d9;font-size:16px}.ant-alert-message{color:#000000d9}.ant-alert-with-description .ant-alert-description{display:block}.ant-alert.ant-alert-motion-leave{overflow:hidden;opacity:1;transition:max-height .3s cubic-bezier(.78,.14,.15,.86),opacity .3s cubic-bezier(.78,.14,.15,.86),padding-top .3s cubic-bezier(.78,.14,.15,.86),padding-bottom .3s cubic-bezier(.78,.14,.15,.86),margin-bottom .3s cubic-bezier(.78,.14,.15,.86)}.ant-alert.ant-alert-motion-leave-active{max-height:0;margin-bottom:0!important;padding-top:0;padding-bottom:0;opacity:0}.ant-alert-banner{margin-bottom:0;border:0;border-radius:0}.ant-alert.ant-alert-rtl{direction:rtl}.ant-alert-rtl .ant-alert-icon{margin-right:auto;margin-left:8px}.ant-alert-rtl .ant-alert-action,.ant-alert-rtl .ant-alert-close-icon{margin-right:8px;margin-left:auto}.ant-alert-rtl.ant-alert-with-description{padding-right:24px;padding-left:15px}.ant-alert-rtl.ant-alert-with-description .ant-alert-icon{margin-right:auto;margin-left:15px}.access-mode-message[data-v-903b3fda]{display:flex;flex-direction:row;align-items:center}.access-mode-message a[data-v-903b3fda]{margin-left:16px}.container[data-v-903b3fda]{padding:20px;background-color:var(--zp-secondary-background);height:100%;overflow:auto}.header[data-v-903b3fda]{display:flex;justify-content:space-between;align-items:center}.header h1[data-v-903b3fda]{font-size:28px;font-weight:700;color:var(--zp-primary);margin:0}.last-record[data-v-903b3fda]{margin-left:16px;font-size:14px;color:var(--zp-secondary)}.last-record a[data-v-903b3fda]{text-decoration:none;color:var(--zp-secondary)}.last-record a[data-v-903b3fda]:hover{color:var(--zp-primary)}.content[data-v-903b3fda]{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));grid-gap:20px;margin-top:16px}.feature-item[data-v-903b3fda]{background-color:var(--zp-primary-background);border-radius:8px;box-shadow:0 1px 2px #0000001a;padding:20px}.feature-item ul[data-v-903b3fda]{list-style:none;padding:4px;max-height:70vh;overflow-y:auto}.feature-item .item[data-v-903b3fda]{margin-bottom:10px;padding:4px 8px;display:flex;align-items:center}.feature-item .item[data-v-903b3fda]:hover{background:var(--zp-secondary-background);border-radius:4px;color:var(--primary-color);cursor:pointer}.feature-item .icon[data-v-903b3fda]{margin-right:8px}.feature-item h2[data-v-903b3fda]{margin-top:0;margin-bottom:20px;font-size:20px;font-weight:700;color:var(--zp-primary)}.text[data-v-903b3fda]{flex:1;font-size:16px}
|
||||
.ant-alert{box-sizing:border-box;margin:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;display:flex;align-items:center;padding:8px 15px;word-wrap:break-word;border-radius:2px}.ant-alert-content{flex:1;min-width:0}.ant-alert-icon{margin-right:8px}.ant-alert-description{display:none;font-size:14px;line-height:22px}.ant-alert-success{background-color:#f6ffed;border:1px solid #b7eb8f}.ant-alert-success .ant-alert-icon{color:#52c41a}.ant-alert-info{background-color:#fff1e6;border:1px solid #f7ae83}.ant-alert-info .ant-alert-icon{color:#d03f0a}.ant-alert-warning{background-color:#fffbe6;border:1px solid #ffe58f}.ant-alert-warning .ant-alert-icon{color:#faad14}.ant-alert-error{background-color:#fff2f0;border:1px solid #ffccc7}.ant-alert-error .ant-alert-icon{color:#ff4d4f}.ant-alert-error .ant-alert-description>pre{margin:0;padding:0}.ant-alert-action{margin-left:8px}.ant-alert-close-icon{margin-left:8px;padding:0;overflow:hidden;font-size:12px;line-height:12px;background-color:transparent;border:none;outline:none;cursor:pointer}.ant-alert-close-icon .anticon-close{color:#00000073;transition:color .3s}.ant-alert-close-icon .anticon-close:hover{color:#000000bf}.ant-alert-close-text{color:#00000073;transition:color .3s}.ant-alert-close-text:hover{color:#000000bf}.ant-alert-with-description{align-items:flex-start;padding:15px 15px 15px 24px}.ant-alert-with-description.ant-alert-no-icon{padding:15px}.ant-alert-with-description .ant-alert-icon{margin-right:15px;font-size:24px}.ant-alert-with-description .ant-alert-message{display:block;margin-bottom:4px;color:#000000d9;font-size:16px}.ant-alert-message{color:#000000d9}.ant-alert-with-description .ant-alert-description{display:block}.ant-alert.ant-alert-motion-leave{overflow:hidden;opacity:1;transition:max-height .3s cubic-bezier(.78,.14,.15,.86),opacity .3s cubic-bezier(.78,.14,.15,.86),padding-top .3s cubic-bezier(.78,.14,.15,.86),padding-bottom .3s cubic-bezier(.78,.14,.15,.86),margin-bottom .3s cubic-bezier(.78,.14,.15,.86)}.ant-alert.ant-alert-motion-leave-active{max-height:0;margin-bottom:0!important;padding-top:0;padding-bottom:0;opacity:0}.ant-alert-banner{margin-bottom:0;border:0;border-radius:0}.ant-alert.ant-alert-rtl{direction:rtl}.ant-alert-rtl .ant-alert-icon{margin-right:auto;margin-left:8px}.ant-alert-rtl .ant-alert-action,.ant-alert-rtl .ant-alert-close-icon{margin-right:8px;margin-left:auto}.ant-alert-rtl.ant-alert-with-description{padding-right:24px;padding-left:15px}.ant-alert-rtl.ant-alert-with-description .ant-alert-icon{margin-right:auto;margin-left:15px}.access-mode-message[data-v-81c5212e]{display:flex;flex-direction:row;align-items:center}.access-mode-message a[data-v-81c5212e]{margin-left:16px}.container[data-v-81c5212e]{padding:20px;background-color:var(--zp-secondary-background);height:100%;overflow:auto}.header[data-v-81c5212e]{display:flex;justify-content:space-between;align-items:center}.header h1[data-v-81c5212e]{font-size:28px;font-weight:700;color:var(--zp-primary);margin:0}.last-record[data-v-81c5212e]{margin-left:16px;font-size:14px;color:var(--zp-secondary)}.last-record a[data-v-81c5212e]{text-decoration:none;color:var(--zp-secondary)}.last-record a[data-v-81c5212e]:hover{color:var(--zp-primary)}.content[data-v-81c5212e]{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));grid-gap:20px;margin-top:16px}.feature-item[data-v-81c5212e]{background-color:var(--zp-primary-background);border-radius:8px;box-shadow:0 1px 2px #0000001a;padding:20px}.feature-item ul[data-v-81c5212e]{list-style:none;padding:4px;max-height:70vh;overflow-y:auto}.feature-item .item[data-v-81c5212e]{margin-bottom:10px;padding:4px 8px;display:flex;align-items:center}.feature-item .item[data-v-81c5212e]:hover{background:var(--zp-secondary-background);border-radius:4px;color:var(--primary-color);cursor:pointer}.feature-item .icon[data-v-81c5212e]{margin-right:8px}.feature-item h2[data-v-81c5212e]{margin-top:0;margin-bottom:20px;font-size:20px;font-weight:700;color:var(--zp-primary)}.text[data-v-81c5212e]{flex:1;font-size:16px}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
.ant-spin{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:absolute;display:none;color:#d03f0a;text-align:center;vertical-align:middle;opacity:0;transition:transform .3s cubic-bezier(.78,.14,.15,.86)}.ant-spin-spinning{position:static;display:inline-block;opacity:1}.ant-spin-nested-loading{position:relative}.ant-spin-nested-loading>div>.ant-spin{position:absolute;top:0;left:0;z-index:4;display:block;width:100%;height:100%;max-height:400px}.ant-spin-nested-loading>div>.ant-spin .ant-spin-dot{position:absolute;top:50%;left:50%;margin:-10px}.ant-spin-nested-loading>div>.ant-spin .ant-spin-text{position:absolute;top:50%;width:100%;padding-top:5px;text-shadow:0 1px 2px #fff}.ant-spin-nested-loading>div>.ant-spin.ant-spin-show-text .ant-spin-dot{margin-top:-20px}.ant-spin-nested-loading>div>.ant-spin-sm .ant-spin-dot{margin:-7px}.ant-spin-nested-loading>div>.ant-spin-sm .ant-spin-text{padding-top:2px}.ant-spin-nested-loading>div>.ant-spin-sm.ant-spin-show-text .ant-spin-dot{margin-top:-17px}.ant-spin-nested-loading>div>.ant-spin-lg .ant-spin-dot{margin:-16px}.ant-spin-nested-loading>div>.ant-spin-lg .ant-spin-text{padding-top:11px}.ant-spin-nested-loading>div>.ant-spin-lg.ant-spin-show-text .ant-spin-dot{margin-top:-26px}.ant-spin-container{position:relative;transition:opacity .3s}.ant-spin-container:after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;display:none \ ;width:100%;height:100%;background:#fff;opacity:0;transition:all .3s;content:"";pointer-events:none}.ant-spin-blur{clear:both;opacity:.5;user-select:none;pointer-events:none}.ant-spin-blur:after{opacity:.4;pointer-events:auto}.ant-spin-tip{color:#00000073}.ant-spin-dot{position:relative;display:inline-block;font-size:20px;width:1em;height:1em}.ant-spin-dot-item{position:absolute;display:block;width:9px;height:9px;background-color:#d03f0a;border-radius:100%;transform:scale(.75);transform-origin:50% 50%;opacity:.3;animation:antSpinMove 1s infinite linear alternate}.ant-spin-dot-item:nth-child(1){top:0;left:0}.ant-spin-dot-item:nth-child(2){top:0;right:0;animation-delay:.4s}.ant-spin-dot-item:nth-child(3){right:0;bottom:0;animation-delay:.8s}.ant-spin-dot-item:nth-child(4){bottom:0;left:0;animation-delay:1.2s}.ant-spin-dot-spin{transform:rotate(45deg);animation:antRotate 1.2s infinite linear}.ant-spin-sm .ant-spin-dot{font-size:14px}.ant-spin-sm .ant-spin-dot i{width:6px;height:6px}.ant-spin-lg .ant-spin-dot{font-size:32px}.ant-spin-lg .ant-spin-dot i{width:14px;height:14px}.ant-spin.ant-spin-show-text .ant-spin-text{display:block}@media all and (-ms-high-contrast: none),(-ms-high-contrast: active){.ant-spin-blur{background:#fff;opacity:.5}}@keyframes antSpinMove{to{opacity:1}}@keyframes antRotate{to{transform:rotate(405deg)}}.ant-spin-rtl{direction:rtl}.ant-spin-rtl .ant-spin-dot-spin{transform:rotate(-45deg);animation-name:antRotateRtl}@keyframes antRotateRtl{to{transform:rotate(-405deg)}}.full-screen-menu[data-v-c968315f]{position:fixed;z-index:99999;background:var(--zp-primary-background);padding:8px 16px;box-shadow:0 0 4px var(--zp-secondary);border-radius:4px}.full-screen-menu .tags-container>*[data-v-c968315f]{margin-right:4px;font-size:14px;line-height:1.6}.full-screen-menu .container[data-v-c968315f]{height:100%;display:flex;overflow:hidden;flex-direction:column}.full-screen-menu .gen-info[data-v-c968315f]{flex:1;word-break:break-all;white-space:pre-line;overflow:auto;z-index:1;padding-top:4px;position:relative}.full-screen-menu .gen-info .tags .tag[data-v-c968315f]{display:inline-block;overflow:hidden;border-radius:4px;margin-right:8px;border:2px solid var(--zp-primary)}.full-screen-menu .gen-info .tags .name[data-v-c968315f]{background-color:var(--zp-primary);color:var(--zp-primary-background);padding:4px}.full-screen-menu .gen-info .tags .value[data-v-c968315f]{padding:4px}.full-screen-menu.unset-size[data-v-c968315f]{width:unset!important;height:unset!important}.full-screen-menu .mouse-sensor[data-v-c968315f]{position:absolute;bottom:0;right:0;transform:rotate(90deg);cursor:se-resize;z-index:1;background:var(--zp-primary-background);border-radius:2px}.full-screen-menu .mouse-sensor>*[data-v-c968315f]{font-size:18px;padding:4px}.full-screen-menu .action-bar[data-v-c968315f]{display:flex;align-items:center;user-select:none}.full-screen-menu .action-bar .icon[data-v-c968315f]{font-size:1.5em;padding:2px 4px;border-radius:4px}.full-screen-menu .action-bar .icon[data-v-c968315f]:hover{background:var(--zp-secondary-variant-background)}.full-screen-menu .action-bar>*[data-v-c968315f]{flex-wrap:wrap}.full-screen-menu .action-bar>*[data-v-c968315f]:not(:last-child){margin-right:8px}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +0,0 @@
|
|||
import{$ as D,bO as E,bd as P,aC as $}from"./index-23e5bc7c.js";import{k as z,u as G,b as L,f as O,a as Q,c as R,d as V,e as _,l as A}from"./fullScreenContextMenu-c5f9ce74.js";const U=()=>{const e=D(),c=E(),u=z(),n={tabIdx:-1,target:"local",paneIdx:-1,walkMode:!1},{stackViewEl:r,multiSelectedIdxs:d,stack:m,scroller:o}=G({images:e}).toRefs(),{itemSize:g,gridItems:p,cellWidth:v}=L(n),{showMenuIdx:I}=O();Q(n);const{onFileDragStart:f,onFileDragEnd:x}=R(),{showGenInfo:h,imageGenInfo:w,q:k,onContextMenuClick:i,onFileItemClick:S}=V(n,{openNext:P}),{previewIdx:M,previewing:b,onPreviewVisibleChange:C,previewImgMove:F,canPreview:y}=_(n),T=async(s,a,t)=>{m.value=[{curr:"",files:e.value}],await i(s,a,t)};A("removeFiles",async({paths:s})=>{var a;e.value=(a=e.value)==null?void 0:a.filter(t=>!s.includes(t.fullpath))});const l=()=>{const s=o.value;if(s&&e.value){const a=e.value.slice(Math.max(s.$_startIndex-10,0),s.$_endIndex+10).map(t=>t.fullpath);u.fetchImageTags(a)}},q=$(l,300);return{scroller:o,queue:c,images:e,onContextMenuClickU:T,stackViewEl:r,previewIdx:M,previewing:b,onPreviewVisibleChange:C,previewImgMove:F,canPreview:y,itemSize:g,gridItems:p,showGenInfo:h,imageGenInfo:w,q:k,onContextMenuClick:i,onFileItemClick:S,showMenuIdx:I,multiSelectedIdxs:d,onFileDragStart:f,onFileDragEnd:x,cellWidth:v,onScroll:q,updateImageTag:l}};export{U as u};
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{$ as q,bO as D,bd as E,aC as P}from"./index-af270b30.js";import{h as $,u as z,b as G,f as L,a as O,c as Q,d as R,e as V,i as _}from"./FileItem-a4055f0b.js";const N=()=>{const e=q(),c=D(),l=$(),{stackViewEl:u,multiSelectedIdxs:r,stack:m,scroller:n}=z({images:e}).toRefs(),{itemSize:v,gridItems:d,cellWidth:g}=G(),{showMenuIdx:f}=L();O();const{onFileDragStart:I,onFileDragEnd:p}=Q(),{showGenInfo:h,imageGenInfo:w,q:x,onContextMenuClick:o,onFileItemClick:S}=R({openNext:E}),{previewIdx:C,previewing:F,onPreviewVisibleChange:b,previewImgMove:k,canPreview:M}=V(),y=async(s,t,a)=>{m.value=[{curr:"",files:e.value}],await o(s,t,a)};_("removeFiles",async({paths:s})=>{var t;e.value=(t=e.value)==null?void 0:t.filter(a=>!s.includes(a.fullpath))});const i=()=>{const s=n.value;if(s&&e.value){const t=e.value.slice(Math.max(s.$_startIndex-10,0),s.$_endIndex+10).map(a=>a.fullpath);l.fetchImageTags(t)}},T=P(i,300);return{scroller:n,queue:c,images:e,onContextMenuClickU:y,stackViewEl:u,previewIdx:C,previewing:F,onPreviewVisibleChange:b,previewImgMove:k,canPreview:M,itemSize:v,gridItems:d,showGenInfo:h,imageGenInfo:w,q:x,onContextMenuClick:o,onFileItemClick:S,showMenuIdx:f,multiSelectedIdxs:r,onFileDragStart:I,onFileDragEnd:p,cellWidth:g,onScroll:T,updateImageTag:i}};export{N as u};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
import{cH as s}from"./index-23e5bc7c.js";var r=1/0,i=17976931348623157e292;function e(t){if(!t)return t===0?t:0;if(t=s(t),t===r||t===-r){var n=t<0?-1:1;return n*i}return t===t?t:0}function f(t){var n=t==null?0:t.length;return n?t[n-1]:void 0}const h=t=>{const n=[];return t.shiftKey&&n.push("Shift"),t.ctrlKey&&n.push("Ctrl"),t.metaKey&&n.push("Cmd"),(t.code.startsWith("Key")||t.code.startsWith("Digit"))&&n.push(t.code),n.join(" + ")};export{h as g,f as l,e as t};
|
||||
import{cK as s}from"./index-af270b30.js";var r=1/0,i=17976931348623157e292;function e(t){if(!t)return t===0?t:0;if(t=s(t),t===r||t===-r){var n=t<0?-1:1;return n*i}return t===t?t:0}function f(t){var n=t==null?0:t.length;return n?t[n-1]:void 0}const h=t=>{const n=[];return t.shiftKey&&n.push("Shift"),t.ctrlKey&&n.push("Ctrl"),t.metaKey&&n.push("Cmd"),(t.code.startsWith("Key")||t.code.startsWith("Digit"))&&n.push(t.code),n.join(" + ")};export{h as g,f as l,e as t};
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
.ant-breadcrumb{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";color:#00000073;font-size:14px}.ant-breadcrumb .anticon{font-size:14px}.ant-breadcrumb a{color:#00000073;transition:color .3s}.ant-breadcrumb a:hover{color:#de632f}.ant-breadcrumb>span:last-child{color:#000000d9}.ant-breadcrumb>span:last-child a{color:#000000d9}.ant-breadcrumb>span:last-child .ant-breadcrumb-separator{display:none}.ant-breadcrumb-separator{margin:0 8px;color:#00000073}.ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-link>.anticon+a{margin-left:4px}.ant-breadcrumb-overlay-link>.anticon{margin-left:4px}.ant-breadcrumb-rtl{direction:rtl}.ant-breadcrumb-rtl:before{display:table;content:""}.ant-breadcrumb-rtl:after{display:table;clear:both;content:""}.ant-breadcrumb-rtl>span{float:right}.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+a{margin-right:4px;margin-left:0}.ant-breadcrumb-rtl .ant-breadcrumb-overlay-link>.anticon{margin-right:4px;margin-left:0}.nprogress{pointer-events:none}.nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}.nprogress .peg{display:block;position:absolute;right:0px;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0px,-4px);-ms-transform:rotate(3deg) translate(0px,-4px);transform:rotate(3deg) translateY(-4px)}.nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}.nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent .nprogress .spinner,.nprogress-custom-parent .nprogress .bar{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preview-switch[data-v-43659a67]{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-43659a67]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-43659a67]{opacity:0;pointer-events:none;cursor:none}.breadcrumb[data-v-43659a67]{display:flex;align-items:center}.breadcrumb>*[data-v-43659a67]{margin-right:4px}.container[data-v-43659a67]{background:var(--zp-secondary-background);height:var(--pane-max-height)}.location-bar[data-v-43659a67]{padding:4px 16px;background:var(--zp-primary-background);border-bottom:1px solid var(--zp-border);display:flex;align-items:center;justify-content:space-between}.location-bar .actions[data-v-43659a67]{display:flex;align-items:center;flex-shrink:0}.location-bar a.opt[data-v-43659a67]{margin-left:8px}.view[data-v-43659a67]{padding:8px;height:calc(100vh - 48px)}.view .file-list[data-v-43659a67]{list-style:none;padding:8px;height:100%;overflow:auto}.hint[data-v-43659a67]{padding:4px;border:4px;background:var(--zp-secondary-background);border:1px solid var(--zp-border)}
|
||||
.ant-breadcrumb{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";color:#00000073;font-size:14px}.ant-breadcrumb .anticon{font-size:14px}.ant-breadcrumb a{color:#00000073;transition:color .3s}.ant-breadcrumb a:hover{color:#de632f}.ant-breadcrumb>span:last-child{color:#000000d9}.ant-breadcrumb>span:last-child a{color:#000000d9}.ant-breadcrumb>span:last-child .ant-breadcrumb-separator{display:none}.ant-breadcrumb-separator{margin:0 8px;color:#00000073}.ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-link>.anticon+a{margin-left:4px}.ant-breadcrumb-overlay-link>.anticon{margin-left:4px}.ant-breadcrumb-rtl{direction:rtl}.ant-breadcrumb-rtl:before{display:table;content:""}.ant-breadcrumb-rtl:after{display:table;clear:both;content:""}.ant-breadcrumb-rtl>span{float:right}.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+span,.ant-breadcrumb-rtl .ant-breadcrumb-link>.anticon+a{margin-right:4px;margin-left:0}.ant-breadcrumb-rtl .ant-breadcrumb-overlay-link>.anticon{margin-right:4px;margin-left:0}.nprogress{pointer-events:none}.nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}.nprogress .peg{display:block;position:absolute;right:0px;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0px,-4px);-ms-transform:rotate(3deg) translate(0px,-4px);transform:rotate(3deg) translateY(-4px)}.nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}.nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent .nprogress .spinner,.nprogress-custom-parent .nprogress .bar{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preview-switch[data-v-4d3aae06]{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-4d3aae06]{color:#fff;margin:16px;font-size:4em;pointer-events:all;cursor:pointer}.preview-switch>*.disable[data-v-4d3aae06]{opacity:0;pointer-events:none;cursor:none}.breadcrumb[data-v-4d3aae06]{display:flex;align-items:center}.breadcrumb>*[data-v-4d3aae06]{margin-right:4px}.container[data-v-4d3aae06]{background:var(--zp-secondary-background);height:var(--pane-max-height)}.location-bar[data-v-4d3aae06]{padding:4px 16px;background:var(--zp-primary-background);border-bottom:1px solid var(--zp-border);display:flex;align-items:center;justify-content:space-between}.location-bar .actions[data-v-4d3aae06]{display:flex;align-items:center;flex-shrink:0}.location-bar a.opt[data-v-4d3aae06]{margin-left:8px}.view[data-v-4d3aae06]{padding:8px;height:calc(100vh - 48px)}.view .file-list[data-v-4d3aae06]{list-style:none;padding:8px;height:100%;overflow:auto}.hint[data-v-4d3aae06]{padding:4px;border:4px;background:var(--zp-secondary-background);border:1px solid var(--zp-border)}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -7,8 +7,8 @@
|
|||
<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-23e5bc7c.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-618900f2.css">
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-af270b30.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-90388ea3.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ const tags = computed(() => {
|
|||
<a-menu-item key="send2outpaint">openOutpaint</a-menu-item>
|
||||
</a-sub-menu>
|
||||
</template>
|
||||
<a-menu-item key="send2BatchDownload">{{ $t('sendToBatchDownload') }}</a-menu-item>
|
||||
<a-menu-item key="send2savedDir">{{ $t('send2savedDir') }}</a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-sub-menu key="toggle-tag" :title="$t('toggleTag')">
|
||||
|
|
@ -4,11 +4,12 @@ import { useGlobalStore } from '@/store/useGlobalStore'
|
|||
import { fallbackImage } from 'vue3-ts-util'
|
||||
import type { FileNodeInfo } from '@/api/files'
|
||||
import { isImageFile } from '@/util'
|
||||
import { toImageThumbnailUrl, toRawFileUrl } from './hook'
|
||||
import { toImageThumbnailUrl, toRawFileUrl } from '@/util/file'
|
||||
import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'
|
||||
import { computed } from 'vue'
|
||||
import ContextMenu from './ContextMenu.vue'
|
||||
import { useTagStore } from '@/store/useTagStore'
|
||||
import { CloseCircleOutlined } from '@/icon'
|
||||
|
||||
const global = useGlobalStore()
|
||||
const tagStore = useTagStore()
|
||||
|
|
@ -20,17 +21,20 @@ const props = withDefaults(
|
|||
showMenuIdx?: number
|
||||
cellWidth: number
|
||||
fullScreenPreviewImageUrl?: string
|
||||
enableRightClickMenu: boolean,
|
||||
enableCloseIcon: boolean
|
||||
}>(),
|
||||
{ selected: false }
|
||||
{ selected: false, enableRightClickMenu: true, enableCloseIcon: false }
|
||||
)
|
||||
|
||||
const emit = defineEmits<{
|
||||
(type: 'update:showMenuIdx', v: number): void
|
||||
(type: 'fileItemClick', event: MouseEvent, file: FileNodeInfo, idx: number): void
|
||||
(type: 'dragstart', event: DragEvent, idx: number): void
|
||||
(type: 'dragend', event: DragEvent, idx: number): void
|
||||
(type: 'previewVisibleChange', value: boolean, last: boolean): void
|
||||
(type: 'contextMenuClick', e: MenuInfo, file: FileNodeInfo, idx: number): void
|
||||
'update:showMenuIdx': [v: number],
|
||||
'fileItemClick': [event: MouseEvent, file: FileNodeInfo, idx: number],
|
||||
'dragstart': [event: DragEvent, idx: number],
|
||||
'dragend': [event: DragEvent, idx: number],
|
||||
'previewVisibleChange': [value: boolean, last: boolean],
|
||||
'contextMenuClick': [e: MenuInfo, file: FileNodeInfo, idx: number],
|
||||
'close-icon-click': []
|
||||
}>()
|
||||
|
||||
const customTags = computed(() => {
|
||||
|
|
@ -52,7 +56,10 @@ const imageSrc = computed(() => {
|
|||
@dragend="emit('dragend', $event, idx)" @click.capture="emit('fileItemClick', $event, file, idx)">
|
||||
|
||||
<div>
|
||||
<a-dropdown>
|
||||
<div class="close-icon" v-if="enableCloseIcon" @click="emit('close-icon-click')">
|
||||
<close-circle-outlined />
|
||||
</div>
|
||||
<a-dropdown v-if="enableRightClickMenu">
|
||||
<div class="more">
|
||||
<ellipsis-outlined />
|
||||
</div>
|
||||
|
|
@ -95,7 +102,7 @@ const imageSrc = computed(() => {
|
|||
</div>
|
||||
</li>
|
||||
<template #overlay>
|
||||
<context-menu :file="file" :idx="idx" :selected-tag="customTags"
|
||||
<context-menu :file="file" :idx="idx" :selected-tag="customTags" v-if="enableRightClickMenu"
|
||||
@context-menu-click="(e, f, i) => emit('contextMenuClick', e, f, i)" />
|
||||
</template>
|
||||
</a-dropdown>
|
||||
|
|
@ -123,6 +130,19 @@ const imageSrc = computed(() => {
|
|||
}
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
transform: translate(50%, -50%) scale(1.5);
|
||||
cursor: pointer;
|
||||
z-index: 100;
|
||||
border-radius: 100%;
|
||||
overflow: hidden;
|
||||
line-height: 1;
|
||||
background-color: var(--zp-primary-background);
|
||||
}
|
||||
|
||||
.file {
|
||||
padding: 8px 16px;
|
||||
margin: 8px;
|
||||
|
|
@ -132,7 +152,6 @@ const imageSrc = computed(() => {
|
|||
border-radius: 8px;
|
||||
box-shadow: 0 0 4px var(--zp-secondary-variant-background);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover .more {
|
||||
opacity: 1;
|
||||
|
|
@ -220,6 +239,7 @@ const imageSrc = computed(() => {
|
|||
}
|
||||
|
||||
.basic-info {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
|
|
@ -51,6 +51,7 @@ const zh = {
|
|||
sendToImg2img: '发送到图生图',
|
||||
sendToInpaint: '发送到局部重绘',
|
||||
sendToControlNet: '发送到ControlNet',
|
||||
sendToBatchDownload: '发送到批量下载',
|
||||
sendToExtraFeatures: '发送到附加功能',
|
||||
loadNextPage: '加载下一页',
|
||||
localFile: '本地文件',
|
||||
|
|
@ -185,11 +186,21 @@ const zh = {
|
|||
inputFolderName: '输入文件夹名',
|
||||
createFolder: '创建文件夹',
|
||||
sendToThirdPartyExtension: '发送到第三方拓展',
|
||||
lyco: 'LyCORIS'
|
||||
lyco: 'LyCORIS',
|
||||
batchDownloaDDragAndDropHint:
|
||||
'使用拖拽或者右键菜单中的“发送到批量下载”将其他页面的图片添加到这里,支持多选',
|
||||
zipDownload: '打包成zip下载',
|
||||
archive: '归档',
|
||||
batchDownload: '批量下载'
|
||||
}
|
||||
const en: Record<keyof typeof zh, string> = {
|
||||
//! MissingTranslations: "Mark missing translations like this""shortcutKey": "Keyboard Shortcuts",
|
||||
//! MissingTranslations
|
||||
batchDownload: 'Batch Download',
|
||||
archive: 'Archive',
|
||||
zipDownload: 'Download as ZIP',
|
||||
batchDownloaDDragAndDropHint:
|
||||
"Use drag and drop or the 'Send to Batch Download' option in the right-click menu to add images from other pages here. Multiple selections are supported.",
|
||||
lyco: 'LyCORIS',
|
||||
sendToThirdPartyExtension: 'Send to third-party extension',
|
||||
createFolder: 'Create Folder',
|
||||
|
|
@ -354,6 +365,7 @@ const en: Record<keyof typeof zh, string> = {
|
|||
sendToTxt2img: 'Send to txt2img',
|
||||
sendToImg2img: 'Send to img2img',
|
||||
sendToInpaint: 'Send to Inpaint',
|
||||
sendToBatchDownload: 'Send to BatchDownload',
|
||||
sendToExtraFeatures: 'Send to Extra',
|
||||
sendToControlNet: 'Send to ControlNet',
|
||||
loadNextPage: 'Load next page',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { useImgSliStore } from '@/store/useImgSli'
|
||||
import { isFileTransferData, toImageThumbnailUrl, toRawFileUrl } from '@/page/fileTransfer/util'
|
||||
import { toImageThumbnailUrl, toRawFileUrl, getFileTransferDataFromDragEvent } from '@/util/file'
|
||||
import { CloseCircleOutlined } from '@/icon'
|
||||
import { isImageFile } from '@/util'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
|
@ -14,8 +14,8 @@ const g = useGlobalStore()
|
|||
const { left, right } = storeToRefs(sliStore)
|
||||
|
||||
const onImageDrop = async (e: DragEvent, side: 'left' | 'right') => {
|
||||
const data = JSON.parse(e.dataTransfer?.getData('text') ?? '{}')
|
||||
if (isFileTransferData(data)) {
|
||||
const data = getFileTransferDataFromDragEvent(e)
|
||||
if (data) {
|
||||
const img = data.nodes[0]
|
||||
if (!isImageFile(img.name)) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import ImgSliSide from './ImgSliSide.vue'
|
|||
import { asyncComputed, useElementSize } from '@vueuse/core'
|
||||
import { ref } from 'vue'
|
||||
import { FileNodeInfo } from '@/api/files'
|
||||
import { toRawFileUrl } from '../fileTransfer/util'
|
||||
import { toRawFileUrl } from '@/util/file'
|
||||
import { createImage } from '@/util'
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { toRawFileUrl } from '../fileTransfer/util'
|
||||
import { toRawFileUrl } from '@/util/file'
|
||||
import { computed } from 'vue'
|
||||
import { FileNodeInfo } from '@/api/files'
|
||||
const props = defineProps<{ side: 'left' | 'right', containerWidth: number, img: FileNodeInfo, maxEdge: 'width' | 'height', percent: number }>()
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ const compMap: Record<TabPane['type'], ReturnType<typeof defineAsyncComponent>>
|
|||
'tag-search': defineAsyncComponent(() => import('@/page/TagSearch/TagSearch.vue')),
|
||||
'fuzzy-search': defineAsyncComponent(() => import('@/page/TagSearch/SubstrSearch.vue')),
|
||||
'img-sli': defineAsyncComponent(() => import('@/page/ImgSli/ImgSliPagePane.vue')),
|
||||
'batch-download': defineAsyncComponent(() => import('@/page/batchDownload/batchDownload.vue'))
|
||||
}
|
||||
const onEdit = (idx: number, targetKey: any, action: string) => {
|
||||
const tab = global.tabList[idx]
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ const compCnMap: Partial<Record<TabPane['type'], string>> = {
|
|||
local: t('local'),
|
||||
'tag-search': t('imgSearch'),
|
||||
'fuzzy-search': t('fuzzy-search'),
|
||||
'global-setting': t('globalSettings')
|
||||
'global-setting': t('globalSettings'),
|
||||
'batch-download': t('batchDownload') + ' / ' + t('archive')
|
||||
}
|
||||
const openInCurrentTab = (type: TabPane['type'], path?: string, walkMode = false) => {
|
||||
let pane: TabPane
|
||||
|
|
@ -30,6 +31,7 @@ const openInCurrentTab = (type: TabPane['type'], path?: string, walkMode = false
|
|||
return
|
||||
case 'global-setting':
|
||||
case 'tag-search':
|
||||
case 'batch-download':
|
||||
case 'fuzzy-search':
|
||||
case 'empty':
|
||||
pane = { type, name: compCnMap[type]!, key: Date.now() + uniqueId() }
|
||||
|
|
@ -162,7 +164,9 @@ const addToSearchScanPathAndQuickMove = async () => {
|
|||
<h2>{{ $t('launchFromQuickMove') }}</h2>
|
||||
<ul>
|
||||
<li @click="addToSearchScanPathAndQuickMove" class="item" style="text-align: ;">
|
||||
<span class="text line-clamp-1"> <PlusOutlined/> {{ $t('add') }}</span>
|
||||
<span class="text line-clamp-1">
|
||||
<PlusOutlined /> {{ $t('add') }}
|
||||
</span>
|
||||
</li>
|
||||
<li v-for="dir in global.quickMovePaths" :key="dir.key" class="item"
|
||||
@click.prevent="openInCurrentTab('local', dir.dir)">
|
||||
|
|
@ -177,7 +181,7 @@ const addToSearchScanPathAndQuickMove = async () => {
|
|||
@click.prevent="openInCurrentTab(comp)">
|
||||
<span class="text line-clamp-1">{{ compCnMap[comp] }}</span>
|
||||
</li>
|
||||
<li class="item" @click="imgsli.opened = true">
|
||||
<li class="item" @click="imgsli.opened = true">
|
||||
<span class="text line-clamp-1">{{ $t('imgCompare') }}</span>
|
||||
</li>
|
||||
<li class="item" v-if="canpreviewInNewWindow" @click="previewInNewWindow">
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script lang="ts" setup>
|
||||
import fileItemCell from '@/page/fileTransfer/FileItem.vue'
|
||||
import fileItemCell from '@/components/FileItem.vue'
|
||||
import '@zanllp/vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
||||
// @ts-ignore
|
||||
import { RecycleScroller } from '@zanllp/vue-virtual-scroller'
|
||||
import { toRawFileUrl } from '@/page/fileTransfer/hook'
|
||||
import { toRawFileUrl } from '@/util/file'
|
||||
import { getImagesByTags, type MatchImageByTagsReq } from '@/api/db'
|
||||
import { nextTick, watch } from 'vue'
|
||||
import { copy2clipboardI18n } from '@/util'
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import { nextTick, onMounted, ref } from 'vue'
|
||||
import fileItemCell from '@/page/fileTransfer/FileItem.vue'
|
||||
import fileItemCell from '@/components/FileItem.vue'
|
||||
import '@zanllp/vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
||||
// @ts-ignore
|
||||
import { RecycleScroller } from '@zanllp/vue-virtual-scroller'
|
||||
import { toRawFileUrl } from '@/page/fileTransfer/hook'
|
||||
import { toRawFileUrl } from '@/util/file'
|
||||
import { getDbBasicInfo, getExpiredDirs, getImagesBySubstr, updateImageData, type DataBaseBasicInfo } from '@/api/db'
|
||||
import { copy2clipboardI18n, makeAsyncFunctionSingle, useGlobalEventListen } from '@/util'
|
||||
import fullScreenContextMenu from '@/page/fileTransfer/fullScreenContextMenu.vue'
|
||||
|
|
|
|||
|
|
@ -19,11 +19,10 @@ export const useImageSearch = () => {
|
|||
const images = ref<FileNodeInfo[]>()
|
||||
const queue = createReactiveQueue()
|
||||
const tagStore = useTagStore()
|
||||
const propsMock = { tabIdx: -1, target: 'local', paneIdx: -1, walkMode: false } as const
|
||||
const { stackViewEl, multiSelectedIdxs, stack, scroller } = useHookShareState({ images }).toRefs()
|
||||
const { itemSize, gridItems, cellWidth } = useFilesDisplay(propsMock)
|
||||
const { itemSize, gridItems, cellWidth } = useFilesDisplay()
|
||||
const { showMenuIdx } = useMobileOptimization()
|
||||
useLocation(propsMock)
|
||||
useLocation()
|
||||
const { onFileDragStart, onFileDragEnd } = useFileTransfer()
|
||||
const {
|
||||
showGenInfo,
|
||||
|
|
@ -31,8 +30,8 @@ export const useImageSearch = () => {
|
|||
q: genInfoQueue,
|
||||
onContextMenuClick,
|
||||
onFileItemClick
|
||||
} = useFileItemActions(propsMock, { openNext: identity })
|
||||
const { previewIdx, previewing, onPreviewVisibleChange, previewImgMove, canPreview } = usePreview(propsMock)
|
||||
} = useFileItemActions({ openNext: identity })
|
||||
const { previewIdx, previewing, onPreviewVisibleChange, previewImgMove, canPreview } = usePreview()
|
||||
|
||||
const onContextMenuClickU: typeof onContextMenuClick = async (e, file, idx) => {
|
||||
stack.value = [{ curr: '', files: images.value! }] // hack,for delete multi files
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
<script lang="ts" setup>
|
||||
// @ts-ignore
|
||||
import { RecycleScroller } from '@zanllp/vue-virtual-scroller'
|
||||
import '@zanllp/vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
||||
import FileItem from '@/components/FileItem.vue'
|
||||
import { useBatchDownloadStore } from '@/store/useBatchDownloadStore'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useFilesDisplay, useHookShareState } from '@/page/fileTransfer/hook'
|
||||
import { getFileTransferDataFromDragEvent, toRawFileUrl } from '@/util/file'
|
||||
import { axiosInst } from '@/api'
|
||||
import { createReactiveQueue } from '@/util'
|
||||
const { stackViewEl } = useHookShareState().toRefs()
|
||||
const { itemSize, gridItems, cellWidth } = useFilesDisplay()
|
||||
const store = useBatchDownloadStore()
|
||||
const { selectdFiles } = storeToRefs(store)
|
||||
const q = createReactiveQueue()
|
||||
defineProps<{
|
||||
tabIdx: number
|
||||
paneIdx: number
|
||||
id: string
|
||||
}>()
|
||||
const onDrop = async (e: DragEvent) => {
|
||||
const data = getFileTransferDataFromDragEvent(e)
|
||||
if (data) {
|
||||
store.addFiles(data.nodes)
|
||||
}
|
||||
}
|
||||
|
||||
const onDownloadClick = async () => {
|
||||
q.pushAction(async () => {
|
||||
const resp = await axiosInst.value.post('/zip', { paths: selectdFiles.value.map(v => v.fullpath) }, {
|
||||
responseType: 'blob',
|
||||
})
|
||||
const url = window.URL.createObjectURL(new Blob([resp.data]))
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.setAttribute('download', `iib_${new Date().toLocaleString()}.zip`)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
})
|
||||
}
|
||||
const onDeleteClick = (idx: number) => {
|
||||
selectdFiles.value.splice(idx, 1)
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div class="container" ref="stackViewEl" @drop="onDrop">
|
||||
<div class="actions-panel actions">
|
||||
<AButton @click="store.selectdFiles = []">{{ $t('clear') }}</AButton>
|
||||
<AButton @click="onDownloadClick" type="primary" :loading="!q.isIdle">{{ $t('zipDownload') }}</AButton>
|
||||
</div>
|
||||
<div v-if="!selectdFiles.length" class="file-list">
|
||||
<p class="hint">{{ $t('batchDownloaDDragAndDropHint') }}</p>
|
||||
</div>
|
||||
<RecycleScroller ref="scroller" v-else class="file-list" :items="selectdFiles.slice()" :item-size="itemSize.first"
|
||||
key-field="fullpath" :item-secondary-size="itemSize.second" :gridItems="gridItems">
|
||||
<template v-slot="{ item: file, index: idx }">
|
||||
<file-item :idx="idx" :file="file" :cell-width="cellWidth" enable-close-icon
|
||||
@close-icon-click="onDeleteClick(idx)" :full-screen-preview-image-url="toRawFileUrl(file)"
|
||||
:enable-right-click-menu="false" />
|
||||
</template>
|
||||
</RecycleScroller>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
background: var(--zp-secondary-background);
|
||||
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.actions-panel {
|
||||
padding: 8px;
|
||||
background-color: var(--zp-primary-background);
|
||||
}
|
||||
|
||||
.file-list {
|
||||
flex: 1;
|
||||
list-style: none;
|
||||
padding: 8px;
|
||||
height: var(--pane-max-height);
|
||||
width: 100%;
|
||||
|
||||
.hint {
|
||||
text-align: center;
|
||||
font-size: 2em;
|
||||
padding: 30vh 128px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -21,8 +21,8 @@ import {
|
|||
import { t } from '@/i18n'
|
||||
import { type Tag } from '@/api/db'
|
||||
import { createReactiveQueue } from '@/util'
|
||||
import { toRawFileUrl } from './hook'
|
||||
import ContextMenu from './ContextMenu.vue'
|
||||
import { toRawFileUrl } from '@/util/file'
|
||||
import ContextMenu from '@/components/ContextMenu.vue'
|
||||
import { useWatchDocument } from 'vue3-ts-util'
|
||||
import { useTagStore } from '@/store/useTagStore'
|
||||
|
||||
|
|
@ -156,6 +156,7 @@ const baseInfoTags = computed(() => {
|
|||
<a-menu-item key="send2outpaint">openOutpaint</a-menu-item>
|
||||
</a-sub-menu>
|
||||
</template>
|
||||
<a-menu-item key="send2BatchDownload">{{ $t('sendToBatchDownload') }}</a-menu-item>
|
||||
<a-menu-item key="send2savedDir">{{ $t('send2savedDir') }}</a-menu-item>
|
||||
<a-menu-item key="deleteFiles" :disabled="toRawFileUrl(file) === global.fullscreenPreviewInitialUrl">
|
||||
{{ $t('deleteSelected') }}
|
||||
|
|
|
|||
|
|
@ -30,16 +30,16 @@ import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'
|
|||
import { t } from '@/i18n'
|
||||
import { DatabaseOutlined } from '@/icon'
|
||||
import { addScannedPath, removeScannedPath, toggleCustomTagToImg } from '@/api/db'
|
||||
import { FileTransferData, getFileTransferDataFromDragEvent, toRawFileUrl } from './util'
|
||||
import { FileTransferData, getFileTransferDataFromDragEvent, toRawFileUrl } from '../../util/file'
|
||||
import { getShortcutStrFromEvent } from '@/util/shortcut'
|
||||
import { openCreateFlodersModal, MultiSelectTips } from './functionalCallableComp'
|
||||
import { useTagStore } from '@/store/useTagStore'
|
||||
export * from './util'
|
||||
import { useBatchDownloadStore } from '@/store/useBatchDownloadStore'
|
||||
|
||||
export const stackCache = new Map<string, Page[]>()
|
||||
|
||||
const global = useGlobalStore()
|
||||
|
||||
const batchDownload = useBatchDownloadStore()
|
||||
const tagStore = useTagStore()
|
||||
const sli = useImgSliStore()
|
||||
const imgTransferBus = new BroadcastChannel('iib-image-transfer-bus')
|
||||
|
|
@ -143,14 +143,15 @@ export interface Page {
|
|||
* @param props
|
||||
* @returns
|
||||
*/
|
||||
export function usePreview (props: Props) {
|
||||
export function usePreview () {
|
||||
const {
|
||||
previewIdx,
|
||||
eventEmitter,
|
||||
canLoadNext,
|
||||
previewing,
|
||||
sortedFiles: files,
|
||||
scroller
|
||||
scroller,
|
||||
props
|
||||
} = useHookShareState().toRefs()
|
||||
const { state } = useHookShareState()
|
||||
let waitScrollTo = null as number | null
|
||||
|
|
@ -164,7 +165,7 @@ export function usePreview (props: Props) {
|
|||
}
|
||||
|
||||
const loadNextIfNeeded = () => {
|
||||
if (props.walkModePath) {
|
||||
if (props.value.walkModePath) {
|
||||
if (!canPreview('next') && canLoadNext) {
|
||||
message.info(t('loadingNextFolder'))
|
||||
eventEmitter.value.emit('loadNextDir', true) // 如果在全屏预览时外面scroller可能还停留在很久之前,使用全屏预览的索引
|
||||
|
|
@ -259,7 +260,7 @@ export function usePreview (props: Props) {
|
|||
/**
|
||||
* 路径栏相关
|
||||
*/
|
||||
export function useLocation (props: Props) {
|
||||
export function useLocation () {
|
||||
const np = ref<Progress.NProgress>()
|
||||
const {
|
||||
scroller,
|
||||
|
|
@ -272,7 +273,8 @@ export function useLocation (props: Props) {
|
|||
eventEmitter,
|
||||
getPane,
|
||||
multiSelectedIdxs,
|
||||
sortedFiles
|
||||
sortedFiles,
|
||||
props
|
||||
} = useHookShareState().toRefs()
|
||||
|
||||
watch(
|
||||
|
|
@ -286,7 +288,7 @@ export function useLocation (props: Props) {
|
|||
|
||||
const handleWalkModeTo = async (path: string) => {
|
||||
await to(path)
|
||||
if (props.walkModePath) {
|
||||
if (props.value.walkModePath) {
|
||||
await delay()
|
||||
const [firstDir] = sortFiles(currPage.value!.files, sortMethod.value).filter(
|
||||
(v) => v.type === 'dir'
|
||||
|
|
@ -309,8 +311,8 @@ export function useLocation (props: Props) {
|
|||
}
|
||||
np.value = new NProgress()
|
||||
np.value!.configure({ parent: stackViewEl.value as any })
|
||||
if (props.path && props.path !== '/') {
|
||||
await handleWalkModeTo(props.walkModePath ?? props.path)
|
||||
if (props.value.path && props.value.path !== '/') {
|
||||
await handleWalkModeTo(props.value.walkModePath ?? props.value.path)
|
||||
} else {
|
||||
global.conf?.home && to(global.conf.home)
|
||||
}
|
||||
|
|
@ -326,7 +328,7 @@ export function useLocation (props: Props) {
|
|||
pane.path = loc
|
||||
const filename = pane.path!.split('/').pop()
|
||||
const getTitle = () => {
|
||||
if (!props.walkModePath) {
|
||||
if (!props.value.walkModePath) {
|
||||
const np = Path.normalize(loc)
|
||||
for (const [k, v] of Object.entries(global.pathAliasMap)) {
|
||||
if (np.startsWith(v)) {
|
||||
|
|
@ -430,9 +432,9 @@ export function useLocation (props: Props) {
|
|||
const refresh = makeAsyncFunctionSingle(async () => {
|
||||
try {
|
||||
np.value?.start()
|
||||
if (props.walkModePath) {
|
||||
if (props.value.walkModePath) {
|
||||
back(0)
|
||||
await handleWalkModeTo(props.walkModePath)
|
||||
await handleWalkModeTo(props.value.walkModePath)
|
||||
} else {
|
||||
const { files } = await getTargetFolderFiles(
|
||||
stack.value.length === 1 ? '/' : currLocation.value
|
||||
|
|
@ -449,7 +451,7 @@ export function useLocation (props: Props) {
|
|||
useGlobalEventListen(
|
||||
'returnToIIB',
|
||||
makeAsyncFunctionSingle(async () => {
|
||||
if (!props.walkModePath) {
|
||||
if (!props.value.walkModePath) {
|
||||
try {
|
||||
np.value?.start()
|
||||
const { files } = await getTargetFolderFiles(
|
||||
|
|
@ -470,7 +472,7 @@ export function useLocation (props: Props) {
|
|||
useEventListen.value('refresh', refresh)
|
||||
|
||||
const quickMoveTo = (path: string) => {
|
||||
if (props.walkModePath) {
|
||||
if (props.value.walkModePath) {
|
||||
getPane.value().walkModePath = path
|
||||
}
|
||||
handleWalkModeTo(path)
|
||||
|
|
@ -564,7 +566,7 @@ export function useLocation (props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
export function useFilesDisplay (props: Props) {
|
||||
export function useFilesDisplay () {
|
||||
const {
|
||||
scroller,
|
||||
sortedFiles,
|
||||
|
|
@ -574,7 +576,8 @@ export function useFilesDisplay (props: Props) {
|
|||
currPage,
|
||||
stackViewEl,
|
||||
canLoadNext,
|
||||
previewIdx
|
||||
previewIdx,
|
||||
props
|
||||
} = useHookShareState().toRefs()
|
||||
const { state } = useHookShareState()
|
||||
const moreActionsDropdownShow = ref(false)
|
||||
|
|
@ -597,7 +600,7 @@ export function useFilesDisplay (props: Props) {
|
|||
const loadNextDirLoading = ref(false)
|
||||
|
||||
const loadNextDir = async () => {
|
||||
if (loadNextDirLoading.value || !props.walkModePath || !canLoadNext.value) {
|
||||
if (loadNextDirLoading.value || !props.value.walkModePath || !canLoadNext.value) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
|
|
@ -763,7 +766,6 @@ export function useFileTransfer () {
|
|||
}
|
||||
|
||||
export function useFileItemActions (
|
||||
props: Props,
|
||||
{ openNext }: { openNext: (file: FileNodeInfo) => Promise<void> }
|
||||
) {
|
||||
const showGenInfo = ref(false)
|
||||
|
|
@ -777,7 +779,8 @@ export function useFileItemActions (
|
|||
spinning,
|
||||
previewing,
|
||||
stackViewEl,
|
||||
eventEmitter
|
||||
eventEmitter,
|
||||
props
|
||||
} = useHookShareState().toRefs()
|
||||
const nor = Path.normalize
|
||||
useEventListen('removeFiles', ({ paths, loc }) => {
|
||||
|
|
@ -944,7 +947,7 @@ export function useFileItemActions (
|
|||
}
|
||||
case 'openWithWalkMode': {
|
||||
stackCache.set(path, stack.value)
|
||||
const tab = global.tabList[props.tabIdx]
|
||||
const tab = global.tabList[props.value.tabIdx]
|
||||
const pane: FileTransferTabPane = {
|
||||
type: 'local',
|
||||
key: uniqueId(),
|
||||
|
|
@ -959,7 +962,7 @@ export function useFileItemActions (
|
|||
}
|
||||
case 'openInNewTab': {
|
||||
stackCache.set(path, stack.value)
|
||||
const tab = global.tabList[props.tabIdx]
|
||||
const tab = global.tabList[props.value.tabIdx]
|
||||
const pane: FileTransferTabPane = {
|
||||
type: 'local',
|
||||
key: uniqueId(),
|
||||
|
|
@ -973,10 +976,10 @@ export function useFileItemActions (
|
|||
}
|
||||
case 'openOnTheRight': {
|
||||
stackCache.set(path, stack.value)
|
||||
let tab = global.tabList[props.tabIdx + 1]
|
||||
let tab = global.tabList[props.value.tabIdx + 1]
|
||||
if (!tab) {
|
||||
tab = { panes: [], key: '', id: uniqueId() }
|
||||
global.tabList[props.tabIdx + 1] = tab
|
||||
global.tabList[props.value.tabIdx + 1] = tab
|
||||
}
|
||||
const pane: FileTransferTabPane = {
|
||||
type: 'local',
|
||||
|
|
@ -989,6 +992,10 @@ export function useFileItemActions (
|
|||
tab.key = pane.key
|
||||
break
|
||||
}
|
||||
case 'send2BatchDownload': {
|
||||
batchDownload.addFiles(getSelectedImg())
|
||||
break
|
||||
}
|
||||
case 'viewGenInfo': {
|
||||
showGenInfo.value = true
|
||||
imageGenInfo.value = await q.pushAction(() => getImageGenerationInfo(file.fullpath)).res
|
||||
|
|
|
|||
|
|
@ -8,18 +8,18 @@ import {
|
|||
useLocation,
|
||||
usePreview,
|
||||
useFileItemActions,
|
||||
toRawFileUrl,
|
||||
stackCache,
|
||||
useMobileOptimization
|
||||
} from './hook'
|
||||
import { SearchSelect } from 'vue3-ts-util'
|
||||
import { toRawFileUrl } from '@/util/file'
|
||||
|
||||
import 'multi-nprogress/nprogress.css'
|
||||
// @ts-ignore
|
||||
import { RecycleScroller } from '@zanllp/vue-virtual-scroller'
|
||||
import '@zanllp/vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
||||
import { watch } from 'vue'
|
||||
import FileItem from './FileItem.vue'
|
||||
import FileItem from '@/components/FileItem.vue'
|
||||
import fullScreenContextMenu from './fullScreenContextMenu.vue'
|
||||
import { copy2clipboardI18n } from '@/util'
|
||||
import { openFolder } from '@/api'
|
||||
|
|
@ -50,7 +50,7 @@ const {
|
|||
const { currLocation, currPage, refresh, copyLocation, back, openNext, stack, quickMoveTo,
|
||||
addToSearchScanPathAndQuickMove, searchPathInfo, locInputValue, isLocationEditing,
|
||||
onLocEditEnter, onEditBtnClick, share, selectAll, onCreateFloderBtnClick
|
||||
} = useLocation(props)
|
||||
} = useLocation()
|
||||
const {
|
||||
gridItems,
|
||||
sortMethodConv,
|
||||
|
|
@ -63,14 +63,10 @@ const {
|
|||
canLoadNext,
|
||||
onScroll,
|
||||
cellWidth
|
||||
} = useFilesDisplay(props)
|
||||
} = useFilesDisplay()
|
||||
const { onDrop, onFileDragStart, onFileDragEnd } = useFileTransfer()
|
||||
const { onFileItemClick, onContextMenuClick, showGenInfo, imageGenInfo, q } = useFileItemActions(
|
||||
props,
|
||||
{ openNext }
|
||||
)
|
||||
const { previewIdx, onPreviewVisibleChange, previewing, previewImgMove, canPreview } =
|
||||
usePreview(props)
|
||||
const { onFileItemClick, onContextMenuClick, showGenInfo, imageGenInfo, q } = useFileItemActions({ openNext })
|
||||
const { previewIdx, onPreviewVisibleChange, previewing, previewImgMove, canPreview } = usePreview()
|
||||
const { showMenuIdx } = useMobileOptimization()
|
||||
|
||||
watch(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import { FileNodeInfo } from '@/api/files'
|
||||
import { uniqueFile } from '@/util'
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const useBatchDownloadStore = defineStore('useBatchDownloadStore', () => {
|
||||
const selectdFiles = ref<FileNodeInfo[]>([])
|
||||
const addFiles = (files: FileNodeInfo[]) => {
|
||||
selectdFiles.value = uniqueFile([...selectdFiles.value,...files])
|
||||
}
|
||||
return {
|
||||
selectdFiles,
|
||||
addFiles
|
||||
}
|
||||
})
|
||||
|
|
@ -19,7 +19,7 @@ interface TabPaneBase {
|
|||
}
|
||||
|
||||
interface OtherTabPane extends TabPaneBase {
|
||||
type: 'empty' | 'global-setting' | 'tag-search' | 'fuzzy-search'
|
||||
type: 'empty' | 'global-setting' | 'tag-search' | 'fuzzy-search' | 'batch-download'
|
||||
}
|
||||
// logDetailId
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useTagSearch = defineStore('useTagSearch', () => {
|
||||
return {}
|
||||
})
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import type { FileNodeInfo } from '@/api/files'
|
||||
import { apiBase } from '@/api'
|
||||
import { uniqBy } from 'lodash-es'
|
||||
|
||||
const encode = encodeURIComponent
|
||||
export const toRawFileUrl = (file: FileNodeInfo, download = false) =>
|
||||
|
|
@ -26,3 +27,14 @@ export const getFileTransferDataFromDragEvent = (e: DragEvent) => {
|
|||
const data = JSON.parse(e.dataTransfer?.getData('text') ?? '{}')
|
||||
return isFileTransferData(data) ? data : null
|
||||
}
|
||||
|
||||
export const uniqueFile = (files: FileNodeInfo[]) => uniqBy(files, 'fullpath')
|
||||
|
||||
export function isImageFile(filename: string): boolean {
|
||||
if (typeof filename !== 'string') {
|
||||
return false
|
||||
}
|
||||
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
|
||||
const extension = filename.split('.').pop()?.toLowerCase()
|
||||
return extension !== undefined && imageExtensions.includes(`.${extension}`)
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import { t } from '@/i18n'
|
|||
import { message } from 'ant-design-vue'
|
||||
import { reactive } from 'vue'
|
||||
import { FetchQueue, idKey, typedEventEmitter, type UniqueId } from 'vue3-ts-util'
|
||||
export * from './file'
|
||||
|
||||
export const parentWindow = () => {
|
||||
return parent.window as any as Window & {
|
||||
|
|
@ -74,16 +75,6 @@ export const pick = <T extends Dict, keys extends Array<keyof T>>(v: T, ...keys:
|
|||
* ReturnTypeAsync\<typeof fn\>
|
||||
*/
|
||||
export type ReturnTypeAsync<T extends (...arg: any) => Promise<any>> = Awaited<ReturnType<T>>
|
||||
|
||||
export function isImageFile(filename: string): boolean {
|
||||
if (typeof filename !== 'string') {
|
||||
return false
|
||||
}
|
||||
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
|
||||
const extension = filename.split('.').pop()?.toLowerCase()
|
||||
return extension !== undefined && imageExtensions.includes(`.${extension}`)
|
||||
}
|
||||
|
||||
export const createReactiveQueue = () => reactive(new FetchQueue(-1, 0, -1, 'throw'))
|
||||
|
||||
export const copy2clipboardI18n = async (text: string, msg?: string) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue