Merge pull request #937 from zanllp/feat/comfyui-drag-drop

feat(drag): add ComfyUI-ready image dragging feature
feat/panel-settings
zanllp 2026-03-17 23:47:12 +08:00 committed by GitHub
commit 363b073622
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 377 additions and 46 deletions

View File

@ -1,6 +1,31 @@
[跳到中文](#中文)
# English
## 2026-03-17
### 🖼️ ComfyUI-Ready Image Dragging
Added drag-to-transfer functionality specifically designed for ComfyUI workflow integration.
**Features:**
- **One-Click Image Access**: Click to display original images ready for dragging
- **ComfyUI Integration**: Drag images directly into ComfyUI to restore complete workflows
- **Dual Placement**: Available in both full-screen info panel and file grid overlays
**How to use:**
1. Click the "Click to get original image, grab and drag to other apps" button
2. The original image appears instantly
3. Drag the image directly into ComfyUI
4. ComfyUI will automatically extract metadata and reconstruct the workflow
**Use Case:**
Perfect for moving images from IIB to ComfyUI. When you drag an image into ComfyUI:
- The original image is loaded
- Generation parameters are extracted from metadata
- The complete workflow is reconstructed automatically
- No manual parameter input required
**Note:** This feature preserves all generation metadata in the image, enabling seamless workflow transfer to ComfyUI and other compatible tools.
## 2026-03-15
### 📝 Editable Generation Information
Added the ability to edit image generation prompts and metadata directly in the UI.
@ -750,6 +775,30 @@ Triggered under the same circumstances as above, there will be a button to updat
# 中文
## 2026-03-17
### 🖼️ 专为ComfyUI设计的图片拖拽功能
新增了专为ComfyUI工作流还原设计的图片拖拽传输功能。
**功能特性:**
- **一键获取原图**:点击即可显示原始图片,随时准备拖拽
- **ComfyUI集成**可直接将图片拖拽到ComfyUI中自动还原完整工作流
- **双重入口**:在全屏信息面板和文件网格中均可使用)
**使用方法:**
1. 点击"点击获取原图,抓取拖拽至其他应用"按钮
2. 原始图片立即显示
3. 将图片直接拖拽到ComfyUI界面中
4. ComfyUI会自动提取元数据并重建工作流
**使用场景:**
完美支持从IIB到ComfyUI的图片转移。当您将图片拖拽到ComfyUI时
- 原始图片被加载
- 从元数据中提取生成参数
- 自动重建完整工作流
- 无需手动输入参数
**注意:** 此功能保留图片中的所有生成元数据实现与ComfyUI及其他兼容工具的无缝工作流传输。
## 2026-03-15
### 📝 可编辑的生成信息
新增了在界面中直接编辑图片生成提示词和元数据的功能。

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-ac2041d9.js"></script>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-0236195f.js"></script>
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-882e7f3d.css">
</head>

1
vue/components.d.ts vendored
View File

@ -53,6 +53,7 @@ declare module '@vue/runtime-core' {
BaseFileListInfo: typeof import('./src/components/BaseFileListInfo.vue')['default']
ChangeIndicator: typeof import('./src/components/ChangeIndicator.vue')['default']
ContextMenu: typeof import('./src/components/ContextMenu.vue')['default']
DraggableImage: typeof import('./src/components/DraggableImage.vue')['default']
ExifBrowser: typeof import('./src/components/ExifBrowser.vue')['default']
FileItem: typeof import('./src/components/FileItem.vue')['default']
HistoryRecord: typeof import('./src/components/HistoryRecord.vue')['default']

2
vue/dist/assets/FileItem-0178f9f2.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

1
vue/dist/assets/FileItem-f935dd79.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d as a,o as t,j as n,c as s,c1 as _,n as o}from"./index-ac2041d9.js";const c={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),n("div",c,[s(_,{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,o as t,j as n,c as s,c1 as _,n as o}from"./index-0236195f.js";const c={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),n("div",c,[s(_,{left:e.left,right:e.right},null,8,["left","right"])]))}});const d=o(i,[["__scopeId","data-v-ae3fb9a8"]]);export{d as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
import{bJ as N,bK as E,bL as q,c as u,A as U,d as R,o as d,j as p,k as _,F as X,K as G,ah as K,C as f,l as g,t as h,E as L,a3 as H,n as z,aq as Q,aC as C,aD as F,r as W,aj as I,X as V,v as Y,bM as Z,m as T,bN as ee,bO as te}from"./index-ac2041d9.js";const ge=N(E),me=N(q);var ne={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 se=ne;function k(i){for(var e=1;e<arguments.length;e++){var t=arguments[e]!=null?Object(arguments[e]):{},n=Object.keys(t);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(t).filter(function(s){return Object.getOwnPropertyDescriptor(t,s).enumerable}))),n.forEach(function(s){ie(i,s,t[s])})}return i}function ie(i,e,t){return e in i?Object.defineProperty(i,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):i[e]=t,i}var P=function(e,t){var n=k({},e,t.attrs);return u(U,k({},n,{icon:se}),null)};P.displayName="PushpinFilled";P.inheritAttrs=!1;const re=P,ae={class:"record-container"},oe={style:{flex:"1"}},ce={class:"rec-actions"},le=["onClick"],ue=R({__name:"HistoryRecord",props:{records:{}},emits:["reuseRecord"],setup(i){return(e,t)=>{const n=H;return d(),p("div",null,[_("ul",ae,[(d(!0),p(X,null,G(e.records.getRecords(),s=>(d(),p("li",{key:s.id,class:"record"},[_("div",oe,[K(e.$slots,"default",{record:s},void 0,!0)]),_("div",ce,[u(n,{onClick:o=>e.$emit("reuseRecord",s),type:"primary"},{default:f(()=>[g(h(e.$t("restore")),1)]),_:2},1032,["onClick"]),_("div",{class:"pin",onClick:o=>e.records.switchPin(s)},[u(L(re)),g(" "+h(e.records.isPinned(s)?e.$t("unpin"):e.$t("pin")),1)],8,le)])]))),128))])])}}});const ve=z(ue,[["__scopeId","data-v-834a248f"]]);class m{constructor(e=128,t=[],n=[]){this.maxLength=e,this.records=t,this.pinnedValues=n}isPinned(e){return this.pinnedValues.some(t=>t.id===e.id)}add(e){this.records.length>=this.maxLength&&this.records.pop(),this.records.unshift({...e,id:Q()+Date.now(),time:new Date().toLocaleString()})}pin(e){const t=this.records.findIndex(n=>n.id===e.id);t!==-1&&this.records.splice(t,1),this.pinnedValues.push(e)}unpin(e){const t=this.pinnedValues.findIndex(n=>n.id===e.id);t!==-1&&this.pinnedValues.splice(t,1),this.records.unshift(e)}switchPin(e){this.isPinned(e)?this.unpin(e):this.pin(e)}getRecords(){return[...this.pinnedValues,...this.records]}getPinnedValues(){return this.pinnedValues}}const ye=C(`${F}fuzzy-search-HistoryRecord`,new m,{serializer:{read:i=>{const e=JSON.parse(i);return new m(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),be=C(`${F}tag-search-HistoryRecord`,new m,{serializer:{read:i=>{const e=JSON.parse(i);return new m(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),de={key:0,class:"tips-carousel"},pe={class:"tip-text"},_e={key:0,class:"tip-actions"},he=R({__name:"TipsCarousel",props:{interval:{type:Number,default:1e4}},setup(i){const e=i,t=C("iib-dismissed-tips-v2",{}),n=W(0);let s=null;const o=I(()=>{var v;const r=[];for(let a=1;a<=10;a++){const l=`loadingTip${a}`,y=V(l);if(!y||typeof y!="string")continue;const $=y.split("|"),b=$[0],M=((v=$[1])==null?void 0:v.trim())||"info",S=`
import{bJ as N,bK as E,bL as q,c as u,A as U,d as R,o as d,j as p,k as _,F as X,K as G,ah as K,C as f,l as g,t as h,E as L,a3 as H,n as z,aq as Q,aC as C,aD as F,r as W,aj as I,X as V,v as Y,bM as Z,m as T,bN as ee,bO as te}from"./index-0236195f.js";const ge=N(E),me=N(q);var ne={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 se=ne;function k(i){for(var e=1;e<arguments.length;e++){var t=arguments[e]!=null?Object(arguments[e]):{},n=Object.keys(t);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(t).filter(function(s){return Object.getOwnPropertyDescriptor(t,s).enumerable}))),n.forEach(function(s){ie(i,s,t[s])})}return i}function ie(i,e,t){return e in i?Object.defineProperty(i,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):i[e]=t,i}var P=function(e,t){var n=k({},e,t.attrs);return u(U,k({},n,{icon:se}),null)};P.displayName="PushpinFilled";P.inheritAttrs=!1;const re=P,ae={class:"record-container"},oe={style:{flex:"1"}},ce={class:"rec-actions"},le=["onClick"],ue=R({__name:"HistoryRecord",props:{records:{}},emits:["reuseRecord"],setup(i){return(e,t)=>{const n=H;return d(),p("div",null,[_("ul",ae,[(d(!0),p(X,null,G(e.records.getRecords(),s=>(d(),p("li",{key:s.id,class:"record"},[_("div",oe,[K(e.$slots,"default",{record:s},void 0,!0)]),_("div",ce,[u(n,{onClick:o=>e.$emit("reuseRecord",s),type:"primary"},{default:f(()=>[g(h(e.$t("restore")),1)]),_:2},1032,["onClick"]),_("div",{class:"pin",onClick:o=>e.records.switchPin(s)},[u(L(re)),g(" "+h(e.records.isPinned(s)?e.$t("unpin"):e.$t("pin")),1)],8,le)])]))),128))])])}}});const ve=z(ue,[["__scopeId","data-v-834a248f"]]);class m{constructor(e=128,t=[],n=[]){this.maxLength=e,this.records=t,this.pinnedValues=n}isPinned(e){return this.pinnedValues.some(t=>t.id===e.id)}add(e){this.records.length>=this.maxLength&&this.records.pop(),this.records.unshift({...e,id:Q()+Date.now(),time:new Date().toLocaleString()})}pin(e){const t=this.records.findIndex(n=>n.id===e.id);t!==-1&&this.records.splice(t,1),this.pinnedValues.push(e)}unpin(e){const t=this.pinnedValues.findIndex(n=>n.id===e.id);t!==-1&&this.pinnedValues.splice(t,1),this.records.unshift(e)}switchPin(e){this.isPinned(e)?this.unpin(e):this.pin(e)}getRecords(){return[...this.pinnedValues,...this.records]}getPinnedValues(){return this.pinnedValues}}const ye=C(`${F}fuzzy-search-HistoryRecord`,new m,{serializer:{read:i=>{const e=JSON.parse(i);return new m(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),be=C(`${F}tag-search-HistoryRecord`,new m,{serializer:{read:i=>{const e=JSON.parse(i);return new m(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),de={key:0,class:"tips-carousel"},pe={class:"tip-text"},_e={key:0,class:"tip-actions"},he=R({__name:"TipsCarousel",props:{interval:{type:Number,default:1e4}},setup(i){const e=i,t=C("iib-dismissed-tips-v2",{}),n=W(0);let s=null;const o=I(()=>{var v;const r=[];for(let a=1;a<=10;a++){const l=`loadingTip${a}`,y=V(l);if(!y||typeof y!="string")continue;const $=y.split("|"),b=$[0],M=((v=$[1])==null?void 0:v.trim())||"info",S=`
`,w=b.indexOf(S);if(w===-1)continue;const x=b.substring(0,w).trim(),A=b.substring(w+S.length).trim(),O={title:x,content:A,type:M};O.type==="warning"&&t.value[x]||r.push(O)}for(let a=r.length-1;a>0;a--){const l=Math.floor(Math.random()*(a+1));[r[a],r[l]]=[r[l],r[a]]}return r}),c=I(()=>{const r=o.value;return r.length===0?{title:"",content:"",type:"info"}:r[n.value%r.length]}),j=r=>{switch(r){case"warning":return"warning";case"info":return"blue";case"tip":return"green";default:return"default"}},B=()=>{c.value.type==="warning"&&(t.value={...t.value,[c.value.title]:!0})},D=()=>{s&&clearInterval(s),s=setInterval(()=>{o.value.length>1&&(n.value=(n.value+1)%o.value.length)},e.interval)},J=()=>{s&&(clearInterval(s),s=null)};return Y(()=>{D()}),Z(()=>{J()}),(r,v)=>{const a=te,l=H;return o.value.length>0?(d(),p("div",de,[u(ee,{name:"tip-fade",mode:"out-in"},{default:f(()=>[(d(),p("div",{key:n.value,class:"tip-content"},[u(a,{color:j(c.value.type),class:"tip-tag"},{default:f(()=>[g(h(c.value.title),1)]),_:1},8,["color"]),_("span",pe,h(c.value.content),1),c.value.type==="warning"?(d(),p("div",_e,[u(l,{size:"small",type:"link",onClick:B},{default:f(()=>[g(h(L(V)("dontShowAgain")),1)]),_:1})])):T("",!0)]))]),_:1})])):T("",!0)}}});const we=z(he,[["__scopeId","data-v-3b5692ee"]]);export{ve as H,we as T,me as _,ge as a,ye as f,be as t};

View File

@ -1,4 +1,4 @@
import{d as LA,r as Kt,aj as Rr,X as Ut,s as gs,x as Dh,v as IA,bM as zk,o as te,j as Ce,c as Ht,k as Mt,t as Vt,E as ve,C as le,l as ze,bC as PA,B as Ka,bP as Vk,bQ as Gk,m as fr,W as Jr,bR as Fk,a8 as RA,av as kA,bO as EA,bS as Hk,a0 as OA,a2 as NA,bT as BA,a3 as zA,aw as VA,ax as GA,bU as Wk,n as FA,p as $k,aC as H_,bV as Uk,T as Yk,F as W_,K as Zk,bW as Xk,bX as qk,bY as Kk,bt as jk,bZ as Jk,b_ as Qk,aq as Ro,b$ as tE,a6 as eE,Z as rE,c0 as aE}from"./index-ac2041d9.js";/*! *****************************************************************************
import{d as LA,r as Kt,aj as Rr,X as Ut,s as gs,x as Dh,v as IA,bM as zk,o as te,j as Ce,c as Ht,k as Mt,t as Vt,E as ve,C as le,l as ze,bC as PA,B as Ka,bP as Vk,bQ as Gk,m as fr,W as Jr,bR as Fk,a8 as RA,av as kA,bO as EA,bS as Hk,a0 as OA,a2 as NA,bT as BA,a3 as zA,aw as VA,ax as GA,bU as Wk,n as FA,p as $k,aC as H_,bV as Uk,T as Yk,F as W_,K as Zk,bW as Xk,bX as qk,bY as Kk,bt as jk,bZ as Jk,b_ as Qk,aq as Ro,b$ as tE,a6 as eE,Z as rE,c0 as aE}from"./index-0236195f.js";/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any

View File

@ -1 +1 @@
import{b2 as i,aO as t,dM as f,aS as n}from"./index-ac2041d9.js";function u(e,a,r){if(!i(r))return!1;var s=typeof a;return(s=="number"?t(r)&&f(a,r.length):s=="string"&&a in r)?n(r[a],e):!1}export{u as i};
import{b2 as i,aO as t,dM as f,aS as n}from"./index-0236195f.js";function u(e,a,r){if(!i(r))return!1;var s=typeof a;return(s=="number"?t(r)&&f(a,r.length):s=="string"&&a in r)?n(r[a],e):!1}export{u as i};

View File

@ -1 +1 @@
import{d as z,p as B,c2 as $,bp as S,o as _,j as w,k as f,c as l,C as d,l as p,t as c,E as s,B as A,U as E,c3 as R,c4 as y,W as x,X as T,a3 as U,a6 as V,n as N}from"./index-ac2041d9.js";import{F as j,s as L}from"./FileItem-b13cf2ec.js";import{u as H,b as O,j as W}from"./index-087e0eb8.js";import"./index-e0feaff2.js";import"./shortcut-7567da19.js";import"./_isIterateeCall-43a7a0bb.js";const q={class:"actions-panel actions"},G={class:"item"},P={key:0,class:"file-list"},Q={class:"hint"},X=z({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(J){const{stackViewEl:b}=H().toRefs(),{itemSize:h,gridItems:D,cellWidth:g}=O(),i=B(),m=W(),{selectdFiles:a}=$(m),r=S(),v=async e=>{const t=R(e);t&&m.addFiles(t.nodes)},C=async()=>{r.pushAction(async()=>{const e=await y.value.post("/zip",{paths:a.value.map(u=>u.fullpath),compress:i.batchDownloadCompress,pack_only:!1},{responseType:"blob"}),t=window.URL.createObjectURL(new Blob([e.data])),o=document.createElement("a");o.href=t,o.setAttribute("download",`iib_${new Date().toLocaleString()}.zip`),document.body.appendChild(o),o.click()})},I=async()=>{r.pushAction(async()=>{await y.value.post("/zip",{paths:a.value.map(e=>e.fullpath),compress:i.batchDownloadCompress,pack_only:!0},{responseType:"blob"}),x.success(T("success"))})},F=e=>{a.value.splice(e,1)};return(e,t)=>{const o=U,u=V;return _(),w("div",{class:"container",ref_key:"stackViewEl",ref:b,onDrop:v},[f("div",q,[l(o,{onClick:t[0]||(t[0]=n=>s(m).selectdFiles=[])},{default:d(()=>[p(c(e.$t("clear")),1)]),_:1}),f("div",G,[p(c(e.$t("compressFile"))+": ",1),l(u,{checked:s(i).batchDownloadCompress,"onUpdate:checked":t[1]||(t[1]=n=>s(i).batchDownloadCompress=n)},null,8,["checked"])]),l(o,{onClick:I,type:"primary",loading:!s(r).isIdle},{default:d(()=>[p(c(e.$t("packOnlyNotDownload")),1)]),_:1},8,["loading"]),l(o,{onClick:C,type:"primary",loading:!s(r).isIdle},{default:d(()=>[p(c(e.$t("zipDownload")),1)]),_:1},8,["loading"])]),s(a).length?(_(),A(s(L),{key:1,ref:"scroller",class:"file-list",items:s(a).slice(),"item-size":s(h).first,"key-field":"fullpath","item-secondary-size":s(h).second,gridItems:s(D)},{default:d(({item:n,index:k})=>[l(j,{idx:k,file:n,"cell-width":s(g),"enable-close-icon":"",onCloseIconClick:K=>F(k),"full-screen-preview-image-url":s(E)(n),"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"])):(_(),w("div",P,[f("p",Q,c(e.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const oe=N(X,[["__scopeId","data-v-a2642a17"]]);export{oe as default};
import{d as z,p as B,c2 as $,bp as S,o as _,j as w,k as f,c as l,C as d,l as p,t as c,E as s,B as A,U as E,c3 as R,c4 as y,W as x,X as T,a3 as U,a6 as V,n as N}from"./index-0236195f.js";import{F as j,s as L}from"./FileItem-0178f9f2.js";import{u as H,b as O,j as W}from"./index-1b3df0c9.js";import"./index-bb784bbb.js";import"./shortcut-feec8cda.js";import"./_isIterateeCall-a5c9e9ee.js";const q={class:"actions-panel actions"},G={class:"item"},P={key:0,class:"file-list"},Q={class:"hint"},X=z({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(J){const{stackViewEl:b}=H().toRefs(),{itemSize:h,gridItems:D,cellWidth:g}=O(),i=B(),m=W(),{selectdFiles:a}=$(m),r=S(),v=async e=>{const t=R(e);t&&m.addFiles(t.nodes)},C=async()=>{r.pushAction(async()=>{const e=await y.value.post("/zip",{paths:a.value.map(u=>u.fullpath),compress:i.batchDownloadCompress,pack_only:!1},{responseType:"blob"}),t=window.URL.createObjectURL(new Blob([e.data])),o=document.createElement("a");o.href=t,o.setAttribute("download",`iib_${new Date().toLocaleString()}.zip`),document.body.appendChild(o),o.click()})},I=async()=>{r.pushAction(async()=>{await y.value.post("/zip",{paths:a.value.map(e=>e.fullpath),compress:i.batchDownloadCompress,pack_only:!0},{responseType:"blob"}),x.success(T("success"))})},F=e=>{a.value.splice(e,1)};return(e,t)=>{const o=U,u=V;return _(),w("div",{class:"container",ref_key:"stackViewEl",ref:b,onDrop:v},[f("div",q,[l(o,{onClick:t[0]||(t[0]=n=>s(m).selectdFiles=[])},{default:d(()=>[p(c(e.$t("clear")),1)]),_:1}),f("div",G,[p(c(e.$t("compressFile"))+": ",1),l(u,{checked:s(i).batchDownloadCompress,"onUpdate:checked":t[1]||(t[1]=n=>s(i).batchDownloadCompress=n)},null,8,["checked"])]),l(o,{onClick:I,type:"primary",loading:!s(r).isIdle},{default:d(()=>[p(c(e.$t("packOnlyNotDownload")),1)]),_:1},8,["loading"]),l(o,{onClick:C,type:"primary",loading:!s(r).isIdle},{default:d(()=>[p(c(e.$t("zipDownload")),1)]),_:1},8,["loading"])]),s(a).length?(_(),A(s(L),{key:1,ref:"scroller",class:"file-list",items:s(a).slice(),"item-size":s(h).first,"key-field":"fullpath","item-secondary-size":s(h).second,gridItems:s(D)},{default:d(({item:n,index:k})=>[l(j,{idx:k,file:n,"cell-width":s(g),"enable-close-icon":"",onCloseIconClick:K=>F(k),"full-screen-preview-image-url":s(E)(n),"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"])):(_(),w("div",P,[f("p",Q,c(e.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const oe=N(X,[["__scopeId","data-v-a2642a17"]]);export{oe 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 +1 @@
import{F as w,s as y}from"./FileItem-b13cf2ec.js";import{u as k,b as x}from"./index-087e0eb8.js";import{d as F,p as b,bm as h,r as C,c5 as D,c6 as I,o as E,j as V,c,C as z,E as e,U as S,c3 as B,c7 as R,n as A}from"./index-ac2041d9.js";import"./index-e0feaff2.js";import"./shortcut-7567da19.js";import"./_isIterateeCall-43a7a0bb.js";const K=F({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,m=b(),{stackViewEl:d}=k().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=x(),g=h(),s=C(o.files??[]),_=async t=>{const l=B(t);o.allowDragAndDrop&&l&&(s.value=R([...s.value,...l.nodes]))},v=t=>{s.value.splice(t,1)};return D(()=>{m.pageFuncExportMap.set(o.paneKey,{getFiles:()=>I(s.value),setFiles:t=>s.value=t})}),(t,l)=>(E(),V("div",{class:"container",ref_key:"stackViewEl",ref:d,onDrop:_},[c(e(y),{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:a,index:r})=>{var n;return[c(w,{idx:r,file:a,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:T=>v(r),"full-screen-preview-image-url":e(S)(a),"extra-tags":(n=a==null?void 0:a.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 M=A(K,[["__scopeId","data-v-f35f4802"]]);export{M as default};
import{F as w,s as y}from"./FileItem-0178f9f2.js";import{u as k,b as x}from"./index-1b3df0c9.js";import{d as F,p as b,bm as h,r as C,c5 as D,c6 as I,o as E,j as V,c,C as z,E as e,U as S,c3 as B,c7 as R,n as A}from"./index-0236195f.js";import"./index-bb784bbb.js";import"./shortcut-feec8cda.js";import"./_isIterateeCall-a5c9e9ee.js";const K=F({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,m=b(),{stackViewEl:d}=k().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=x(),g=h(),s=C(o.files??[]),_=async t=>{const l=B(t);o.allowDragAndDrop&&l&&(s.value=R([...s.value,...l.nodes]))},v=t=>{s.value.splice(t,1)};return D(()=>{m.pageFuncExportMap.set(o.paneKey,{getFiles:()=>I(s.value),setFiles:t=>s.value=t})}),(t,l)=>(E(),V("div",{class:"container",ref_key:"stackViewEl",ref:d,onDrop:_},[c(e(y),{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:a,index:r})=>{var n;return[c(w,{idx:r,file:a,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:T=>v(r),"full-screen-preview-image-url":e(S)(a),"extra-tags":(n=a==null?void 0:a.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 M=A(K,[["__scopeId","data-v-f35f4802"]]);export{M as default};

View File

@ -1 +1 @@
import{aL as F,r as g,bF as P,bG as S,ar as A,aj as R,bp as q,bH as L,bI as j}from"./index-ac2041d9.js";import{u as z,b as H,f as O,c as Q,d as T,e as U,i as W,h as B}from"./index-087e0eb8.js";let K=0;const V=()=>++K,X=(n,i,{dataUpdateStrategy:l="replace"}={})=>{const a=F([""]),c=g(!1),t=g(),o=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=>S(void 0,void 0,void 0,function*(){if(o.value||c.value&&typeof e>"u")return!1;o.value=!0;const s=V();f.value=s;try{let r;if(typeof e=="number"){if(r=a[e],typeof r!="string")return!1}else r=a[a.length-1];const m=yield n(r);if(v.has(s))return v.delete(s),!1;w(i(m));const u=m.cursor;if((e===a.length-1||typeof e!="number")&&(c.value=!u.has_next,u.has_next)){const y=u.next_cursor||u.next;A(typeof y=="string"),a.push(y)}}finally{f.value===s&&(o.value=!1)}return!0}),I=()=>{v.add(f.value),o.value=!1},x=(e=!1)=>S(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&I(),A(!o.value),a.splice(0,a.length,""),o.value=!1,t.value=void 0,c.value=!1,s&&(yield d())}),h=()=>({next:()=>S(void 0,void 0,void 0,function*(){if(o.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return P({abort:I,load:c,next:d,res:t,loading:o,cursorStack:a,reset:x,[Symbol.asyncIterator]:h,iter:{[Symbol.asyncIterator]:h}})},ee=n=>F(X(n,i=>i.files,{dataUpdateStrategy:"merge"})),te=n=>{const i=F(new Set),l=R(()=>(n.res??[]).filter(p=>!i.has(p.fullpath))),a=q(),{stackViewEl:c,multiSelectedIdxs:t,stack:o,scroller:f,props:v}=z({images:l}).toRefs(),{itemSize:w,gridItems:d,cellWidth:I,onScroll:x}=H({fetchNext:()=>n.next()}),{showMenuIdx:h}=O(),{onFileDragStart:e,onFileDragEnd:s}=Q(),{showGenInfo:r,imageGenInfo:m,q:u,onContextMenuClick:y,onFileItemClick:C}=T({openNext:L}),{previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G}=U({loadNext:()=>n.next()}),J=async(p,b,N)=>{o.value=[{curr:"",files:l.value}],await y(p,b,N)};W("removeFiles",async({paths:p})=>{p.forEach(b=>i.add(b))});const k=()=>{j(l.value)};return{images:l,scroller:f,queue:a,iter:n,onContextMenuClickU:J,stackViewEl:c,previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G,itemSize:w,gridItems:d,showGenInfo:r,imageGenInfo:m,q:u,onContextMenuClick:y,onFileItemClick:C,showMenuIdx:h,multiSelectedIdxs:t,onFileDragStart:e,onFileDragEnd:s,cellWidth:I,onScroll:x,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!n.load;)await n.next();k()},props:v,...B()}};export{ee as c,te as u};
import{aL as F,r as g,bF as P,bG as S,ar as A,aj as R,bp as q,bH as L,bI as j}from"./index-0236195f.js";import{u as z,b as H,f as O,c as Q,d as T,e as U,i as W,h as B}from"./index-1b3df0c9.js";let K=0;const V=()=>++K,X=(n,i,{dataUpdateStrategy:l="replace"}={})=>{const a=F([""]),c=g(!1),t=g(),o=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=>S(void 0,void 0,void 0,function*(){if(o.value||c.value&&typeof e>"u")return!1;o.value=!0;const s=V();f.value=s;try{let r;if(typeof e=="number"){if(r=a[e],typeof r!="string")return!1}else r=a[a.length-1];const m=yield n(r);if(v.has(s))return v.delete(s),!1;w(i(m));const u=m.cursor;if((e===a.length-1||typeof e!="number")&&(c.value=!u.has_next,u.has_next)){const y=u.next_cursor||u.next;A(typeof y=="string"),a.push(y)}}finally{f.value===s&&(o.value=!1)}return!0}),I=()=>{v.add(f.value),o.value=!1},x=(e=!1)=>S(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&I(),A(!o.value),a.splice(0,a.length,""),o.value=!1,t.value=void 0,c.value=!1,s&&(yield d())}),h=()=>({next:()=>S(void 0,void 0,void 0,function*(){if(o.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return P({abort:I,load:c,next:d,res:t,loading:o,cursorStack:a,reset:x,[Symbol.asyncIterator]:h,iter:{[Symbol.asyncIterator]:h}})},ee=n=>F(X(n,i=>i.files,{dataUpdateStrategy:"merge"})),te=n=>{const i=F(new Set),l=R(()=>(n.res??[]).filter(p=>!i.has(p.fullpath))),a=q(),{stackViewEl:c,multiSelectedIdxs:t,stack:o,scroller:f,props:v}=z({images:l}).toRefs(),{itemSize:w,gridItems:d,cellWidth:I,onScroll:x}=H({fetchNext:()=>n.next()}),{showMenuIdx:h}=O(),{onFileDragStart:e,onFileDragEnd:s}=Q(),{showGenInfo:r,imageGenInfo:m,q:u,onContextMenuClick:y,onFileItemClick:C}=T({openNext:L}),{previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G}=U({loadNext:()=>n.next()}),J=async(p,b,N)=>{o.value=[{curr:"",files:l.value}],await y(p,b,N)};W("removeFiles",async({paths:p})=>{p.forEach(b=>i.add(b))});const k=()=>{j(l.value)};return{images:l,scroller:f,queue:a,iter:n,onContextMenuClickU:J,stackViewEl:c,previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G,itemSize:w,gridItems:d,showGenInfo:r,imageGenInfo:m,q:u,onContextMenuClick:y,onFileItemClick:C,showMenuIdx:h,multiSelectedIdxs:t,onFileDragStart:e,onFileDragEnd:s,cellWidth:I,onScroll:x,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!n.load;)await n.next();k()},props:v,...B()}};export{ee as c,te as u};

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 x,p as $,an as g,c8 as b,r as w,o as p,j as d,k as a,c as l,C as i,l as u,t as n,F as B,K as I,E as m,as as W,W as _,X as v,a2 as D,a3 as F,c9 as N,n as R}from"./index-ac2041d9.js";const V={class:"container"},E={class:"actions"},K={class:"uni-desc"},L={class:"snapshot"},j=x({__name:"index",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(q){const h=$(),t=g(),f=e=>{h.tabList=W(e.tabs)},k=b(async e=>{await N(`workspace_snapshot_${e.id}`),t.snapshots=t.snapshots.filter(c=>c.id!==e.id),_.success(v("deleteSuccess"))}),o=w(""),C=async()=>{if(!o.value){_.error(v("nameRequired"));return}const e=t.createSnapshot(o.value);await t.addSnapshot(e),_.success(v("saveCompleted"))};return(e,c)=>{const y=D,r=F;return p(),d("div",V,[a("div",E,[l(y,{value:o.value,"onUpdate:value":c[0]||(c[0]=s=>o.value=s),placeholder:e.$t("name"),style:{"max-width":"300px"}},null,8,["value","placeholder"]),l(r,{type:"primary",onClick:C},{default:i(()=>[u(n(e.$t("saveWorkspaceSnapshot")),1)]),_:1})]),a("p",K,n(e.$t("WorkspaceSnapshotDesc")),1),a("ul",L,[(p(!0),d(B,null,I(m(t).snapshots,s=>(p(),d("li",{key:s.id},[a("div",null,[a("span",null,n(s.name),1)]),a("div",null,[l(r,{onClick:S=>f(s)},{default:i(()=>[u(n(e.$t("restore")),1)]),_:2},1032,["onClick"]),l(r,{onClick:S=>m(k)(s)},{default:i(()=>[u(n(e.$t("remove")),1)]),_:2},1032,["onClick"])])]))),128))])])}}});const G=R(j,[["__scopeId","data-v-2c44013c"]]);export{G as default};
import{d as x,p as $,an as g,c8 as b,r as w,o as p,j as d,k as a,c as l,C as i,l as u,t as n,F as B,K as I,E as m,as as W,W as _,X as v,a2 as D,a3 as F,c9 as N,n as R}from"./index-0236195f.js";const V={class:"container"},E={class:"actions"},K={class:"uni-desc"},L={class:"snapshot"},j=x({__name:"index",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(q){const h=$(),t=g(),f=e=>{h.tabList=W(e.tabs)},k=b(async e=>{await N(`workspace_snapshot_${e.id}`),t.snapshots=t.snapshots.filter(c=>c.id!==e.id),_.success(v("deleteSuccess"))}),o=w(""),C=async()=>{if(!o.value){_.error(v("nameRequired"));return}const e=t.createSnapshot(o.value);await t.addSnapshot(e),_.success(v("saveCompleted"))};return(e,c)=>{const y=D,r=F;return p(),d("div",V,[a("div",E,[l(y,{value:o.value,"onUpdate:value":c[0]||(c[0]=s=>o.value=s),placeholder:e.$t("name"),style:{"max-width":"300px"}},null,8,["value","placeholder"]),l(r,{type:"primary",onClick:C},{default:i(()=>[u(n(e.$t("saveWorkspaceSnapshot")),1)]),_:1})]),a("p",K,n(e.$t("WorkspaceSnapshotDesc")),1),a("ul",L,[(p(!0),d(B,null,I(m(t).snapshots,s=>(p(),d("li",{key:s.id},[a("div",null,[a("span",null,n(s.name),1)]),a("div",null,[l(r,{onClick:S=>f(s)},{default:i(()=>[u(n(e.$t("restore")),1)]),_:2},1032,["onClick"]),l(r,{onClick:S=>m(k)(s)},{default:i(()=>[u(n(e.$t("remove")),1)]),_:2},1032,["onClick"])])]))),128))])])}}});const G=R(j,[["__scopeId","data-v-2c44013c"]]);export{G as default};

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
import{d as Y,p as ee,r as F,aC as te,aD as le,v as se,ca as ie,o as v,j as N,c as s,E as e,k as g,C as n,l as k,t as u,G as R,I as oe,H as ae,U as ne,V as A,m as $,B as re,W as w,X as ce,cb as de,a3 as ue,a1 as me,Z as fe,n as pe}from"./index-ac2041d9.js";import{F as ve,s as ge}from"./FileItem-b13cf2ec.js";import{u as ke,g as we,c as he,b as Ce,d as Se,e as _e,o as z}from"./index-087e0eb8.js";import{M as Ie,L as ye,R as be,f as xe}from"./MultiSelectKeep-964aa0b8.js";import"./index-e0feaff2.js";import"./shortcut-7567da19.js";import"./_isIterateeCall-43a7a0bb.js";const Ve={class:"refresh-button"},Me={class:"hint"},Te={key:0,class:"preview-switch"},Fe=Y({__name:"randomImage",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(Ne){const B=ee(),m=F(!1),l=F([]),r=l,h=te(`${le}randomImageSettingNotificationShown`,!1),P=()=>{h.value||(w.info({content:ce("randomImageSettingNotification"),duration:6,key:"randomImageSetting"}),h.value=!0)},f=async()=>{try{m.value=!0;const i=await de();i.length===0&&w.warn("No data, please generate index in image search page first"),l.value=i}finally{m.value=!1,_()}},C=()=>{if(l.value.length===0){w.warn("没有图片可以浏览");return}z(l.value,a.value||0)};se(()=>{f(),setTimeout(()=>{P()},2e3)});const{stackViewEl:D,multiSelectedIdxs:p,stack:E,scroller:G}=ke({images:l}).toRefs(),{onClearAllSelected:U,onSelectAll:K,onReverseSelect:L}=we();he();const{itemSize:S,gridItems:O,cellWidth:W,onScroll:_}=Ce(),{showGenInfo:c,imageGenInfo:I,q:H,onContextMenuClick:j,onFileItemClick:q}=Se({openNext:ie}),{previewIdx:a,previewing:y,onPreviewVisibleChange:Q,previewImgMove:b,canPreview:x}=_e(),V=async(i,t,d)=>{E.value=[{curr:"",files:l.value}],await j(i,t,d)};return(i,t)=>{var M;const d=ue,X=me,Z=fe;return v(),N("div",{class:"container",ref_key:"stackViewEl",ref:D},[s(Ie,{show:!!e(p).length||e(B).keepMultiSelect,onClearAllSelected:e(U),onSelectAll:e(K),onReverseSelect:e(L)},null,8,["show","onClearAllSelected","onSelectAll","onReverseSelect"]),g("div",Ve,[s(d,{onClick:f,onTouchstart:R(f,["prevent"]),type:"primary",loading:m.value,shape:"round"},{default:n(()=>[k(u(i.$t("shuffle")),1)]),_:1},8,["onTouchstart","loading"]),s(d,{onClick:C,onTouchstart:R(C,["prevent"]),type:"default",disabled:!((M=l.value)!=null&&M.length),shape:"round"},{default:n(()=>[k(u(i.$t("tiktokView")),1)]),_:1},8,["onTouchstart","disabled"])]),s(Z,{visible:e(c),"onUpdate:visible":t[1]||(t[1]=o=>ae(c)?c.value=o:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=o=>c.value=!1)},{cancelText:n(()=>[]),default:n(()=>[s(X,{active:"",loading:!e(H).isIdle},{default:n(()=>[g("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[0]||(t[0]=o=>e(oe)(e(I)))},[g("div",Me,u(i.$t("doubleClickToCopy")),1),k(" "+u(e(I)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),s(e(ge),{ref_key:"scroller",ref:G,class:"file-list",items:l.value.slice(),"item-size":e(S).first,"key-field":"fullpath","item-secondary-size":e(S).second,gridItems:e(O),onScroll:e(_)},{default:n(({item:o,index:T})=>[s(ve,{idx:T,file:o,"cell-width":e(W),"full-screen-preview-image-url":e(r)[e(a)]?e(ne)(e(r)[e(a)]):"",onContextMenuClick:V,onPreviewVisibleChange:e(Q),"is-selected-mutil-files":e(p).length>1,selected:e(p).includes(T),onFileItemClick:e(q),onTiktokView:(Re,J)=>e(z)(l.value,J)},null,8,["idx","file","cell-width","full-screen-preview-image-url","onPreviewVisibleChange","is-selected-mutil-files","selected","onFileItemClick","onTiktokView"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"]),e(y)?(v(),N("div",Te,[s(e(ye),{onClick:t[3]||(t[3]=o=>e(b)("prev")),class:A({disable:!e(x)("prev")})},null,8,["class"]),s(e(be),{onClick:t[4]||(t[4]=o=>e(b)("next")),class:A({disable:!e(x)("next")})},null,8,["class"])])):$("",!0),e(y)&&e(r)&&e(r)[e(a)]?(v(),re(xe,{key:1,file:e(r)[e(a)],idx:e(a),onContextMenuClick:V},null,8,["file","idx"])):$("",!0)],512)}}});const Ge=pe(Fe,[["__scopeId","data-v-49082269"]]);export{Ge as default};
import{d as Y,p as ee,r as F,aC as te,aD as le,v as se,ca as ie,o as v,j as N,c as s,E as e,k as g,C as n,l as k,t as u,G as R,I as oe,H as ae,U as ne,V as A,m as $,B as re,W as w,X as ce,cb as de,a3 as ue,a1 as me,Z as fe,n as pe}from"./index-0236195f.js";import{F as ve,s as ge}from"./FileItem-0178f9f2.js";import{u as ke,g as we,c as he,b as Ce,d as Se,e as _e,o as z}from"./index-1b3df0c9.js";import{M as Ie,L as ye,R as be,f as xe}from"./MultiSelectKeep-beba09aa.js";import"./index-bb784bbb.js";import"./shortcut-feec8cda.js";import"./_isIterateeCall-a5c9e9ee.js";const Ve={class:"refresh-button"},Me={class:"hint"},Te={key:0,class:"preview-switch"},Fe=Y({__name:"randomImage",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(Ne){const B=ee(),m=F(!1),l=F([]),r=l,h=te(`${le}randomImageSettingNotificationShown`,!1),P=()=>{h.value||(w.info({content:ce("randomImageSettingNotification"),duration:6,key:"randomImageSetting"}),h.value=!0)},f=async()=>{try{m.value=!0;const i=await de();i.length===0&&w.warn("No data, please generate index in image search page first"),l.value=i}finally{m.value=!1,_()}},C=()=>{if(l.value.length===0){w.warn("没有图片可以浏览");return}z(l.value,a.value||0)};se(()=>{f(),setTimeout(()=>{P()},2e3)});const{stackViewEl:D,multiSelectedIdxs:p,stack:E,scroller:G}=ke({images:l}).toRefs(),{onClearAllSelected:U,onSelectAll:K,onReverseSelect:L}=we();he();const{itemSize:S,gridItems:O,cellWidth:W,onScroll:_}=Ce(),{showGenInfo:c,imageGenInfo:I,q:H,onContextMenuClick:j,onFileItemClick:q}=Se({openNext:ie}),{previewIdx:a,previewing:y,onPreviewVisibleChange:Q,previewImgMove:b,canPreview:x}=_e(),V=async(i,t,d)=>{E.value=[{curr:"",files:l.value}],await j(i,t,d)};return(i,t)=>{var M;const d=ue,X=me,Z=fe;return v(),N("div",{class:"container",ref_key:"stackViewEl",ref:D},[s(Ie,{show:!!e(p).length||e(B).keepMultiSelect,onClearAllSelected:e(U),onSelectAll:e(K),onReverseSelect:e(L)},null,8,["show","onClearAllSelected","onSelectAll","onReverseSelect"]),g("div",Ve,[s(d,{onClick:f,onTouchstart:R(f,["prevent"]),type:"primary",loading:m.value,shape:"round"},{default:n(()=>[k(u(i.$t("shuffle")),1)]),_:1},8,["onTouchstart","loading"]),s(d,{onClick:C,onTouchstart:R(C,["prevent"]),type:"default",disabled:!((M=l.value)!=null&&M.length),shape:"round"},{default:n(()=>[k(u(i.$t("tiktokView")),1)]),_:1},8,["onTouchstart","disabled"])]),s(Z,{visible:e(c),"onUpdate:visible":t[1]||(t[1]=o=>ae(c)?c.value=o:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=o=>c.value=!1)},{cancelText:n(()=>[]),default:n(()=>[s(X,{active:"",loading:!e(H).isIdle},{default:n(()=>[g("div",{style:{width:"100%","word-break":"break-all","white-space":"pre-line","max-height":"70vh",overflow:"auto"},onDblclick:t[0]||(t[0]=o=>e(oe)(e(I)))},[g("div",Me,u(i.$t("doubleClickToCopy")),1),k(" "+u(e(I)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),s(e(ge),{ref_key:"scroller",ref:G,class:"file-list",items:l.value.slice(),"item-size":e(S).first,"key-field":"fullpath","item-secondary-size":e(S).second,gridItems:e(O),onScroll:e(_)},{default:n(({item:o,index:T})=>[s(ve,{idx:T,file:o,"cell-width":e(W),"full-screen-preview-image-url":e(r)[e(a)]?e(ne)(e(r)[e(a)]):"",onContextMenuClick:V,onPreviewVisibleChange:e(Q),"is-selected-mutil-files":e(p).length>1,selected:e(p).includes(T),onFileItemClick:e(q),onTiktokView:(Re,J)=>e(z)(l.value,J)},null,8,["idx","file","cell-width","full-screen-preview-image-url","onPreviewVisibleChange","is-selected-mutil-files","selected","onFileItemClick","onTiktokView"])]),_:1},8,["items","item-size","item-secondary-size","gridItems","onScroll"]),e(y)?(v(),N("div",Te,[s(e(ye),{onClick:t[3]||(t[3]=o=>e(b)("prev")),class:A({disable:!e(x)("prev")})},null,8,["class"]),s(e(be),{onClick:t[4]||(t[4]=o=>e(b)("next")),class:A({disable:!e(x)("next")})},null,8,["class"])])):$("",!0),e(y)&&e(r)&&e(r)[e(a)]?(v(),re(xe,{key:1,file:e(r)[e(a)],idx:e(a),onContextMenuClick:V},null,8,["file","idx"])):$("",!0)],512)}}});const Ge=pe(Fe,[["__scopeId","data-v-49082269"]]);export{Ge as default};

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-ac2041d9.js"></script>
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-0236195f.js"></script>
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-882e7f3d.css">
</head>

View File

@ -0,0 +1,255 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { toRawFileUrl } from '@/util/file'
import type { FileNodeInfo } from '@/api/files'
import { DragOutlined } from '@/icon'
interface Props {
file: FileNodeInfo
title?: string
size?: string
}
const props = withDefaults(defineProps<Props>(), {
title: 'Drag to transfer image'
})
const imageUrl = computed(() => {
if (!props.file) return ''
return toRawFileUrl(props.file)
})
const showImage = ref(false)
function toggleImage() {
showImage.value = !showImage.value
}
const closeImage = () => {
showImage.value=false
}
</script>
<template>
<div class="draggable-image-wrapper"
@mouseleave="closeImage">
<div class="trigger-container" :title="title" @click="toggleImage" >
<slot class="trigger-slot">
<div class="default-trigger">
<DragOutlined class="trigger-icon" />
<span class="trigger-text">{{ $t('dragImageToTransfer') }}</span>
</div>
</slot>
<img
v-if="showImage"
:src="imageUrl"
:alt="file.name"
draggable="true"
class="hover-image"
:style="{ width: size||'256px', height: size || '256px' }"
@mouseleave="closeImage"
@error="(e) => (e.target as HTMLImageElement).style.display = 'none'"
@click.stop
/>
</div>
</div>
</template>
<style scoped lang="scss">
.draggable-image-wrapper {
padding: 4px 0;
margin-top: 8px;
display: flex;
cursor: pointer;
justify-content: center;
align-items: center;
.trigger-container {
display: inline-flex;
align-items: center;
position: relative;
user-select: none;
:deep(.trigger-slot) {
display: inline-flex;
align-items: center;
cursor: pointer;
transition: all 0.3s ease;
}
&:active :deep(.trigger-slot) {
transform: scale(0.95);
}
:deep(.custom-drag-trigger) {
display: inline-flex;
align-items: center;
gap: 10px;
padding: 6px 24px;
border-radius: 8px;
background: var(--zp-primary-background);
color: var(--zp-primary);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
//
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: 8px;
padding: 2px;
background: linear-gradient(
135deg,
#ff6b6b 0%,
#feca57 16.67%,
#48dbfb 33.33%,
#ff9ff3 50%,
#54a0ff 66.67%,
#5f27cd 83.33%,
#ff6b6b 100%
);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0.9;
}
&:hover {
background: linear-gradient(
135deg,
rgba(255, 107, 107, 0.1),
rgba(72, 219, 251, 0.1)
);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
transform: translateY(-1px);
}
&:active {
transform: translateY(0);
}
.trigger-icon {
font-size: 18px;
transition: transform 0.3s ease;
position: relative;
z-index: 1;
}
.trigger-text {
font-size: 14px;
font-weight: 500;
white-space: nowrap;
position: relative;
z-index: 1;
letter-spacing: 0.5px;
}
&:hover .trigger-icon {
transform: scale(1.1) rotate(5deg);
}
}
.default-trigger {
display: inline-flex;
align-items: center;
gap: 10px;
padding: 6px 24px;
border-radius: 8px;
background: var(--zp-primary-background);
color: var(--zp-primary);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
//
&::before {
content: '';
position: absolute;
inset: 0;
border-radius: 8px;
padding: 2px;
background: linear-gradient(
135deg,
#ff6b6b 0%,
#feca57 16.67%,
#48dbfb 33.33%,
#ff9ff3 50%,
#54a0ff 66.67%,
#5f27cd 83.33%,
#ff6b6b 100%
);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0.9;
}
&:hover {
background: linear-gradient(
135deg,
rgba(255, 107, 107, 0.1),
rgba(72, 219, 251, 0.1)
);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
transform: translateY(-1px);
}
&:active {
transform: translateY(0);
}
.trigger-icon {
font-size: 18px;
transition: transform 0.3s ease;
position: relative;
z-index: 1;
}
.trigger-text {
font-size: 14px;
font-weight: 500;
white-space: nowrap;
position: relative;
z-index: 1;
letter-spacing: 0.5px;
}
&:hover .trigger-icon {
transform: scale(1.1) rotate(5deg);
}
}
.hover-image {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(1);
object-fit: contain;
border-radius: 8px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
background: var(--zp-primary-background);
opacity: 1;
pointer-events: auto;
animation: scaleIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 10000;
cursor: grab;
@keyframes scaleIn {
from {
transform: translate(-50%, -50%) scale(0.8);
opacity: 0;
}
to {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
}
&:active {
cursor: grabbing;
}
}
}
}
</style>

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import { FileOutlined, FolderOpenOutlined, EllipsisOutlined, HeartOutlined, HeartFilled } from '@/icon'
import { FileOutlined, FolderOpenOutlined, EllipsisOutlined, HeartOutlined, HeartFilled, DragOutlined } from '@/icon'
import { useGlobalStore } from '@/store/useGlobalStore'
import { fallbackImage, ok } from 'vue3-ts-util'
import type { FileNodeInfo } from '@/api/files'
@ -9,6 +9,7 @@ import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'
import { computed, ref, nextTick, watch } from 'vue'
import ContextMenu from './ContextMenu.vue'
import ChangeIndicator from './ChangeIndicator.vue'
import DraggableImage from './DraggableImage.vue'
import { useTagStore } from '@/store/useTagStore'
import { CloseCircleOutlined, StarFilled, StarOutlined } from '@/icon'
import { Tag } from '@/api/db'
@ -282,6 +283,11 @@ const handleAudioClick = () => {
</a-menu>
</template>
</a-dropdown>
<DraggableImage size="192px" v-if="file.type === 'file' && isImageFile(file.fullpath)" :file="file">
<div class="float-btn-wrap">
<DragOutlined />
</div>
</DraggableImage>
</div>
<!-- :key="fullScreenPreviewImageUrl ? undefined : file.fullpath"
这么复杂是因为再全屏查看时可能因为直接删除导致fullpath变化然后整个预览直接退出-->

View File

@ -353,5 +353,8 @@ export const de: Partial<IIBI18nMap> = {
jsonValuePlaceholder: 'JSON-Wert',
stringValuePlaceholder: 'Zeichenfolgenwert',
clearBeforeSwitchToJson: 'Bitte aktuellen Wert leeren vor dem Wechsel zu JSON-Modus',
clearBeforeSwitchToString: 'Bitte aktuellen Wert leeren vor dem Wechsel zu Zeichenfolgen-Modus'
clearBeforeSwitchToString: 'Bitte aktuellen Wert leeren vor dem Wechsel zu Zeichenfolgen-Modus',
dragImageToTransfer: 'Klicken Sie, um das Originalbild zu erhalten, greifen und ziehen Sie es zu anderen Apps',
dragImage: 'Klicken Sie, um das Originalbild zu erhalten, greifen und ziehen Sie es zu anderen Apps',
close: 'Schließen'
}

View File

@ -613,5 +613,7 @@ You can specify which snapshot to restore to when starting IIB in the global set
jsonValuePlaceholder: 'JSON Value',
stringValuePlaceholder: 'String Value',
clearBeforeSwitchToJson: 'Please clear current value before switching to JSON mode',
clearBeforeSwitchToString: 'Please clear current value before switching to string mode'
clearBeforeSwitchToString: 'Please clear current value before switching to string mode',
dragImageToTransfer: 'Click to get original image, grab and drag to other apps',
dragImage: 'Click to get original image, grab and drag to other apps'
}

View File

@ -591,5 +591,7 @@ export const zhHans = {
jsonValuePlaceholder: 'JSON Value',
stringValuePlaceholder: '字符串值',
clearBeforeSwitchToJson: '切换到 JSON 模式前请先清空当前值',
clearBeforeSwitchToString: '切换到字符串模式前请先清空当前值'
clearBeforeSwitchToString: '切换到字符串模式前请先清空当前值',
dragImageToTransfer: '点击获取原图,抓取拖拽至其他应用',
dragImage: '点击获取原图,抓取拖拽至其他应用'
}

View File

@ -593,5 +593,7 @@ export const zhHant: Partial<IIBI18nMap> = {
jsonValuePlaceholder: 'JSON Value',
stringValuePlaceholder: '字符串值',
clearBeforeSwitchToJson: '切換到 JSON 模式前請先清空當前值',
clearBeforeSwitchToString: '切換到字符串模式前請先清空當前值'
clearBeforeSwitchToString: '切換到字符串模式前請先清空當前值',
dragImageToTransfer: '點擊獲取原圖,抓取拖拽至其他應用',
dragImage: '點擊獲取原圖,抓取拖拽至其他應用'
}

View File

@ -2,6 +2,7 @@
import { getImageGenerationInfo, getImageExif } from '@/api'
import type { FileNodeInfo } from '@/api/files'
import ExifBrowser from '@/components/ExifBrowser.vue'
import DraggableImage from '@/components/DraggableImage.vue'
import { useGlobalStore } from '@/store/useGlobalStore'
import { useLocalStorage } from '@vueuse/core'
import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'
@ -184,7 +185,7 @@ function getParNode (p: any) {
}
function getTextLength(text: string): number {
// 3
// chinese characters are counted as 3 English letters
let length = 0
for (const char of text) {
if (/[\u4e00-\u9fa5]/.test(char)) {
@ -455,6 +456,7 @@ const editPromptAndReload = async () => {
<div v-if="lr">
</div>
<div class="container">
<div class="action-bar">
<div v-if="!lr" ref="dragHandle" class="icon" style="cursor: grab" :title="t('dragToMovePanel')">
@ -549,6 +551,7 @@ const editPromptAndReload = async () => {
</div>
</div>
<div class="gen-info" v-if="showFullContent">
<div class="info-tags">
<span class="info-tag">
<span class="name">
@ -617,6 +620,14 @@ const editPromptAndReload = async () => {
</a-tooltip>
</template>
</div>
<!-- 可拖拽的原图 -->
<DraggableImage :file="file">
<div class="custom-drag-trigger">
<DragOutlined class="trigger-icon" />
<span class="trigger-text">{{ $t('dragImageToTransfer') }}</span>
</div>
</DraggableImage>
<a-tabs v-model:activeKey="promptTabActivedKey">
<a-tab-pane key="structedData" :tab="$t('structuredData')">
<div>