feat: 优化query搜索并加入tag图(去掉max抽象层与d3依赖)
parent
67cbda36d1
commit
59bef3915e
|
|
@ -1,252 +0,0 @@
|
|||
# Tag Relationship Graph 功能说明
|
||||
|
||||
## 功能概述
|
||||
|
||||
Tag 关系图是基于聚类结果的 keywords 构建的交互式可视化系统,帮助用户更直观地探索和索引图像数据集。
|
||||
|
||||
## 核心特性
|
||||
|
||||
### 1. 节点类型
|
||||
|
||||
- **Tag 节点**(圆形)
|
||||
- 大小:正比于权重(出现频率 × 图片数量)
|
||||
- 颜色:根据类别区分
|
||||
- 蓝色:人物 (character)
|
||||
- 绿色:风格 (style)
|
||||
- 黄色:场景 (scene)
|
||||
- 红色:物体 (object)
|
||||
- 紫色:其他 (other)
|
||||
- 社区着色:启用社区检测后,同社区的节点使用相同颜色
|
||||
|
||||
- **Cluster 节点**(圆形,cyan 色)
|
||||
- 大小:正比于簇内图片数量
|
||||
- 标签:簇的标题
|
||||
|
||||
### 2. 边(连线)
|
||||
|
||||
- **Tag-Tag 连线**
|
||||
- 粗细:正比于共现权重(两个 tag 同时出现在簇中的图片数)
|
||||
- 透明度:0.4(降低视觉干扰)
|
||||
|
||||
- **Cluster-Tag 连线**
|
||||
- 连接簇节点与其包含的 tag
|
||||
- 便于查看簇的组成
|
||||
|
||||
### 3. 权重计算
|
||||
|
||||
使用混合权重模式(alpha=0.3):
|
||||
|
||||
```python
|
||||
weight = 0.3 × 频次权重 + 0.7 × TF-IDF 权重
|
||||
|
||||
频次权重 = Σ(所在聚类的图片数)
|
||||
TF-IDF 权重 = 频次权重 × log(总聚类数 / 包含该tag的聚类数)
|
||||
```
|
||||
|
||||
**效果**:
|
||||
- 突出特征性 tag(如 "Warhammer 40K"、"赛博朋克")
|
||||
- 压制通用 tag(如 "女孩"、"风景")
|
||||
|
||||
### 4. 社区检测
|
||||
|
||||
使用 Louvain 算法自动发现 tag 社区:
|
||||
- 相关的 tag 自动聚成一组
|
||||
- 每个社区用不同颜色区分
|
||||
- 示例:
|
||||
- 社区1:赛博朋克、机甲、霓虹、未来
|
||||
- 社区2:森林、精灵、魔法、奇幻
|
||||
- 社区3:女孩、制服、校园、青春
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 1. 切换到 Tag Graph 视图
|
||||
|
||||
1. 在 Topic Search 页面
|
||||
2. 点击右上角的 Switch 切换按钮
|
||||
3. 选择 "Tag Graph"
|
||||
|
||||
### 2. 参数调整
|
||||
|
||||
- **Top Tags**: 显示前 N 个权重最高的 tag(默认 50)
|
||||
- **Top Clusters**: 显示前 N 个簇节点(默认 20)
|
||||
- **Show Clusters**: 是否显示簇节点(勾选/取消)
|
||||
|
||||
### 3. 交互操作
|
||||
|
||||
#### 基本交互
|
||||
- **拖拽**:拖动节点调整布局
|
||||
- **缩放**:鼠标滚轮缩放视图
|
||||
- **平移**:按住 Shift + 拖拽平移视图
|
||||
|
||||
#### 节点操作
|
||||
- **悬停**:显示详细信息(类别、图片数、聚类数、社区)
|
||||
- **点击**:在右侧面板显示详细信息
|
||||
- **搜索**:点击 "Search Images" 按钮,自动搜索该 tag 的图片
|
||||
|
||||
#### 工具栏
|
||||
- **Refresh**: 重新加载图数据
|
||||
- **Fit View**: 自动调整视图以显示所有节点
|
||||
|
||||
### 4. 典型使用场景
|
||||
|
||||
#### 场景1:探索式浏览
|
||||
|
||||
```
|
||||
问题:不知道数据集里有什么主题
|
||||
|
||||
操作:
|
||||
1. 打开 Tag Graph
|
||||
2. 观察大节点(核心主题)
|
||||
3. 点击感兴趣的 tag
|
||||
4. 点击 "Search Images" 查看图片
|
||||
```
|
||||
|
||||
#### 场景2:精准索引
|
||||
|
||||
```
|
||||
需求:找所有包含"机甲"和"战斗"的图片
|
||||
|
||||
操作:
|
||||
1. 在图中找到"机甲"节点
|
||||
2. 观察相连的节点
|
||||
3. 如果有"战斗"节点且相连,说明有共现
|
||||
4. 分别搜索两个 tag 的交集
|
||||
```
|
||||
|
||||
#### 场景3:主题发现
|
||||
|
||||
```
|
||||
发现:原来数据集有强烈的 Warhammer 40K 主题
|
||||
|
||||
可视化效果:
|
||||
- "Warhammer 40K" 节点很大(高 TF-IDF)
|
||||
- 周围连接 "星际战士"、"帝国"、"混沌"
|
||||
- 形成明显的社区簇(同色区域)
|
||||
```
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 后端 API
|
||||
|
||||
```python
|
||||
POST /infinite_image_browsing/db/cluster_tag_graph
|
||||
|
||||
Request:
|
||||
{
|
||||
"folder_paths": [...],
|
||||
"top_n_tags": 50,
|
||||
"top_n_clusters": 20,
|
||||
"show_clusters": true,
|
||||
"detect_communities": true,
|
||||
"weight_mode": "hybrid",
|
||||
"alpha": 0.3
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "tag_机甲",
|
||||
"label": "机甲",
|
||||
"weight": 629.5,
|
||||
"image_count": 224,
|
||||
"cluster_count": 3,
|
||||
"category": "object",
|
||||
"community": 0
|
||||
},
|
||||
...
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"source": "tag_机甲",
|
||||
"target": "tag_科幻",
|
||||
"weight": 192,
|
||||
"image_count": 192,
|
||||
"cluster_count": 2
|
||||
},
|
||||
...
|
||||
],
|
||||
"communities": [
|
||||
{
|
||||
"id": 0,
|
||||
"nodes": ["tag_机甲", "tag_科幻", ...],
|
||||
"size": 5
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 前端组件
|
||||
|
||||
- 基于 **ECharts Graph** 实现
|
||||
- 力导向布局(Force-Directed Layout)
|
||||
- 支持 roam(缩放/平移/拖拽)
|
||||
|
||||
### 依赖
|
||||
|
||||
**后端**(可选):
|
||||
```bash
|
||||
pip install networkx
|
||||
```
|
||||
|
||||
如果没有 networkx,社区检测功能会被禁用,但其他功能正常工作。
|
||||
|
||||
**前端**:
|
||||
- echarts(已包含在项目中)
|
||||
|
||||
## 性能优化
|
||||
|
||||
- **Top-N 截断**:只显示权重最高的节点,避免视觉混乱
|
||||
- **边权重过滤**:低权重的边不显示
|
||||
- **标签隐藏**:只有大节点显示标签(labelLayout.hideOverlap)
|
||||
- **力学参数**:调整斥力/引力平衡,避免节点重叠
|
||||
|
||||
## 后续优化方向
|
||||
|
||||
1. **增量更新**:新增图片时只更新受影响的节点
|
||||
2. **多层级钻取**:点击 tag 展开为更细粒度的子 tag
|
||||
3. **热力图叠加**:显示 tag 的热度分布
|
||||
4. **时序动画**:展示 tag 关系随时间的演变
|
||||
5. **导出功能**:导出为 PNG/SVG/JSON
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: 为什么有些常见词(如"女孩")节点不大?
|
||||
|
||||
A: 因为使用了 TF-IDF 权重,压制了过于常见的 tag。如果想突出频次,可以修改 alpha 参数(增大到 0.8-1.0)。
|
||||
|
||||
### Q2: 为什么有些 tag 之间没有连线?
|
||||
|
||||
A: 只有在同一个簇中同时出现的 tag 才会有连线。如果两个 tag 从未共现,则不会连接。
|
||||
|
||||
### Q3: 社区检测有什么用?
|
||||
|
||||
A: 自动发现主题群组,用颜色区分。例如"赛博朋克相关"、"奇幻相关"、"校园相关"会自动分组。
|
||||
|
||||
### Q4: 如何调整图的疏密度?
|
||||
|
||||
A: 修改 ECharts 的 force 参数:
|
||||
- `repulsion`: 增大 = 节点更分散
|
||||
- `edgeLength`: 增大 = 边更长
|
||||
- `gravity`: 增大 = 更聚拢到中心
|
||||
|
||||
### Q5: 为什么点击 Search Images 没反应?
|
||||
|
||||
A: 需要先运行一次聚类(Refresh 按钮),确保有聚类结果。
|
||||
|
||||
## 贡献
|
||||
|
||||
欢迎提交 PR 改进此功能!
|
||||
|
||||
重点优化方向:
|
||||
- 更好的布局算法
|
||||
- 更丰富的交互方式
|
||||
- 更精准的权重计算
|
||||
- 性能优化(处理 100+ tag)
|
||||
|
||||
---
|
||||
|
||||
**开发者**: Claude Code
|
||||
**版本**: 1.0.0
|
||||
**更新日期**: 2026-01-09
|
||||
|
|
@ -13,8 +13,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-632e7cf6.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-d385cc4f.css">
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-d6594e8e.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-af514ea9.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -1264,6 +1264,8 @@ def infinite_image_browsing_api(app: FastAPI, **kwargs):
|
|||
verify_secret=verify_secret,
|
||||
embedding_model=EMBEDDING_MODEL,
|
||||
ai_model=AI_MODEL,
|
||||
openai_base_url=OPENAI_BASE_URL,
|
||||
openai_api_key=OPENAI_API_KEY,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ class DataBase:
|
|||
# 创建连接并打开数据库
|
||||
conn = connect(clz.get_db_file_path())
|
||||
|
||||
# # 禁用 WAL 模式,使用传统的 DELETE 日志模式
|
||||
# conn.execute("PRAGMA journal_mode=DELETE")
|
||||
|
||||
def regexp(expr, item):
|
||||
if not isinstance(item, str):
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -1,64 +1,50 @@
|
|||
"""
|
||||
Tag relationship graph generation for topic clusters.
|
||||
Builds a weighted graph showing connections between tags from cluster keywords.
|
||||
Hierarchical tag graph generation for topic clusters.
|
||||
Builds a multi-layer neural-network-style visualization with LLM-driven abstraction.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
from typing import Dict, List, Optional, Set, Tuple
|
||||
from typing import Dict, List, Optional
|
||||
from pydantic import BaseModel
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
|
||||
from scripts.iib.db.datamodel import DataBase, TopicClusterCache
|
||||
from scripts.iib.db.datamodel import DataBase, GlobalSetting
|
||||
from scripts.iib.tool import normalize_output_lang
|
||||
|
||||
# Cache version for tag abstraction - increment to invalidate all caches
|
||||
TAG_ABSTRACTION_CACHE_VERSION = 2
|
||||
|
||||
|
||||
class TagGraphReq(BaseModel):
|
||||
folder_paths: List[str]
|
||||
model: Optional[str] = None
|
||||
threshold: Optional[float] = 0.90
|
||||
min_cluster_size: Optional[int] = 2
|
||||
lang: Optional[str] = None
|
||||
# Graph parameters
|
||||
top_n_tags: Optional[int] = 50
|
||||
top_n_clusters: Optional[int] = 20
|
||||
weight_mode: Optional[str] = "hybrid" # frequency / tfidf / hybrid
|
||||
alpha: Optional[float] = 0.3 # for hybrid mode
|
||||
show_clusters: Optional[bool] = True
|
||||
detect_communities: Optional[bool] = True
|
||||
lang: Optional[str] = "en" # Language for LLM output
|
||||
|
||||
|
||||
class TagNode(BaseModel):
|
||||
class LayerNode(BaseModel):
|
||||
id: str
|
||||
label: str
|
||||
weight: float
|
||||
image_count: int
|
||||
cluster_count: int
|
||||
category: str
|
||||
community: Optional[int] = None
|
||||
size: float # Weight/importance of this node
|
||||
metadata: Optional[dict] = None
|
||||
|
||||
|
||||
class ClusterNode(BaseModel):
|
||||
id: str
|
||||
label: str
|
||||
weight: float
|
||||
size: int
|
||||
category: str = "cluster"
|
||||
community: Optional[int] = None
|
||||
class GraphLayer(BaseModel):
|
||||
level: int
|
||||
name: str # Layer name: "Clusters", "Tags", "Abstract-1", "Abstract-2"
|
||||
nodes: List[LayerNode]
|
||||
|
||||
|
||||
class GraphLink(BaseModel):
|
||||
source: str
|
||||
target: str
|
||||
weight: float
|
||||
image_count: Optional[int] = None
|
||||
cluster_count: Optional[int] = None
|
||||
|
||||
|
||||
class TagGraphResp(BaseModel):
|
||||
nodes: List[dict] # TagNode or ClusterNode
|
||||
layers: List[GraphLayer]
|
||||
links: List[GraphLink]
|
||||
communities: Optional[List[dict]] = None
|
||||
stats: dict
|
||||
|
||||
|
||||
|
|
@ -68,115 +54,180 @@ def mount_tag_graph_routes(
|
|||
verify_secret,
|
||||
embedding_model: str,
|
||||
ai_model: str,
|
||||
openai_base_url: str,
|
||||
openai_api_key: str,
|
||||
):
|
||||
"""Mount tag relationship graph endpoints"""
|
||||
"""Mount hierarchical tag graph endpoints"""
|
||||
|
||||
def _get_cluster_cache_key(req: TagGraphReq, model: str) -> str:
|
||||
"""Compute cache key for cluster result lookup"""
|
||||
from scripts.iib.topic_cluster import _PROMPT_NORMALIZE_VERSION, _PROMPT_NORMALIZE_MODE
|
||||
async def _call_llm_for_abstraction(
|
||||
tags: List[str],
|
||||
lang: str,
|
||||
model: str,
|
||||
base_url: str,
|
||||
api_key: str
|
||||
) -> dict:
|
||||
"""
|
||||
Call LLM to create hierarchical abstraction of tags.
|
||||
Returns a dict with layers and groupings.
|
||||
"""
|
||||
import asyncio
|
||||
import requests
|
||||
import re
|
||||
|
||||
cache_params = {
|
||||
"model": model,
|
||||
"threshold": float(req.threshold or 0.90),
|
||||
"min_cluster_size": int(req.min_cluster_size or 2),
|
||||
"assign_noise_threshold": None,
|
||||
"title_model": None,
|
||||
"lang": str(req.lang or ""),
|
||||
"nv": _PROMPT_NORMALIZE_VERSION,
|
||||
"nm": _PROMPT_NORMALIZE_MODE,
|
||||
}
|
||||
h = hashlib.sha1()
|
||||
h.update(
|
||||
json.dumps(
|
||||
{"folders": sorted(req.folder_paths), "params": cache_params},
|
||||
ensure_ascii=False,
|
||||
sort_keys=True,
|
||||
).encode("utf-8")
|
||||
)
|
||||
return h.hexdigest()
|
||||
def _normalize_base_url(url: str) -> str:
|
||||
url = url.strip()
|
||||
if not url.startswith(("http://", "https://")):
|
||||
url = f"https://{url}"
|
||||
return url.rstrip("/")
|
||||
|
||||
def _infer_tag_category(tag: str) -> str:
|
||||
"""Infer tag category from content"""
|
||||
tag_lower = tag.lower()
|
||||
def _call_sync():
|
||||
if not api_key:
|
||||
raise HTTPException(500, "OpenAI API Key not configured")
|
||||
|
||||
# Character
|
||||
char_keywords = [
|
||||
"girl", "boy", "woman", "man", "character", "person",
|
||||
"女孩", "男孩", "女性", "男性", "人物", "角色", "战士", "精灵"
|
||||
]
|
||||
if any(k in tag_lower for k in char_keywords):
|
||||
return "character"
|
||||
url = f"{_normalize_base_url(base_url)}/chat/completions"
|
||||
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
|
||||
|
||||
# Style
|
||||
style_keywords = [
|
||||
"style", "punk", "sci-fi", "fantasy", "realistic", "anime",
|
||||
"风格", "朋克", "科幻", "奇幻", "写实", "动漫", "赛博"
|
||||
]
|
||||
if any(k in tag_lower for k in style_keywords):
|
||||
return "style"
|
||||
# Normalize language for consistent LLM output
|
||||
normalized_lang = normalize_output_lang(lang)
|
||||
sys_prompt = f"""You are a tag categorization assistant. Organize tags into hierarchical categories.
|
||||
|
||||
# Scene
|
||||
scene_keywords = [
|
||||
"forest", "city", "mountain", "ocean", "indoor", "outdoor", "landscape",
|
||||
"森林", "城市", "山", "海", "室内", "室外", "风景", "场景"
|
||||
]
|
||||
if any(k in tag_lower for k in scene_keywords):
|
||||
return "scene"
|
||||
STRICT RULES:
|
||||
1. Create 5-15 Level 1 categories (broad groupings)
|
||||
2. Optionally create 2-5 Level 2 super-categories IF Level 1 has 8+ categories
|
||||
3. Every tag must belong to exactly ONE Level 1 category
|
||||
4. Use {normalized_lang} for all category labels
|
||||
5. Category IDs must be simple lowercase (e.g., "style", "char", "scene1")
|
||||
|
||||
# Object
|
||||
object_keywords = [
|
||||
"sword", "weapon", "machine", "building", "vehicle",
|
||||
"机甲", "武器", "建筑", "车", "剑"
|
||||
]
|
||||
if any(k in tag_lower for k in object_keywords):
|
||||
return "object"
|
||||
OUTPUT ONLY VALID JSON - NO markdown, NO explanations, NO extra text:
|
||||
{{"layers":[{{"level":1,"groups":[{{"id":"cat1","label":"Label1","tags":["tag1"]}},{{"id":"cat2","label":"Label2","tags":["tag2"]}}]}},{{"level":2,"groups":[{{"id":"super1","label":"SuperLabel","categories":["cat1","cat2"]}}]}}]}}
|
||||
|
||||
return "other"
|
||||
If unsure about Level 2, OMIT it entirely. Start response with {{ and end with }}"""
|
||||
|
||||
def _detect_communities(nodes: List[dict], links: List[GraphLink]) -> Optional[List[dict]]:
|
||||
"""Detect communities using Louvain algorithm"""
|
||||
try:
|
||||
import networkx as nx
|
||||
from networkx.algorithms import community
|
||||
except ImportError:
|
||||
return None
|
||||
user_prompt = f"Tags to categorize:\n{', '.join(tags)}"
|
||||
|
||||
# Build graph
|
||||
G = nx.Graph()
|
||||
for node in nodes:
|
||||
G.add_node(node["id"], weight=node["weight"])
|
||||
payload = {
|
||||
"model": model,
|
||||
"messages": [
|
||||
{"role": "system", "content": sys_prompt},
|
||||
{"role": "user", "content": user_prompt}
|
||||
],
|
||||
"temperature": 0.0,
|
||||
"max_tokens": 2048,
|
||||
}
|
||||
|
||||
for link in links:
|
||||
if G.has_node(link.source) and G.has_node(link.target):
|
||||
G.add_edge(link.source, link.target, weight=link.weight)
|
||||
# Retry up to 5 times
|
||||
last_error = ""
|
||||
for attempt in range(1, 6):
|
||||
try:
|
||||
resp = requests.post(url, json=payload, headers=headers, timeout=60)
|
||||
except requests.RequestException as e:
|
||||
last_error = f"network_error: {type(e).__name__}: {e}"
|
||||
continue
|
||||
|
||||
if len(G.nodes()) < 2:
|
||||
return None
|
||||
# Retry on 429 or 5xx, fail immediately on other 4xx
|
||||
if resp.status_code != 200:
|
||||
body = (resp.text or "")[:400]
|
||||
if resp.status_code == 429 or resp.status_code >= 500:
|
||||
last_error = f"api_error_retriable: status={resp.status_code}"
|
||||
continue
|
||||
# 4xx client error - fail immediately
|
||||
raise Exception(f"API client error: {resp.status_code} {body}")
|
||||
|
||||
# Detect communities
|
||||
try:
|
||||
communities = community.louvain_communities(G, weight="weight", resolution=1.0)
|
||||
except Exception:
|
||||
return None
|
||||
try:
|
||||
data = resp.json()
|
||||
except Exception as e:
|
||||
last_error = f"response_not_json: {type(e).__name__}"
|
||||
continue
|
||||
|
||||
# Format result
|
||||
result = []
|
||||
node_to_community = {}
|
||||
for idx, comm in enumerate(communities):
|
||||
comm_list = list(comm)
|
||||
result.append({
|
||||
"id": idx,
|
||||
"nodes": comm_list,
|
||||
"size": len(comm_list),
|
||||
})
|
||||
for node_id in comm_list:
|
||||
node_to_community[node_id] = idx
|
||||
choice0 = (data.get("choices") or [{}])[0]
|
||||
msg = (choice0 or {}).get("message") or {}
|
||||
content = (msg.get("content") or "").strip()
|
||||
|
||||
# Assign community to nodes
|
||||
for node in nodes:
|
||||
node["community"] = node_to_community.get(node["id"], -1)
|
||||
# Extract JSON from content - try multiple strategies
|
||||
json_str = None
|
||||
|
||||
return result
|
||||
# Strategy 1: Direct parse (if response is pure JSON)
|
||||
try:
|
||||
result = json.loads(content)
|
||||
if isinstance(result, dict) and "layers" in result:
|
||||
return result
|
||||
except:
|
||||
pass
|
||||
|
||||
# Strategy 2: Extract JSON from markdown code blocks
|
||||
code_block = re.search(r"```(?:json)?\s*(\{[\s\S]*?\})\s*```", content)
|
||||
if code_block:
|
||||
json_str = code_block.group(1)
|
||||
else:
|
||||
# Strategy 3: Find largest JSON object
|
||||
m = re.search(r"\{[\s\S]*\}", content)
|
||||
if m:
|
||||
json_str = m.group(0)
|
||||
|
||||
if not json_str:
|
||||
last_error = f"no_json_found: {content[:200]}"
|
||||
continue
|
||||
|
||||
# Clean up common JSON issues
|
||||
json_str = json_str.strip()
|
||||
# Remove trailing commas before closing braces/brackets
|
||||
json_str = re.sub(r',(\s*[}\]])', r'\1', json_str)
|
||||
|
||||
try:
|
||||
result = json.loads(json_str)
|
||||
except json.JSONDecodeError as e:
|
||||
last_error = f"json_parse_error: {e}"
|
||||
continue
|
||||
|
||||
# Validate structure
|
||||
if not isinstance(result, dict) or "layers" not in result:
|
||||
last_error = f"invalid_structure: {str(result)[:200]}"
|
||||
continue
|
||||
|
||||
# Success!
|
||||
return result
|
||||
|
||||
# All retries exhausted
|
||||
# Fallback: create simple heuristic grouping
|
||||
# Group by first character/prefix for basic organization
|
||||
groups_dict = {}
|
||||
for tag in tags:
|
||||
# Simple heuristic: group by first 2 chars or common keywords
|
||||
prefix = tag[:2] if len(tag) >= 2 else tag
|
||||
if prefix not in groups_dict:
|
||||
groups_dict[prefix] = []
|
||||
groups_dict[prefix].append(tag)
|
||||
|
||||
# Merge small groups
|
||||
merged_groups = []
|
||||
for prefix, tag_list in sorted(groups_dict.items()):
|
||||
if len(merged_groups) > 0 and len(tag_list) < 3:
|
||||
# Merge into last group if this group is too small
|
||||
merged_groups[-1]["tags"].extend(tag_list)
|
||||
else:
|
||||
group_id = f"group{len(merged_groups) + 1}"
|
||||
label = f"Group {len(merged_groups) + 1}"
|
||||
merged_groups.append({
|
||||
"id": group_id,
|
||||
"label": label,
|
||||
"tags": tag_list
|
||||
})
|
||||
|
||||
# Limit to max 12 groups
|
||||
if len(merged_groups) > 12:
|
||||
# Merge smallest groups
|
||||
merged_groups = sorted(merged_groups, key=lambda g: len(g["tags"]), reverse=True)[:12]
|
||||
|
||||
return {
|
||||
"layers": [
|
||||
{
|
||||
"level": 1,
|
||||
"groups": merged_groups
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return await asyncio.to_thread(_call_sync)
|
||||
|
||||
@app.post(
|
||||
f"{db_api_base}/cluster_tag_graph",
|
||||
|
|
@ -184,36 +235,98 @@ def mount_tag_graph_routes(
|
|||
)
|
||||
async def cluster_tag_graph(req: TagGraphReq):
|
||||
"""
|
||||
Build tag relationship graph from clustering results.
|
||||
Returns nodes (tags + clusters) and weighted edges.
|
||||
Build hierarchical tag graph from clustering results.
|
||||
Returns multi-layer structure similar to neural network visualization.
|
||||
|
||||
Layer structure (bottom to top):
|
||||
- Layer 0: Cluster nodes
|
||||
- Layer 1: Tag nodes (deduplicated cluster keywords)
|
||||
- Layer 2+: Abstract groupings (LLM-generated, max 2 layers)
|
||||
"""
|
||||
# Validate
|
||||
if not req.folder_paths:
|
||||
raise HTTPException(400, "folder_paths is required")
|
||||
|
||||
folders = sorted(req.folder_paths)
|
||||
model = req.model or embedding_model
|
||||
|
||||
# Get cached cluster result
|
||||
# Get the latest cluster result for these folders
|
||||
conn = DataBase.get_conn()
|
||||
cache_key = _get_cluster_cache_key(req, model)
|
||||
cached = TopicClusterCache.get(conn, cache_key)
|
||||
|
||||
if not cached or not isinstance(cached.get("result"), dict):
|
||||
from contextlib import closing
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"""SELECT cache_key, folders, result FROM topic_cluster_cache
|
||||
ORDER BY updated_at DESC"""
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
|
||||
# Find a cache that matches the folders (order-independent)
|
||||
folders_set = set(folders)
|
||||
row = None
|
||||
|
||||
for cache_row in rows:
|
||||
try:
|
||||
cached_folders = json.loads(cache_row[1]) if isinstance(cache_row[1], str) else cache_row[1]
|
||||
if isinstance(cached_folders, list) and set(cached_folders) == folders_set:
|
||||
row = (cache_row[0], cache_row[2])
|
||||
break
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if not row:
|
||||
raise HTTPException(
|
||||
400,
|
||||
"No clustering result found. Please run clustering first."
|
||||
f"No clustering result found for these {len(folders)} folders. Please run clustering first."
|
||||
)
|
||||
|
||||
result = cached["result"]
|
||||
cached_result = json.loads(row[1]) if isinstance(row[1], str) else row[1]
|
||||
|
||||
if not cached_result or not isinstance(cached_result, dict):
|
||||
raise HTTPException(400, "Invalid clustering result format.")
|
||||
|
||||
result = cached_result
|
||||
clusters = result.get("clusters", [])
|
||||
|
||||
if not clusters:
|
||||
raise HTTPException(400, "No clusters found in result")
|
||||
|
||||
# 1. Collect tag statistics
|
||||
# === Layer 0: Cluster Nodes ===
|
||||
top_n_clusters = req.top_n_clusters or 20
|
||||
top_clusters = sorted(clusters, key=lambda c: c.get("size", 0), reverse=True)[:top_n_clusters]
|
||||
|
||||
cluster_nodes = []
|
||||
cluster_to_tags_links = []
|
||||
|
||||
for cluster in top_clusters:
|
||||
cluster_id = cluster.get("id", "")
|
||||
cluster_title = cluster.get("title", "Untitled")
|
||||
cluster_size = cluster.get("size", 0)
|
||||
keywords = cluster.get("keywords", [])
|
||||
paths = cluster.get("paths", [])
|
||||
|
||||
node_id = f"cluster_{cluster_id}"
|
||||
cluster_nodes.append(LayerNode(
|
||||
id=node_id,
|
||||
label=cluster_title,
|
||||
size=float(cluster_size),
|
||||
metadata={
|
||||
"type": "cluster",
|
||||
"image_count": cluster_size,
|
||||
"paths": paths
|
||||
}
|
||||
))
|
||||
|
||||
# Store links from clusters to their tags (will be created later)
|
||||
for keyword in keywords:
|
||||
if keyword:
|
||||
cluster_to_tags_links.append({
|
||||
"cluster_id": node_id,
|
||||
"tag": str(keyword).strip(),
|
||||
"weight": float(cluster_size)
|
||||
})
|
||||
|
||||
# === Layer 1: Tag Nodes (deduplicated) ===
|
||||
tag_stats: Dict[str, Dict] = {}
|
||||
total_images = sum(c.get("size", 0) for c in clusters)
|
||||
|
||||
for cluster in clusters:
|
||||
keywords = cluster.get("keywords", [])
|
||||
|
|
@ -227,141 +340,190 @@ def mount_tag_graph_routes(
|
|||
|
||||
if keyword not in tag_stats:
|
||||
tag_stats[keyword] = {
|
||||
"clusters": [],
|
||||
"cluster_ids": [],
|
||||
"total_images": 0,
|
||||
}
|
||||
|
||||
tag_stats[keyword]["clusters"].append(cluster_id)
|
||||
tag_stats[keyword]["cluster_ids"].append(cluster_id)
|
||||
tag_stats[keyword]["total_images"] += cluster_size
|
||||
|
||||
# 2. Calculate tag weights
|
||||
tag_nodes = []
|
||||
alpha = float(req.alpha or 0.3)
|
||||
|
||||
for tag, stats in tag_stats.items():
|
||||
cluster_count = len(stats["clusters"])
|
||||
image_count = stats["total_images"]
|
||||
|
||||
# Frequency weight
|
||||
freq_weight = float(image_count)
|
||||
|
||||
# TF-IDF weight
|
||||
idf = math.log(len(clusters) / max(cluster_count, 1))
|
||||
tfidf_weight = freq_weight * idf
|
||||
|
||||
# Hybrid weight
|
||||
if req.weight_mode == "frequency":
|
||||
weight = freq_weight
|
||||
elif req.weight_mode == "tfidf":
|
||||
weight = tfidf_weight
|
||||
else: # hybrid
|
||||
weight = alpha * freq_weight + (1 - alpha) * tfidf_weight
|
||||
|
||||
tag_nodes.append({
|
||||
"id": f"tag_{tag}",
|
||||
"label": tag,
|
||||
"weight": weight,
|
||||
"image_count": image_count,
|
||||
"cluster_count": cluster_count,
|
||||
"category": _infer_tag_category(tag),
|
||||
})
|
||||
|
||||
# 3. Filter top-N tags
|
||||
# Filter and sort tags
|
||||
top_n_tags = req.top_n_tags or 50
|
||||
tag_nodes = sorted(tag_nodes, key=lambda x: x["weight"], reverse=True)[:top_n_tags]
|
||||
selected_tags = {node["label"] for node in tag_nodes}
|
||||
sorted_tags = sorted(
|
||||
tag_stats.items(),
|
||||
key=lambda x: x[1]["total_images"],
|
||||
reverse=True
|
||||
)[:top_n_tags]
|
||||
|
||||
# 4. Calculate tag-tag co-occurrence
|
||||
tag_pairs: Dict[Tuple[str, str], Dict] = {}
|
||||
tag_nodes = []
|
||||
selected_tags = set()
|
||||
|
||||
for cluster in clusters:
|
||||
keywords = cluster.get("keywords", [])
|
||||
keywords = [k for k in keywords if k in selected_tags]
|
||||
cluster_size = cluster.get("size", 0)
|
||||
cluster_id = cluster.get("id", "")
|
||||
for tag, stats in sorted_tags:
|
||||
tag_id = f"tag_{tag}"
|
||||
selected_tags.add(tag)
|
||||
tag_nodes.append(LayerNode(
|
||||
id=tag_id,
|
||||
label=tag,
|
||||
size=float(stats["total_images"]),
|
||||
metadata={
|
||||
"type": "tag",
|
||||
"cluster_count": len(stats["cluster_ids"]),
|
||||
"image_count": stats["total_images"]
|
||||
}
|
||||
))
|
||||
|
||||
for i in range(len(keywords)):
|
||||
for j in range(i + 1, len(keywords)):
|
||||
tag1, tag2 = sorted([keywords[i], keywords[j]])
|
||||
key = (tag1, tag2)
|
||||
# Filter cluster->tag links to only include selected tags
|
||||
layer0_to_1_links = []
|
||||
for link in cluster_to_tags_links:
|
||||
if link["tag"] in selected_tags:
|
||||
layer0_to_1_links.append(GraphLink(
|
||||
source=link["cluster_id"],
|
||||
target=f"tag_{link['tag']}",
|
||||
weight=link["weight"]
|
||||
))
|
||||
|
||||
if key not in tag_pairs:
|
||||
tag_pairs[key] = {
|
||||
"clusters": [],
|
||||
"images": 0,
|
||||
}
|
||||
# === Layer 2+: LLM-driven abstraction ===
|
||||
abstract_layers = []
|
||||
layer1_to_2_links = []
|
||||
|
||||
tag_pairs[key]["clusters"].append(cluster_id)
|
||||
tag_pairs[key]["images"] += cluster_size
|
||||
if len(selected_tags) > 3: # Only abstract if we have enough tags
|
||||
# Use language from request
|
||||
lang = req.lang or "en"
|
||||
|
||||
# 5. Build tag-tag links
|
||||
tag_links = []
|
||||
for (tag1, tag2), stats in tag_pairs.items():
|
||||
tag_links.append(
|
||||
GraphLink(
|
||||
source=f"tag_{tag1}",
|
||||
target=f"tag_{tag2}",
|
||||
weight=float(stats["images"]),
|
||||
image_count=stats["images"],
|
||||
cluster_count=len(stats["clusters"]),
|
||||
# Generate cache key for this set of tags (with version)
|
||||
import hashlib
|
||||
tags_sorted = sorted(selected_tags)
|
||||
cache_input = f"v{TAG_ABSTRACTION_CACHE_VERSION}|{ai_model}|{lang}|{','.join(tags_sorted)}"
|
||||
cache_key_hash = hashlib.md5(cache_input.encode()).hexdigest()
|
||||
cache_key = f"tag_abstraction_v{TAG_ABSTRACTION_CACHE_VERSION}_{cache_key_hash}"
|
||||
|
||||
# Try to get from cache
|
||||
abstraction = None
|
||||
try:
|
||||
cached_data = GlobalSetting.get_setting(conn, cache_key)
|
||||
if cached_data and isinstance(cached_data, dict):
|
||||
abstraction = cached_data
|
||||
except:
|
||||
pass
|
||||
|
||||
# Call LLM if not cached
|
||||
if not abstraction:
|
||||
abstraction = await _call_llm_for_abstraction(
|
||||
list(selected_tags),
|
||||
lang,
|
||||
ai_model,
|
||||
openai_base_url,
|
||||
openai_api_key
|
||||
)
|
||||
)
|
||||
|
||||
# 6. Add cluster nodes (if requested)
|
||||
cluster_nodes = []
|
||||
cluster_links = []
|
||||
# Save to cache if successful
|
||||
if abstraction and isinstance(abstraction, dict) and abstraction.get("layers"):
|
||||
try:
|
||||
GlobalSetting.save_setting(conn, cache_key, json.dumps(abstraction, ensure_ascii=False))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if req.show_clusters:
|
||||
# Filter top-N clusters by size
|
||||
top_n_clusters = req.top_n_clusters or 20
|
||||
top_clusters = sorted(clusters, key=lambda c: c.get("size", 0), reverse=True)[:top_n_clusters]
|
||||
# Build abstract layers from LLM response
|
||||
llm_layers = abstraction.get("layers", [])
|
||||
|
||||
for cluster in top_clusters:
|
||||
cluster_id = cluster.get("id", "")
|
||||
cluster_title = cluster.get("title", "Untitled")
|
||||
cluster_size = cluster.get("size", 0)
|
||||
keywords = cluster.get("keywords", [])
|
||||
for layer_info in llm_layers:
|
||||
level = layer_info.get("level", 1)
|
||||
groups = layer_info.get("groups", [])
|
||||
|
||||
cluster_nodes.append({
|
||||
"id": f"cluster_{cluster_id}",
|
||||
"label": cluster_title,
|
||||
"weight": float(cluster_size),
|
||||
"size": cluster_size,
|
||||
"category": "cluster",
|
||||
})
|
||||
if not groups:
|
||||
continue
|
||||
|
||||
# Link cluster to its tags
|
||||
for keyword in keywords:
|
||||
if keyword in selected_tags:
|
||||
cluster_links.append(
|
||||
GraphLink(
|
||||
source=f"cluster_{cluster_id}",
|
||||
target=f"tag_{keyword}",
|
||||
weight=float(cluster_size),
|
||||
)
|
||||
abstract_nodes = []
|
||||
|
||||
# Process each group in this layer
|
||||
for group in groups:
|
||||
group_id = f"abstract_l{level}_{group.get('id', 'unknown')}"
|
||||
group_label = group.get("label", "Unnamed")
|
||||
|
||||
# Calculate size based on contained tags/categories
|
||||
if "tags" in group:
|
||||
# Level 1: references tags directly
|
||||
contained_tags = group.get("tags", [])
|
||||
total_size = sum(
|
||||
tag_stats.get(tag, {}).get("total_images", 0)
|
||||
for tag in contained_tags
|
||||
if tag in selected_tags
|
||||
)
|
||||
|
||||
# 7. Combine all nodes and links
|
||||
all_nodes = tag_nodes + cluster_nodes
|
||||
all_links = [link.dict() for link in (tag_links + cluster_links)]
|
||||
abstract_nodes.append(LayerNode(
|
||||
id=group_id,
|
||||
label=group_label,
|
||||
size=float(total_size),
|
||||
metadata={"type": "abstract", "level": level}
|
||||
))
|
||||
|
||||
# 8. Community detection
|
||||
communities = None
|
||||
if req.detect_communities:
|
||||
communities = _detect_communities(all_nodes, tag_links + cluster_links)
|
||||
# Create links from tags to this abstract node
|
||||
for tag in contained_tags:
|
||||
if tag in selected_tags:
|
||||
tag_id = f"tag_{tag}"
|
||||
layer1_to_2_links.append(GraphLink(
|
||||
source=tag_id,
|
||||
target=group_id,
|
||||
weight=float(tag_stats.get(tag, {}).get("total_images", 1))
|
||||
))
|
||||
|
||||
elif "categories" in group and level == 2:
|
||||
# Level 2: references Level 1 categories
|
||||
# Calculate size from contained categories
|
||||
contained_cats = group.get("categories", [])
|
||||
total_size = 0.0
|
||||
|
||||
# Find size from level 1 nodes
|
||||
level1_nodes = abstract_layers[0].nodes if abstract_layers else []
|
||||
for cat_id in contained_cats:
|
||||
full_cat_id = f"abstract_l1_{cat_id}"
|
||||
for node in level1_nodes:
|
||||
if node.id == full_cat_id:
|
||||
total_size += node.size
|
||||
break
|
||||
|
||||
abstract_nodes.append(LayerNode(
|
||||
id=group_id,
|
||||
label=group_label,
|
||||
size=float(total_size),
|
||||
metadata={"type": "abstract", "level": level}
|
||||
))
|
||||
|
||||
# Create links from Level 1 categories to this Level 2 node
|
||||
for cat_id in contained_cats:
|
||||
full_cat_id = f"abstract_l1_{cat_id}"
|
||||
# Verify the category exists
|
||||
if any(n.id == full_cat_id for n in level1_nodes):
|
||||
layer1_to_2_links.append(GraphLink(
|
||||
source=full_cat_id,
|
||||
target=group_id,
|
||||
weight=total_size # Use aggregated weight
|
||||
))
|
||||
|
||||
if abstract_nodes:
|
||||
abstract_layers.append(GraphLayer(
|
||||
level=level + 1, # +1 because Layer 0=clusters, Layer 1=tags
|
||||
name=f"Abstract-{level}",
|
||||
nodes=abstract_nodes
|
||||
))
|
||||
|
||||
# === Build final response ===
|
||||
layers = [
|
||||
GraphLayer(level=0, name="Clusters", nodes=cluster_nodes),
|
||||
GraphLayer(level=1, name="Tags", nodes=tag_nodes),
|
||||
] + abstract_layers
|
||||
|
||||
all_links = [link.dict() for link in (layer0_to_1_links + layer1_to_2_links)]
|
||||
|
||||
# 9. Build response
|
||||
return TagGraphResp(
|
||||
nodes=all_nodes,
|
||||
layers=layers,
|
||||
links=all_links,
|
||||
communities=communities,
|
||||
stats={
|
||||
"total_tags": len(tag_stats),
|
||||
"selected_tags": len(tag_nodes),
|
||||
"total_clusters": len(clusters),
|
||||
"selected_clusters": len(cluster_nodes),
|
||||
"total_images": total_images,
|
||||
"tag_links": len(tag_links),
|
||||
"cluster_links": len(cluster_links),
|
||||
},
|
||||
"total_tags": len(tag_stats),
|
||||
"selected_tags": len(tag_nodes),
|
||||
"abstraction_layers": len(abstract_layers),
|
||||
"total_links": len(all_links),
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import platform
|
|||
import re
|
||||
import tempfile
|
||||
import subprocess
|
||||
from typing import Dict, List
|
||||
from typing import Dict, List, Optional
|
||||
import sys
|
||||
import piexif
|
||||
import piexif.helper
|
||||
|
|
@ -36,6 +36,37 @@ cwd = os.getcwd() if is_exe_ver else os.path.normpath(os.path.join(__file__, "..
|
|||
is_win = platform.system().lower().find("windows") != -1
|
||||
|
||||
|
||||
def normalize_output_lang(lang: Optional[str]) -> str:
|
||||
"""
|
||||
Map frontend language keys to a human-readable instruction for LLM output language.
|
||||
Frontend uses: en / zhHans / zhHant / de
|
||||
|
||||
Args:
|
||||
lang: Language code from frontend (e.g., "zhHans", "en", "de")
|
||||
|
||||
Returns:
|
||||
Human-readable language name for LLM instruction
|
||||
"""
|
||||
if not lang:
|
||||
return "English"
|
||||
l = str(lang).strip()
|
||||
ll = l.lower()
|
||||
# Simplified Chinese
|
||||
if ll in ["zh", "zhhans", "zh-hans", "zh_cn", "zh-cn", "cn", "zh-hans-cn", "zhs"]:
|
||||
return "Chinese (Simplified)"
|
||||
# Traditional Chinese (Taiwan, Hong Kong, Macau)
|
||||
if ll in ["zhhant", "zh-hant", "zh_tw", "zh-tw", "zh_hk", "zh-hk", "zh_mo", "zh-mo", "tw", "hk", "mo", "macau", "macao", "zht"]:
|
||||
return "Chinese (Traditional)"
|
||||
# German
|
||||
if ll.startswith("de"):
|
||||
return "German"
|
||||
# English
|
||||
if ll.startswith("en"):
|
||||
return "English"
|
||||
# fallback
|
||||
return "English"
|
||||
|
||||
|
||||
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ declare module '@vue/runtime-core' {
|
|||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||
ASkeleton: typeof import('ant-design-vue/es')['Skeleton']
|
||||
ASlider: typeof import('ant-design-vue/es')['Slider']
|
||||
ASpace: typeof import('ant-design-vue/es')['Space']
|
||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||
ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
|
||||
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
import{d as E,bC as $,r as f,m as M,_ as T,a as c,an as W,h as m,c as v,P as z}from"./index-632e7cf6.js";var G=["prefixCls","name","id","type","disabled","readonly","tabindex","autofocus","value","required"],H={prefixCls:String,name:String,id:String,type:String,defaultChecked:{type:[Boolean,Number],default:void 0},checked:{type:[Boolean,Number],default:void 0},disabled:Boolean,tabindex:{type:[Number,String]},readonly:Boolean,autofocus:Boolean,value:z.any,required:Boolean};const L=E({compatConfig:{MODE:3},name:"Checkbox",inheritAttrs:!1,props:$(H,{prefixCls:"rc-checkbox",type:"checkbox",defaultChecked:!1}),emits:["click","change"],setup:function(a,d){var t=d.attrs,h=d.emit,g=d.expose,o=f(a.checked===void 0?a.defaultChecked:a.checked),i=f();M(function(){return a.checked},function(){o.value=a.checked}),g({focus:function(){var e;(e=i.value)===null||e===void 0||e.focus()},blur:function(){var e;(e=i.value)===null||e===void 0||e.blur()}});var l=f(),x=function(e){if(!a.disabled){a.checked===void 0&&(o.value=e.target.checked),e.shiftKey=l.value;var r={target:c(c({},a),{},{checked:e.target.checked}),stopPropagation:function(){e.stopPropagation()},preventDefault:function(){e.preventDefault()},nativeEvent:e};a.checked!==void 0&&(i.value.checked=!!a.checked),h("change",r),l.value=!1}},C=function(e){h("click",e),l.value=e.shiftKey};return function(){var n,e=a.prefixCls,r=a.name,s=a.id,p=a.type,b=a.disabled,K=a.readonly,P=a.tabindex,B=a.autofocus,S=a.value,N=a.required,_=T(a,G),q=t.class,D=t.onFocus,j=t.onBlur,w=t.onKeydown,A=t.onKeypress,F=t.onKeyup,y=c(c({},_),t),O=Object.keys(y).reduce(function(k,u){return(u.substr(0,5)==="aria-"||u.substr(0,5)==="data-"||u==="role")&&(k[u]=y[u]),k},{}),R=W(e,q,(n={},m(n,"".concat(e,"-checked"),o.value),m(n,"".concat(e,"-disabled"),b),n)),V=c(c({name:r,id:s,type:p,readonly:K,disabled:b,tabindex:P,class:"".concat(e,"-input"),checked:!!o.value,autofocus:B,value:S},O),{},{onChange:x,onClick:C,onFocus:D,onBlur:j,onKeydown:w,onKeypress:A,onKeyup:F,required:N});return v("span",{class:R},[v("input",c({ref:i},V),null),v("span",{class:"".concat(e,"-inner")},null)])}}});export{L as V};
|
||||
import{d as E,bC as $,r as f,m as M,_ as T,a as c,an as W,h as m,c as v,P as z}from"./index-d6594e8e.js";var G=["prefixCls","name","id","type","disabled","readonly","tabindex","autofocus","value","required"],H={prefixCls:String,name:String,id:String,type:String,defaultChecked:{type:[Boolean,Number],default:void 0},checked:{type:[Boolean,Number],default:void 0},disabled:Boolean,tabindex:{type:[Number,String]},readonly:Boolean,autofocus:Boolean,value:z.any,required:Boolean};const L=E({compatConfig:{MODE:3},name:"Checkbox",inheritAttrs:!1,props:$(H,{prefixCls:"rc-checkbox",type:"checkbox",defaultChecked:!1}),emits:["click","change"],setup:function(a,d){var t=d.attrs,h=d.emit,g=d.expose,o=f(a.checked===void 0?a.defaultChecked:a.checked),i=f();M(function(){return a.checked},function(){o.value=a.checked}),g({focus:function(){var e;(e=i.value)===null||e===void 0||e.focus()},blur:function(){var e;(e=i.value)===null||e===void 0||e.blur()}});var l=f(),x=function(e){if(!a.disabled){a.checked===void 0&&(o.value=e.target.checked),e.shiftKey=l.value;var r={target:c(c({},a),{},{checked:e.target.checked}),stopPropagation:function(){e.stopPropagation()},preventDefault:function(){e.preventDefault()},nativeEvent:e};a.checked!==void 0&&(i.value.checked=!!a.checked),h("change",r),l.value=!1}},C=function(e){h("click",e),l.value=e.shiftKey};return function(){var n,e=a.prefixCls,r=a.name,s=a.id,p=a.type,b=a.disabled,K=a.readonly,P=a.tabindex,B=a.autofocus,S=a.value,N=a.required,_=T(a,G),q=t.class,D=t.onFocus,j=t.onBlur,w=t.onKeydown,A=t.onKeypress,F=t.onKeyup,y=c(c({},_),t),O=Object.keys(y).reduce(function(k,u){return(u.substr(0,5)==="aria-"||u.substr(0,5)==="data-"||u==="role")&&(k[u]=y[u]),k},{}),R=W(e,q,(n={},m(n,"".concat(e,"-checked"),o.value),m(n,"".concat(e,"-disabled"),b),n)),V=c(c({name:r,id:s,type:p,readonly:K,disabled:b,tabindex:P,class:"".concat(e,"-input"),checked:!!o.value,autofocus:B,value:S},O),{},{onChange:x,onClick:C,onFocus:D,onBlur:j,onKeydown:w,onKeypress:A,onKeyup:F,required:N});return v("span",{class:R},[v("input",c({ref:i},V),null),v("span",{class:"".concat(e,"-inner")},null)])}}});export{L as V};
|
||||
File diff suppressed because one or more lines are too long
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{d as a,U as t,V as s,c as n,cN as _,a0 as o}from"./index-632e7cf6.js";const c={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),s("div",c,[n(_,{left:e.left,right:e.right},null,8,["left","right"])]))}});const d=o(i,[["__scopeId","data-v-ae3fb9a8"]]);export{d as default};
|
||||
|
|
@ -0,0 +1 @@
|
|||
.img-sli-container[data-v-ec71de83]{position:relative;overflow-y:auto;height:calc(100vh - 40px)}
|
||||
|
|
@ -1 +0,0 @@
|
|||
.img-sli-container[data-v-ae3fb9a8]{position:relative;overflow-y:auto;height:calc(100vh - 40px)}
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{d as a,U as t,V as s,c as n,cO as _,a0 as c}from"./index-d6594e8e.js";const o={class:"img-sli-container"},i=a({__name:"ImgSliPagePane",props:{paneIdx:{},tabIdx:{},left:{},right:{}},setup(l){return(e,r)=>(t(),s("div",o,[n(_,{left:e.left,right:e.right},null,8,["left","right"])]))}});const p=c(i,[["__scopeId","data-v-ec71de83"]]);export{p as default};
|
||||
|
|
@ -0,0 +1 @@
|
|||
.container[data-v-6e837a6f]{background:var(--zp-secondary-background);position:relative}.container .action-bar[data-v-6e837a6f]{display:flex;align-items:center;user-select:none;gap:4px;padding:4px}.container .action-bar>*[data-v-6e837a6f]{flex-wrap:wrap}.container .file-list[data-v-6e837a6f]{list-style:none;padding:8px;overflow:auto;height:calc(var(--pane-max-height) - 40px);width:100%}.container .no-res-hint[data-v-6e837a6f]{height:var(--pane-max-height);display:flex;align-items:center;flex-direction:column;justify-content:center}.container .no-res-hint .hint[data-v-6e837a6f]{font-size:1.6em;margin-bottom:2em;text-align:center}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
.container[data-v-795e5ef4]{background:var(--zp-secondary-background);position:relative;height:var(--pane-max-height)}.action-bar[data-v-795e5ef4]{display:flex;align-items:center;user-select:none;gap:6px;padding:6px 8px}.title[data-v-795e5ef4]{font-weight:700;max-width:40vw}.file-list[data-v-795e5ef4]{list-style:none;padding:8px;overflow:auto;height:calc(var(--pane-max-height) - 44px);width:100%}.no-res-hint[data-v-795e5ef4]{height:calc(var(--pane-max-height) - 44px);display:flex;align-items:center;flex-direction:column;justify-content:center}.no-res-hint .hint[data-v-795e5ef4]{font-size:1.2em;opacity:.7}.preview-switch[data-v-795e5ef4]{position:fixed;bottom:24px;right:24px;display:flex;gap:8px;font-size:36px;user-select:none}.disable[data-v-795e5ef4]{opacity:.3;pointer-events:none}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +0,0 @@
|
|||
.container[data-v-4815fec6]{background:var(--zp-secondary-background);position:relative}.container .action-bar[data-v-4815fec6]{display:flex;align-items:center;user-select:none;gap:4px;padding:4px}.container .action-bar>*[data-v-4815fec6]{flex-wrap:wrap}.container .file-list[data-v-4815fec6]{list-style:none;padding:8px;overflow:auto;height:calc(var(--pane-max-height) - 40px);width:100%}.container .no-res-hint[data-v-4815fec6]{height:var(--pane-max-height);display:flex;align-items:center;flex-direction:column;justify-content:center}.container .no-res-hint .hint[data-v-4815fec6]{font-size:1.6em;margin-bottom:2em;text-align:center}
|
||||
|
|
@ -1 +0,0 @@
|
|||
.container[data-v-aea581a5]{background:var(--zp-secondary-background);position:relative;height:var(--pane-max-height)}.action-bar[data-v-aea581a5]{display:flex;align-items:center;user-select:none;gap:6px;padding:6px 8px}.title[data-v-aea581a5]{font-weight:700;max-width:40vw}.file-list[data-v-aea581a5]{list-style:none;padding:8px;overflow:auto;height:calc(var(--pane-max-height) - 44px);width:100%}.no-res-hint[data-v-aea581a5]{height:calc(var(--pane-max-height) - 44px);display:flex;align-items:center;flex-direction:column;justify-content:center}.no-res-hint .hint[data-v-aea581a5]{font-size:1.2em;opacity:.7}.preview-switch[data-v-aea581a5]{position:fixed;bottom:24px;right:24px;display:flex;gap:8px;font-size:36px;user-select:none}.disable[data-v-aea581a5]{opacity:.3;pointer-events:none}
|
||||
|
|
@ -1 +0,0 @@
|
|||
.full-screen-menu[data-v-bb3c8014]{position:fixed;z-index:9999;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-bb3c8014]{margin:4px 0}.full-screen-menu .tags-container .tag[data-v-bb3c8014]{margin-right:4px;margin-bottom:4px;padding:2px 16px;border-radius:4px;display:inline-block;cursor:pointer;font-weight:700;transition:.5s all ease;border:2px solid var(--tag-color);color:var(--tag-color);background:var(--zp-primary-background);user-select:none}.full-screen-menu .tags-container .tag.selected[data-v-bb3c8014]{background:var(--tag-color);color:#fff}.full-screen-menu .container[data-v-bb3c8014]{height:100%;display:flex;overflow:hidden;flex-direction:column}.full-screen-menu .gen-info[data-v-bb3c8014]{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 code[data-v-bb3c8014]{font-size:.9em;display:block;padding:4px;background:var(--zp-primary-background);border-radius:4px;margin-right:20px;white-space:pre-wrap;word-break:break-word;line-height:1.78em}.full-screen-menu .gen-info code[data-v-bb3c8014] .natural-text{margin:.5em 0;line-height:1.6em;text-align:justify;color:var(--zp-primary)}.full-screen-menu .gen-info code[data-v-bb3c8014] .short-tag{word-break:break-all;white-space:nowrap}.full-screen-menu .gen-info code[data-v-bb3c8014] span.tag{background:var(--zp-secondary-variant-background);color:var(--zp-primary);padding:2px 4px;border-radius:6px;margin-right:6px;margin-top:4px;line-height:1.3em;display:inline-block}.full-screen-menu .gen-info code[data-v-bb3c8014] .has-parentheses.tag{background:rgba(255,100,100,.14)}.full-screen-menu .gen-info code[data-v-bb3c8014] span.tag:hover{background:rgba(120,0,0,.15)}.full-screen-menu .gen-info table[data-v-bb3c8014]{font-size:1em;border-radius:4px;border-collapse:separate;margin-bottom:3em}.full-screen-menu .gen-info table tr td[data-v-bb3c8014]:first-child{white-space:nowrap;vertical-align:top}.full-screen-menu .gen-info table.extra-meta-table .extra-meta-value[data-v-bb3c8014]{display:block;max-height:200px;overflow:auto;white-space:pre-wrap;word-break:break-word;font-size:.85em;background:var(--zp-secondary-variant-background);padding:8px;border-radius:4px}.full-screen-menu .gen-info table td[data-v-bb3c8014]{padding-right:14px;padding-left:4px;border-bottom:1px solid var(--zp-secondary);border-collapse:collapse}.full-screen-menu .gen-info .info-tags .info-tag[data-v-bb3c8014]{display:inline-block;overflow:hidden;border-radius:4px;margin-right:8px;border:2px solid var(--zp-primary)}.full-screen-menu .gen-info .info-tags .name[data-v-bb3c8014]{background-color:var(--zp-primary);color:var(--zp-primary-background);padding:4px;border-bottom-right-radius:4px}.full-screen-menu .gen-info .info-tags .value[data-v-bb3c8014]{padding:4px}.full-screen-menu.unset-size[data-v-bb3c8014]{width:unset!important;height:unset!important}.full-screen-menu .mouse-sensor[data-v-bb3c8014]{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-bb3c8014]{font-size:18px;padding:4px}.full-screen-menu .action-bar[data-v-bb3c8014]{display:flex;align-items:center;user-select:none;gap:4px}.full-screen-menu .action-bar .icon[data-v-bb3c8014]{font-size:1.5em;padding:2px 4px;border-radius:4px}.full-screen-menu .action-bar .icon[data-v-bb3c8014]:hover{background:var(--zp-secondary-variant-background)}.full-screen-menu .action-bar>*[data-v-bb3c8014]{flex-wrap:wrap}.full-screen-menu.lr[data-v-bb3c8014]{top:var(--3fe0608e)!important;right:0!important;bottom:0!important;left:100vw!important;height:unset!important;width:var(--2653b66c)!important;transition:left ease .3s}.full-screen-menu.lr.always-on[data-v-bb3c8014],.full-screen-menu.lr.mouse-in[data-v-bb3c8014]{left:var(--1097f730)!important}.tag-alpha-item[data-v-bb3c8014]{display:flex;margin-top:4px}.tag-alpha-item h4[data-v-bb3c8014]{width:32px;flex-shrink:0}.sort-tag-switch[data-v-bb3c8014]{display:inline-block;padding-right:16px;padding-left:8px;cursor:pointer;user-select:none}.sort-tag-switch span[data-v-bb3c8014]{transition:all ease .3s;transform:scale(1.2)}.sort-tag-switch:hover span[data-v-bb3c8014]{transform:scale(1.3)}.lr-layout-control[data-v-bb3c8014]{display:flex;align-items:center;gap:16px;padding:4px 8px;flex-wrap:wrap;border-radius:2px;border-left:3px solid var(--zp-luminous);background-color:var(--zp-secondary-background)}.lr-layout-control .ctrl-item[data-v-bb3c8014]{display:flex;align-items:center;gap:4px;flex-wrap:nowrap}.select-actions[data-v-b04c3508]>:not(:last-child){margin-right:4px}.float-panel[data-v-b04c3508]{position:absolute;bottom:32px;right:32px;background:var(--zp-primary-background);border-radius:4px;z-index:1000;padding:8px;box-shadow:0 0 4px var(--zp-secondary)}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
.full-screen-menu[data-v-c7e0b9b7]{position:fixed;z-index:9999;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-c7e0b9b7]{margin:4px 0}.full-screen-menu .tags-container .tag[data-v-c7e0b9b7]{margin-right:4px;margin-bottom:4px;padding:2px 16px;border-radius:4px;display:inline-block;cursor:pointer;font-weight:700;transition:.5s all ease;border:2px solid var(--tag-color);color:var(--tag-color);background:var(--zp-primary-background);user-select:none}.full-screen-menu .tags-container .tag.selected[data-v-c7e0b9b7]{background:var(--tag-color);color:#fff}.full-screen-menu .container[data-v-c7e0b9b7]{height:100%;display:flex;overflow:hidden;flex-direction:column}.full-screen-menu .gen-info[data-v-c7e0b9b7]{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 code[data-v-c7e0b9b7]{font-size:.9em;display:block;padding:4px;background:var(--zp-primary-background);border-radius:4px;margin-right:20px;white-space:pre-wrap;word-break:break-word;line-height:1.78em}.full-screen-menu .gen-info code[data-v-c7e0b9b7] .natural-text{margin:.5em 0;line-height:1.6em;text-align:justify;color:var(--zp-primary)}.full-screen-menu .gen-info code[data-v-c7e0b9b7] .short-tag{word-break:break-all;white-space:nowrap}.full-screen-menu .gen-info code[data-v-c7e0b9b7] span.tag{background:var(--zp-secondary-variant-background);color:var(--zp-primary);padding:2px 4px;border-radius:6px;margin-right:6px;margin-top:4px;line-height:1.3em;display:inline-block}.full-screen-menu .gen-info code[data-v-c7e0b9b7] .has-parentheses.tag{background:rgba(255,100,100,.14)}.full-screen-menu .gen-info code[data-v-c7e0b9b7] span.tag:hover{background:rgba(120,0,0,.15)}.full-screen-menu .gen-info table[data-v-c7e0b9b7]{font-size:1em;border-radius:4px;border-collapse:separate;margin-bottom:3em}.full-screen-menu .gen-info table tr td[data-v-c7e0b9b7]:first-child{white-space:nowrap;vertical-align:top}.full-screen-menu .gen-info table.extra-meta-table .extra-meta-value[data-v-c7e0b9b7]{display:block;max-height:200px;overflow:auto;white-space:pre-wrap;word-break:break-word;font-size:.85em;background:var(--zp-secondary-variant-background);padding:8px;border-radius:4px}.full-screen-menu .gen-info table td[data-v-c7e0b9b7]{padding-right:14px;padding-left:4px;border-bottom:1px solid var(--zp-secondary);border-collapse:collapse}.full-screen-menu .gen-info .info-tags .info-tag[data-v-c7e0b9b7]{display:inline-block;overflow:hidden;border-radius:4px;margin-right:8px;border:2px solid var(--zp-primary)}.full-screen-menu .gen-info .info-tags .name[data-v-c7e0b9b7]{background-color:var(--zp-primary);color:var(--zp-primary-background);padding:4px;border-bottom-right-radius:4px}.full-screen-menu .gen-info .info-tags .value[data-v-c7e0b9b7]{padding:4px}.full-screen-menu.unset-size[data-v-c7e0b9b7]{width:unset!important;height:unset!important}.full-screen-menu .mouse-sensor[data-v-c7e0b9b7]{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-c7e0b9b7]{font-size:18px;padding:4px}.full-screen-menu .action-bar[data-v-c7e0b9b7]{display:flex;align-items:center;user-select:none;gap:4px}.full-screen-menu .action-bar .icon[data-v-c7e0b9b7]{font-size:1.5em;padding:2px 4px;border-radius:4px}.full-screen-menu .action-bar .icon[data-v-c7e0b9b7]:hover{background:var(--zp-secondary-variant-background)}.full-screen-menu .action-bar>*[data-v-c7e0b9b7]{flex-wrap:wrap}.full-screen-menu.lr[data-v-c7e0b9b7]{top:var(--b7cd59ce)!important;right:0!important;bottom:0!important;left:100vw!important;height:unset!important;width:var(--0e09e1cc)!important;transition:left ease .3s}.full-screen-menu.lr.always-on[data-v-c7e0b9b7],.full-screen-menu.lr.mouse-in[data-v-c7e0b9b7]{left:var(--62228ae0)!important}.tag-alpha-item[data-v-c7e0b9b7]{display:flex;margin-top:4px}.tag-alpha-item h4[data-v-c7e0b9b7]{width:32px;flex-shrink:0}.sort-tag-switch[data-v-c7e0b9b7]{display:inline-block;padding-right:16px;padding-left:8px;cursor:pointer;user-select:none}.sort-tag-switch span[data-v-c7e0b9b7]{transition:all ease .3s;transform:scale(1.2)}.sort-tag-switch:hover span[data-v-c7e0b9b7]{transform:scale(1.3)}.lr-layout-control[data-v-c7e0b9b7]{display:flex;align-items:center;gap:16px;padding:4px 8px;flex-wrap:wrap;border-radius:2px;border-left:3px solid var(--zp-luminous);background-color:var(--zp-secondary-background)}.lr-layout-control .ctrl-item[data-v-c7e0b9b7]{display:flex;align-items:center;gap:4px;flex-wrap:nowrap}.select-actions[data-v-b6f9a67c]>:not(:last-child){margin-right:4px}.float-panel[data-v-b6f9a67c]{position:absolute;bottom:32px;right:32px;background:var(--zp-primary-background);border-radius:4px;z-index:1000;padding:8px;box-shadow:0 0 4px var(--zp-secondary)}
|
||||
|
|
@ -1 +0,0 @@
|
|||
[data-v-e1bd92bd] .float-panel{position:fixed}.regex-icon[data-v-e1bd92bd]{user-select:none;padding:4px;margin:0 4px;cursor:pointer;border:1px solid var(--zp-border);border-radius:4px}.regex-icon img[data-v-e1bd92bd]{height:1.5em}.regex-icon[data-v-e1bd92bd]:hover{background:var(--zp-border)}.regex-icon.selected[data-v-e1bd92bd]{background:var(--primary-color-1);border:1px solid var(--primary-color)}.search-bar[data-v-e1bd92bd]{padding:8px 8px 0;display:flex}.search-bar.last[data-v-e1bd92bd]{padding-bottom:8px}.search-bar .form-name[data-v-e1bd92bd]{flex-shrink:0;padding:4px 8px}.search-bar .actions>*[data-v-e1bd92bd]{margin-right:4px}.container[data-v-e1bd92bd]{background:var(--zp-secondary-background);position:relative}.container .file-list[data-v-e1bd92bd]{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 @@
|
|||
[data-v-2a7f2e56] .float-panel{position:fixed}.regex-icon[data-v-2a7f2e56]{user-select:none;padding:4px;margin:0 4px;cursor:pointer;border:1px solid var(--zp-border);border-radius:4px}.regex-icon img[data-v-2a7f2e56]{height:1.5em}.regex-icon[data-v-2a7f2e56]:hover{background:var(--zp-border)}.regex-icon.selected[data-v-2a7f2e56]{background:var(--primary-color-1);border:1px solid var(--primary-color)}.search-bar[data-v-2a7f2e56]{padding:8px 8px 0;display:flex}.search-bar.last[data-v-2a7f2e56]{padding-bottom:8px}.search-bar .form-name[data-v-2a7f2e56]{flex-shrink:0;padding:4px 8px}.search-bar .actions>*[data-v-2a7f2e56]{margin-right:4px}.container[data-v-2a7f2e56]{background:var(--zp-secondary-background);position:relative}.container .file-list[data-v-2a7f2e56]{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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
import{bV as i,b1 as t,e5 as f,bM as n}from"./index-632e7cf6.js";function u(e,s,r){if(!i(r))return!1;var a=typeof s;return(a=="number"?t(r)&&f(s,r.length):a=="string"&&s in r)?n(r[s],e):!1}export{u as i};
|
||||
import{bV as i,b1 as t,e6 as f,bM as n}from"./index-d6594e8e.js";function u(e,s,r){if(!i(r))return!1;var a=typeof s;return(a=="number"?t(r)&&f(s,r.length):a=="string"&&s in r)?n(r[s],e):!1}export{u as i};
|
||||
|
|
@ -1 +0,0 @@
|
|||
.container[data-v-a2642a17]{background:var(--zp-secondary-background);height:100%;overflow:auto;display:flex;flex-direction:column}.container .actions-panel[data-v-a2642a17]{padding:8px;background-color:var(--zp-primary-background)}.container .actions-panel.actions[data-v-a2642a17]{display:flex;align-items:center;gap:16px;z-index:333}.container .file-list[data-v-a2642a17]{flex:1;z-index:222;list-style:none;padding:8px;height:var(--pane-max-height);width:100%}.container .file-list .hint[data-v-a2642a17]{text-align:center;font-size:2em;padding:30vh 128px 0}
|
||||
|
|
@ -0,0 +1 @@
|
|||
.container[data-v-3d7e6f2d]{background:var(--zp-secondary-background);height:100%;overflow:auto;display:flex;flex-direction:column}.container .actions-panel[data-v-3d7e6f2d]{padding:8px;background-color:var(--zp-primary-background)}.container .actions-panel.actions[data-v-3d7e6f2d]{display:flex;align-items:center;gap:16px;z-index:333}.container .file-list[data-v-3d7e6f2d]{flex:1;z-index:222;list-style:none;padding:8px;height:var(--pane-max-height);width:100%}.container .file-list .hint[data-v-3d7e6f2d]{text-align:center;font-size:2em;padding:30vh 128px 0}
|
||||
|
|
@ -1 +1 @@
|
|||
import{d as F,a1 as B,cO as $,cc as S,U as _,V as w,W as f,c as l,a3 as d,X as p,Y as c,a4 as s,a2 as A,af as R,cP as V,cQ as y,z as x,B as E,ak as T,a0 as U}from"./index-632e7cf6.js";import{_ as N}from"./index-1bd869eb.js";import{u as L,a as O,f as H,F as P,d as Q}from"./FileItem-70868dea.js";import"./numInput.vue_vue_type_style_index_0_scoped_55978858_lang-221425da.js";/* empty css */import"./index-a2a27adc.js";import"./_isIterateeCall-582f579a.js";import"./index-9d95a206.js";import"./index-a44b2ffa.js";const W={class:"actions-panel actions"},j={class:"item"},q={key:0,class:"file-list"},G={class:"hint"},X=F({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(Y){const{stackViewEl:D}=L().toRefs(),{itemSize:h,gridItems:b,cellWidth:g}=O(),i=B(),m=H(),{selectdFiles:a}=$(m),r=S(),v=async e=>{const t=V(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(E("success"))})},z=e=>{a.value.splice(e,1)};return(e,t)=>{const o=T,u=N;return _(),w("div",{class:"container",ref_key:"stackViewEl",ref:D,onDrop:v},[f("div",W,[l(o,{onClick:t[0]||(t[0]=n=>s(m).selectdFiles=[])},{default:d(()=>[p(c(e.$t("clear")),1)]),_:1}),f("div",j,[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(Q),{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(b)},{default:d(({item:n,index:k})=>[l(P,{idx:k,file:n,"cell-width":s(g),"enable-close-icon":"",onCloseIconClick:J=>z(k),"full-screen-preview-image-url":s(R)(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",q,[f("p",G,c(e.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const le=U(X,[["__scopeId","data-v-a2642a17"]]);export{le as default};
|
||||
import{d as F,a1 as B,cP as $,cc as S,U as _,V as w,W as f,c as l,a3 as d,X as p,Y as c,a4 as s,a2 as R,af as A,cQ as V,cR as y,z as x,B as E,ak as T,a0 as U}from"./index-d6594e8e.js";import{_ as N}from"./index-e620c28b.js";import{u as L,a as H,f as O,F as P,d as Q}from"./FileItem-2eb00024.js";import"./numInput.vue_vue_type_style_index_0_scoped_bd954eda_lang-c8c8013d.js";/* empty css */import"./index-cb6a3d31.js";import"./_isIterateeCall-bfd79848.js";import"./index-30b8f89a.js";import"./index-9b184148.js";const W={class:"actions-panel actions"},j={class:"item"},q={key:0,class:"file-list"},G={class:"hint"},X=F({__name:"batchDownload",props:{tabIdx:{},paneIdx:{},id:{}},setup(Y){const{stackViewEl:D}=L().toRefs(),{itemSize:h,gridItems:b,cellWidth:g}=H(),i=B(),m=O(),{selectdFiles:a}=$(m),r=S(),v=async e=>{const t=V(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(E("success"))})},z=e=>{a.value.splice(e,1)};return(e,t)=>{const o=T,u=N;return _(),w("div",{class:"container",ref_key:"stackViewEl",ref:D,onDrop:v},[f("div",W,[l(o,{onClick:t[0]||(t[0]=n=>s(m).selectdFiles=[])},{default:d(()=>[p(c(e.$t("clear")),1)]),_:1}),f("div",j,[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?(_(),R(s(Q),{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(b)},{default:d(({item:n,index:k})=>[l(P,{idx:k,file:n,"cell-width":s(g),"enable-close-icon":"",onCloseIconClick:J=>z(k),"full-screen-preview-image-url":s(A)(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",q,[f("p",G,c(e.$t("batchDownloaDDragAndDropHint")),1)]))],544)}}});const le=U(X,[["__scopeId","data-v-3d7e6f2d"]]);export{le 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
|
|
@ -0,0 +1 @@
|
|||
import{u as w,a as y,F as b,d as k}from"./FileItem-2eb00024.js";import{d as x,a1 as h,c9 as F,r as D,bh as I,bl as C,U as V,V as E,c as n,a3 as S,a4 as e,af as z,cQ as B,cS as R,a0 as A}from"./index-d6594e8e.js";import"./numInput.vue_vue_type_style_index_0_scoped_bd954eda_lang-c8c8013d.js";/* empty css */import"./index-cb6a3d31.js";import"./_isIterateeCall-bfd79848.js";import"./index-30b8f89a.js";import"./index-9b184148.js";const K=x({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,m=h(),{stackViewEl:d}=w().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=y(),g=F(),a=D(o.files??[]),_=async s=>{const l=B(s);o.allowDragAndDrop&&l&&(a.value=R([...a.value,...l.nodes]))},v=s=>{a.value.splice(s,1)};return I(()=>{m.pageFuncExportMap.set(o.paneKey,{getFiles:()=>C(a.value),setFiles:s=>a.value=s})}),(s,l)=>(V(),E("div",{class:"container",ref_key:"stackViewEl",ref:d,onDrop:_},[n(e(k),{ref:"scroller",class:"file-list",items:a.value.slice(),"item-size":e(i).first,"key-field":"fullpath","item-secondary-size":e(i).second,gridItems:e(u)},{default:S(({item:t,index:r})=>{var c;return[n(b,{idx:r,file:t,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:T=>v(r),"full-screen-preview-image-url":e(z)(t),"extra-tags":(c=t==null?void 0:t.tags)==null?void 0:c.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 W=A(K,[["__scopeId","data-v-0c31f6b2"]]);export{W as default};
|
||||
|
|
@ -0,0 +1 @@
|
|||
.container[data-v-0c31f6b2]{background:var(--zp-secondary-background);height:100%;overflow:auto;display:flex;flex-direction:column}.container .actions-panel[data-v-0c31f6b2]{padding:8px;background-color:var(--zp-primary-background)}.container .file-list[data-v-0c31f6b2]{flex:1;list-style:none;padding:8px;height:var(--pane-max-height);width:100%}.container .file-list .hint[data-v-0c31f6b2]{text-align:center;font-size:2em;padding:30vh 128px 0}
|
||||
|
|
@ -1 +0,0 @@
|
|||
import{u as w,a as y,F as k,d as x}from"./FileItem-70868dea.js";import{d as h,a1 as F,c9 as b,r as D,bh as I,bl as C,U as V,V as E,c,a3 as z,a4 as e,af as S,cP as B,cR as R,a0 as A}from"./index-632e7cf6.js";import"./numInput.vue_vue_type_style_index_0_scoped_55978858_lang-221425da.js";/* empty css */import"./index-a2a27adc.js";import"./_isIterateeCall-582f579a.js";import"./index-9d95a206.js";import"./index-a44b2ffa.js";const K=h({__name:"gridView",props:{tabIdx:{},paneIdx:{},id:{},removable:{type:Boolean},allowDragAndDrop:{type:Boolean},files:{},paneKey:{}},setup(p){const o=p,m=F(),{stackViewEl:d}=w().toRefs(),{itemSize:i,gridItems:u,cellWidth:f}=y(),g=b(),a=D(o.files??[]),_=async s=>{const l=B(s);o.allowDragAndDrop&&l&&(a.value=R([...a.value,...l.nodes]))},v=s=>{a.value.splice(s,1)};return I(()=>{m.pageFuncExportMap.set(o.paneKey,{getFiles:()=>C(a.value),setFiles:s=>a.value=s})}),(s,l)=>(V(),E("div",{class:"container",ref_key:"stackViewEl",ref:d,onDrop:_},[c(e(x),{ref:"scroller",class:"file-list",items:a.value.slice(),"item-size":e(i).first,"key-field":"fullpath","item-secondary-size":e(i).second,gridItems:e(u)},{default:z(({item:t,index:r})=>{var n;return[c(k,{idx:r,file:t,"cell-width":e(f),"enable-close-icon":o.removable,onCloseIconClick:T=>v(r),"full-screen-preview-image-url":e(S)(t),"extra-tags":(n=t==null?void 0:t.tags)==null?void 0:n.map(e(g).tagConvert),"enable-right-click-menu":!1},null,8,["idx","file","cell-width","enable-close-icon","onCloseIconClick","full-screen-preview-image-url","extra-tags"])]}),_:1},8,["items","item-size","item-secondary-size","gridItems"])],544))}});const W=A(K,[["__scopeId","data-v-f35f4802"]]);export{W as default};
|
||||
|
|
@ -1 +0,0 @@
|
|||
.container[data-v-f35f4802]{background:var(--zp-secondary-background);height:100%;overflow:auto;display:flex;flex-direction:column}.container .actions-panel[data-v-f35f4802]{padding:8px;background-color:var(--zp-primary-background)}.container .file-list[data-v-f35f4802]{flex:1;list-style:none;padding:8px;height:var(--pane-max-height);width:100%}.container .file-list .hint[data-v-f35f4802]{text-align:center;font-size:2em;padding:30vh 128px 0}
|
||||
|
|
@ -1 +1 @@
|
|||
import{am as F,r as g,l as P,k as A,O as b,G as R,cc as q,cn as O,cs as z}from"./index-632e7cf6.js";import{u as L,a as Q,b as j,e as H}from"./FileItem-70868dea.js";import{a as T,b as U,c as W}from"./MultiSelectKeep-a8fa9049.js";import{u as B}from"./useGenInfoDiff-021d05e1.js";let K=0;const V=()=>++K,X=(n,i,{dataUpdateStrategy:l="replace"}={})=>{const o=F([""]),c=g(!1),t=g(),a=g(!1);let f=g(-1);const v=new Set,w=e=>{var s;l==="replace"?t.value=e:l==="merge"&&(b((Array.isArray(t.value)||typeof t.value>"u")&&Array.isArray(e),"数据更新策略为合并时仅可用于值为数组的情况"),t.value=[...(s=t==null?void 0:t.value)!==null&&s!==void 0?s:[],...e])},d=e=>A(void 0,void 0,void 0,function*(){if(a.value||c.value&&typeof e>"u")return!1;a.value=!0;const s=V();f.value=s;try{let r;if(typeof e=="number"){if(r=o[e],typeof r!="string")return!1}else r=o[o.length-1];const h=yield n(r);if(v.has(s))return v.delete(s),!1;w(i(h));const u=h.cursor;if((e===o.length-1||typeof e!="number")&&(c.value=!u.has_next,u.has_next)){const m=u.next_cursor||u.next;b(typeof m=="string"),o.push(m)}}finally{f.value===s&&(a.value=!1)}return!0}),p=()=>{v.add(f.value),a.value=!1},x=(e=!1)=>A(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&p(),b(!a.value),o.splice(0,o.length,""),a.value=!1,t.value=void 0,c.value=!1,s&&(yield d())}),I=()=>({next:()=>A(void 0,void 0,void 0,function*(){if(a.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return P({abort:p,load:c,next:d,res:t,loading:a,cursorStack:o,reset:x,[Symbol.asyncIterator]:I,iter:{[Symbol.asyncIterator]:I}})},se=n=>F(X(n,i=>i.files,{dataUpdateStrategy:"merge"})),ne=n=>{const i=F(new Set),l=R(()=>(n.res??[]).filter(y=>!i.has(y.fullpath))),o=q(),{stackViewEl:c,multiSelectedIdxs:t,stack:a,scroller:f,props:v}=L({images:l}).toRefs(),{itemSize:w,gridItems:d,cellWidth:p,onScroll:x}=Q({fetchNext:()=>n.next()}),{showMenuIdx:I}=j(),{onFileDragStart:e,onFileDragEnd:s}=T(),{showGenInfo:r,imageGenInfo:h,q:u,onContextMenuClick:m,onFileItemClick:C}=U({openNext:O}),{previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G}=W({loadNext:()=>n.next()}),J=async(y,S,N)=>{a.value=[{curr:"",files:l.value}],await m(y,S,N)};H("removeFiles",async({paths:y})=>{y.forEach(S=>i.add(S))});const k=()=>{z(l.value)};return{images:l,scroller:f,queue:o,iter:n,onContextMenuClickU:J,stackViewEl:c,previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G,itemSize:w,gridItems:d,showGenInfo:r,imageGenInfo:h,q:u,onContextMenuClick:m,onFileItemClick:C,showMenuIdx:I,multiSelectedIdxs:t,onFileDragStart:e,onFileDragEnd:s,cellWidth:p,onScroll:x,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!n.load;)await n.next();k()},props:v,...B()}};export{se as c,ne as u};
|
||||
import{am as F,r as g,l as P,k as A,O as b,G as R,cc as q,cn as O,cs as z}from"./index-d6594e8e.js";import{u as L,a as Q,b as j,e as H}from"./FileItem-2eb00024.js";import{a as T,b as U,c as W}from"./MultiSelectKeep-ba3817a4.js";import{u as B}from"./useGenInfoDiff-f63a5430.js";let K=0;const V=()=>++K,X=(n,i,{dataUpdateStrategy:l="replace"}={})=>{const o=F([""]),c=g(!1),t=g(),a=g(!1);let f=g(-1);const v=new Set,w=e=>{var s;l==="replace"?t.value=e:l==="merge"&&(b((Array.isArray(t.value)||typeof t.value>"u")&&Array.isArray(e),"数据更新策略为合并时仅可用于值为数组的情况"),t.value=[...(s=t==null?void 0:t.value)!==null&&s!==void 0?s:[],...e])},d=e=>A(void 0,void 0,void 0,function*(){if(a.value||c.value&&typeof e>"u")return!1;a.value=!0;const s=V();f.value=s;try{let r;if(typeof e=="number"){if(r=o[e],typeof r!="string")return!1}else r=o[o.length-1];const h=yield n(r);if(v.has(s))return v.delete(s),!1;w(i(h));const u=h.cursor;if((e===o.length-1||typeof e!="number")&&(c.value=!u.has_next,u.has_next)){const m=u.next_cursor||u.next;b(typeof m=="string"),o.push(m)}}finally{f.value===s&&(a.value=!1)}return!0}),p=()=>{v.add(f.value),a.value=!1},x=(e=!1)=>A(void 0,void 0,void 0,function*(){const{refetch:s,force:r}=typeof e=="object"?e:{refetch:e};r&&p(),b(!a.value),o.splice(0,o.length,""),a.value=!1,t.value=void 0,c.value=!1,s&&(yield d())}),I=()=>({next:()=>A(void 0,void 0,void 0,function*(){if(a.value)throw new Error("不允许同时迭代");return{done:!(yield d()),value:t.value}})});return P({abort:p,load:c,next:d,res:t,loading:a,cursorStack:o,reset:x,[Symbol.asyncIterator]:I,iter:{[Symbol.asyncIterator]:I}})},se=n=>F(X(n,i=>i.files,{dataUpdateStrategy:"merge"})),ne=n=>{const i=F(new Set),l=R(()=>(n.res??[]).filter(y=>!i.has(y.fullpath))),o=q(),{stackViewEl:c,multiSelectedIdxs:t,stack:a,scroller:f,props:v}=L({images:l}).toRefs(),{itemSize:w,gridItems:d,cellWidth:p,onScroll:x}=Q({fetchNext:()=>n.next()}),{showMenuIdx:I}=j(),{onFileDragStart:e,onFileDragEnd:s}=T(),{showGenInfo:r,imageGenInfo:h,q:u,onContextMenuClick:m,onFileItemClick:C}=U({openNext:O}),{previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G}=W({loadNext:()=>n.next()}),J=async(y,S,N)=>{a.value=[{curr:"",files:l.value}],await m(y,S,N)};H("removeFiles",async({paths:y})=>{y.forEach(S=>i.add(S))});const k=()=>{z(l.value)};return{images:l,scroller:f,queue:o,iter:n,onContextMenuClickU:J,stackViewEl:c,previewIdx:_,previewing:E,onPreviewVisibleChange:M,previewImgMove:D,canPreview:G,itemSize:w,gridItems:d,showGenInfo:r,imageGenInfo:h,q:u,onContextMenuClick:m,onFileItemClick:C,showMenuIdx:I,multiSelectedIdxs:t,onFileDragStart:e,onFileDragEnd:s,cellWidth:p,onScroll:x,saveLoadedFileAsJson:k,saveAllFileAsJson:async()=>{for(;!n.load;)await n.next();k()},props:v,...B()}};export{se as c,ne as u};
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{r as o,o as t,cJ as n}from"./index-d6594e8e.js";const a=function(){var e=o(!1);return t(function(){e.value=n()}),e};export{a as u};
|
||||
|
|
@ -1 +1 @@
|
|||
import{d as F,u as S,G as k,an as j,h as d,c as s,aq as U,e6 as W,r as q,bh as G,Z as V,dv as Z,P as N,cb as z}from"./index-632e7cf6.js";var H=function(){return{prefixCls:String,checked:{type:Boolean,default:void 0},onChange:{type:Function},onClick:{type:Function},"onUpdate:checked":Function}},J=F({compatConfig:{MODE:3},name:"ACheckableTag",props:H(),setup:function(e,i){var l=i.slots,r=i.emit,g=S("tag",e),u=g.prefixCls,o=function(C){var v=e.checked;r("update:checked",!v),r("change",!v),r("click",C)},p=k(function(){var a;return j(u.value,(a={},d(a,"".concat(u.value,"-checkable"),!0),d(a,"".concat(u.value,"-checkable-checked"),e.checked),a))});return function(){var a;return s("span",{class:p.value,onClick:o},[(a=l.default)===null||a===void 0?void 0:a.call(l)])}}});const b=J;var K=new RegExp("^(".concat(U.join("|"),")(-inverse)?$")),L=new RegExp("^(".concat(W.join("|"),")$")),Q=function(){return{prefixCls:String,color:{type:String},closable:{type:Boolean,default:!1},closeIcon:N.any,visible:{type:Boolean,default:void 0},onClose:{type:Function},"onUpdate:visible":Function,icon:N.any}},f=F({compatConfig:{MODE:3},name:"ATag",props:Q(),slots:["closeIcon","icon"],setup:function(e,i){var l=i.slots,r=i.emit,g=i.attrs,u=S("tag",e),o=u.prefixCls,p=u.direction,a=q(!0);G(function(){e.visible!==void 0&&(a.value=e.visible)});var C=function(t){t.stopPropagation(),r("update:visible",!1),r("close",t),!t.defaultPrevented&&e.visible===void 0&&(a.value=!1)},v=k(function(){var n=e.color;return n?K.test(n)||L.test(n):!1}),E=k(function(){var n;return j(o.value,(n={},d(n,"".concat(o.value,"-").concat(e.color),v.value),d(n,"".concat(o.value,"-has-color"),e.color&&!v.value),d(n,"".concat(o.value,"-hidden"),!a.value),d(n,"".concat(o.value,"-rtl"),p.value==="rtl"),n))});return function(){var n,t,h,m=e.icon,R=m===void 0?(n=l.icon)===null||n===void 0?void 0:n.call(l):m,y=e.color,_=e.closeIcon,P=_===void 0?(t=l.closeIcon)===null||t===void 0?void 0:t.call(l):_,x=e.closable,w=x===void 0?!1:x,B=function(){return w?P?s("span",{class:"".concat(o.value,"-close-icon"),onClick:C},[P]):s(z,{class:"".concat(o.value,"-close-icon"),onClick:C},null):null},O={backgroundColor:y&&!v.value?y:void 0},I=R||null,T=(h=l.default)===null||h===void 0?void 0:h.call(l),A=I?s(V,null,[I,s("span",null,[T])]):T,D="onClick"in g,$=s("span",{class:E.value,style:O},[A,B()]);return D?s(Z,null,{default:function(){return[$]}}):$}}});f.CheckableTag=b;f.install=function(c){return c.component(f.name,f),c.component(b.name,b),c};const Y=f;export{Y as _};
|
||||
import{d as F,u as S,G as k,an as j,h as d,c as s,aq as U,e7 as W,r as q,bh as G,Z as V,dw as Z,P as N,cb as z}from"./index-d6594e8e.js";var H=function(){return{prefixCls:String,checked:{type:Boolean,default:void 0},onChange:{type:Function},onClick:{type:Function},"onUpdate:checked":Function}},J=F({compatConfig:{MODE:3},name:"ACheckableTag",props:H(),setup:function(e,i){var l=i.slots,r=i.emit,g=S("tag",e),u=g.prefixCls,o=function(C){var v=e.checked;r("update:checked",!v),r("change",!v),r("click",C)},p=k(function(){var a;return j(u.value,(a={},d(a,"".concat(u.value,"-checkable"),!0),d(a,"".concat(u.value,"-checkable-checked"),e.checked),a))});return function(){var a;return s("span",{class:p.value,onClick:o},[(a=l.default)===null||a===void 0?void 0:a.call(l)])}}});const b=J;var K=new RegExp("^(".concat(U.join("|"),")(-inverse)?$")),L=new RegExp("^(".concat(W.join("|"),")$")),Q=function(){return{prefixCls:String,color:{type:String},closable:{type:Boolean,default:!1},closeIcon:N.any,visible:{type:Boolean,default:void 0},onClose:{type:Function},"onUpdate:visible":Function,icon:N.any}},f=F({compatConfig:{MODE:3},name:"ATag",props:Q(),slots:["closeIcon","icon"],setup:function(e,i){var l=i.slots,r=i.emit,g=i.attrs,u=S("tag",e),o=u.prefixCls,p=u.direction,a=q(!0);G(function(){e.visible!==void 0&&(a.value=e.visible)});var C=function(t){t.stopPropagation(),r("update:visible",!1),r("close",t),!t.defaultPrevented&&e.visible===void 0&&(a.value=!1)},v=k(function(){var n=e.color;return n?K.test(n)||L.test(n):!1}),E=k(function(){var n;return j(o.value,(n={},d(n,"".concat(o.value,"-").concat(e.color),v.value),d(n,"".concat(o.value,"-has-color"),e.color&&!v.value),d(n,"".concat(o.value,"-hidden"),!a.value),d(n,"".concat(o.value,"-rtl"),p.value==="rtl"),n))});return function(){var n,t,h,m=e.icon,w=m===void 0?(n=l.icon)===null||n===void 0?void 0:n.call(l):m,y=e.color,_=e.closeIcon,P=_===void 0?(t=l.closeIcon)===null||t===void 0?void 0:t.call(l):_,x=e.closable,R=x===void 0?!1:x,B=function(){return R?P?s("span",{class:"".concat(o.value,"-close-icon"),onClick:C},[P]):s(z,{class:"".concat(o.value,"-close-icon"),onClick:C},null):null},O={backgroundColor:y&&!v.value?y:void 0},I=w||null,T=(h=l.default)===null||h===void 0?void 0:h.call(l),A=I?s(V,null,[I,s("span",null,[T])]):T,D="onClick"in g,$=s("span",{class:E.value,style:O},[A,B()]);return D?s(Z,null,{default:function(){return[$]}}):$}}});f.CheckableTag=b;f.install=function(c){return c.component(f.name,f),c.component(b.name,b),c};const Y=f;export{Y as _};
|
||||
|
|
@ -1 +1 @@
|
|||
import{d as w,bC as D,av as A,cJ as j,az as k,n as V,cK as B,cL as y,e as $,c as a,_ as M,h as r,a as P,cM as T,P as b}from"./index-632e7cf6.js";var J=["class","style"],K=function(){return{prefixCls:String,spinning:{type:Boolean,default:void 0},size:String,wrapperClassName:String,tip:b.any,delay:Number,indicator:b.any}},p=null;function L(t,n){return!!t&&!!n&&!isNaN(Number(n))}function W(t){var n=t.indicator;p=typeof n=="function"?n:function(){return a(n,null,null)}}const q=w({compatConfig:{MODE:3},name:"ASpin",inheritAttrs:!1,props:D(K(),{size:"default",spinning:!0,wrapperClassName:""}),setup:function(){return{originalUpdateSpinning:null,configProvider:A("configProvider",j)}},data:function(){var n=this.spinning,e=this.delay,i=L(n,e);return{sSpinning:n&&!i}},created:function(){this.originalUpdateSpinning=this.updateSpinning,this.debouncifyUpdateSpinning(this.$props)},mounted:function(){this.updateSpinning()},updated:function(){var n=this;k(function(){n.debouncifyUpdateSpinning(),n.updateSpinning()})},beforeUnmount:function(){this.cancelExistingSpin()},methods:{debouncifyUpdateSpinning:function(n){var e=n||this.$props,i=e.delay;i&&(this.cancelExistingSpin(),this.updateSpinning=V(this.originalUpdateSpinning,i))},updateSpinning:function(){var n=this.spinning,e=this.sSpinning;e!==n&&(this.sSpinning=n)},cancelExistingSpin:function(){var n=this.updateSpinning;n&&n.cancel&&n.cancel()},renderIndicator:function(n){var e="".concat(n,"-dot"),i=B(this,"indicator");return i===null?null:(Array.isArray(i)&&(i=i.length===1?i[0]:i),y(i)?$(i,{class:e}):p&&y(p())?$(p(),{class:e}):a("span",{class:"".concat(e," ").concat(n,"-dot-spin")},[a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null)]))}},render:function(){var n,e,i,o=this.$props,f=o.size,x=o.prefixCls,h=o.tip,d=h===void 0?(n=(e=this.$slots).tip)===null||n===void 0?void 0:n.call(e):h,N=o.wrapperClassName,l=this.$attrs,v=l.class,_=l.style,C=M(l,J),S=this.configProvider,U=S.getPrefixCls,z=S.direction,s=U("spin",x),u=this.sSpinning,E=(i={},r(i,s,!0),r(i,"".concat(s,"-sm"),f==="small"),r(i,"".concat(s,"-lg"),f==="large"),r(i,"".concat(s,"-spinning"),u),r(i,"".concat(s,"-show-text"),!!d),r(i,"".concat(s,"-rtl"),z==="rtl"),r(i,v,!!v),i),m=a("div",P(P({},C),{},{style:_,class:E}),[this.renderIndicator(s),d?a("div",{class:"".concat(s,"-text")},[d]):null]),g=T(this);if(g&&g.length){var c,I=(c={},r(c,"".concat(s,"-container"),!0),r(c,"".concat(s,"-blur"),u),c);return a("div",{class:["".concat(s,"-nested-loading"),N]},[u&&a("div",{key:"loading"},[m]),a("div",{class:I,key:"container"},[g])])}return m}});export{q as S,W as s};
|
||||
import{d as w,bC as D,av as A,cK as j,az as k,n as V,cL as B,cM as y,e as $,c as a,_ as M,h as r,a as P,cN as T,P as b}from"./index-d6594e8e.js";var K=["class","style"],L=function(){return{prefixCls:String,spinning:{type:Boolean,default:void 0},size:String,wrapperClassName:String,tip:b.any,delay:Number,indicator:b.any}},p=null;function O(t,n){return!!t&&!!n&&!isNaN(Number(n))}function q(t){var n=t.indicator;p=typeof n=="function"?n:function(){return a(n,null,null)}}const F=w({compatConfig:{MODE:3},name:"ASpin",inheritAttrs:!1,props:D(L(),{size:"default",spinning:!0,wrapperClassName:""}),setup:function(){return{originalUpdateSpinning:null,configProvider:A("configProvider",j)}},data:function(){var n=this.spinning,e=this.delay,i=O(n,e);return{sSpinning:n&&!i}},created:function(){this.originalUpdateSpinning=this.updateSpinning,this.debouncifyUpdateSpinning(this.$props)},mounted:function(){this.updateSpinning()},updated:function(){var n=this;k(function(){n.debouncifyUpdateSpinning(),n.updateSpinning()})},beforeUnmount:function(){this.cancelExistingSpin()},methods:{debouncifyUpdateSpinning:function(n){var e=n||this.$props,i=e.delay;i&&(this.cancelExistingSpin(),this.updateSpinning=V(this.originalUpdateSpinning,i))},updateSpinning:function(){var n=this.spinning,e=this.sSpinning;e!==n&&(this.sSpinning=n)},cancelExistingSpin:function(){var n=this.updateSpinning;n&&n.cancel&&n.cancel()},renderIndicator:function(n){var e="".concat(n,"-dot"),i=B(this,"indicator");return i===null?null:(Array.isArray(i)&&(i=i.length===1?i[0]:i),y(i)?$(i,{class:e}):p&&y(p())?$(p(),{class:e}):a("span",{class:"".concat(e," ").concat(n,"-dot-spin")},[a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null),a("i",{class:"".concat(n,"-dot-item")},null)]))}},render:function(){var n,e,i,o=this.$props,f=o.size,N=o.prefixCls,h=o.tip,d=h===void 0?(n=(e=this.$slots).tip)===null||n===void 0?void 0:n.call(e):h,x=o.wrapperClassName,l=this.$attrs,v=l.class,_=l.style,C=M(l,K),S=this.configProvider,U=S.getPrefixCls,z=S.direction,s=U("spin",N),u=this.sSpinning,E=(i={},r(i,s,!0),r(i,"".concat(s,"-sm"),f==="small"),r(i,"".concat(s,"-lg"),f==="large"),r(i,"".concat(s,"-spinning"),u),r(i,"".concat(s,"-show-text"),!!d),r(i,"".concat(s,"-rtl"),z==="rtl"),r(i,v,!!v),i),m=a("div",P(P({},C),{},{style:_,class:E}),[this.renderIndicator(s),d?a("div",{class:"".concat(s,"-text")},[d]):null]),g=T(this);if(g&&g.length){var c,I=(c={},r(c,"".concat(s,"-container"),!0),r(c,"".concat(s,"-blur"),u),c);return a("div",{class:["".concat(s,"-nested-loading"),x]},[u&&a("div",{key:"loading"},[m]),a("div",{class:I,key:"container"},[g])])}return m}});export{F as S,q as s};
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{av as M,G as l,ax as D,ay as P,d as F,u as I,r as K,o as L,cx as _,b as y,bk as T,cy as A,an as $,h as o,c as B,a as G}from"./index-d6594e8e.js";import{u as V}from"./index-154b94da.js";var E=Symbol("rowContextKey"),W=function(r){D(E,r)},k=function(){return M(E,{gutter:l(function(){}),wrap:l(function(){}),supportFlexGap:l(function(){})})};P("top","middle","bottom","stretch");P("start","end","center","space-around","space-between");var U=function(){return{align:String,justify:String,prefixCls:String,gutter:{type:[Number,Array,Object],default:0},wrap:{type:Boolean,default:void 0}}},q=F({compatConfig:{MODE:3},name:"ARow",props:U(),setup:function(r,N){var g=N.slots,v=I("row",r),d=v.prefixCls,h=v.direction,j,x=K({xs:!0,sm:!0,md:!0,lg:!0,xl:!0,xxl:!0,xxxl:!0}),w=V();L(function(){j=_.subscribe(function(e){var t=r.gutter||0;(!Array.isArray(t)&&y(t)==="object"||Array.isArray(t)&&(y(t[0])==="object"||y(t[1])==="object"))&&(x.value=e)})}),T(function(){_.unsubscribe(j)});var S=l(function(){var e=[0,0],t=r.gutter,n=t===void 0?0:t,s=Array.isArray(n)?n:[n,0];return s.forEach(function(i,b){if(y(i)==="object")for(var a=0;a<A.length;a++){var p=A[a];if(x.value[p]&&i[p]!==void 0){e[b]=i[p];break}}else e[b]=i||0}),e});W({gutter:S,supportFlexGap:w,wrap:l(function(){return r.wrap})});var R=l(function(){var e;return $(d.value,(e={},o(e,"".concat(d.value,"-no-wrap"),r.wrap===!1),o(e,"".concat(d.value,"-").concat(r.justify),r.justify),o(e,"".concat(d.value,"-").concat(r.align),r.align),o(e,"".concat(d.value,"-rtl"),h.value==="rtl"),e))}),O=l(function(){var e=S.value,t={},n=e[0]>0?"".concat(e[0]/-2,"px"):void 0,s=e[1]>0?"".concat(e[1]/-2,"px"):void 0;return n&&(t.marginLeft=n,t.marginRight=n),w.value?t.rowGap="".concat(e[1],"px"):s&&(t.marginTop=s,t.marginBottom=s),t});return function(){var e;return B("div",{class:R.value,style:O.value},[(e=g.default)===null||e===void 0?void 0:e.call(g)])}}});const Y=q;function H(c){return typeof c=="number"?"".concat(c," ").concat(c," auto"):/^\d+(\.\d+)?(px|em|rem|%)$/.test(c)?"0 0 ".concat(c):c}var J=function(){return{span:[String,Number],order:[String,Number],offset:[String,Number],push:[String,Number],pull:[String,Number],xs:{type:[String,Number,Object],default:void 0},sm:{type:[String,Number,Object],default:void 0},md:{type:[String,Number,Object],default:void 0},lg:{type:[String,Number,Object],default:void 0},xl:{type:[String,Number,Object],default:void 0},xxl:{type:[String,Number,Object],default:void 0},xxxl:{type:[String,Number,Object],default:void 0},prefixCls:String,flex:[String,Number]}};const Z=F({compatConfig:{MODE:3},name:"ACol",props:J(),setup:function(r,N){var g=N.slots,v=k(),d=v.gutter,h=v.supportFlexGap,j=v.wrap,x=I("col",r),w=x.prefixCls,S=x.direction,R=l(function(){var e,t=r.span,n=r.order,s=r.offset,i=r.push,b=r.pull,a=w.value,p={};return["xs","sm","md","lg","xl","xxl","xxxl"].forEach(function(m){var f,u={},C=r[m];typeof C=="number"?u.span=C:y(C)==="object"&&(u=C||{}),p=G(G({},p),{},(f={},o(f,"".concat(a,"-").concat(m,"-").concat(u.span),u.span!==void 0),o(f,"".concat(a,"-").concat(m,"-order-").concat(u.order),u.order||u.order===0),o(f,"".concat(a,"-").concat(m,"-offset-").concat(u.offset),u.offset||u.offset===0),o(f,"".concat(a,"-").concat(m,"-push-").concat(u.push),u.push||u.push===0),o(f,"".concat(a,"-").concat(m,"-pull-").concat(u.pull),u.pull||u.pull===0),o(f,"".concat(a,"-rtl"),S.value==="rtl"),f))}),$(a,(e={},o(e,"".concat(a,"-").concat(t),t!==void 0),o(e,"".concat(a,"-order-").concat(n),n),o(e,"".concat(a,"-offset-").concat(s),s),o(e,"".concat(a,"-push-").concat(i),i),o(e,"".concat(a,"-pull-").concat(b),b),e),p)}),O=l(function(){var e=r.flex,t=d.value,n={};if(t&&t[0]>0){var s="".concat(t[0]/2,"px");n.paddingLeft=s,n.paddingRight=s}if(t&&t[1]>0&&!h.value){var i="".concat(t[1]/2,"px");n.paddingTop=i,n.paddingBottom=i}return e&&(n.flex=H(e),j.value===!1&&!n.minWidth&&(n.minWidth=0)),n});return function(){var e;return B("div",{class:R.value,style:O.value},[(e=g.default)===null||e===void 0?void 0:e.call(g)])}}});export{Z as C,Y as R};
|
||||
|
|
@ -0,0 +1 @@
|
|||
.container[data-v-e55e3025]{background:var(--zp-secondary-background);height:100%;overflow:auto;display:flex;flex-direction:column;padding:16px}.container .actions[data-v-e55e3025]{margin-bottom:16px}.container .actions *[data-v-e55e3025]{margin-right:10px}.snapshot[data-v-e55e3025]{list-style:none;padding:0;margin:0;width:512px}.snapshot li[data-v-e55e3025]{display:flex;justify-content:space-between;align-items:center;padding:10px;background-color:var(--zp-secondary-variant-background);border-radius:4px;margin-bottom:10px;transition:all .3s ease;border-bottom:2px solid var(--zp-luminous-deep)}.snapshot li[data-v-e55e3025]:hover{border-bottom:2px solid var(--zp-luminous)}.snapshot li div[data-v-e55e3025]:first-child{flex-grow:1;font-weight:700}.snapshot li div[data-v-e55e3025]:last-child{display:flex;gap:10px}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +0,0 @@
|
|||
import{r as F,o as P,cx as K,av as L,G as i,ax as T,ay as I,d as $,u as B,cy as _,b as y,bk as V,cz as A,an as E,h as c,c as M,a as G}from"./index-632e7cf6.js";const W=function(){var o=F(!1);return P(function(){o.value=K()}),o};var D=Symbol("rowContextKey"),k=function(r){T(D,r)},U=function(){return L(D,{gutter:i(function(){}),wrap:i(function(){}),supportFlexGap:i(function(){})})};I("top","middle","bottom","stretch");I("start","end","center","space-around","space-between");var q=function(){return{align:String,justify:String,prefixCls:String,gutter:{type:[Number,Array,Object],default:0},wrap:{type:Boolean,default:void 0}}},z=$({compatConfig:{MODE:3},name:"ARow",props:q(),setup:function(r,N){var m=N.slots,v=B("row",r),d=v.prefixCls,h=v.direction,j,x=F({xs:!0,sm:!0,md:!0,lg:!0,xl:!0,xxl:!0,xxxl:!0}),S=W();P(function(){j=_.subscribe(function(e){var t=r.gutter||0;(!Array.isArray(t)&&y(t)==="object"||Array.isArray(t)&&(y(t[0])==="object"||y(t[1])==="object"))&&(x.value=e)})}),V(function(){_.unsubscribe(j)});var w=i(function(){var e=[0,0],t=r.gutter,n=t===void 0?0:t,s=Array.isArray(n)?n:[n,0];return s.forEach(function(l,b){if(y(l)==="object")for(var a=0;a<A.length;a++){var p=A[a];if(x.value[p]&&l[p]!==void 0){e[b]=l[p];break}}else e[b]=l||0}),e});k({gutter:w,supportFlexGap:S,wrap:i(function(){return r.wrap})});var R=i(function(){var e;return E(d.value,(e={},c(e,"".concat(d.value,"-no-wrap"),r.wrap===!1),c(e,"".concat(d.value,"-").concat(r.justify),r.justify),c(e,"".concat(d.value,"-").concat(r.align),r.align),c(e,"".concat(d.value,"-rtl"),h.value==="rtl"),e))}),O=i(function(){var e=w.value,t={},n=e[0]>0?"".concat(e[0]/-2,"px"):void 0,s=e[1]>0?"".concat(e[1]/-2,"px"):void 0;return n&&(t.marginLeft=n,t.marginRight=n),S.value?t.rowGap="".concat(e[1],"px"):s&&(t.marginTop=s,t.marginBottom=s),t});return function(){var e;return M("div",{class:R.value,style:O.value},[(e=m.default)===null||e===void 0?void 0:e.call(m)])}}});const X=z;function H(o){return typeof o=="number"?"".concat(o," ").concat(o," auto"):/^\d+(\.\d+)?(px|em|rem|%)$/.test(o)?"0 0 ".concat(o):o}var J=function(){return{span:[String,Number],order:[String,Number],offset:[String,Number],push:[String,Number],pull:[String,Number],xs:{type:[String,Number,Object],default:void 0},sm:{type:[String,Number,Object],default:void 0},md:{type:[String,Number,Object],default:void 0},lg:{type:[String,Number,Object],default:void 0},xl:{type:[String,Number,Object],default:void 0},xxl:{type:[String,Number,Object],default:void 0},xxxl:{type:[String,Number,Object],default:void 0},prefixCls:String,flex:[String,Number]}};const Y=$({compatConfig:{MODE:3},name:"ACol",props:J(),setup:function(r,N){var m=N.slots,v=U(),d=v.gutter,h=v.supportFlexGap,j=v.wrap,x=B("col",r),S=x.prefixCls,w=x.direction,R=i(function(){var e,t=r.span,n=r.order,s=r.offset,l=r.push,b=r.pull,a=S.value,p={};return["xs","sm","md","lg","xl","xxl","xxxl"].forEach(function(g){var f,u={},C=r[g];typeof C=="number"?u.span=C:y(C)==="object"&&(u=C||{}),p=G(G({},p),{},(f={},c(f,"".concat(a,"-").concat(g,"-").concat(u.span),u.span!==void 0),c(f,"".concat(a,"-").concat(g,"-order-").concat(u.order),u.order||u.order===0),c(f,"".concat(a,"-").concat(g,"-offset-").concat(u.offset),u.offset||u.offset===0),c(f,"".concat(a,"-").concat(g,"-push-").concat(u.push),u.push||u.push===0),c(f,"".concat(a,"-").concat(g,"-pull-").concat(u.pull),u.pull||u.pull===0),c(f,"".concat(a,"-rtl"),w.value==="rtl"),f))}),E(a,(e={},c(e,"".concat(a,"-").concat(t),t!==void 0),c(e,"".concat(a,"-order-").concat(n),n),c(e,"".concat(a,"-offset-").concat(s),s),c(e,"".concat(a,"-push-").concat(l),l),c(e,"".concat(a,"-pull-").concat(b),b),e),p)}),O=i(function(){var e=r.flex,t=d.value,n={};if(t&&t[0]>0){var s="".concat(t[0]/2,"px");n.paddingLeft=s,n.paddingRight=s}if(t&&t[1]>0&&!h.value){var l="".concat(t[1]/2,"px");n.paddingTop=l,n.paddingBottom=l}return e&&(n.flex=H(e),j.value===!1&&!n.minWidth&&(n.minWidth=0)),n});return function(){var e;return M("div",{class:R.value,style:O.value},[(e=m.default)===null||e===void 0?void 0:e.call(m)])}}});export{Y as C,X as R};
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
import{d as x,a1 as $,aK as g,cS as b,r as w,U as p,V as i,W as a,c as r,a3 as d,X as u,Y as n,Z as B,a8 as I,a4 as m,y as V,z as _,B as v,aj as W,ak as D,cT as N,a0 as R}from"./index-632e7cf6.js";/* empty css */const F={class:"container"},K={class:"actions"},L={class:"uni-desc"},T={class:"snapshot"},U=x({__name:"index",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(j){const h=$(),t=g(),f=e=>{h.tabList=V(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(""),y=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 C=W,l=D;return p(),i("div",F,[a("div",K,[r(C,{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"]),r(l,{type:"primary",onClick:y},{default:d(()=>[u(n(e.$t("saveWorkspaceSnapshot")),1)]),_:1})]),a("p",L,n(e.$t("WorkspaceSnapshotDesc")),1),a("ul",T,[(p(!0),i(B,null,I(m(t).snapshots,s=>(p(),i("li",{key:s.id},[a("div",null,[a("span",null,n(s.name),1)]),a("div",null,[r(l,{onClick:S=>f(s)},{default:d(()=>[u(n(e.$t("restore")),1)]),_:2},1032,["onClick"]),r(l,{onClick:S=>m(k)(s)},{default:d(()=>[u(n(e.$t("remove")),1)]),_:2},1032,["onClick"])])]))),128))])])}}});const A=R(U,[["__scopeId","data-v-2c44013c"]]);export{A as default};
|
||||
import{d as x,a1 as $,aK as g,cT as b,r as w,U as p,V as i,W as a,c as r,a3 as d,X as u,Y as n,Z as B,a8 as I,a4 as m,y as V,z as _,B as v,aj as W,ak as D,cU as N,a0 as R}from"./index-d6594e8e.js";/* empty css */const U={class:"container"},F={class:"actions"},K={class:"uni-desc"},L={class:"snapshot"},T=x({__name:"index",props:{tabIdx:{},paneIdx:{},id:{},paneKey:{}},setup(j){const h=$(),t=g(),f=e=>{h.tabList=V(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(""),y=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 C=W,l=D;return p(),i("div",U,[a("div",F,[r(C,{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"]),r(l,{type:"primary",onClick:y},{default:d(()=>[u(n(e.$t("saveWorkspaceSnapshot")),1)]),_:1})]),a("p",K,n(e.$t("WorkspaceSnapshotDesc")),1),a("ul",L,[(p(!0),i(B,null,I(m(t).snapshots,s=>(p(),i("li",{key:s.id},[a("div",null,[a("span",null,n(s.name),1)]),a("div",null,[r(l,{onClick:S=>f(s)},{default:d(()=>[u(n(e.$t("restore")),1)]),_:2},1032,["onClick"]),r(l,{onClick:S=>m(k)(s)},{default:d(()=>[u(n(e.$t("remove")),1)]),_:2},1032,["onClick"])])]))),128))])])}}});const A=R(T,[["__scopeId","data-v-e55e3025"]]);export{A as default};
|
||||
|
|
@ -1 +0,0 @@
|
|||
.container[data-v-2c44013c]{background:var(--zp-secondary-background);height:100%;overflow:auto;display:flex;flex-direction:column;padding:16px}.container .actions[data-v-2c44013c]{margin-bottom:16px}.container .actions *[data-v-2c44013c]{margin-right:10px}.snapshot[data-v-2c44013c]{list-style:none;padding:0;margin:0;width:512px}.snapshot li[data-v-2c44013c]{display:flex;justify-content:space-between;align-items:center;padding:10px;background-color:var(--zp-secondary-variant-background);border-radius:4px;margin-bottom:10px;transition:all .3s ease;border-bottom:2px solid var(--zp-luminous-deep)}.snapshot li[data-v-2c44013c]:hover{border-bottom:2px solid var(--zp-luminous)}.snapshot li div[data-v-2c44013c]:first-child{flex-grow:1;font-weight:700}.snapshot li div[data-v-2c44013c]:last-child{display:flex;gap:10px}
|
||||
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{cw as j,ay as z,d as K,j as U,du as $,w as g,r as b,G as S,m as A,u as D,o as E,az as G,h as d,c as s,a as C,aw as H,bf as L,g as _,dv as W,P as u,dw as x}from"./index-632e7cf6.js";var R=z("small","default"),q=function(){return{id:String,prefixCls:String,size:u.oneOf(R),disabled:{type:Boolean,default:void 0},checkedChildren:u.any,unCheckedChildren:u.any,tabindex:u.oneOfType([u.string,u.number]),autofocus:{type:Boolean,default:void 0},loading:{type:Boolean,default:void 0},checked:u.oneOfType([u.string,u.number,u.looseBool]),checkedValue:u.oneOfType([u.string,u.number,u.looseBool]).def(!0),unCheckedValue:u.oneOfType([u.string,u.number,u.looseBool]).def(!1),onChange:{type:Function},onClick:{type:Function},onKeydown:{type:Function},onMouseup:{type:Function},"onUpdate:checked":{type:Function},onBlur:Function,onFocus:Function}},J=K({compatConfig:{MODE:3},name:"ASwitch",__ANT_SWITCH:!0,inheritAttrs:!1,props:q(),slots:["checkedChildren","unCheckedChildren"],setup:function(n,r){var o=r.attrs,y=r.slots,B=r.expose,l=r.emit,m=U();$(function(){g(!("defaultChecked"in o),"Switch","'defaultChecked' is deprecated, please use 'v-model:checked'"),g(!("value"in o),"Switch","`value` is not validate prop, do you mean `checked`?")});var h=b(n.checked!==void 0?n.checked:o.defaultChecked),f=S(function(){return h.value===n.checkedValue});A(function(){return n.checked},function(){h.value=n.checked});var v=D("switch",n),c=v.prefixCls,F=v.direction,T=v.size,i=b(),w=function(){var e;(e=i.value)===null||e===void 0||e.focus()},V=function(){var e;(e=i.value)===null||e===void 0||e.blur()};B({focus:w,blur:V}),E(function(){G(function(){n.autofocus&&!n.disabled&&i.value.focus()})});var k=function(e,t){n.disabled||(l("update:checked",e),l("change",e,t),m.onFieldChange())},I=function(e){l("blur",e)},N=function(e){w();var t=f.value?n.unCheckedValue:n.checkedValue;k(t,e),l("click",t,e)},M=function(e){e.keyCode===x.LEFT?k(n.unCheckedValue,e):e.keyCode===x.RIGHT&&k(n.checkedValue,e),l("keydown",e)},O=function(e){var t;(t=i.value)===null||t===void 0||t.blur(),l("mouseup",e)},P=S(function(){var a;return a={},d(a,"".concat(c.value,"-small"),T.value==="small"),d(a,"".concat(c.value,"-loading"),n.loading),d(a,"".concat(c.value,"-checked"),f.value),d(a,"".concat(c.value,"-disabled"),n.disabled),d(a,c.value,!0),d(a,"".concat(c.value,"-rtl"),F.value==="rtl"),a});return function(){var a;return s(W,{insertExtraNode:!0},{default:function(){return[s("button",C(C(C({},H(n,["prefixCls","checkedChildren","unCheckedChildren","checked","autofocus","checkedValue","unCheckedValue","id","onChange","onUpdate:checked"])),o),{},{id:(a=n.id)!==null&&a!==void 0?a:m.id.value,onKeydown:M,onClick:N,onBlur:I,onMouseup:O,type:"button",role:"switch","aria-checked":h.value,disabled:n.disabled||n.loading,class:[o.class,P.value],ref:i}),[s("div",{class:"".concat(c.value,"-handle")},[n.loading?s(L,{class:"".concat(c.value,"-loading-icon")},null):null]),s("span",{class:"".concat(c.value,"-inner")},[f.value?_(y,n,"checkedChildren"):_(y,n,"unCheckedChildren")])])]}})}}});const X=j(J);export{X as _};
|
||||
import{cw as j,ay as z,d as K,j as U,dv as $,w as g,r as b,G as S,m as A,u as D,o as E,az as G,h as d,c as s,a as C,aw as H,bf as L,g as x,dw as W,P as c,dx as _}from"./index-d6594e8e.js";var R=z("small","default"),q=function(){return{id:String,prefixCls:String,size:c.oneOf(R),disabled:{type:Boolean,default:void 0},checkedChildren:c.any,unCheckedChildren:c.any,tabindex:c.oneOfType([c.string,c.number]),autofocus:{type:Boolean,default:void 0},loading:{type:Boolean,default:void 0},checked:c.oneOfType([c.string,c.number,c.looseBool]),checkedValue:c.oneOfType([c.string,c.number,c.looseBool]).def(!0),unCheckedValue:c.oneOfType([c.string,c.number,c.looseBool]).def(!1),onChange:{type:Function},onClick:{type:Function},onKeydown:{type:Function},onMouseup:{type:Function},"onUpdate:checked":{type:Function},onBlur:Function,onFocus:Function}},J=K({compatConfig:{MODE:3},name:"ASwitch",__ANT_SWITCH:!0,inheritAttrs:!1,props:q(),slots:["checkedChildren","unCheckedChildren"],setup:function(n,r){var o=r.attrs,y=r.slots,B=r.expose,l=r.emit,m=U();$(function(){g(!("defaultChecked"in o),"Switch","'defaultChecked' is deprecated, please use 'v-model:checked'"),g(!("value"in o),"Switch","`value` is not validate prop, do you mean `checked`?")});var h=b(n.checked!==void 0?n.checked:o.defaultChecked),f=S(function(){return h.value===n.checkedValue});A(function(){return n.checked},function(){h.value=n.checked});var v=D("switch",n),u=v.prefixCls,F=v.direction,T=v.size,i=b(),w=function(){var e;(e=i.value)===null||e===void 0||e.focus()},V=function(){var e;(e=i.value)===null||e===void 0||e.blur()};B({focus:w,blur:V}),E(function(){G(function(){n.autofocus&&!n.disabled&&i.value.focus()})});var k=function(e,t){n.disabled||(l("update:checked",e),l("change",e,t),m.onFieldChange())},I=function(e){l("blur",e)},N=function(e){w();var t=f.value?n.unCheckedValue:n.checkedValue;k(t,e),l("click",t,e)},M=function(e){e.keyCode===_.LEFT?k(n.unCheckedValue,e):e.keyCode===_.RIGHT&&k(n.checkedValue,e),l("keydown",e)},O=function(e){var t;(t=i.value)===null||t===void 0||t.blur(),l("mouseup",e)},P=S(function(){var a;return a={},d(a,"".concat(u.value,"-small"),T.value==="small"),d(a,"".concat(u.value,"-loading"),n.loading),d(a,"".concat(u.value,"-checked"),f.value),d(a,"".concat(u.value,"-disabled"),n.disabled),d(a,u.value,!0),d(a,"".concat(u.value,"-rtl"),F.value==="rtl"),a});return function(){var a;return s(W,{insertExtraNode:!0},{default:function(){return[s("button",C(C(C({},H(n,["prefixCls","checkedChildren","unCheckedChildren","checked","autofocus","checkedValue","unCheckedValue","id","onChange","onUpdate:checked"])),o),{},{id:(a=n.id)!==null&&a!==void 0?a:m.id.value,onKeydown:M,onClick:N,onBlur:I,onMouseup:O,type:"button",role:"switch","aria-checked":h.value,disabled:n.disabled||n.loading,class:[o.class,P.value],ref:i}),[s("div",{class:"".concat(u.value,"-handle")},[n.loading?s(L,{class:"".concat(u.value,"-loading-icon")},null):null]),s("span",{class:"".concat(u.value,"-inner")},[f.value?x(y,n,"checkedChildren"):x(y,n,"unCheckedChildren")])])]}})}}});const X=j(J);export{X as _};
|
||||
|
|
@ -0,0 +1 @@
|
|||
import{cl as e,cm as i,cn as r,co as a,b1 as n}from"./index-d6594e8e.js";function c(s,t){return e(i(s,t,r),s+"")}function b(s){return a(s)&&n(s)}export{c as b,b as i};
|
||||
|
|
@ -1 +0,0 @@
|
|||
import{cl as e,cm as i,cn as r,co as a,b1 as n}from"./index-632e7cf6.js";function c(s,t){return e(i(s,t,r),s+"")}function b(s){return a(s)&&n(s)}export{c as b,b as i};
|
||||
|
|
@ -1 +1 @@
|
|||
.ant-slider{box-sizing:border-box;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;height:12px;margin:10px 6px;padding:4px 0;cursor:pointer;touch-action:none}.ant-slider-vertical{width:12px;height:100%;margin:6px 10px;padding:0 4px}.ant-slider-vertical .ant-slider-rail{width:4px;height:100%}.ant-slider-vertical .ant-slider-track{width:4px}.ant-slider-vertical .ant-slider-handle{margin-top:-6px;margin-left:-5px}.ant-slider-vertical .ant-slider-mark{top:0;left:12px;width:18px;height:100%}.ant-slider-vertical .ant-slider-mark-text{left:4px;white-space:nowrap}.ant-slider-vertical .ant-slider-step{width:4px;height:100%}.ant-slider-vertical .ant-slider-dot{top:auto;left:2px;margin-bottom:-4px}.ant-slider-tooltip .ant-tooltip-inner{min-width:unset}.ant-slider-rtl.ant-slider-vertical .ant-slider-handle{margin-right:-5px;margin-left:0}.ant-slider-rtl.ant-slider-vertical .ant-slider-mark{right:12px;left:auto}.ant-slider-rtl.ant-slider-vertical .ant-slider-mark-text{right:4px;left:auto}.ant-slider-rtl.ant-slider-vertical .ant-slider-dot{right:2px;left:auto}.ant-slider-with-marks{margin-bottom:28px}.ant-slider-rail{position:absolute;width:100%;height:4px;background-color:#f5f5f5;border-radius:2px;transition:background-color .3s}.ant-slider-track{position:absolute;height:4px;background-color:#f7ae83;border-radius:2px;transition:background-color .3s}.ant-slider-handle{position:absolute;width:14px;height:14px;margin-top:-5px;background-color:#fff;border:solid 2px #f7ae83;border-radius:50%;box-shadow:0;cursor:pointer;transition:border-color .3s,box-shadow .6s,transform .3s cubic-bezier(.18,.89,.32,1.28)}.ant-slider-handle-dragging.ant-slider-handle-dragging.ant-slider-handle-dragging{border-color:#d9653b;box-shadow:0 0 0 5px #d03f0a1f}.ant-slider-handle:focus{border-color:#d9653b;outline:none;box-shadow:0 0 0 5px #d03f0a1f}.ant-slider-handle.ant-tooltip-open{border-color:#d03f0a}.ant-slider:hover .ant-slider-rail{background-color:#e1e1e1}.ant-slider:hover .ant-slider-track{background-color:#eb8857}.ant-slider:hover .ant-slider-handle:not(.ant-tooltip-open){border-color:#eb8857}.ant-slider-mark{position:absolute;top:14px;left:0;width:100%;font-size:14px}.ant-slider-mark-text{position:absolute;display:inline-block;color:#00000073;text-align:center;word-break:keep-all;cursor:pointer;user-select:none}.ant-slider-mark-text-active{color:#000000d9}.ant-slider-step{position:absolute;width:100%;height:4px;background:transparent}.ant-slider-dot{position:absolute;top:-2px;width:8px;height:8px;margin-left:-4px;background-color:#fff;border:2px solid #f0f0f0;border-radius:50%;cursor:pointer}.ant-slider-dot:first-child{margin-left:-4px}.ant-slider-dot:last-child{margin-left:-4px}.ant-slider-dot-active{border-color:#e89f85}.ant-slider-disabled{cursor:not-allowed}.ant-slider-disabled .ant-slider-rail{background-color:#f5f5f5!important}.ant-slider-disabled .ant-slider-track{background-color:#00000040!important}.ant-slider-disabled .ant-slider-handle,.ant-slider-disabled .ant-slider-dot{background-color:#fff;border-color:#00000040!important;box-shadow:none;cursor:not-allowed}.ant-slider-disabled .ant-slider-mark-text,.ant-slider-disabled .ant-slider-dot{cursor:not-allowed!important}.ant-slider-rtl{direction:rtl}.ant-slider-rtl .ant-slider-mark{right:0;left:auto}.ant-slider-rtl .ant-slider-dot,.ant-slider-rtl .ant-slider-dot:first-child{margin-right:-4px;margin-left:0}.ant-slider-rtl .ant-slider-dot:last-child{margin-right:-4px;margin-left:0}.num-input[data-v-55978858]{display:flex}.num-input .slide[data-v-55978858]{flex:1;min-width:128px;max-width:256px;margin-left:8px}
|
||||
.ant-slider{box-sizing:border-box;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";position:relative;height:12px;margin:10px 6px;padding:4px 0;cursor:pointer;touch-action:none}.ant-slider-vertical{width:12px;height:100%;margin:6px 10px;padding:0 4px}.ant-slider-vertical .ant-slider-rail{width:4px;height:100%}.ant-slider-vertical .ant-slider-track{width:4px}.ant-slider-vertical .ant-slider-handle{margin-top:-6px;margin-left:-5px}.ant-slider-vertical .ant-slider-mark{top:0;left:12px;width:18px;height:100%}.ant-slider-vertical .ant-slider-mark-text{left:4px;white-space:nowrap}.ant-slider-vertical .ant-slider-step{width:4px;height:100%}.ant-slider-vertical .ant-slider-dot{top:auto;left:2px;margin-bottom:-4px}.ant-slider-tooltip .ant-tooltip-inner{min-width:unset}.ant-slider-rtl.ant-slider-vertical .ant-slider-handle{margin-right:-5px;margin-left:0}.ant-slider-rtl.ant-slider-vertical .ant-slider-mark{right:12px;left:auto}.ant-slider-rtl.ant-slider-vertical .ant-slider-mark-text{right:4px;left:auto}.ant-slider-rtl.ant-slider-vertical .ant-slider-dot{right:2px;left:auto}.ant-slider-with-marks{margin-bottom:28px}.ant-slider-rail{position:absolute;width:100%;height:4px;background-color:#f5f5f5;border-radius:2px;transition:background-color .3s}.ant-slider-track{position:absolute;height:4px;background-color:#f7ae83;border-radius:2px;transition:background-color .3s}.ant-slider-handle{position:absolute;width:14px;height:14px;margin-top:-5px;background-color:#fff;border:solid 2px #f7ae83;border-radius:50%;box-shadow:0;cursor:pointer;transition:border-color .3s,box-shadow .6s,transform .3s cubic-bezier(.18,.89,.32,1.28)}.ant-slider-handle-dragging.ant-slider-handle-dragging.ant-slider-handle-dragging{border-color:#d9653b;box-shadow:0 0 0 5px #d03f0a1f}.ant-slider-handle:focus{border-color:#d9653b;outline:none;box-shadow:0 0 0 5px #d03f0a1f}.ant-slider-handle.ant-tooltip-open{border-color:#d03f0a}.ant-slider:hover .ant-slider-rail{background-color:#e1e1e1}.ant-slider:hover .ant-slider-track{background-color:#eb8857}.ant-slider:hover .ant-slider-handle:not(.ant-tooltip-open){border-color:#eb8857}.ant-slider-mark{position:absolute;top:14px;left:0;width:100%;font-size:14px}.ant-slider-mark-text{position:absolute;display:inline-block;color:#00000073;text-align:center;word-break:keep-all;cursor:pointer;user-select:none}.ant-slider-mark-text-active{color:#000000d9}.ant-slider-step{position:absolute;width:100%;height:4px;background:transparent}.ant-slider-dot{position:absolute;top:-2px;width:8px;height:8px;margin-left:-4px;background-color:#fff;border:2px solid #f0f0f0;border-radius:50%;cursor:pointer}.ant-slider-dot:first-child{margin-left:-4px}.ant-slider-dot:last-child{margin-left:-4px}.ant-slider-dot-active{border-color:#e89f85}.ant-slider-disabled{cursor:not-allowed}.ant-slider-disabled .ant-slider-rail{background-color:#f5f5f5!important}.ant-slider-disabled .ant-slider-track{background-color:#00000040!important}.ant-slider-disabled .ant-slider-handle,.ant-slider-disabled .ant-slider-dot{background-color:#fff;border-color:#00000040!important;box-shadow:none;cursor:not-allowed}.ant-slider-disabled .ant-slider-mark-text,.ant-slider-disabled .ant-slider-dot{cursor:not-allowed!important}.ant-slider-rtl{direction:rtl}.ant-slider-rtl .ant-slider-mark{right:0;left:auto}.ant-slider-rtl .ant-slider-dot,.ant-slider-rtl .ant-slider-dot:first-child{margin-right:-4px;margin-left:0}.ant-slider-rtl .ant-slider-dot:last-child{margin-right:-4px;margin-left:0}.num-input[data-v-bd954eda]{display:flex}.num-input .slide[data-v-bd954eda]{flex:1;min-width:128px;max-width:256px;margin-left:8px}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 195 B After Width: | Height: | Size: 195 B |
|
|
@ -1 +1 @@
|
|||
.container[data-v-49082269]{background:var(--zp-secondary-background);height:100%;overflow:auto;display:flex;flex-direction:column}.container .actions-panel[data-v-49082269]{padding:8px;background-color:var(--zp-primary-background)}.container .refresh-button[data-v-49082269]{position:absolute;top:90%;left:50%;transform:translate(-50%,-50%);z-index:99;background:white;border-radius:9999px;box-shadow:0 0 20px var(--zp-secondary);padding:4px;display:flex;align-items:center;gap:8px}.container .file-list[data-v-49082269]{flex:1;list-style:none;padding:8px;height:var(--pane-max-height);width:100%}.container .file-list .hint[data-v-49082269]{text-align:center;font-size:2em;padding:30vh 128px 0}
|
||||
.container[data-v-e1531e89]{background:var(--zp-secondary-background);height:100%;overflow:auto;display:flex;flex-direction:column}.container .actions-panel[data-v-e1531e89]{padding:8px;background-color:var(--zp-primary-background)}.container .refresh-button[data-v-e1531e89]{position:absolute;top:90%;left:50%;transform:translate(-50%,-50%);z-index:99;background:white;border-radius:9999px;box-shadow:0 0 20px var(--zp-secondary);padding:4px;display:flex;align-items:center;gap:8px}.container .file-list[data-v-e1531e89]{flex:1;list-style:none;padding:8px;height:var(--pane-max-height);width:100%}.container .file-list .hint[data-v-e1531e89]{text-align:center;font-size:2em;padding:30vh 128px 0}
|
||||
|
|
@ -1 +1 @@
|
|||
import{d as Z,a1 as ee,r as F,J as te,K as le,o as ie,U as v,V as N,c as i,a4 as e,W as g,a3 as n,X as k,Y as u,a5 as R,L as se,a6 as ae,af as oe,ag as $,$ as A,a2 as ne,z as w,B as re,cU as ce,cV as de,ak as ue,ai as me,T as fe,a0 as pe}from"./index-632e7cf6.js";import{u as ve,c as ge,a as ke,F as we,d as he}from"./FileItem-70868dea.js";import{a as Ce,b as Se,c as _e,M as Ie,o as z,L as ye,R as xe,f as be}from"./MultiSelectKeep-a8fa9049.js";import"./numInput.vue_vue_type_style_index_0_scoped_55978858_lang-221425da.js";/* empty css */import"./index-a2a27adc.js";import"./_isIterateeCall-582f579a.js";import"./index-9d95a206.js";import"./index-a44b2ffa.js";import"./shortcut-5c51118c.js";import"./Checkbox-2af1c4fc.js";import"./index-1bd869eb.js";const Ve={class:"refresh-button"},Me={class:"hint"},Te={key:0,class:"preview-switch"},Fe=Z({__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:re("randomImageSettingNotification"),duration:6,key:"randomImageSetting"}),h.value=!0)},f=async()=>{try{m.value=!0;const s=await ce();s.length===0&&w.warn("No data, please generate index in image search page first"),l.value=s}finally{m.value=!1,_()}},C=()=>{if(l.value.length===0){w.warn("没有图片可以浏览");return}z(l.value,o.value||0)};ie(()=>{f(),setTimeout(()=>{P()},2e3)});const{stackViewEl:U,multiSelectedIdxs:p,stack:K,scroller:L}=ve({images:l}).toRefs(),{onClearAllSelected:D,onSelectAll:E,onReverseSelect:G}=ge();Ce();const{itemSize:S,gridItems:O,cellWidth:W,onScroll:_}=ke(),{showGenInfo:c,imageGenInfo:I,q,onContextMenuClick:H,onFileItemClick:J}=Se({openNext:de}),{previewIdx:o,previewing:y,onPreviewVisibleChange:Q,previewImgMove:x,canPreview:b}=_e(),V=async(s,t,d)=>{K.value=[{curr:"",files:l.value}],await H(s,t,d)};return(s,t)=>{var M;const d=ue,X=me,Y=fe;return v(),N("div",{class:"container",ref_key:"stackViewEl",ref:U},[i(Ie,{show:!!e(p).length||e(B).keepMultiSelect,onClearAllSelected:e(D),onSelectAll:e(E),onReverseSelect:e(G)},null,8,["show","onClearAllSelected","onSelectAll","onReverseSelect"]),g("div",Ve,[i(d,{onClick:f,onTouchstart:R(f,["prevent"]),type:"primary",loading:m.value,shape:"round"},{default:n(()=>[k(u(s.$t("shuffle")),1)]),_:1},8,["onTouchstart","loading"]),i(d,{onClick:C,onTouchstart:R(C,["prevent"]),type:"default",disabled:!((M=l.value)!=null&&M.length),shape:"round"},{default:n(()=>[k(u(s.$t("tiktokView")),1)]),_:1},8,["onTouchstart","disabled"])]),i(Y,{visible:e(c),"onUpdate:visible":t[1]||(t[1]=a=>ae(c)?c.value=a:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=a=>c.value=!1)},{cancelText:n(()=>[]),default:n(()=>[i(X,{active:"",loading:!e(q).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]=a=>e(se)(e(I)))},[g("div",Me,u(s.$t("doubleClickToCopy")),1),k(" "+u(e(I)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),i(e(he),{ref_key:"scroller",ref:L,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:a,index:T})=>[i(we,{idx:T,file:a,"cell-width":e(W),"full-screen-preview-image-url":e(r)[e(o)]?e(oe)(e(r)[e(o)]):"",onContextMenuClick:V,onPreviewVisibleChange:e(Q),"is-selected-mutil-files":e(p).length>1,selected:e(p).includes(T),onFileItemClick:e(J),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,[i(e(ye),{onClick:t[3]||(t[3]=a=>e(x)("prev")),class:$({disable:!e(b)("prev")})},null,8,["class"]),i(e(xe),{onClick:t[4]||(t[4]=a=>e(x)("next")),class:$({disable:!e(b)("next")})},null,8,["class"])])):A("",!0),e(y)&&e(r)&&e(r)[e(o)]?(v(),ne(be,{key:1,file:e(r)[e(o)],idx:e(o),onContextMenuClick:V},null,8,["file","idx"])):A("",!0)],512)}}});const We=pe(Fe,[["__scopeId","data-v-49082269"]]);export{We as default};
|
||||
import{d as Z,a1 as ee,r as F,J as te,K as le,o as ie,U as v,V as N,c as i,a4 as e,W as g,a3 as n,X as k,Y as u,a5 as R,L as se,a6 as ae,af as oe,ag as $,$ as A,a2 as ne,z as w,B as re,cV as ce,cW as de,ak as ue,ai as me,T as fe,a0 as pe}from"./index-d6594e8e.js";import{u as ve,c as ge,a as ke,F as we,d as he}from"./FileItem-2eb00024.js";import{a as Ce,b as Se,c as _e,M as Ie,o as z,L as ye,R as xe,f as be}from"./MultiSelectKeep-ba3817a4.js";import"./numInput.vue_vue_type_style_index_0_scoped_bd954eda_lang-c8c8013d.js";/* empty css */import"./index-cb6a3d31.js";import"./_isIterateeCall-bfd79848.js";import"./index-30b8f89a.js";import"./index-9b184148.js";import"./shortcut-0468cdd7.js";import"./Checkbox-59427a1c.js";import"./index-e620c28b.js";const Ve={class:"refresh-button"},Me={class:"hint"},Te={key:0,class:"preview-switch"},Fe=Z({__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:re("randomImageSettingNotification"),duration:6,key:"randomImageSetting"}),h.value=!0)},f=async()=>{try{m.value=!0;const s=await ce();s.length===0&&w.warn("No data, please generate index in image search page first"),l.value=s}finally{m.value=!1,_()}},C=()=>{if(l.value.length===0){w.warn("没有图片可以浏览");return}z(l.value,o.value||0)};ie(()=>{f(),setTimeout(()=>{P()},2e3)});const{stackViewEl:K,multiSelectedIdxs:p,stack:L,scroller:U}=ve({images:l}).toRefs(),{onClearAllSelected:W,onSelectAll:D,onReverseSelect:E}=ge();Ce();const{itemSize:S,gridItems:G,cellWidth:O,onScroll:_}=ke(),{showGenInfo:c,imageGenInfo:I,q,onContextMenuClick:H,onFileItemClick:J}=Se({openNext:de}),{previewIdx:o,previewing:y,onPreviewVisibleChange:Q,previewImgMove:x,canPreview:b}=_e(),V=async(s,t,d)=>{L.value=[{curr:"",files:l.value}],await H(s,t,d)};return(s,t)=>{var M;const d=ue,X=me,Y=fe;return v(),N("div",{class:"container",ref_key:"stackViewEl",ref:K},[i(Ie,{show:!!e(p).length||e(B).keepMultiSelect,onClearAllSelected:e(W),onSelectAll:e(D),onReverseSelect:e(E)},null,8,["show","onClearAllSelected","onSelectAll","onReverseSelect"]),g("div",Ve,[i(d,{onClick:f,onTouchstart:R(f,["prevent"]),type:"primary",loading:m.value,shape:"round"},{default:n(()=>[k(u(s.$t("shuffle")),1)]),_:1},8,["onTouchstart","loading"]),i(d,{onClick:C,onTouchstart:R(C,["prevent"]),type:"default",disabled:!((M=l.value)!=null&&M.length),shape:"round"},{default:n(()=>[k(u(s.$t("tiktokView")),1)]),_:1},8,["onTouchstart","disabled"])]),i(Y,{visible:e(c),"onUpdate:visible":t[1]||(t[1]=a=>ae(c)?c.value=a:null),width:"70vw","mask-closable":"",onOk:t[2]||(t[2]=a=>c.value=!1)},{cancelText:n(()=>[]),default:n(()=>[i(X,{active:"",loading:!e(q).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]=a=>e(se)(e(I)))},[g("div",Me,u(s.$t("doubleClickToCopy")),1),k(" "+u(e(I)),1)],32)]),_:1},8,["loading"])]),_:1},8,["visible"]),i(e(he),{ref_key:"scroller",ref:U,class:"file-list",items:l.value.slice(),"item-size":e(S).first,"key-field":"fullpath","item-secondary-size":e(S).second,gridItems:e(G),onScroll:e(_)},{default:n(({item:a,index:T})=>[i(we,{idx:T,file:a,"cell-width":e(O),"full-screen-preview-image-url":e(r)[e(o)]?e(oe)(e(r)[e(o)]):"",onContextMenuClick:V,onPreviewVisibleChange:e(Q),"is-selected-mutil-files":e(p).length>1,selected:e(p).includes(T),onFileItemClick:e(J),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,[i(e(ye),{onClick:t[3]||(t[3]=a=>e(x)("prev")),class:$({disable:!e(b)("prev")})},null,8,["class"]),i(e(xe),{onClick:t[4]||(t[4]=a=>e(x)("next")),class:$({disable:!e(b)("next")})},null,8,["class"])])):A("",!0),e(y)&&e(r)&&e(r)[e(o)]?(v(),ne(be,{key:1,file:e(r)[e(o)],idx:e(o),onContextMenuClick:V},null,8,["file","idx"])):A("",!0)],512)}}});const Oe=pe(Fe,[["__scopeId","data-v-e1531e89"]]);export{Oe as default};
|
||||
|
|
@ -1 +1 @@
|
|||
import{R as y,C as v}from"./index-ab5ead62.js";import{cw as f,c as d,A as w,d as P,U as o,V as c,W as r,Z as S,a8 as V,aG as O,a3 as R,X as u,Y as p,a4 as b,ak as $,a0 as x,R as H,J as _,K as m}from"./index-632e7cf6.js";const A=f(y),E=f(v);var L={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 C=L;function h(t){for(var e=1;e<arguments.length;e++){var s=arguments[e]!=null?Object(arguments[e]):{},n=Object.keys(s);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(s).filter(function(i){return Object.getOwnPropertyDescriptor(s,i).enumerable}))),n.forEach(function(i){N(t,i,s[i])})}return t}function N(t,e,s){return e in t?Object.defineProperty(t,e,{value:s,enumerable:!0,configurable:!0,writable:!0}):t[e]=s,t}var l=function(e,s){var n=h({},e,s.attrs);return d(w,h({},n,{icon:C}),null)};l.displayName="PushpinFilled";l.inheritAttrs=!1;const z=l,F={class:"record-container"},k={style:{flex:"1"}},I={class:"rec-actions"},B=["onClick"],J=P({__name:"HistoryRecord",props:{records:{}},emits:["reuseRecord"],setup(t){return(e,s)=>{const n=$;return o(),c("div",null,[r("ul",F,[(o(!0),c(S,null,V(e.records.getRecords(),i=>(o(),c("li",{key:i.id,class:"record"},[r("div",k,[O(e.$slots,"default",{record:i},void 0,!0)]),r("div",I,[d(n,{onClick:g=>e.$emit("reuseRecord",i),type:"primary"},{default:R(()=>[u(p(e.$t("restore")),1)]),_:2},1032,["onClick"]),r("div",{class:"pin",onClick:g=>e.records.switchPin(i)},[d(b(z)),u(" "+p(e.records.isPinned(i)?e.$t("unpin"):e.$t("pin")),1)],8,B)])]))),128))])])}}});const q=x(J,[["__scopeId","data-v-834a248f"]]);class a{constructor(e=128,s=[],n=[]){this.maxLength=e,this.records=s,this.pinnedValues=n}isPinned(e){return this.pinnedValues.some(s=>s.id===e.id)}add(e){this.records.length>=this.maxLength&&this.records.pop(),this.records.unshift({...e,id:H()+Date.now(),time:new Date().toLocaleString()})}pin(e){const s=this.records.findIndex(n=>n.id===e.id);s!==-1&&this.records.splice(s,1),this.pinnedValues.push(e)}unpin(e){const s=this.pinnedValues.findIndex(n=>n.id===e.id);s!==-1&&this.pinnedValues.splice(s,1),this.records.unshift(e)}switchPin(e){this.isPinned(e)?this.unpin(e):this.pin(e)}getRecords(){return[...this.pinnedValues,...this.records]}getPinnedValues(){return this.pinnedValues}}const G=_(`${m}fuzzy-search-HistoryRecord`,new a,{serializer:{read:t=>{const e=JSON.parse(t);return new a(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),M=_(`${m}tag-search-HistoryRecord`,new a,{serializer:{read:t=>{const e=JSON.parse(t);return new a(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}});export{q as H,E as _,A as a,G as f,M as t};
|
||||
import{R as y,C as v}from"./index-68461333.js";import{cw as f,c as d,A as w,d as P,U as a,V as c,W as r,Z as S,a8 as V,aG as O,a3 as R,X as u,Y as p,a4 as b,ak as $,a0 as x,R as H,J as _,K as m}from"./index-d6594e8e.js";const A=f(y),E=f(v);var L={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 C=L;function h(t){for(var e=1;e<arguments.length;e++){var s=arguments[e]!=null?Object(arguments[e]):{},n=Object.keys(s);typeof Object.getOwnPropertySymbols=="function"&&(n=n.concat(Object.getOwnPropertySymbols(s).filter(function(i){return Object.getOwnPropertyDescriptor(s,i).enumerable}))),n.forEach(function(i){N(t,i,s[i])})}return t}function N(t,e,s){return e in t?Object.defineProperty(t,e,{value:s,enumerable:!0,configurable:!0,writable:!0}):t[e]=s,t}var l=function(e,s){var n=h({},e,s.attrs);return d(w,h({},n,{icon:C}),null)};l.displayName="PushpinFilled";l.inheritAttrs=!1;const z=l,F={class:"record-container"},k={style:{flex:"1"}},I={class:"rec-actions"},B=["onClick"],J=P({__name:"HistoryRecord",props:{records:{}},emits:["reuseRecord"],setup(t){return(e,s)=>{const n=$;return a(),c("div",null,[r("ul",F,[(a(!0),c(S,null,V(e.records.getRecords(),i=>(a(),c("li",{key:i.id,class:"record"},[r("div",k,[O(e.$slots,"default",{record:i},void 0,!0)]),r("div",I,[d(n,{onClick:g=>e.$emit("reuseRecord",i),type:"primary"},{default:R(()=>[u(p(e.$t("restore")),1)]),_:2},1032,["onClick"]),r("div",{class:"pin",onClick:g=>e.records.switchPin(i)},[d(b(z)),u(" "+p(e.records.isPinned(i)?e.$t("unpin"):e.$t("pin")),1)],8,B)])]))),128))])])}}});const q=x(J,[["__scopeId","data-v-fff181dd"]]);class o{constructor(e=128,s=[],n=[]){this.maxLength=e,this.records=s,this.pinnedValues=n}isPinned(e){return this.pinnedValues.some(s=>s.id===e.id)}add(e){this.records.length>=this.maxLength&&this.records.pop(),this.records.unshift({...e,id:H()+Date.now(),time:new Date().toLocaleString()})}pin(e){const s=this.records.findIndex(n=>n.id===e.id);s!==-1&&this.records.splice(s,1),this.pinnedValues.push(e)}unpin(e){const s=this.pinnedValues.findIndex(n=>n.id===e.id);s!==-1&&this.pinnedValues.splice(s,1),this.records.unshift(e)}switchPin(e){this.isPinned(e)?this.unpin(e):this.pin(e)}getRecords(){return[...this.pinnedValues,...this.records]}getPinnedValues(){return this.pinnedValues}}const G=_(`${m}fuzzy-search-HistoryRecord`,new o,{serializer:{read:t=>{const e=JSON.parse(t);return new o(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}}),M=_(`${m}tag-search-HistoryRecord`,new o,{serializer:{read:t=>{const e=JSON.parse(t);return new o(e.maxLength,e.records,e.pinnedValues)},write:JSON.stringify}});export{q as H,E as _,A as a,G as f,M as t};
|
||||
|
|
@ -0,0 +1 @@
|
|||
[data-v-fff181dd] .ant-row .ant-col:nth-child(1){font-weight:700}.record-container[data-v-fff181dd]{list-style:none;padding:8px;margin:16px;max-height:50vh;overflow:auto}.record[data-v-fff181dd]{display:flex;flex-direction:row;justify-content:space-between;align-items:center;padding:10px;border-bottom:1px solid var(--zp-tertiary);position:relative;flex-wrap:nowrap;transition:all .3s ease}.record[data-v-fff181dd]:hover{background:var(--zp-secondary-background)}.record .rec-actions[data-v-fff181dd]{user-select:none;display:flex;gap:8px}.record .pin[data-v-fff181dd]{cursor:pointer;padding:4px 8px;border-radius:4px;transition:all .3s ease}.record .pin[data-v-fff181dd]:hover{background:var(--zp-primary-background)}
|
||||
|
|
@ -1 +0,0 @@
|
|||
[data-v-834a248f] .ant-row .ant-col:nth-child(1){font-weight:700}.record-container[data-v-834a248f]{list-style:none;padding:8px;margin:16px;max-height:50vh;overflow:auto}.record[data-v-834a248f]{display:flex;flex-direction:row;justify-content:space-between;align-items:center;padding:10px;border-bottom:1px solid var(--zp-tertiary);position:relative;flex-wrap:nowrap;transition:all .3s ease}.record[data-v-834a248f]:hover{background:var(--zp-secondary-background)}.record .rec-actions[data-v-834a248f]{user-select:none;display:flex;gap:8px}.record .pin[data-v-834a248f]{cursor:pointer;padding:4px 8px;border-radius:4px;transition:all .3s ease}.record .pin[data-v-834a248f]:hover{background:var(--zp-primary-background)}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -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)}}.base-info[data-v-afd25667]{position:absolute;padding:4px;font-size:.8em;background:var(--zp-primary-background);color:var(--zp-primary);left:0;bottom:0;border-top-right-radius:4px}.location-act[data-v-317d328e]{margin-left:8px}.location-act .copy[data-v-317d328e]{margin-right:4px}@media (max-width: 768px){.location-act[data-v-317d328e]{display:flex;flex-direction:column}.location-act>*[data-v-317d328e],.location-act .copy[data-v-317d328e]{margin:2px}}.breadcrumb[data-v-317d328e]{display:flex;align-items:center}.breadcrumb>*[data-v-317d328e]{margin-right:4px}@media (max-width: 768px){.breadcrumb[data-v-317d328e]{width:100%}.breadcrumb .ant-breadcrumb>*[data-v-317d328e]{display:inline-block}}.container[data-v-317d328e]{background:var(--zp-secondary-background);height:var(--pane-max-height)}.location-bar[data-v-317d328e]{padding:4px 16px;background:var(--zp-primary-background);border-bottom:1px solid var(--zp-border);display:flex;align-items:center;justify-content:space-between}@media (max-width: 768px){.location-bar[data-v-317d328e]{flex-direction:column}.location-bar[data-v-317d328e] ::-webkit-scrollbar{height:2px;background-color:var(--zp-secondary-variant-background)}.location-bar .actions[data-v-317d328e]{padding:4px 0;width:100%;overflow:auto;display:flex;align-items:center}.location-bar .actions>*[data-v-317d328e]{flex-shrink:0}}.location-bar .actions[data-v-317d328e]{display:flex;align-items:center;flex-shrink:0}.location-bar a.opt[data-v-317d328e]{margin-left:8px}.view[data-v-317d328e]{padding:8px;height:calc(100vh - 48px)}.view .file-list[data-v-317d328e]{list-style:none;padding:8px;height:100%;overflow:auto}.hint[data-v-317d328e]{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)}}.base-info[data-v-7f9c0b15]{position:absolute;padding:4px;font-size:.8em;background:var(--zp-primary-background);color:var(--zp-primary);left:0;bottom:0;border-top-right-radius:4px}.location-act[data-v-8d4bd42a]{margin-left:8px}.location-act .copy[data-v-8d4bd42a]{margin-right:4px}@media (max-width: 768px){.location-act[data-v-8d4bd42a]{display:flex;flex-direction:column}.location-act>*[data-v-8d4bd42a],.location-act .copy[data-v-8d4bd42a]{margin:2px}}.breadcrumb[data-v-8d4bd42a]{display:flex;align-items:center}.breadcrumb>*[data-v-8d4bd42a]{margin-right:4px}@media (max-width: 768px){.breadcrumb[data-v-8d4bd42a]{width:100%}.breadcrumb .ant-breadcrumb>*[data-v-8d4bd42a]{display:inline-block}}.container[data-v-8d4bd42a]{background:var(--zp-secondary-background);height:var(--pane-max-height)}.location-bar[data-v-8d4bd42a]{padding:4px 16px;background:var(--zp-primary-background);border-bottom:1px solid var(--zp-border);display:flex;align-items:center;justify-content:space-between}@media (max-width: 768px){.location-bar[data-v-8d4bd42a]{flex-direction:column}.location-bar[data-v-8d4bd42a] ::-webkit-scrollbar{height:2px;background-color:var(--zp-secondary-variant-background)}.location-bar .actions[data-v-8d4bd42a]{padding:4px 0;width:100%;overflow:auto;display:flex;align-items:center}.location-bar .actions>*[data-v-8d4bd42a]{flex-shrink:0}}.location-bar .actions[data-v-8d4bd42a]{display:flex;align-items:center;flex-shrink:0}.location-bar a.opt[data-v-8d4bd42a]{margin-left:8px}.view[data-v-8d4bd42a]{padding:8px;height:calc(100vh - 48px)}.view .file-list[data-v-8d4bd42a]{list-style:none;padding:8px;height:100%;overflow:auto}.hint[data-v-8d4bd42a]{padding:4px;border:4px;background:var(--zp-secondary-background);border:1px solid var(--zp-border)}
|
||||
|
|
@ -1 +1 @@
|
|||
import{u as G,g as d}from"./FileItem-70868dea.js";import{r as b,t as j,ct as m,cu as y,cv as D}from"./index-632e7cf6.js";const r=new Map,A=()=>{const{useEventListen:k,sortedFiles:f,getViewableAreaFiles:w}=G().toRefs(),c=b(d.defaultChangeIndchecked),u=b(d.defaultSeedChangeChecked),g=async()=>{if(await j(100),!c.value)return;const o=w.value().filter(e=>m(e.fullpath)&&!e.gen_info_obj);if(!o.length)return;const t=await y(o.map(e=>e.fullpath).filter(e=>!r.has(e)));o.forEach(e=>{const i=t[e.fullpath]||r.get(e.fullpath)||"";r.set(e.fullpath,i),e.gen_info_obj=D(i),e.gen_info_raw=i})};k.value("viewableAreaFilesChange",g);const F=o=>{const t=f.value;return[o,u.value,t[o-1],t[o],t[o+1]]};function I(o,t,e,i){const a={diff:{},empty:!0,ownFile:"",otherFile:""};if(t+e<0||t+e>=f.value.length||f.value[t]==null||!("gen_info_obj"in f.value[t])||!("gen_info_obj"in f.value[t+e]))return a;const l=o,s=f.value[t+e].gen_info_obj;if(s==null)return a;const h=["hashes","resources"];a.diff={},a.ownFile=i.name,a.otherFile=f.value[t+e].name,a.empty=!1,u.value||h.push("seed");for(const n in l)if(!h.includes(n)){if(!(n in s)){a.diff[n]="+";continue}if(l[n]!=s[n])if(n.includes("rompt")&&l[n]!=""&&s[n]!=""){const p=l[n].split(","),C=s[n].split(",");let _=0;for(const v in p)p[v]!=C[v]&&_++;a.diff[n]=_}else a.diff[n]=[l[n],s[n]]}return a}return{getGenDiff:I,changeIndchecked:c,seedChangeChecked:u,getRawGenParams:()=>g(),getGenDiffWatchDep:F}};export{A as u};
|
||||
import{u as G,g as d}from"./FileItem-2eb00024.js";import{r as b,t as j,ct as m,cu as y,cv as D}from"./index-d6594e8e.js";const r=new Map,A=()=>{const{useEventListen:k,sortedFiles:f,getViewableAreaFiles:w}=G().toRefs(),c=b(d.defaultChangeIndchecked),u=b(d.defaultSeedChangeChecked),g=async()=>{if(await j(100),!c.value)return;const o=w.value().filter(e=>m(e.fullpath)&&!e.gen_info_obj);if(!o.length)return;const t=await y(o.map(e=>e.fullpath).filter(e=>!r.has(e)));o.forEach(e=>{const i=t[e.fullpath]||r.get(e.fullpath)||"";r.set(e.fullpath,i),e.gen_info_obj=D(i),e.gen_info_raw=i})};k.value("viewableAreaFilesChange",g);const F=o=>{const t=f.value;return[o,u.value,t[o-1],t[o],t[o+1]]};function I(o,t,e,i){const a={diff:{},empty:!0,ownFile:"",otherFile:""};if(t+e<0||t+e>=f.value.length||f.value[t]==null||!("gen_info_obj"in f.value[t])||!("gen_info_obj"in f.value[t+e]))return a;const l=o,s=f.value[t+e].gen_info_obj;if(s==null)return a;const h=["hashes","resources"];a.diff={},a.ownFile=i.name,a.otherFile=f.value[t+e].name,a.empty=!1,u.value||h.push("seed");for(const n in l)if(!h.includes(n)){if(!(n in s)){a.diff[n]="+";continue}if(l[n]!=s[n])if(n.includes("rompt")&&l[n]!=""&&s[n]!=""){const p=l[n].split(","),C=s[n].split(",");let _=0;for(const v in p)p[v]!=C[v]&&_++;a.diff[n]=_}else a.diff[n]=[l[n],s[n]]}return a}return{getGenDiff:I,changeIndchecked:c,seedChangeChecked:u,getRawGenParams:()=>g(),getGenDiffWatchDep:F}};export{A as u};
|
||||
|
|
@ -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-632e7cf6.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-d385cc4f.css">
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-d6594e8e.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-af514ea9.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -310,56 +310,48 @@ export const searchIibOutputByPrompt = async (req: PromptSearchReq) => {
|
|||
return resp.data as PromptSearchResp
|
||||
}
|
||||
|
||||
// ===== Tag Relationship Graph =====
|
||||
// ===== Hierarchical Tag Graph =====
|
||||
export interface TagGraphReq {
|
||||
folder_paths: string[]
|
||||
model?: string
|
||||
threshold?: number
|
||||
min_cluster_size?: number
|
||||
lang?: string
|
||||
top_n_tags?: number
|
||||
top_n_clusters?: number
|
||||
weight_mode?: 'frequency' | 'tfidf' | 'hybrid'
|
||||
alpha?: number
|
||||
show_clusters?: boolean
|
||||
detect_communities?: boolean
|
||||
lang?: string
|
||||
}
|
||||
|
||||
export interface TagGraphNode {
|
||||
export interface LayerNode {
|
||||
id: string
|
||||
label: string
|
||||
weight: number
|
||||
image_count?: number
|
||||
cluster_count?: number
|
||||
size?: number
|
||||
category: string
|
||||
community?: number
|
||||
size: number
|
||||
metadata?: {
|
||||
type: string
|
||||
image_count?: number
|
||||
cluster_count?: number
|
||||
level?: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface TagGraphLink {
|
||||
export interface GraphLayer {
|
||||
level: number
|
||||
name: string
|
||||
nodes: LayerNode[]
|
||||
}
|
||||
|
||||
export interface GraphLink {
|
||||
source: string
|
||||
target: string
|
||||
weight: number
|
||||
image_count?: number
|
||||
cluster_count?: number
|
||||
}
|
||||
|
||||
export interface TagGraphResp {
|
||||
nodes: TagGraphNode[]
|
||||
links: TagGraphLink[]
|
||||
communities?: Array<{
|
||||
id: number
|
||||
nodes: string[]
|
||||
size: number
|
||||
}>
|
||||
layers: GraphLayer[]
|
||||
links: GraphLink[]
|
||||
stats: {
|
||||
total_tags: number
|
||||
selected_tags: number
|
||||
total_clusters: number
|
||||
selected_clusters: number
|
||||
total_images: number
|
||||
tag_links: number
|
||||
cluster_links: number
|
||||
total_tags: number
|
||||
selected_tags: number
|
||||
abstraction_layers: number
|
||||
total_links: number
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,424 +1,346 @@
|
|||
<template>
|
||||
<div class="tag-graph-container">
|
||||
<!-- Toolbar -->
|
||||
<div class="toolbar">
|
||||
<a-space>
|
||||
<a-button type="primary" @click="loadGraph" :loading="loading">
|
||||
{{ $t('refresh') }}
|
||||
</a-button>
|
||||
<a-divider type="vertical" />
|
||||
<span class="label">Top Tags:</span>
|
||||
<a-input-number v-model:value="topNTags" :min="10" :max="100" :step="10" style="width: 80px" />
|
||||
<span class="label">Top Clusters:</span>
|
||||
<a-input-number v-model:value="topNClusters" :min="5" :max="50" :step="5" style="width: 80px" />
|
||||
<a-checkbox v-model:checked="showClusters">Show Clusters</a-checkbox>
|
||||
<a-button @click="fitView" size="small">Fit View</a-button>
|
||||
</a-space>
|
||||
<div class="tag-hierarchy-graph">
|
||||
<div v-if="loading" class="loading-container">
|
||||
<a-spin size="large" />
|
||||
<div class="loading-text">Generating hierarchical graph...</div>
|
||||
</div>
|
||||
|
||||
<!-- Graph Canvas -->
|
||||
<div ref="chartContainer" class="chart-container"></div>
|
||||
|
||||
<!-- Info Panel -->
|
||||
<div v-if="selectedNode" class="info-panel">
|
||||
<div class="info-header">
|
||||
<span class="info-title">{{ selectedNode.label }}</span>
|
||||
<a-button size="small" type="text" @click="selectedNode = null">✕</a-button>
|
||||
</div>
|
||||
<div class="info-body">
|
||||
<div class="info-item">
|
||||
<span class="info-label">Category:</span>
|
||||
<span class="info-value">{{ selectedNode.category }}</span>
|
||||
</div>
|
||||
<div class="info-item" v-if="selectedNode.image_count">
|
||||
<span class="info-label">Images:</span>
|
||||
<span class="info-value">{{ selectedNode.image_count }}</span>
|
||||
</div>
|
||||
<div class="info-item" v-if="selectedNode.cluster_count">
|
||||
<span class="info-label">Clusters:</span>
|
||||
<span class="info-value">{{ selectedNode.cluster_count }}</span>
|
||||
</div>
|
||||
<div class="info-item" v-if="selectedNode.size">
|
||||
<span class="info-label">Size:</span>
|
||||
<span class="info-value">{{ selectedNode.size }}</span>
|
||||
</div>
|
||||
<div class="info-item" v-if="selectedNode.community !== undefined">
|
||||
<span class="info-label">Community:</span>
|
||||
<span class="info-value">{{ selectedNode.community }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-actions">
|
||||
<a-button size="small" type="primary" @click="searchByTag(selectedNode.label)">
|
||||
Search Images
|
||||
</a-button>
|
||||
</div>
|
||||
<div v-else-if="error" class="error-container">
|
||||
<a-alert type="error" :message="error" show-icon />
|
||||
</div>
|
||||
|
||||
<!-- Stats Panel -->
|
||||
<div v-if="stats" class="stats-panel">
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">{{ stats.selected_tags }}</div>
|
||||
<div class="stat-label">Tags</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">{{ stats.selected_clusters }}</div>
|
||||
<div class="stat-label">Clusters</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-value">{{ stats.total_images }}</div>
|
||||
<div class="stat-label">Images</div>
|
||||
<div v-else-if="graphData" class="graph-container">
|
||||
<!-- Control Panel -->
|
||||
<div class="control-panel">
|
||||
<a-space>
|
||||
<a-tag>Layers: {{ graphData.layers.length }}</a-tag>
|
||||
<a-tag>Total Links: {{ graphData.stats.total_links }}</a-tag>
|
||||
</a-space>
|
||||
</div>
|
||||
|
||||
<!-- ECharts Container -->
|
||||
<div ref="chartRef" class="chart-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
|
||||
import { getClusterTagGraph, type TagGraphReq, type TagGraphResp, type TagGraphNode } from '@/api/db'
|
||||
import { ref, onMounted, watch, nextTick, onUnmounted } from 'vue'
|
||||
import { getClusterTagGraph, type TagGraphReq, type TagGraphResp } from '@/api/db'
|
||||
import { message } from 'ant-design-vue'
|
||||
import * as echarts from 'echarts'
|
||||
import type { ECharts } from 'echarts'
|
||||
|
||||
const props = defineProps<{
|
||||
interface Props {
|
||||
folders: string[]
|
||||
threshold: number
|
||||
minClusterSize: number
|
||||
lang?: string
|
||||
model?: string
|
||||
}>()
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<{
|
||||
searchTag: [tag: string]
|
||||
openCluster: [cluster: { title: string; paths: string[]; size: number }]
|
||||
}>()
|
||||
|
||||
const loading = ref(false)
|
||||
const chartContainer = ref<HTMLDivElement>()
|
||||
const chart = ref<ECharts>()
|
||||
const error = ref<string>('')
|
||||
const graphData = ref<TagGraphResp | null>(null)
|
||||
const selectedNode = ref<TagGraphNode | null>(null)
|
||||
const stats = ref<TagGraphResp['stats'] | null>(null)
|
||||
const chartRef = ref<HTMLDivElement>()
|
||||
let chartInstance: echarts.ECharts | null = null
|
||||
let _handleResize: (() => void) | null = null
|
||||
|
||||
// Parameters
|
||||
const topNTags = ref(50)
|
||||
const topNClusters = ref(20)
|
||||
const showClusters = ref(true)
|
||||
|
||||
// Category colors
|
||||
const categoryColors: Record<string, string> = {
|
||||
character: '#5470c6',
|
||||
style: '#91cc75',
|
||||
scene: '#fac858',
|
||||
object: '#ee6666',
|
||||
cluster: '#73c0de',
|
||||
other: '#9a60b4',
|
||||
}
|
||||
|
||||
// Community colors (generated dynamically)
|
||||
const communityColors: string[] = [
|
||||
'#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de',
|
||||
'#3ba272', '#fc8452', '#9a60b4', '#ea7ccc', '#5d7092'
|
||||
// Layer colors (different for each layer)
|
||||
const layerColors = [
|
||||
'#4A90E2', // Layer 0: Clusters - Blue
|
||||
'#7B68EE', // Layer 1: Tags - Purple
|
||||
'#50C878', // Layer 2: Abstract-1 - Green
|
||||
'#FF6B6B', // Layer 3: Abstract-2 - Red
|
||||
]
|
||||
|
||||
const getCategoryColor = (category: string, community?: number): string => {
|
||||
if (community !== undefined && community >= 0) {
|
||||
return communityColors[community % communityColors.length]
|
||||
}
|
||||
return categoryColors[category] || categoryColors.other
|
||||
const getLayerColor = (layer: number): string => {
|
||||
return layerColors[layer % layerColors.length]
|
||||
}
|
||||
|
||||
const loadGraph = async () => {
|
||||
if (!props.folders.length) {
|
||||
message.error('Please select folders first')
|
||||
const fetchGraphData = async () => {
|
||||
if (!props.folders || props.folders.length === 0) {
|
||||
error.value = 'No folders selected'
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
|
||||
try {
|
||||
const req: TagGraphReq = {
|
||||
folder_paths: props.folders,
|
||||
model: props.model,
|
||||
threshold: props.threshold,
|
||||
min_cluster_size: props.minClusterSize,
|
||||
lang: props.lang,
|
||||
top_n_tags: topNTags.value,
|
||||
top_n_clusters: topNClusters.value,
|
||||
show_clusters: showClusters.value,
|
||||
detect_communities: true,
|
||||
weight_mode: 'hybrid',
|
||||
alpha: 0.3,
|
||||
top_n_tags: 50,
|
||||
top_n_clusters: 20,
|
||||
lang: props.lang || 'en',
|
||||
}
|
||||
|
||||
const data = await getClusterTagGraph(req)
|
||||
graphData.value = data
|
||||
stats.value = data.stats
|
||||
|
||||
renderGraph(data)
|
||||
message.success(`Graph loaded: ${data.stats.selected_tags} tags, ${data.stats.selected_clusters} clusters`)
|
||||
} catch (e: any) {
|
||||
message.error(e.message || 'Failed to load tag graph')
|
||||
graphData.value = await getClusterTagGraph(req)
|
||||
} catch (err: any) {
|
||||
error.value = err.response?.data?.detail || err.message || 'Failed to load graph'
|
||||
message.error(error.value)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const renderGraph = (data: TagGraphResp) => {
|
||||
if (!chartContainer.value) return
|
||||
|
||||
if (!chart.value) {
|
||||
chart.value = echarts.init(chartContainer.value)
|
||||
const renderChart = () => {
|
||||
if (!graphData.value || !chartRef.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// Prepare data for ECharts
|
||||
const nodes = data.nodes.map(node => ({
|
||||
id: node.id,
|
||||
name: node.label,
|
||||
symbolSize: Math.sqrt(node.weight) * 0.5 + 10,
|
||||
value: node.weight,
|
||||
category: node.category,
|
||||
itemStyle: {
|
||||
color: getCategoryColor(node.category, node.community)
|
||||
},
|
||||
label: {
|
||||
show: node.category === 'cluster' || node.weight > 100,
|
||||
},
|
||||
// Store original data
|
||||
_data: node,
|
||||
}))
|
||||
// Dispose old instance
|
||||
if (chartInstance) {
|
||||
chartInstance.dispose()
|
||||
}
|
||||
|
||||
const links = data.links.map(link => ({
|
||||
chartInstance = echarts.init(chartRef.value)
|
||||
|
||||
const layers = graphData.value.layers
|
||||
// Reverse to show abstract on left
|
||||
const reversedLayers = [...layers].reverse()
|
||||
|
||||
// Build nodes with scattered positions for better visualization
|
||||
const nodes: any[] = []
|
||||
const layerSpacing = 1200 / (reversedLayers.length + 1) // Increased from 1000 to 1200
|
||||
const horizontalRange = 150 // Horizontal scatter range
|
||||
|
||||
reversedLayers.forEach((layer, layerIdx) => {
|
||||
const baseX = layerSpacing * (layerIdx + 1)
|
||||
const numNodes = layer.nodes.length
|
||||
const verticalSpacing = 800 / (numNodes + 1)
|
||||
|
||||
layer.nodes.forEach((node, nodeIdx) => {
|
||||
const y = verticalSpacing * (nodeIdx + 1)
|
||||
|
||||
// Add horizontal offset for visual spacing
|
||||
// Alternate left/right based on index, with some randomness based on node id
|
||||
const hashOffset = node.id.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)
|
||||
const horizontalOffset = ((hashOffset % horizontalRange) - horizontalRange / 2)
|
||||
const x = baseX + horizontalOffset
|
||||
|
||||
// Calculate size with max 3x ratio
|
||||
const minSize = 20
|
||||
const maxSize = 60 // 3x ratio: 60 / 20 = 3
|
||||
const normalizedSize = Math.sqrt(node.size) / 5
|
||||
const clampedSize = Math.max(minSize, Math.min(maxSize, minSize + normalizedSize))
|
||||
|
||||
nodes.push({
|
||||
id: node.id,
|
||||
name: node.label,
|
||||
x: x,
|
||||
y: y,
|
||||
fixed: true,
|
||||
symbolSize: clampedSize,
|
||||
value: node.size,
|
||||
category: layer.level,
|
||||
itemStyle: {
|
||||
color: getLayerColor(layer.level)
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 11,
|
||||
color: '#fff',
|
||||
formatter: (params: any) => {
|
||||
const maxLen = 10
|
||||
const name = params.name
|
||||
return name.length > maxLen ? name.substring(0, maxLen) + '...' : name
|
||||
}
|
||||
},
|
||||
metadata: node.metadata,
|
||||
layerName: layer.name,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Build links
|
||||
const links = graphData.value.links.map(link => ({
|
||||
source: link.source,
|
||||
target: link.target,
|
||||
value: link.weight,
|
||||
lineStyle: {
|
||||
width: Math.sqrt(link.weight) * 0.02 + 0.5,
|
||||
opacity: 0.4,
|
||||
},
|
||||
width: Math.max(0.5, Math.min(2, link.weight / 100)),
|
||||
opacity: 0.3,
|
||||
curveness: 0.1
|
||||
}
|
||||
}))
|
||||
|
||||
// Build categories
|
||||
const categories = Object.keys(categoryColors).map(name => ({ name }))
|
||||
// Build categories for legend
|
||||
const categories = reversedLayers.map(layer => ({
|
||||
name: layer.name
|
||||
}))
|
||||
|
||||
const option: echarts.EChartsOption = {
|
||||
title: {
|
||||
text: 'Tag Relationship Graph',
|
||||
left: 'center',
|
||||
top: 10,
|
||||
},
|
||||
tooltip: {
|
||||
formatter: (params: any) => {
|
||||
if (params.dataType === 'node') {
|
||||
const node = params.data._data as TagGraphNode
|
||||
let html = `<strong>${node.label}</strong><br/>`
|
||||
html += `Category: ${node.category}<br/>`
|
||||
if (node.image_count) html += `Images: ${node.image_count}<br/>`
|
||||
if (node.cluster_count) html += `Clusters: ${node.cluster_count}<br/>`
|
||||
if (node.size) html += `Size: ${node.size}<br/>`
|
||||
if (node.community !== undefined) html += `Community: ${node.community}<br/>`
|
||||
const node = params.data
|
||||
let html = `<strong>${params.name}</strong><br/>`
|
||||
html += `Layer: ${node.layerName}<br/>`
|
||||
if (node.metadata?.image_count) {
|
||||
html += `Images: ${node.metadata.image_count}`
|
||||
}
|
||||
return html
|
||||
} else if (params.dataType === 'edge') {
|
||||
return `Weight: ${params.value.toFixed(1)}`
|
||||
}
|
||||
return ''
|
||||
}
|
||||
},
|
||||
legend: [
|
||||
{
|
||||
data: categories.map(c => c.name),
|
||||
orient: 'vertical',
|
||||
left: 10,
|
||||
top: 50,
|
||||
legend: [{
|
||||
data: categories.map(c => c.name),
|
||||
orient: 'vertical',
|
||||
right: 10,
|
||||
bottom: 10,
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: 'graph',
|
||||
layout: 'force',
|
||||
data: nodes,
|
||||
links: links,
|
||||
categories: categories,
|
||||
roam: true,
|
||||
draggable: true,
|
||||
force: {
|
||||
repulsion: 200,
|
||||
gravity: 0.1,
|
||||
edgeLength: [50, 150],
|
||||
friction: 0.6,
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'adjacency',
|
||||
lineStyle: {
|
||||
width: 3,
|
||||
},
|
||||
},
|
||||
label: {
|
||||
position: 'right',
|
||||
formatter: '{b}',
|
||||
},
|
||||
labelLayout: {
|
||||
hideOverlap: true,
|
||||
},
|
||||
scaleLimit: {
|
||||
min: 0.5,
|
||||
max: 5,
|
||||
},
|
||||
}
|
||||
]
|
||||
}],
|
||||
series: [{
|
||||
type: 'graph',
|
||||
layout: 'none',
|
||||
data: nodes,
|
||||
links: links,
|
||||
categories: categories,
|
||||
roam: true, // Enable zoom and pan
|
||||
scaleLimit: {
|
||||
min: 0.2,
|
||||
max: 5
|
||||
},
|
||||
draggable: false,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'inside'
|
||||
},
|
||||
lineStyle: {
|
||||
color: 'source',
|
||||
curveness: 0.1
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'adjacency',
|
||||
lineStyle: {
|
||||
width: 3
|
||||
}
|
||||
},
|
||||
zoom: 1 // Initial zoom level
|
||||
}]
|
||||
}
|
||||
|
||||
chart.value.setOption(option)
|
||||
chartInstance.setOption(option)
|
||||
|
||||
// Handle click event
|
||||
chart.value.off('click')
|
||||
chart.value.on('click', (params: any) => {
|
||||
// Handle click events
|
||||
chartInstance.on('click', (params: any) => {
|
||||
if (params.dataType === 'node') {
|
||||
selectedNode.value = params.data._data as TagGraphNode
|
||||
const node = params.data
|
||||
if (node.metadata?.type === 'tag') {
|
||||
emit('searchTag', params.name)
|
||||
message.info(`Searching for tag: ${params.name}`)
|
||||
} else if (node.metadata?.type === 'cluster') {
|
||||
// Open cluster directly with bound images
|
||||
if (node.metadata.paths && node.metadata.paths.length > 0) {
|
||||
emit('openCluster', {
|
||||
title: params.name,
|
||||
paths: node.metadata.paths,
|
||||
size: node.metadata.image_count || node.metadata.paths.length
|
||||
})
|
||||
} else {
|
||||
message.warning('No images found in this cluster')
|
||||
}
|
||||
} else {
|
||||
message.info(`Abstract category: ${params.name}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const fitView = () => {
|
||||
if (!chart.value) return
|
||||
chart.value.resize()
|
||||
}
|
||||
// Watch for folder changes
|
||||
watch(
|
||||
() => props.folders,
|
||||
() => {
|
||||
fetchGraphData()
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const searchByTag = (tag: string) => {
|
||||
emit('searchTag', tag)
|
||||
}
|
||||
|
||||
const resizeHandler = () => {
|
||||
chart.value?.resize()
|
||||
}
|
||||
// Watch for graphData and chartRef to trigger rendering
|
||||
watch(
|
||||
[graphData, chartRef],
|
||||
() => {
|
||||
if (graphData.value && chartRef.value) {
|
||||
nextTick(() => {
|
||||
renderChart()
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
window.addEventListener('resize', resizeHandler)
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', resizeHandler)
|
||||
chart.value?.dispose()
|
||||
})
|
||||
|
||||
// Auto load when folders change
|
||||
watch(() => props.folders, () => {
|
||||
if (props.folders.length) {
|
||||
loadGraph()
|
||||
// Rerender on window resize
|
||||
_handleResize = () => {
|
||||
if (chartInstance) {
|
||||
chartInstance.resize()
|
||||
}
|
||||
}
|
||||
}, { immediate: true })
|
||||
window.addEventListener('resize', _handleResize)
|
||||
})
|
||||
|
||||
// Reload when parameters change
|
||||
watch([topNTags, topNClusters, showClusters], () => {
|
||||
if (graphData.value) {
|
||||
loadGraph()
|
||||
onUnmounted(() => {
|
||||
if (_handleResize) {
|
||||
window.removeEventListener('resize', _handleResize)
|
||||
_handleResize = null
|
||||
}
|
||||
if (chartInstance) {
|
||||
chartInstance.dispose()
|
||||
}
|
||||
})
|
||||
|
||||
defineExpose({ loadGraph })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tag-graph-container {
|
||||
<style scoped lang="scss">
|
||||
.tag-hierarchy-graph {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: calc(100vh - 200px);
|
||||
min-height: 600px;
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.loading-container,
|
||||
.error-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
margin-top: 16px;
|
||||
font-size: 14px;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.graph-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
padding: 12px 16px;
|
||||
background: #fafafa;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.toolbar .label {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
.control-panel {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 16px;
|
||||
z-index: 10;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.info-panel {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
right: 20px;
|
||||
width: 280px;
|
||||
background: white;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.info-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.info-title {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.info-body {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-actions {
|
||||
padding: 12px 16px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.stats-panel {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
left: 20px;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
background: white;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
padding: 12px 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-top: 4px;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ const threshold = ref(0.9)
|
|||
const minClusterSize = ref(2)
|
||||
const result = ref<ClusterIibOutputResp | null>(null)
|
||||
const cacheInfo = ref<ClusterIibOutputCachedResp | null>(null)
|
||||
const embeddingBuilt = ref(false) // Track if embeddings are already built
|
||||
|
||||
const _REQS_LS_KEY = 'iib_topic_search_hide_requirements_v1'
|
||||
// true = show requirements; false = hidden
|
||||
|
|
@ -262,6 +263,7 @@ const refresh = async () => {
|
|||
const runQuery = async () => {
|
||||
const q = (query.value || '').trim()
|
||||
if (!q) return
|
||||
if (qLoading.value) return
|
||||
if (!scopeCount.value) {
|
||||
message.warning(t('topicSearchNeedScope'))
|
||||
scopeOpen.value = true
|
||||
|
|
@ -272,9 +274,13 @@ const runQuery = async () => {
|
|||
qResult.value = await searchIibOutputByPrompt({
|
||||
query: q,
|
||||
top_k: 80,
|
||||
ensure_embed: true,
|
||||
ensure_embed: !embeddingBuilt.value, // Only build on first search
|
||||
folder_paths: scopeFolders.value
|
||||
})
|
||||
// Mark embeddings as built after first successful search
|
||||
if (!embeddingBuilt.value) {
|
||||
embeddingBuilt.value = true
|
||||
}
|
||||
// 搜索完成后自动打开结果页
|
||||
openQueryResult()
|
||||
} finally {
|
||||
|
|
@ -313,6 +319,20 @@ const openCluster = (item: ClusterIibOutputResp['clusters'][0]) => {
|
|||
tab.key = (pane as any).key
|
||||
}
|
||||
|
||||
const openClusterFromGraph = (cluster: { title: string; paths: string[]; size: number }) => {
|
||||
const pane = {
|
||||
type: 'topic-search-matched-image-grid' as const,
|
||||
name: `${cluster.title}(${cluster.size})`,
|
||||
key: Date.now() + uniqueId(),
|
||||
id: uniqueId(),
|
||||
title: cluster.title,
|
||||
paths: cluster.paths
|
||||
}
|
||||
const tab = g.tabList[props.tabIdx]
|
||||
tab.panes.push(pane as any)
|
||||
tab.key = (pane as any).key
|
||||
}
|
||||
|
||||
const handleSearchTag = (tag: string) => {
|
||||
// Search by tag name
|
||||
query.value = tag
|
||||
|
|
@ -333,6 +353,11 @@ onBeforeUnmount(() => {
|
|||
stopJobPoll()
|
||||
})
|
||||
|
||||
// Reset embedding built flag when scope changes
|
||||
watch(scopeFolders, () => {
|
||||
embeddingBuilt.value = false
|
||||
}, { deep: true })
|
||||
|
||||
watch(
|
||||
() => scopeFolders.value,
|
||||
() => {
|
||||
|
|
@ -522,11 +547,9 @@ watch(
|
|||
<div v-else-if="activeTab === 'graph'" style="height: calc(100vh - 300px); min-height: 600px;">
|
||||
<TagRelationGraph
|
||||
:folders="scopeFolders"
|
||||
:threshold="threshold"
|
||||
:min-cluster-size="minClusterSize"
|
||||
:lang="g.lang"
|
||||
:model="undefined"
|
||||
@search-tag="handleSearchTag"
|
||||
@open-cluster="openClusterFromGraph"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue