优化差分,跳过不变的文件,文件夹,增加tag页

pull/31/head
zanllp 2023-04-21 00:29:53 +08:00
parent a2bcf52fb5
commit 7a599d249d
32 changed files with 414 additions and 269 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
BaiduPCS-Go*
*.log
__pycache__
__pycache__
iib.db

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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)

23
vue/components.d.ts vendored
View File

@ -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']
}

1
vue/dist/assets/TagSearch-addb5809.js vendored Normal file
View File

@ -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

View File

@ -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};

View File

@ -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

View File

@ -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

3
vue/dist/assets/stackView-fec1fdd7.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -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

View File

@ -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};

9
vue/dist/index.html vendored
View File

@ -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>

20
vue/src/api/db.ts Normal file
View File

@ -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 })
}

View File

@ -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]

View File

@ -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>

View File

@ -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>

View File

@ -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
}