优化差分,跳过不变的文件,文件夹,增加tag页
parent
a2bcf52fb5
commit
7a599d249d
|
|
@ -1,3 +1,4 @@
|
|||
BaiduPCS-Go*
|
||||
*.log
|
||||
__pycache__
|
||||
__pycache__
|
||||
iib.db
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite App</title>
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-92c1f70c.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-5b1109d3.css">
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-9978e847.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-af635d2c.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ from PIL import Image
|
|||
from io import BytesIO
|
||||
import hashlib
|
||||
from urllib.parse import urlencode
|
||||
from scripts.db.datamodel import DataBase, Image as DbImg, Tag
|
||||
from scripts.db.init_image_data import init_image_data
|
||||
from scripts.db.datamodel import DataBase, Image as DbImg, Tag, Floder
|
||||
from scripts.db.update_image_data import update_image_data
|
||||
|
||||
from scripts.bin import (
|
||||
bin_file_name,
|
||||
|
|
@ -377,29 +377,31 @@ def infinite_image_browsing_api(_: Any, app: FastAPI):
|
|||
)
|
||||
|
||||
forever_cache_path = []
|
||||
img_search_dirs = []
|
||||
try:
|
||||
from modules.shared import opts
|
||||
|
||||
conf = opts.data
|
||||
|
||||
def get_config_path(conf):
|
||||
# 获取配置项
|
||||
def get_config_path(conf,
|
||||
keys = [
|
||||
"outdir_txt2img_samples",
|
||||
"outdir_img2img_samples",
|
||||
"outdir_save",
|
||||
"outdir_extras_samples",
|
||||
"additional_networks_extra_lora_path",
|
||||
"outdir_grids",
|
||||
"outdir_img2img_grids",
|
||||
"outdir_samples",
|
||||
"outdir_txt2img_grids",
|
||||
]
|
||||
]):
|
||||
# 获取配置项
|
||||
paths = [conf.get(key) for key in keys]
|
||||
|
||||
# 判断路径是否有效并转为绝对路径
|
||||
abs_paths = []
|
||||
for path in paths:
|
||||
if len(path.strip()) == 0:
|
||||
continue
|
||||
if os.path.isabs(path): # 已经是绝对路径
|
||||
abs_path = path
|
||||
else: # 转为绝对路径
|
||||
|
|
@ -410,9 +412,9 @@ def infinite_image_browsing_api(_: Any, app: FastAPI):
|
|||
return abs_paths
|
||||
|
||||
forever_cache_path = get_config_path(conf)
|
||||
img_search_dirs = forever_cache_path
|
||||
except:
|
||||
pass
|
||||
|
||||
def need_cache(path, parent_paths=forever_cache_path):
|
||||
"""
|
||||
判断 path 是否是 parent_paths 中某个路径的子路径
|
||||
|
|
@ -522,15 +524,18 @@ def infinite_image_browsing_api(_: Any, app: FastAPI):
|
|||
conn = DataBase.get_conn()
|
||||
img_count = DbImg.count(conn)
|
||||
tags = Tag.get_all(conn)
|
||||
expired_dirs = Floder.get_expired_dirs(conn)
|
||||
return {
|
||||
"img_count": img_count,
|
||||
"tags": tags
|
||||
"tags": tags,
|
||||
"expired": len(expired_dirs) != 0,
|
||||
"expired_dirs": expired_dirs
|
||||
}
|
||||
|
||||
@app.post(db_pre + "/init_image_data")
|
||||
async def generate_image_db_data():
|
||||
@app.post(db_pre + "/update_image_data")
|
||||
async def update_image_db_data():
|
||||
try:
|
||||
DataBase._initing = True
|
||||
init_image_data()
|
||||
update_image_data(img_search_dirs)
|
||||
finally:
|
||||
DataBase._initing = False
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
import sqlite3
|
||||
from typing import Optional
|
||||
from sqlite3 import Connection, connect
|
||||
from typing import List, Optional
|
||||
from scripts.tool import cwd
|
||||
from contextlib import closing
|
||||
import os
|
||||
from scripts.tool import get_modified_date
|
||||
|
||||
|
||||
class DataBase:
|
||||
_conn: Optional[sqlite3.Connection] = None
|
||||
_conn: Optional[Connection] = None
|
||||
|
||||
_initing = False
|
||||
|
||||
@classmethod
|
||||
def get_conn(clz) -> sqlite3.Connection:
|
||||
def get_conn(clz) -> Connection:
|
||||
if not clz._conn:
|
||||
clz.init()
|
||||
return clz._conn
|
||||
|
|
@ -15,12 +20,14 @@ class DataBase:
|
|||
@classmethod
|
||||
def init(clz):
|
||||
# 创建连接并打开数据库
|
||||
conn = sqlite3.connect('example.db')
|
||||
conn = connect(os.path.join(cwd, "iib.db"))
|
||||
clz._conn = conn
|
||||
Floder.create_table(conn)
|
||||
ImageTag.create_table(conn)
|
||||
Tag.create_table(conn)
|
||||
Image.create_table(conn)
|
||||
|
||||
|
||||
class Image:
|
||||
def __init__(self, path, exif=None):
|
||||
self.path = path
|
||||
|
|
@ -28,144 +35,225 @@ class Image:
|
|||
self.id = None
|
||||
|
||||
def save(self, conn):
|
||||
cur = conn.cursor()
|
||||
cur.execute("INSERT INTO image (path, exif) VALUES (?, ?)", (self.path, self.exif))
|
||||
self.id = cur.lastrowid
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"INSERT INTO image (path, exif) VALUES (?, ?)", (self.path, self.exif)
|
||||
)
|
||||
self.id = cur.lastrowid
|
||||
|
||||
@classmethod
|
||||
def get(cls, conn, id):
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT * FROM image WHERE id = ?", (id,))
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
return None
|
||||
else:
|
||||
image = cls(path=row[1], exif=row[2])
|
||||
image.id = row[0]
|
||||
return image
|
||||
def get(cls, conn: Connection, id_or_path):
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"SELECT * FROM image WHERE id = ? OR path = ?", (id_or_path, id_or_path)
|
||||
)
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
return None
|
||||
else:
|
||||
image = cls(path=row[1], exif=row[2])
|
||||
image.id = row[0]
|
||||
return image
|
||||
|
||||
@classmethod
|
||||
def create_table(cls, conn):
|
||||
cur = conn.cursor()
|
||||
cur.execute('''CREATE TABLE IF NOT EXISTS image (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
path TEXT,
|
||||
exif TEXT
|
||||
)''')
|
||||
cur.execute('CREATE INDEX IF NOT EXISTS image_idx_path ON image(path)')
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"""CREATE TABLE IF NOT EXISTS image (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
path TEXT,
|
||||
exif TEXT
|
||||
)"""
|
||||
)
|
||||
cur.execute("CREATE INDEX IF NOT EXISTS image_idx_path ON image(path)")
|
||||
|
||||
@classmethod
|
||||
def count(cls, conn):
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT COUNT(*) FROM image")
|
||||
count = cur.fetchone()[0]
|
||||
return count
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute("SELECT COUNT(*) FROM image")
|
||||
count = cur.fetchone()[0]
|
||||
return count
|
||||
|
||||
|
||||
class Tag:
|
||||
def __init__(self, name, score, type):
|
||||
def __init__(self, name: str, score: int, type: str, count=0):
|
||||
self.name = name
|
||||
self.score = score
|
||||
self.type = type
|
||||
self.count = count
|
||||
self.id = None
|
||||
|
||||
def save(self, conn):
|
||||
cur = conn.cursor()
|
||||
cur.execute("INSERT INTO tag (name, score, type) VALUES (?, ?, ?)", (self.name, self.score, self.type))
|
||||
self.id = cur.lastrowid
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"INSERT INTO tag (name, score, type, count) VALUES (?, ?, ?, ?)",
|
||||
(self.name, self.score, self.type, self.count),
|
||||
)
|
||||
self.id = cur.lastrowid
|
||||
|
||||
@classmethod
|
||||
def get(cls, conn, id):
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT * FROM tag WHERE id = ?", (id,))
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
return None
|
||||
else:
|
||||
tag = cls(name=row[1], score=row[2], type=row[3])
|
||||
tag.id = row[0]
|
||||
return tag
|
||||
|
||||
def get(cls, conn: Connection, id):
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute("SELECT * FROM tag WHERE id = ?", (id,))
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
return None
|
||||
else:
|
||||
tag = cls(name=row[1], score=row[2], type=row[3], count=row[4])
|
||||
tag.id = row[0]
|
||||
return tag
|
||||
|
||||
@classmethod
|
||||
def get_all(cls, conn):
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT * FROM tag")
|
||||
rows = cur.fetchall()
|
||||
tags: list[Tag] = []
|
||||
for row in rows:
|
||||
tag = cls(name=row[1], score=row[2], type=row[3])
|
||||
tag.id = row[0]
|
||||
tags.append(tag)
|
||||
return tags
|
||||
|
||||
@classmethod
|
||||
def get_or_create(cls, conn, name, score = None, type = None):
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT tag.* FROM tag WHERE name = ?", (name,))
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
tag = cls(name=name, score=score, type=type)
|
||||
tag.save(conn)
|
||||
return tag
|
||||
else:
|
||||
tag = cls(name=row[1], score=row[2], type=row[3])
|
||||
tag.id = row[0]
|
||||
return tag
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute("SELECT * FROM tag")
|
||||
rows = cur.fetchall()
|
||||
tags: list[Tag] = []
|
||||
for row in rows:
|
||||
tag = cls(name=row[1], score=row[2], type=row[3], count=row[4])
|
||||
tag.id = row[0]
|
||||
tags.append(tag)
|
||||
return tags
|
||||
|
||||
@classmethod
|
||||
def get_or_create(cls, conn: Connection, name, score=None, type=None):
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute("SELECT tag.* FROM tag WHERE name = ?", (name,))
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
tag = cls(name=name, score=score, type=type)
|
||||
tag.save(conn)
|
||||
return tag
|
||||
else:
|
||||
tag = cls(name=row[1], score=row[2], type=row[3], count=row[4])
|
||||
tag.id = row[0]
|
||||
return tag
|
||||
|
||||
@classmethod
|
||||
def create_table(cls, conn):
|
||||
cur = conn.cursor()
|
||||
cur.execute('''CREATE TABLE IF NOT EXISTS tag (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT,
|
||||
score INTEGER,
|
||||
type TEXT
|
||||
);
|
||||
''')
|
||||
cur.execute('CREATE INDEX IF NOT EXISTS tag_idx_name ON tag(name)')
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"""CREATE TABLE IF NOT EXISTS tag (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT,
|
||||
score INTEGER,
|
||||
type TEXT,
|
||||
count INTEGER
|
||||
);
|
||||
"""
|
||||
)
|
||||
cur.execute("CREATE INDEX IF NOT EXISTS tag_idx_name ON tag(name)")
|
||||
|
||||
|
||||
class ImageTag:
|
||||
def __init__(self, image_id, tag_id):
|
||||
def __init__(self, image_id: int, tag_id: int):
|
||||
assert tag_id and image_id
|
||||
self.image_id = image_id
|
||||
self.tag_id = tag_id
|
||||
|
||||
def save(self, conn):
|
||||
cur = conn.cursor()
|
||||
cur.execute("INSERT INTO image_tag (image_id, tag_id) VALUES (?, ?)", (self.image_id, self.tag_id))
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"INSERT INTO image_tag (image_id, tag_id) VALUES (?, ?)",
|
||||
(self.image_id, self.tag_id),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_tags_for_image(cls, conn, image_id):
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT tag.* FROM tag INNER JOIN image_tag ON tag.id = image_tag.tag_id WHERE image_tag.image_id = ?", (image_id,))
|
||||
rows = cur.fetchall()
|
||||
tags: list[Tag] = []
|
||||
for row in rows:
|
||||
tag = Tag(name=row[1], score=row[2], type=row[3])
|
||||
tag.id = row[0]
|
||||
tags.append(tag)
|
||||
return tags
|
||||
def get_tags_for_image(cls, conn: Connection, image_id):
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"SELECT tag.* FROM tag INNER JOIN image_tag ON tag.id = image_tag.tag_id WHERE image_tag.image_id = ?",
|
||||
(image_id,),
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
tags: list[Tag] = []
|
||||
for row in rows:
|
||||
tag = Tag(name=row[1], score=row[2], type=row[3])
|
||||
tag.id = row[0]
|
||||
tags.append(tag)
|
||||
return tags
|
||||
|
||||
@classmethod
|
||||
def get_images_for_tag(cls, conn, tag_id):
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT image.* FROM image INNER JOIN image_tag ON image.id = image_tag.image_id WHERE image_tag.tag_id = ?", (tag_id,))
|
||||
rows = cur.fetchall()
|
||||
images = []
|
||||
for row in rows:
|
||||
image = Image(path=row[1], exif=row[2])
|
||||
image.id = row[0]
|
||||
images.append(image)
|
||||
return images
|
||||
def get_images_for_tag(cls, conn: Connection, tag_id):
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"SELECT image.* FROM image INNER JOIN image_tag ON image.id = image_tag.image_id WHERE image_tag.tag_id = ?",
|
||||
(tag_id,),
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
images = []
|
||||
for row in rows:
|
||||
image = Image(path=row[1], exif=row[2])
|
||||
image.id = row[0]
|
||||
images.append(image)
|
||||
return images
|
||||
|
||||
@classmethod
|
||||
def create_table(cls, conn):
|
||||
cur = conn.cursor()
|
||||
cur.execute('''CREATE TABLE IF NOT EXISTS image_tag (
|
||||
image_id INTEGER,
|
||||
tag_id INTEGER,
|
||||
FOREIGN KEY (image_id) REFERENCES image(id),
|
||||
FOREIGN KEY (tag_id) REFERENCES tag(id),
|
||||
PRIMARY KEY (image_id, tag_id)
|
||||
)''')
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"""CREATE TABLE IF NOT EXISTS image_tag (
|
||||
image_id INTEGER,
|
||||
tag_id INTEGER,
|
||||
FOREIGN KEY (image_id) REFERENCES image(id),
|
||||
FOREIGN KEY (tag_id) REFERENCES tag(id),
|
||||
PRIMARY KEY (image_id, tag_id)
|
||||
)"""
|
||||
)
|
||||
|
||||
|
||||
class Floder:
|
||||
def __init__(self, id: int, path: str, modified_date: str):
|
||||
self.id = id
|
||||
self.path = path
|
||||
self.modified_date = modified_date
|
||||
|
||||
@classmethod
|
||||
def create_table(cls, conn):
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute(
|
||||
"""CREATE TABLE IF NOT EXISTS folders
|
||||
(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
path TEXT,
|
||||
modified_date TEXT)"""
|
||||
)
|
||||
cur.execute("CREATE INDEX IF NOT EXISTS folders_idx_path ON folders(path)")
|
||||
|
||||
@classmethod
|
||||
def check_need_update(cls, conn: Connection, folder_path: str):
|
||||
folder_path = os.path.normpath(folder_path)
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute("SELECT * FROM folders WHERE path=?", (folder_path,))
|
||||
folder_record = cur.fetchone() # 如果这个文件夹没有记录,或者修改时间与数据库不同,则需要修改
|
||||
return not folder_record or (
|
||||
folder_record[2] != get_modified_date(folder_path)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def update_modified_date_or_create(cls, conn: Connection, folder_path: str):
|
||||
folder_path = os.path.normpath(folder_path)
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute("SELECT * FROM folders WHERE path = ?", (folder_path,))
|
||||
row = cur.fetchone()
|
||||
if row:
|
||||
cur.execute(
|
||||
"UPDATE folders SET modified_date = ? WHERE path = ?",
|
||||
(get_modified_date(folder_path), folder_path),
|
||||
)
|
||||
else:
|
||||
cur.execute(
|
||||
"INSERT INTO folders (path, modified_date) VALUES (?, ?)",
|
||||
(folder_path, get_modified_date(folder_path)),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_expired_dirs(cls, conn: Connection):
|
||||
dirs: List[str] = []
|
||||
with closing(conn.cursor()) as cur:
|
||||
cur.execute("SELECT * FROM folders")
|
||||
result_set = cur.fetchall()
|
||||
for row in result_set:
|
||||
folder_path = row[1]
|
||||
if get_modified_date(folder_path) != row[2]:
|
||||
dirs.append(folder_path)
|
||||
return dirs
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
import sqlite3
|
||||
from scripts.db.datamodel import conn, Image as DbImg, Tag, ImageTag, DataBase
|
||||
import os
|
||||
from PIL import Image
|
||||
from scripts.tool import (
|
||||
read_info_from_image,
|
||||
parse_generation_parameters,
|
||||
is_valid_image_path,
|
||||
get_modified_date,
|
||||
)
|
||||
|
||||
# 定义一个函数来获取图片文件的EXIF数据
|
||||
def get_exif_data(file_path):
|
||||
try:
|
||||
with Image.open(file_path) as img:
|
||||
info = read_info_from_image(img)
|
||||
return parse_generation_parameters(info)
|
||||
except:
|
||||
pass
|
||||
return None
|
||||
|
||||
def init_image_data():
|
||||
conn = DataBase.get_conn()
|
||||
c = conn.cursor()
|
||||
|
||||
# 创建已完成文件夹表
|
||||
c.execute(
|
||||
"""CREATE TABLE IF NOT EXISTS folders
|
||||
(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
path TEXT,
|
||||
modified_date TEXT)"""
|
||||
)
|
||||
|
||||
# 递归处理每个文件夹
|
||||
def process_folder(folder_path: str):
|
||||
# 检查这个文件夹是否已经记录在数据库中
|
||||
c.execute("SELECT * FROM folders WHERE path=?", (folder_path,))
|
||||
folder_record = c.fetchone()
|
||||
|
||||
# 如果这个文件夹没有记录,或者修改时间与数据库不同,则继续
|
||||
if not folder_record or (folder_path) != folder_record[2]:
|
||||
print(f"Processing folder: {folder_path}")
|
||||
|
||||
c.execute(
|
||||
"INSERT INTO folders (path, modified_date) VALUES (?, ?)",
|
||||
(folder_path, get_modified_date(folder_path)),
|
||||
)
|
||||
|
||||
for filename in os.listdir(folder_path):
|
||||
file_path = os.path.join(folder_path, filename)
|
||||
|
||||
if os.path.isdir(file_path):
|
||||
process_folder(file_path)
|
||||
|
||||
elif is_valid_image_path(file_path):
|
||||
exif_data = get_exif_data(file_path)
|
||||
if not exif_data:
|
||||
continue
|
||||
exif, lora, pos, neg = exif_data
|
||||
img = DbImg(file_path)
|
||||
img.save(conn)
|
||||
|
||||
def safe_save_img_tag(img_tag: ImageTag):
|
||||
img_tag.save(conn) # 原先用来处理一些意外,但是写的正确完全没问题
|
||||
|
||||
size_tag = Tag.get_or_create(
|
||||
conn,
|
||||
str(exif.get("Size-1", 0)) + " * " + str(exif.get("Size-2", 0)),
|
||||
type="size",
|
||||
)
|
||||
size_img_tag = ImageTag(img.id, size_tag.id)
|
||||
safe_save_img_tag(size_img_tag)
|
||||
|
||||
for k in ["Model", "Sampler"]:
|
||||
v = exif.get(k)
|
||||
if not v:
|
||||
continue
|
||||
tag = Tag.get_or_create(conn, str(v), None, k)
|
||||
img_tag = ImageTag(img.id, tag.id)
|
||||
safe_save_img_tag(img_tag)
|
||||
for i in lora:
|
||||
tag = Tag.get_or_create(conn, i["name"], None, "lora")
|
||||
img_tag = ImageTag(img.id, tag.id)
|
||||
safe_save_img_tag(img_tag)
|
||||
for k in pos:
|
||||
tag = Tag.get_or_create(conn, k, None, "pos")
|
||||
img_tag = ImageTag(img.id, tag.id)
|
||||
safe_save_img_tag(img_tag)
|
||||
# neg暂时跳过感觉个没人会搜索这个
|
||||
|
||||
# 提交对数据库的更改
|
||||
conn.commit()
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
from typing import Dict, List
|
||||
from scripts.db.datamodel import Image as DbImg, Tag, ImageTag, DataBase, Floder
|
||||
import os
|
||||
from PIL import Image
|
||||
from scripts.tool import (
|
||||
read_info_from_image,
|
||||
parse_generation_parameters,
|
||||
is_valid_image_path
|
||||
)
|
||||
|
||||
# 定义一个函数来获取图片文件的EXIF数据
|
||||
def get_exif_data(file_path):
|
||||
try:
|
||||
with Image.open(file_path) as img:
|
||||
info = read_info_from_image(img)
|
||||
return parse_generation_parameters(info)
|
||||
except Image.DecompressionBombError:
|
||||
pass
|
||||
|
||||
def update_image_data(search_dirs: List[str]):
|
||||
conn = DataBase.get_conn()
|
||||
tag_incr_count_rec: Dict[int, int] = {}
|
||||
|
||||
def safe_save_img_tag(img_tag: ImageTag):
|
||||
tag_incr_count_rec[img_tag.tag_id] = tag_incr_count_rec.get(img_tag.tag_id, 0) + 1
|
||||
img_tag.save(conn) # 原先用来处理一些意外,但是写的正确完全没问题,去掉了try catch
|
||||
|
||||
# 递归处理每个文件夹
|
||||
def process_folder(folder_path: str):
|
||||
if not Floder.check_need_update(conn, folder_path):
|
||||
return
|
||||
print(f"Processing folder: {folder_path}")
|
||||
for filename in os.listdir(folder_path):
|
||||
file_path = os.path.normpath(os.path.join(folder_path, filename))
|
||||
|
||||
if os.path.isdir(file_path):
|
||||
process_folder(file_path)
|
||||
|
||||
elif is_valid_image_path(file_path):
|
||||
if DbImg.get(conn, file_path): # 已存在的跳过
|
||||
continue
|
||||
exif_data = get_exif_data(file_path)
|
||||
if not exif_data:
|
||||
continue
|
||||
exif, lora, pos, _ = exif_data
|
||||
img = DbImg(file_path)
|
||||
img.save(conn)
|
||||
|
||||
size_tag = Tag.get_or_create(
|
||||
conn,
|
||||
str(exif.get("Size-1", 0)) + " * " + str(exif.get("Size-2", 0)),
|
||||
type="size",
|
||||
)
|
||||
size_img_tag = ImageTag(img.id, size_tag.id)
|
||||
safe_save_img_tag(size_img_tag)
|
||||
|
||||
for k in ["Model", "Sampler"]:
|
||||
v = exif.get(k)
|
||||
if not v:
|
||||
continue
|
||||
tag = Tag.get_or_create(conn, str(v), None, k)
|
||||
img_tag = ImageTag(img.id, tag.id)
|
||||
safe_save_img_tag(img_tag)
|
||||
for i in lora:
|
||||
tag = Tag.get_or_create(conn, i["name"], None, "lora")
|
||||
img_tag = ImageTag(img.id, tag.id)
|
||||
safe_save_img_tag(img_tag)
|
||||
for k in pos:
|
||||
tag = Tag.get_or_create(conn, k, None, "pos")
|
||||
img_tag = ImageTag(img.id, tag.id)
|
||||
safe_save_img_tag(img_tag)
|
||||
# neg暂时跳过感觉个没人会搜索这个
|
||||
|
||||
# 提交对数据库的更改
|
||||
Floder.update_modified_date_or_create(conn, folder_path)
|
||||
conn.commit()
|
||||
|
||||
for dir in search_dirs:
|
||||
process_folder(dir)
|
||||
for tag_id in tag_incr_count_rec:
|
||||
tag = Tag.get(conn, tag_id)
|
||||
tag.count += tag_incr_count_rec[tag_id]
|
||||
tag.save(conn)
|
||||
conn.commit()
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ def get_locale():
|
|||
|
||||
locale = get_locale()
|
||||
|
||||
def get_modified_date(folder_path):
|
||||
def get_modified_date(folder_path: str):
|
||||
return datetime.fromtimestamp(os.path.getmtime(folder_path)).strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
|
||||
|
|
@ -185,6 +185,8 @@ def parse_generation_parameters(x: str):
|
|||
prompt = ""
|
||||
negative_prompt = ""
|
||||
done_with_prompt = False
|
||||
if not x:
|
||||
return {},[],[],[]
|
||||
*lines, lastline = x.strip().split("\n")
|
||||
if len(re_param.findall(lastline)) < 3:
|
||||
lines.append(lastline)
|
||||
|
|
@ -220,5 +222,5 @@ def parse_generation_parameters(x: str):
|
|||
model = res[k_s.replace("Module", "Model")]
|
||||
value = res.get(k_s.replace("Module", "Weight A"), "1")
|
||||
lora.append({ "name": model, "value": float(value) })
|
||||
return res, unique_by(lora, lambda x:x.name), unique_by(pos_prompt, lambda x:x), unique_by(neg_prompt, lambda x:x)
|
||||
return res, unique_by(lora, lambda x:x['name']), unique_by(pos_prompt, lambda x:x), unique_by(neg_prompt, lambda x:x)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,12 +9,35 @@ export {}
|
|||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
AAlert: typeof import('ant-design-vue/es')['Alert']
|
||||
ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb']
|
||||
ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem']
|
||||
AButton: typeof import('ant-design-vue/es')['Button']
|
||||
ACol: typeof import('ant-design-vue/es')['Col']
|
||||
ACollapse: typeof import('ant-design-vue/es')['Collapse']
|
||||
ACollapsePanel: typeof import('ant-design-vue/es')['CollapsePanel']
|
||||
ADropdown: typeof import('ant-design-vue/es')['Dropdown']
|
||||
AForm: typeof import('ant-design-vue/es')['Form']
|
||||
AFormItem: typeof import('ant-design-vue/es')['FormItem']
|
||||
AImage: typeof import('ant-design-vue/es')['Image']
|
||||
AInput: typeof import('ant-design-vue/es')['Input']
|
||||
AInputNumber: typeof import('ant-design-vue/es')['InputNumber']
|
||||
AMenu: typeof import('ant-design-vue/es')['Menu']
|
||||
AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
|
||||
AModal: typeof import('ant-design-vue/es')['Modal']
|
||||
AProgress: typeof import('ant-design-vue/es')['Progress']
|
||||
ARow: typeof import('ant-design-vue/es')['Row']
|
||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
||||
ASkeleton: typeof import('ant-design-vue/es')['Skeleton']
|
||||
ASpin: typeof import('ant-design-vue/es')['Spin']
|
||||
AStatistic: typeof import('ant-design-vue/es')['Statistic']
|
||||
ASwitch: typeof import('ant-design-vue/es')['Switch']
|
||||
ATabPane: typeof import('ant-design-vue/es')['TabPane']
|
||||
ATabs: typeof import('ant-design-vue/es')['Tabs']
|
||||
ATag: typeof import('ant-design-vue/es')['Tag']
|
||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
import{aQ as e,d as c,J as i,aV as r,y as u,K as d,L as p,a as _,N as l,R as m}from"./index-9978e847.js";import{B as f}from"./button-a5cee9c7.js";const g=async()=>(await e.get("/db/basic_info")).data,B=async()=>{await e.post("/db/update_image_data",{},{timeout:1/0})},x=c({__name:"TagSearch",setup(n){const t=i(new r);u(async()=>{const a=await g();console.log(a)});const o=()=>{t.pushAction(B)};return(a,I)=>{const s=f;return d(),p("div",null,[_(s,{onClick:o,loading:!t.isIdle},{default:l(()=>[m("安装")]),_:1},8,["loading"])])}}});export{x as default};
|
||||
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{b as s}from"./index-7906bab5.js";import{bO as t,aT as a}from"./index-1e01706b.js";function c(e,o){return e&&e.length?t(e,s(o)):[]}const i=(e,o)=>(a.success({content:o??`已复制内容 "${e}" 到粘贴板`}),navigator.clipboard.writeText(e));export{i as c,c as u};
|
||||
import{b as s}from"./index-4181a331.js";import{bO as t,aT as a}from"./index-9978e847.js";function c(e,o){return e&&e.length?t(e,s(o)):[]}const i=(e,o)=>(a.success({content:o??`已复制内容 "${e}" 到粘贴板`}),navigator.clipboard.writeText(e));export{i as c,c as u};
|
||||
|
|
@ -1 +1 @@
|
|||
.ant-collapse{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";background-color:#fafafa;border:1px solid #d9d9d9;border-bottom:0;border-radius:2px}.ant-collapse>.ant-collapse-item{border-bottom:1px solid #d9d9d9}.ant-collapse>.ant-collapse-item:last-child,.ant-collapse>.ant-collapse-item:last-child>.ant-collapse-header{border-radius:0 0 2px 2px}.ant-collapse>.ant-collapse-item>.ant-collapse-header{position:relative;display:flex;flex-wrap:nowrap;align-items:flex-start;padding:12px 16px;color:#000000d9;line-height:1.5715;cursor:pointer;transition:all .3s,visibility 0s}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{display:inline-block;margin-right:12px;font-size:12px;vertical-align:-1px}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow svg{transition:transform .24s}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-extra{margin-left:auto}.ant-collapse>.ant-collapse-item>.ant-collapse-header:focus{outline:none}.ant-collapse>.ant-collapse-item .ant-collapse-header-collapsible-only{cursor:default}.ant-collapse>.ant-collapse-item .ant-collapse-header-collapsible-only .ant-collapse-header-text{cursor:pointer}.ant-collapse>.ant-collapse-item.ant-collapse-no-arrow>.ant-collapse-header{padding-left:12px}.ant-collapse-icon-position-right>.ant-collapse-item>.ant-collapse-header{position:relative;padding:12px 40px 12px 16px}.ant-collapse-icon-position-right>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{position:absolute;top:50%;right:16px;left:auto;margin:0;transform:translateY(-50%)}.ant-collapse-content{color:#000000d9;background-color:#fff;border-top:1px solid #d9d9d9}.ant-collapse-content>.ant-collapse-content-box{padding:16px}.ant-collapse-content-hidden{display:none}.ant-collapse-item:last-child>.ant-collapse-content{border-radius:0 0 2px 2px}.ant-collapse-borderless{background-color:#fafafa;border:0}.ant-collapse-borderless>.ant-collapse-item{border-bottom:1px solid #d9d9d9}.ant-collapse-borderless>.ant-collapse-item:last-child,.ant-collapse-borderless>.ant-collapse-item:last-child .ant-collapse-header{border-radius:0}.ant-collapse-borderless>.ant-collapse-item>.ant-collapse-content{background-color:transparent;border-top:0}.ant-collapse-borderless>.ant-collapse-item>.ant-collapse-content>.ant-collapse-content-box{padding-top:4px}.ant-collapse-ghost{background-color:transparent;border:0}.ant-collapse-ghost>.ant-collapse-item{border-bottom:0}.ant-collapse-ghost>.ant-collapse-item>.ant-collapse-content{background-color:transparent;border-top:0}.ant-collapse-ghost>.ant-collapse-item>.ant-collapse-content>.ant-collapse-content-box{padding-top:12px;padding-bottom:12px}.ant-collapse .ant-collapse-item-disabled>.ant-collapse-header,.ant-collapse .ant-collapse-item-disabled>.ant-collapse-header>.arrow{color:#00000040;cursor:not-allowed}.ant-collapse-rtl{direction:rtl}.ant-collapse-rtl .ant-collapse>.ant-collapse-item>.ant-collapse-header{padding:12px 40px 12px 16px}.ant-collapse-rtl.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{margin-right:0;margin-left:12px}.ant-collapse-rtl.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow svg{transform:rotate(180deg)}.ant-collapse-rtl.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-extra{margin-right:auto;margin-left:0}.ant-collapse-rtl.ant-collapse>.ant-collapse-item.ant-collapse-no-arrow>.ant-collapse-header{padding-right:12px;padding-left:0}.container[data-v-e6e54882]{padding:20px;background-color:var(--zp-secondary-background);height:100%;overflow:auto}.header[data-v-e6e54882]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.header h1[data-v-e6e54882]{font-size:28px;font-weight:700;color:var(--zp-primary)}.last-record[data-v-e6e54882]{margin-left:8px;font-size:14px;color:var(--zp-tertiary)}.last-record a[data-v-e6e54882]{text-decoration:none;color:var(--zp-tertiary)}.last-record a[data-v-e6e54882]:hover{color:var(--zp-primary)}.content[data-v-e6e54882]{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));grid-gap:20px}.quick-start[data-v-e6e54882]{background-color:var(--zp-primary-background);border-radius:8px;box-shadow:0 1px 2px #0000001a;padding:20px}.quick-start ul[data-v-e6e54882]{list-style:none;padding:4px}.quick-start h2[data-v-e6e54882]{margin-top:0;margin-bottom:20px;font-size:20px;font-weight:700;color:var(--zp-primary)}.quick-start__item[data-v-e6e54882]{margin-bottom:10px;padding:4px 8px;display:flex;align-items:center}.quick-start__item[data-v-e6e54882]:hover{background:var(--zp-secondary-background);border-radius:4px;color:var(--primary-color);cursor:pointer}.quick-start__text[data-v-e6e54882]{flex:1;font-size:16px}.quick-start__icon[data-v-e6e54882]{margin-right:8px}
|
||||
.ant-collapse{box-sizing:border-box;margin:0;padding:0;color:#000000d9;font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;font-feature-settings:"tnum";background-color:#fafafa;border:1px solid #d9d9d9;border-bottom:0;border-radius:2px}.ant-collapse>.ant-collapse-item{border-bottom:1px solid #d9d9d9}.ant-collapse>.ant-collapse-item:last-child,.ant-collapse>.ant-collapse-item:last-child>.ant-collapse-header{border-radius:0 0 2px 2px}.ant-collapse>.ant-collapse-item>.ant-collapse-header{position:relative;display:flex;flex-wrap:nowrap;align-items:flex-start;padding:12px 16px;color:#000000d9;line-height:1.5715;cursor:pointer;transition:all .3s,visibility 0s}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{display:inline-block;margin-right:12px;font-size:12px;vertical-align:-1px}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow svg{transition:transform .24s}.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-extra{margin-left:auto}.ant-collapse>.ant-collapse-item>.ant-collapse-header:focus{outline:none}.ant-collapse>.ant-collapse-item .ant-collapse-header-collapsible-only{cursor:default}.ant-collapse>.ant-collapse-item .ant-collapse-header-collapsible-only .ant-collapse-header-text{cursor:pointer}.ant-collapse>.ant-collapse-item.ant-collapse-no-arrow>.ant-collapse-header{padding-left:12px}.ant-collapse-icon-position-right>.ant-collapse-item>.ant-collapse-header{position:relative;padding:12px 40px 12px 16px}.ant-collapse-icon-position-right>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{position:absolute;top:50%;right:16px;left:auto;margin:0;transform:translateY(-50%)}.ant-collapse-content{color:#000000d9;background-color:#fff;border-top:1px solid #d9d9d9}.ant-collapse-content>.ant-collapse-content-box{padding:16px}.ant-collapse-content-hidden{display:none}.ant-collapse-item:last-child>.ant-collapse-content{border-radius:0 0 2px 2px}.ant-collapse-borderless{background-color:#fafafa;border:0}.ant-collapse-borderless>.ant-collapse-item{border-bottom:1px solid #d9d9d9}.ant-collapse-borderless>.ant-collapse-item:last-child,.ant-collapse-borderless>.ant-collapse-item:last-child .ant-collapse-header{border-radius:0}.ant-collapse-borderless>.ant-collapse-item>.ant-collapse-content{background-color:transparent;border-top:0}.ant-collapse-borderless>.ant-collapse-item>.ant-collapse-content>.ant-collapse-content-box{padding-top:4px}.ant-collapse-ghost{background-color:transparent;border:0}.ant-collapse-ghost>.ant-collapse-item{border-bottom:0}.ant-collapse-ghost>.ant-collapse-item>.ant-collapse-content{background-color:transparent;border-top:0}.ant-collapse-ghost>.ant-collapse-item>.ant-collapse-content>.ant-collapse-content-box{padding-top:12px;padding-bottom:12px}.ant-collapse .ant-collapse-item-disabled>.ant-collapse-header,.ant-collapse .ant-collapse-item-disabled>.ant-collapse-header>.arrow{color:#00000040;cursor:not-allowed}.ant-collapse-rtl{direction:rtl}.ant-collapse-rtl .ant-collapse>.ant-collapse-item>.ant-collapse-header{padding:12px 40px 12px 16px}.ant-collapse-rtl.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow{margin-right:0;margin-left:12px}.ant-collapse-rtl.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-arrow svg{transform:rotate(180deg)}.ant-collapse-rtl.ant-collapse>.ant-collapse-item>.ant-collapse-header .ant-collapse-extra{margin-right:auto;margin-left:0}.ant-collapse-rtl.ant-collapse>.ant-collapse-item.ant-collapse-no-arrow>.ant-collapse-header{padding-right:12px;padding-left:0}.container[data-v-086c4ef8]{padding:20px;background-color:var(--zp-secondary-background);height:100%;overflow:auto}.header[data-v-086c4ef8]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.header h1[data-v-086c4ef8]{font-size:28px;font-weight:700;color:var(--zp-primary)}.last-record[data-v-086c4ef8]{margin-left:8px;font-size:14px;color:var(--zp-tertiary)}.last-record a[data-v-086c4ef8]{text-decoration:none;color:var(--zp-tertiary)}.last-record a[data-v-086c4ef8]:hover{color:var(--zp-primary)}.content[data-v-086c4ef8]{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));grid-gap:20px}.quick-start[data-v-086c4ef8]{background-color:var(--zp-primary-background);border-radius:8px;box-shadow:0 1px 2px #0000001a;padding:20px}.quick-start ul[data-v-086c4ef8]{list-style:none;padding:4px}.quick-start h2[data-v-086c4ef8]{margin-top:0;margin-bottom:20px;font-size:20px;font-weight:700;color:var(--zp-primary)}.quick-start__item[data-v-086c4ef8]{margin-bottom:10px;padding:4px 8px;display:flex;align-items:center}.quick-start__item[data-v-086c4ef8]:hover{background:var(--zp-secondary-background);border-radius:4px;color:var(--primary-color);cursor:pointer}.quick-start__text[data-v-086c4ef8]{flex:1;font-size:16px}.quick-start__icon[data-v-086c4ef8]{margin-right:8px}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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{u as p}from"./useTaskListStore-48f1766b.js";import{d as u,r as d,G as g,ah as f,ai as m,K as t,L as s,V as l,W as k,X as L,U as y,M as D,a0 as h}from"./index-1e01706b.js";const v={class:"container"},x=u({__name:"logDetail",props:{logDetailId:null},setup(r){const n=r,c=p(),a=d(),o=g(()=>c.taskLogMap.get(n.logDetailId));return f(o,async()=>{await m();const e=a.value;e&&(e.scrollTop=e.scrollHeight)},{deep:!0}),(e,B)=>(t(),s("div",v,[l("ul",{class:"list",ref_key:"logListEl",ref:a},[(t(!0),s(k,null,L(D(o),(i,_)=>(t(),s("li",{key:_},[l("pre",null,y(i.log),1)]))),128))],512)]))}});const T=h(x,[["__scopeId","data-v-59148842"]]);export{T as default};
|
||||
import{u as p}from"./useTaskListStore-95feb49c.js";import{d as u,r as d,G as g,ah as f,ai as m,K as t,L as s,V as l,W as k,X as L,U as y,M as D,a0 as h}from"./index-9978e847.js";const v={class:"container"},x=u({__name:"logDetail",props:{logDetailId:null},setup(r){const n=r,c=p(),a=d(),o=g(()=>c.taskLogMap.get(n.logDetailId));return f(o,async()=>{await m();const e=a.value;e&&(e.scrollTop=e.scrollHeight)},{deep:!0}),(e,B)=>(t(),s("div",v,[l("ul",{class:"list",ref_key:"logListEl",ref:a},[(t(!0),s(k,null,L(D(o),(i,_)=>(t(),s("li",{key:_},[l("pre",null,y(i.log),1)]))),128))],512)]))}});const T=h(x,[["__scopeId","data-v-59148842"]]);export{T as default};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,4 @@
|
|||
import{i as Te,I as P,t as Re,f as Oe,C as Ne,a as je,r as ie,E as $e}from"./index-f051364f.js";import{d as K,u as te,G as q,_ as S,a as _,h as g,x as fe,P as ke,r as O,a2 as Ee,bJ as Ve,b as _e,c as ne,B as ae,A as De,aj as U,ab as Ge,ah as Me,ai as J,y as He,f as Le,bK as Ue,bL as Ze,am as Be,af as Ye,H as qe,ae as ee,a6 as ge,D as Ke,i as Qe,bM as oe,bN as We}from"./index-1e01706b.js";import{i as Xe}from"./index-4e356a26.js";import{B as Je}from"./button-0e64deba.js";const et=K({compatConfig:{MODE:3},name:"AInputGroup",props:{prefixCls:String,size:{type:String},compact:{type:Boolean,default:void 0},onMouseenter:{type:Function},onMouseleave:{type:Function},onFocus:{type:Function},onBlur:{type:Function}},setup:function(e,t){var a=t.slots,c=te("input-group",e),p=c.prefixCls,f=c.direction,r=q(function(){var o,u=p.value;return o={},S(o,"".concat(u),!0),S(o,"".concat(u,"-lg"),e.size==="large"),S(o,"".concat(u,"-sm"),e.size==="small"),S(o,"".concat(u,"-compact"),e.compact),S(o,"".concat(u,"-rtl"),f.value==="rtl"),o});return function(){var o;return _("span",{class:r.value,onMouseenter:e.onMouseenter,onMouseleave:e.onMouseleave,onFocus:e.onFocus,onBlur:e.onBlur},[(o=a.default)===null||o===void 0?void 0:o.call(a)])}}});var le=/iPhone/i,me=/iPod/i,pe=/iPad/i,ue=/\bAndroid(?:.+)Mobile\b/i,he=/Android/i,Z=/\bAndroid(?:.+)SD4930UR\b/i,X=/\bAndroid(?:.+)(?:KF[A-Z]{2,4})\b/i,V=/Windows Phone/i,be=/\bWindows(?:.+)ARM\b/i,xe=/BlackBerry/i,ye=/BB10/i,Ce=/Opera Mini/i,ze=/\b(CriOS|Chrome)(?:.+)Mobile/i,Se=/Mobile(?:.+)Firefox\b/i;function i(l,e){return l.test(e)}function we(l){var e=l||(typeof navigator<"u"?navigator.userAgent:""),t=e.split("[FBAN");if(typeof t[1]<"u"){var a=t,c=fe(a,1);e=c[0]}if(t=e.split("Twitter"),typeof t[1]<"u"){var p=t,f=fe(p,1);e=f[0]}var r={apple:{phone:i(le,e)&&!i(V,e),ipod:i(me,e),tablet:!i(le,e)&&i(pe,e)&&!i(V,e),device:(i(le,e)||i(me,e)||i(pe,e))&&!i(V,e)},amazon:{phone:i(Z,e),tablet:!i(Z,e)&&i(X,e),device:i(Z,e)||i(X,e)},android:{phone:!i(V,e)&&i(Z,e)||!i(V,e)&&i(ue,e),tablet:!i(V,e)&&!i(Z,e)&&!i(ue,e)&&(i(X,e)||i(he,e)),device:!i(V,e)&&(i(Z,e)||i(X,e)||i(ue,e)||i(he,e))||i(/\bokhttp\b/i,e)},windows:{phone:i(V,e),tablet:i(be,e),device:i(V,e)||i(be,e)},other:{blackberry:i(xe,e),blackberry10:i(ye,e),opera:i(Ce,e),firefox:i(Se,e),chrome:i(ze,e),device:i(xe,e)||i(ye,e)||i(Ce,e)||i(Se,e)||i(ze,e)},any:null,phone:null,tablet:null};return r.any=r.apple.device||r.android.device||r.windows.device||r.other.device,r.phone=r.apple.phone||r.android.phone||r.windows.phone,r.tablet=r.apple.tablet||r.android.tablet||r.windows.tablet,r}var tt=g(g({},we()),{},{isMobile:we});const nt=tt;var at=["disabled","loading","addonAfter","suffix"];const rt=K({compatConfig:{MODE:3},name:"AInputSearch",inheritAttrs:!1,props:g(g({},Te()),{},{inputPrefixCls:String,enterButton:ke.any,onSearch:{type:Function}}),setup:function(e,t){var a=t.slots,c=t.attrs,p=t.expose,f=t.emit,r=O(),o=function(){var s;(s=r.value)===null||s===void 0||s.focus()},u=function(){var s;(s=r.value)===null||s===void 0||s.blur()};p({focus:o,blur:u});var y=function(s){f("update:value",s.target.value),s&&s.target&&s.type==="click"&&f("search",s.target.value,s),f("change",s)},h=function(s){var C;document.activeElement===((C=r.value)===null||C===void 0?void 0:C.input)&&s.preventDefault()},A=function(s){var C;f("search",(C=r.value)===null||C===void 0?void 0:C.stateValue,s),nt.tablet||r.value.focus()},I=te("input-search",e),T=I.prefixCls,$=I.getPrefixCls,N=I.direction,w=I.size,v=q(function(){return $("input",e.inputPrefixCls)});return function(){var m,s,C,M,E,B=e.disabled,j=e.loading,H=e.addonAfter,k=H===void 0?(m=a.addonAfter)===null||m===void 0?void 0:m.call(a):H,Q=e.suffix,W=Q===void 0?(s=a.suffix)===null||s===void 0?void 0:s.call(a):Q,re=Ee(e,at),b=e.enterButton,n=b===void 0?(C=(M=a.enterButton)===null||M===void 0?void 0:M.call(a))!==null&&C!==void 0?C:!1:b;n=n||n==="";var d=typeof n=="boolean"?_(Ve,null,null):null,x="".concat(T.value,"-button"),z=Array.isArray(n)?n[0]:n,R,L=z.type&&Xe(z.type)&&z.type.__ANT_BUTTON;if(L||z.tagName==="button")R=_e(z,g({onMousedown:h,onClick:A,key:"enterButton"},L?{class:x,size:w.value}:{}),!1);else{var D=d&&!n;R=_(Je,{class:x,type:n?"primary":void 0,size:w.value,disabled:B,key:"enterButton",onMousedown:h,onClick:A,loading:j,icon:D?d:null},{default:function(){return[D?null:d||n]}})}k&&(R=[R,k]);var G=ne(T.value,(E={},S(E,"".concat(T.value,"-rtl"),N.value==="rtl"),S(E,"".concat(T.value,"-").concat(w.value),!!w.value),S(E,"".concat(T.value,"-with-button"),!!n),E),c.class);return _(P,g(g(g({ref:r},ae(re,["onUpdate:value","onSearch","enterButton"])),c),{},{onPressEnter:A,size:w.value,prefixCls:v.value,addonAfter:R,suffix:W,onChange:y,class:G,disabled:B}),a)}}});var it=`
|
||||
import{i as Te,I as P,t as Re,f as Oe,C as Ne,a as je,r as ie,E as $e}from"./index-42e1bffc.js";import{d as K,u as te,G as q,_ as S,a as _,h as g,x as fe,P as ke,r as O,a2 as Ee,bJ as Ve,b as _e,c as ne,B as ae,A as De,aj as U,ab as Ge,ah as Me,ai as J,y as He,f as Le,bK as Ue,bL as Ze,am as Be,af as Ye,H as qe,ae as ee,a6 as ge,D as Ke,i as Qe,bM as oe,bN as We}from"./index-9978e847.js";import{i as Xe}from"./index-96d3719b.js";import{B as Je}from"./button-a5cee9c7.js";const et=K({compatConfig:{MODE:3},name:"AInputGroup",props:{prefixCls:String,size:{type:String},compact:{type:Boolean,default:void 0},onMouseenter:{type:Function},onMouseleave:{type:Function},onFocus:{type:Function},onBlur:{type:Function}},setup:function(e,t){var a=t.slots,c=te("input-group",e),p=c.prefixCls,f=c.direction,r=q(function(){var o,u=p.value;return o={},S(o,"".concat(u),!0),S(o,"".concat(u,"-lg"),e.size==="large"),S(o,"".concat(u,"-sm"),e.size==="small"),S(o,"".concat(u,"-compact"),e.compact),S(o,"".concat(u,"-rtl"),f.value==="rtl"),o});return function(){var o;return _("span",{class:r.value,onMouseenter:e.onMouseenter,onMouseleave:e.onMouseleave,onFocus:e.onFocus,onBlur:e.onBlur},[(o=a.default)===null||o===void 0?void 0:o.call(a)])}}});var le=/iPhone/i,me=/iPod/i,pe=/iPad/i,ue=/\bAndroid(?:.+)Mobile\b/i,he=/Android/i,Z=/\bAndroid(?:.+)SD4930UR\b/i,X=/\bAndroid(?:.+)(?:KF[A-Z]{2,4})\b/i,V=/Windows Phone/i,be=/\bWindows(?:.+)ARM\b/i,xe=/BlackBerry/i,ye=/BB10/i,Ce=/Opera Mini/i,ze=/\b(CriOS|Chrome)(?:.+)Mobile/i,Se=/Mobile(?:.+)Firefox\b/i;function i(l,e){return l.test(e)}function we(l){var e=l||(typeof navigator<"u"?navigator.userAgent:""),t=e.split("[FBAN");if(typeof t[1]<"u"){var a=t,c=fe(a,1);e=c[0]}if(t=e.split("Twitter"),typeof t[1]<"u"){var p=t,f=fe(p,1);e=f[0]}var r={apple:{phone:i(le,e)&&!i(V,e),ipod:i(me,e),tablet:!i(le,e)&&i(pe,e)&&!i(V,e),device:(i(le,e)||i(me,e)||i(pe,e))&&!i(V,e)},amazon:{phone:i(Z,e),tablet:!i(Z,e)&&i(X,e),device:i(Z,e)||i(X,e)},android:{phone:!i(V,e)&&i(Z,e)||!i(V,e)&&i(ue,e),tablet:!i(V,e)&&!i(Z,e)&&!i(ue,e)&&(i(X,e)||i(he,e)),device:!i(V,e)&&(i(Z,e)||i(X,e)||i(ue,e)||i(he,e))||i(/\bokhttp\b/i,e)},windows:{phone:i(V,e),tablet:i(be,e),device:i(V,e)||i(be,e)},other:{blackberry:i(xe,e),blackberry10:i(ye,e),opera:i(Ce,e),firefox:i(Se,e),chrome:i(ze,e),device:i(xe,e)||i(ye,e)||i(Ce,e)||i(Se,e)||i(ze,e)},any:null,phone:null,tablet:null};return r.any=r.apple.device||r.android.device||r.windows.device||r.other.device,r.phone=r.apple.phone||r.android.phone||r.windows.phone,r.tablet=r.apple.tablet||r.android.tablet||r.windows.tablet,r}var tt=g(g({},we()),{},{isMobile:we});const nt=tt;var at=["disabled","loading","addonAfter","suffix"];const rt=K({compatConfig:{MODE:3},name:"AInputSearch",inheritAttrs:!1,props:g(g({},Te()),{},{inputPrefixCls:String,enterButton:ke.any,onSearch:{type:Function}}),setup:function(e,t){var a=t.slots,c=t.attrs,p=t.expose,f=t.emit,r=O(),o=function(){var s;(s=r.value)===null||s===void 0||s.focus()},u=function(){var s;(s=r.value)===null||s===void 0||s.blur()};p({focus:o,blur:u});var y=function(s){f("update:value",s.target.value),s&&s.target&&s.type==="click"&&f("search",s.target.value,s),f("change",s)},h=function(s){var C;document.activeElement===((C=r.value)===null||C===void 0?void 0:C.input)&&s.preventDefault()},A=function(s){var C;f("search",(C=r.value)===null||C===void 0?void 0:C.stateValue,s),nt.tablet||r.value.focus()},I=te("input-search",e),T=I.prefixCls,$=I.getPrefixCls,N=I.direction,w=I.size,v=q(function(){return $("input",e.inputPrefixCls)});return function(){var m,s,C,M,E,B=e.disabled,j=e.loading,H=e.addonAfter,k=H===void 0?(m=a.addonAfter)===null||m===void 0?void 0:m.call(a):H,Q=e.suffix,W=Q===void 0?(s=a.suffix)===null||s===void 0?void 0:s.call(a):Q,re=Ee(e,at),b=e.enterButton,n=b===void 0?(C=(M=a.enterButton)===null||M===void 0?void 0:M.call(a))!==null&&C!==void 0?C:!1:b;n=n||n==="";var d=typeof n=="boolean"?_(Ve,null,null):null,x="".concat(T.value,"-button"),z=Array.isArray(n)?n[0]:n,R,L=z.type&&Xe(z.type)&&z.type.__ANT_BUTTON;if(L||z.tagName==="button")R=_e(z,g({onMousedown:h,onClick:A,key:"enterButton"},L?{class:x,size:w.value}:{}),!1);else{var D=d&&!n;R=_(Je,{class:x,type:n?"primary":void 0,size:w.value,disabled:B,key:"enterButton",onMousedown:h,onClick:A,loading:j,icon:D?d:null},{default:function(){return[D?null:d||n]}})}k&&(R=[R,k]);var G=ne(T.value,(E={},S(E,"".concat(T.value,"-rtl"),N.value==="rtl"),S(E,"".concat(T.value,"-").concat(w.value),!!w.value),S(E,"".concat(T.value,"-with-button"),!!n),E),c.class);return _(P,g(g(g({ref:r},ae(re,["onUpdate:value","onSearch","enterButton"])),c),{},{onPressEnter:A,size:w.value,prefixCls:v.value,addonAfter:R,suffix:W,onChange:y,class:G,disabled:B}),a)}}});var it=`
|
||||
min-height:0 !important;
|
||||
max-height:none !important;
|
||||
height:0 !important;
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
import{cQ as r,r as e,J as t,aV as i,cR as d}from"./index-1e01706b.js";const v=r("useTaskListStore",()=>{const a=e(new Map),n=t(new i),u=e(3),o=e([]),c=t([]),l=e(-1),s=e(null);return{checkBaiduyunInstalled:async()=>(s.value===null&&(s.value=d()),s.value),baiduyunInstalled:s,pollInterval:u,taskLogMap:a,queue:n,tasks:o,showDirAutoCompletedIdx:l,pendingBaiduyunTaskQueue:c}},{persist:{paths:["pollInterval","tasks"],key:"useTaskListStore-v0.0.1"}});export{v as u};
|
||||
import{cO as r,r as e,J as t,aV as i,cP as d}from"./index-9978e847.js";const v=r("useTaskListStore",()=>{const a=e(new Map),n=t(new i),u=e(3),o=e([]),c=t([]),l=e(-1),s=e(null);return{checkBaiduyunInstalled:async()=>(s.value===null&&(s.value=d()),s.value),baiduyunInstalled:s,pollInterval:u,taskLogMap:a,queue:n,tasks:o,showDirAutoCompletedIdx:l,pendingBaiduyunTaskQueue:c}},{persist:{paths:["pollInterval","tasks"],key:"useTaskListStore-v0.0.1"}});export{v as u};
|
||||
|
|
@ -7,13 +7,8 @@
|
|||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite App</title>
|
||||
<<<<<<< HEAD
|
||||
<script type="module" crossorigin src="/baidu_netdisk/fe-static/assets/index-1e01706b.js"></script>
|
||||
<link rel="stylesheet" href="/baidu_netdisk/fe-static/assets/index-5b1109d3.css">
|
||||
=======
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-92c1f70c.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-5b1109d3.css">
|
||||
>>>>>>> 5b1c6c2 (新增tag,image数据库相关,prefix bd -> iib)
|
||||
<script type="module" crossorigin src="/infinite_image_browsing/fe-static/assets/index-9978e847.js"></script>
|
||||
<link rel="stylesheet" href="/infinite_image_browsing/fe-static/assets/index-af635d2c.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import { axiosInst } from './index'
|
||||
|
||||
interface Tag {
|
||||
name: string
|
||||
id: number
|
||||
type: string
|
||||
count: number
|
||||
}
|
||||
|
||||
export const getDbBasicInfo = async () => {
|
||||
const resp = await axiosInst.get('/db/basic_info')
|
||||
return resp.data as {
|
||||
img_count: number,
|
||||
tags: Tag[]
|
||||
}
|
||||
}
|
||||
|
||||
export const InitImageData = async () => {
|
||||
await axiosInst.post('/db/update_image_data', { }, { timeout: Infinity })
|
||||
}
|
||||
|
|
@ -17,7 +17,8 @@ const compMap: Record<TabPane['type'], ReturnType<typeof defineAsyncComponent>>
|
|||
"task-record": defineAsyncComponent(() => import('@/page/taskRecord/taskRecord.vue')),
|
||||
empty: defineAsyncComponent(() => import('./emptyStartup.vue')),
|
||||
"log-detail": defineAsyncComponent(() => import('@/page/taskRecord/logDetail.vue')),
|
||||
"global-setting": defineAsyncComponent(() => import('@/page/globalSetting.vue'))
|
||||
"global-setting": defineAsyncComponent(() => import('@/page/globalSetting.vue')),
|
||||
"tag-search": defineAsyncComponent(() => import('@/page/TagSearch/TagSearch.vue'))
|
||||
}
|
||||
const onEdit = (idx: number, targetKey: any, action: string) => {
|
||||
const tab = global.tabList[idx]
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const global = useGlobalStore()
|
|||
const props = defineProps<{ tabIdx: number, paneIdx: number }>()
|
||||
const compCnMap: Partial<Record<TabPane['type'], string>> = {
|
||||
local: t('local'),
|
||||
"tag-search": 'tag搜索',
|
||||
'global-setting': t('globalSettings'),
|
||||
netdisk: t('baiduCloud'),
|
||||
"task-record": t('taskRecord'),
|
||||
|
|
@ -26,6 +27,7 @@ const openInCurrentTab = (type: TabPane['type'], path?: string, walkMode = false
|
|||
case 'task-record':
|
||||
case 'log-detail':
|
||||
case 'global-setting':
|
||||
case 'tag-search':
|
||||
case 'empty':
|
||||
pane = { type, name: compCnMap[type]!, key: Date.now() + uniqueId() }
|
||||
break
|
||||
|
|
@ -83,13 +85,13 @@ const previewInNewWindow = () => window.parent.open('/infinite_image_browsing')
|
|||
<div class="quick-start">
|
||||
<h2>{{ $t('launch') }}</h2>
|
||||
<ul>
|
||||
<li v-for="comp in Object.keys(compCnMap).slice(0, 2) as TabPane['type'][]" :key="comp"
|
||||
<li v-for="comp in Object.keys(compCnMap).slice(0, 3) as TabPane['type'][]" :key="comp"
|
||||
class="quick-start__item" @click.prevent="openInCurrentTab(comp)">
|
||||
<span class="quick-start__text line-clamp-1">{{ compCnMap[comp] }}</span>
|
||||
</li>
|
||||
<a-collapse style="margin-top: 32px; " v-model:activeKey="global.baiduNetdiskPageOpened" :bordered="false">
|
||||
<a-collapse-panel key="true" :header="$t('baiduNetdiskCollapseTitle')" >
|
||||
<li v-for="comp in Object.keys(compCnMap).slice(2) as TabPane['type'][]" :key="comp"
|
||||
<li v-for="comp in Object.keys(compCnMap).slice(3) as TabPane['type'][]" :key="comp"
|
||||
class="quick-start__item" @click.prevent="openInCurrentTab(comp)">
|
||||
<span class="quick-start__text line-clamp-1">{{ compCnMap[comp] }}</span>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue'
|
||||
import {getDbBasicInfo, InitImageData} from '@/api/db'
|
||||
import { reactive } from 'vue'
|
||||
import { FetchQueue } from 'vue3-ts-util'
|
||||
|
||||
const queue = reactive(new FetchQueue())
|
||||
|
||||
onMounted(async () => {
|
||||
const info = await getDbBasicInfo()
|
||||
console.log(info)
|
||||
})
|
||||
|
||||
const onClick = () => {
|
||||
queue.pushAction(InitImageData)
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<AButton @click="onClick" :loading="!queue.isIdle">安装</AButton>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
|
|
@ -14,7 +14,7 @@ import { typedEventEmitter, type UniqueId, ID } from 'vue3-ts-util'
|
|||
|
||||
|
||||
interface OtherTabPane {
|
||||
type: 'auto-upload' | 'task-record' | 'empty' | 'log-detail' | 'global-setting'
|
||||
type: 'auto-upload' | 'task-record' | 'empty' | 'log-detail' | 'global-setting' | 'tag-search'
|
||||
name: string
|
||||
readonly key: string
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue