Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f22fbd46ad | ||
|
|
8c3a001657 | ||
|
|
d052d9dceb | ||
|
|
652721ac9a | ||
|
|
cfd2bdea4a | ||
|
|
b8cd3c28a5 | ||
|
|
153dbc0788 | ||
|
|
288f026d47 | ||
|
|
0a8c532506 | ||
|
|
8bfe601588 | ||
|
|
7a183464ae | ||
|
|
f9b0afcbf5 | ||
|
|
1f4c55ab89 | ||
|
|
da1ec3a52c | ||
|
|
79b106d986 | ||
|
|
4c1af63d0d |
10
__init__.py
10
__init__.py
@@ -5,7 +5,7 @@ from .py import utils
|
||||
|
||||
|
||||
# Init config settings
|
||||
config.extension_uri = os.path.dirname(__file__)
|
||||
config.extension_uri = utils.normalize_path(os.path.dirname(__file__))
|
||||
utils.resolve_model_base_paths()
|
||||
|
||||
version = utils.get_current_version()
|
||||
@@ -173,12 +173,12 @@ async def read_model_preview(request):
|
||||
try:
|
||||
folders = folder_paths.get_folder_paths(model_type)
|
||||
base_path = folders[index]
|
||||
abs_path = os.path.join(base_path, filename)
|
||||
abs_path = utils.join_path(base_path, filename)
|
||||
except:
|
||||
abs_path = extension_uri
|
||||
|
||||
if not os.path.isfile(abs_path):
|
||||
abs_path = os.path.join(extension_uri, "assets", "no-preview.png")
|
||||
abs_path = utils.join_path(extension_uri, "assets", "no-preview.png")
|
||||
return web.FileResponse(abs_path)
|
||||
|
||||
|
||||
@@ -188,10 +188,10 @@ async def read_download_preview(request):
|
||||
extension_uri = config.extension_uri
|
||||
|
||||
download_path = utils.get_download_path()
|
||||
preview_path = os.path.join(download_path, filename)
|
||||
preview_path = utils.join_path(download_path, filename)
|
||||
|
||||
if not os.path.isfile(preview_path):
|
||||
preview_path = os.path.join(extension_uri, "assets", "no-preview.png")
|
||||
preview_path = utils.join_path(extension_uri, "assets", "no-preview.png")
|
||||
|
||||
return web.FileResponse(preview_path)
|
||||
|
||||
|
||||
@@ -46,13 +46,13 @@ download_thread_pool = thread.DownloadThreadPool()
|
||||
|
||||
def set_task_content(task_id: str, task_content: Union[TaskContent, dict]):
|
||||
download_path = utils.get_download_path()
|
||||
task_file_path = os.path.join(download_path, f"{task_id}.task")
|
||||
task_file_path = utils.join_path(download_path, f"{task_id}.task")
|
||||
utils.save_dict_pickle_file(task_file_path, utils.unpack_dataclass(task_content))
|
||||
|
||||
|
||||
def get_task_content(task_id: str):
|
||||
download_path = utils.get_download_path()
|
||||
task_file = os.path.join(download_path, f"{task_id}.task")
|
||||
task_file = utils.join_path(download_path, f"{task_id}.task")
|
||||
if not os.path.isfile(task_file):
|
||||
raise RuntimeError(f"Task {task_id} not found")
|
||||
task_content = utils.load_dict_pickle_file(task_file)
|
||||
@@ -67,7 +67,7 @@ def get_task_status(task_id: str):
|
||||
if task_status is None:
|
||||
download_path = utils.get_download_path()
|
||||
task_content = get_task_content(task_id)
|
||||
download_file = os.path.join(download_path, f"{task_id}.download")
|
||||
download_file = utils.join_path(download_path, f"{task_id}.download")
|
||||
download_size = 0
|
||||
if os.path.exists(download_file):
|
||||
download_size = os.path.getsize(download_file)
|
||||
@@ -103,7 +103,7 @@ async def scan_model_download_task_list(sid: str):
|
||||
task_files = folder_paths.filter_files_extensions(task_files, [".task"])
|
||||
task_files = sorted(
|
||||
task_files,
|
||||
key=lambda x: os.stat(os.path.join(download_dir, x)).st_ctime,
|
||||
key=lambda x: os.stat(utils.join_path(download_dir, x)).st_ctime,
|
||||
reverse=True,
|
||||
)
|
||||
task_list: list[dict] = []
|
||||
@@ -135,7 +135,7 @@ async def create_model_download_task(post: dict):
|
||||
download_path = utils.get_download_path()
|
||||
|
||||
task_id = uuid.uuid4().hex
|
||||
task_path = os.path.join(download_path, f"{task_id}.task")
|
||||
task_path = utils.join_path(download_path, f"{task_id}.task")
|
||||
if os.path.exists(task_path):
|
||||
raise RuntimeError(f"Task {task_id} already exists")
|
||||
|
||||
@@ -183,7 +183,7 @@ async def delete_model_download_task(task_id: str):
|
||||
task_file_target = os.path.splitext(task_file)[0]
|
||||
if task_file_target == task_id:
|
||||
delete_task_status(task_id)
|
||||
os.remove(os.path.join(download_dir, task_file))
|
||||
os.remove(utils.join_path(download_dir, task_file))
|
||||
|
||||
await socket.send_json("deleteDownloadTask", task_id)
|
||||
|
||||
@@ -264,8 +264,8 @@ async def download_model_file(
|
||||
fullname = task_content.fullname
|
||||
# Write description file
|
||||
description = task_content.description
|
||||
description_file = os.path.join(download_path, f"{task_id}.md")
|
||||
with open(description_file, "w") as f:
|
||||
description_file = utils.join_path(download_path, f"{task_id}.md")
|
||||
with open(description_file, "w", encoding="utf-8", newline="") as f:
|
||||
f.write(description)
|
||||
|
||||
model_path = utils.get_full_path(model_type, path_index, fullname)
|
||||
@@ -273,7 +273,7 @@ async def download_model_file(
|
||||
utils.rename_model(download_tmp_file, model_path)
|
||||
|
||||
time.sleep(1)
|
||||
task_file = os.path.join(download_path, f"{task_id}.task")
|
||||
task_file = utils.join_path(download_path, f"{task_id}.task")
|
||||
os.remove(task_file)
|
||||
await socket.send_json("completeDownloadTask", task_id)
|
||||
|
||||
@@ -297,7 +297,7 @@ async def download_model_file(
|
||||
raise RuntimeError("No downloadUrl found")
|
||||
|
||||
download_path = utils.get_download_path()
|
||||
download_tmp_file = os.path.join(download_path, f"{task_id}.download")
|
||||
download_tmp_file = utils.join_path(download_path, f"{task_id}.download")
|
||||
|
||||
downloaded_size = 0
|
||||
if os.path.isfile(download_tmp_file):
|
||||
|
||||
@@ -46,16 +46,16 @@ def scan_models():
|
||||
image_dict = utils.file_list_to_name_dict(images)
|
||||
|
||||
for fullname in models:
|
||||
fullname = fullname.replace(os.path.sep, "/")
|
||||
fullname = utils.normalize_path(fullname)
|
||||
basename = os.path.splitext(fullname)[0]
|
||||
extension = os.path.splitext(fullname)[1]
|
||||
|
||||
abs_path = os.path.join(base_path, fullname)
|
||||
abs_path = utils.join_path(base_path, fullname)
|
||||
file_stats = os.stat(abs_path)
|
||||
|
||||
# Resolve preview
|
||||
image_name = image_dict.get(basename, "no-preview.png")
|
||||
abs_image_path = os.path.join(base_path, image_name)
|
||||
abs_image_path = utils.join_path(base_path, image_name)
|
||||
if os.path.isfile(abs_image_path):
|
||||
image_state = os.stat(abs_image_path)
|
||||
image_timestamp = round(image_state.st_mtime_ns / 1000000)
|
||||
@@ -87,10 +87,10 @@ def get_model_info(model_path: str):
|
||||
metadata = utils.get_model_metadata(model_path)
|
||||
|
||||
description_file = utils.get_model_description_name(model_path)
|
||||
description_file = os.path.join(directory, description_file)
|
||||
description_file = utils.join_path(directory, description_file)
|
||||
description = None
|
||||
if os.path.isfile(description_file):
|
||||
with open(description_file, "r", encoding="utf-8") as f:
|
||||
with open(description_file, "r", encoding="utf-8", newline="") as f:
|
||||
description = f.read()
|
||||
|
||||
return {
|
||||
@@ -128,11 +128,11 @@ def remove_model(model_path: str):
|
||||
|
||||
model_previews = utils.get_model_all_images(model_path)
|
||||
for preview in model_previews:
|
||||
os.remove(os.path.join(model_dirname, preview))
|
||||
os.remove(utils.join_path(model_dirname, preview))
|
||||
|
||||
model_descriptions = utils.get_model_all_descriptions(model_path)
|
||||
for description in model_descriptions:
|
||||
os.remove(os.path.join(model_dirname, description))
|
||||
os.remove(utils.join_path(model_dirname, description))
|
||||
|
||||
|
||||
async def create_model_download_task(post):
|
||||
|
||||
65
py/utils.py
65
py/utils.py
@@ -15,9 +15,18 @@ from typing import Any
|
||||
from . import config
|
||||
|
||||
|
||||
def normalize_path(path: str):
|
||||
normpath = os.path.normpath(path)
|
||||
return normpath.replace(os.path.sep, "/")
|
||||
|
||||
|
||||
def join_path(path: str, *paths: list[str]):
|
||||
return normalize_path(os.path.join(path, *paths))
|
||||
|
||||
|
||||
def get_current_version():
|
||||
try:
|
||||
pyproject_path = os.path.join(config.extension_uri, "pyproject.toml")
|
||||
pyproject_path = join_path(config.extension_uri, "pyproject.toml")
|
||||
config_parser = configparser.ConfigParser()
|
||||
config_parser.read(pyproject_path)
|
||||
version = config_parser.get("project", "version")
|
||||
@@ -27,15 +36,15 @@ def get_current_version():
|
||||
|
||||
|
||||
def download_web_distribution(version: str):
|
||||
web_path = os.path.join(config.extension_uri, "web")
|
||||
dev_web_file = os.path.join(web_path, "manager-dev.js")
|
||||
web_path = join_path(config.extension_uri, "web")
|
||||
dev_web_file = join_path(web_path, "manager-dev.js")
|
||||
if os.path.exists(dev_web_file):
|
||||
return
|
||||
|
||||
web_version = "0.0.0"
|
||||
version_file = os.path.join(web_path, "version.yaml")
|
||||
version_file = join_path(web_path, "version.yaml")
|
||||
if os.path.exists(version_file):
|
||||
with open(version_file, "r") as f:
|
||||
with open(version_file, "r", encoding="utf-8", newline="") as f:
|
||||
version_content = yaml.safe_load(f)
|
||||
web_version = version_content.get("version", web_version)
|
||||
|
||||
@@ -49,7 +58,7 @@ def download_web_distribution(version: str):
|
||||
response = requests.get(download_url, stream=True)
|
||||
response.raise_for_status()
|
||||
|
||||
temp_file = os.path.join(config.extension_uri, "temp.tar.gz")
|
||||
temp_file = join_path(config.extension_uri, "temp.tar.gz")
|
||||
with open(temp_file, "wb") as f:
|
||||
for chunk in response.iter_content(chunk_size=8192):
|
||||
f.write(chunk)
|
||||
@@ -82,7 +91,8 @@ def resolve_model_base_paths():
|
||||
continue
|
||||
if folder == "custom_nodes":
|
||||
continue
|
||||
config.model_base_paths[folder] = folder_paths.get_folder_paths(folder)
|
||||
folders = folder_paths.get_folder_paths(folder)
|
||||
config.model_base_paths[folder] = [normalize_path(f) for f in folders]
|
||||
|
||||
|
||||
def get_full_path(model_type: str, path_index: int, filename: str):
|
||||
@@ -93,7 +103,8 @@ def get_full_path(model_type: str, path_index: int, filename: str):
|
||||
if not path_index < len(folders):
|
||||
raise RuntimeError(f"PathIndex {path_index} is not in {model_type}")
|
||||
base_path = folders[path_index]
|
||||
return os.path.join(base_path, filename)
|
||||
full_path = join_path(base_path, filename)
|
||||
return full_path
|
||||
|
||||
|
||||
def get_valid_full_path(model_type: str, path_index: int, filename: str):
|
||||
@@ -104,7 +115,7 @@ def get_valid_full_path(model_type: str, path_index: int, filename: str):
|
||||
if not path_index < len(folders):
|
||||
raise RuntimeError(f"PathIndex {path_index} is not in {model_type}")
|
||||
base_path = folders[path_index]
|
||||
full_path = os.path.join(base_path, filename)
|
||||
full_path = join_path(base_path, filename)
|
||||
if os.path.isfile(full_path):
|
||||
return full_path
|
||||
elif os.path.islink(full_path):
|
||||
@@ -114,7 +125,7 @@ def get_valid_full_path(model_type: str, path_index: int, filename: str):
|
||||
|
||||
|
||||
def get_download_path():
|
||||
download_path = os.path.join(config.extension_uri, "downloads")
|
||||
download_path = join_path(config.extension_uri, "downloads")
|
||||
if not os.path.exists(download_path):
|
||||
os.makedirs(download_path)
|
||||
return download_path
|
||||
@@ -124,12 +135,12 @@ def recursive_search_files(directory: str):
|
||||
files, folder_all = folder_paths.recursive_search(
|
||||
directory, excluded_dir_names=[".git"]
|
||||
)
|
||||
return files
|
||||
return [normalize_path(f) for f in files]
|
||||
|
||||
|
||||
def search_files(directory: str):
|
||||
entries = os.listdir(directory)
|
||||
files = [f for f in entries if os.path.isfile(os.path.join(directory, f))]
|
||||
files = [f for f in entries if os.path.isfile(join_path(directory, f))]
|
||||
return files
|
||||
|
||||
|
||||
@@ -193,13 +204,13 @@ def save_model_preview_image(model_path: str, image_file: Any):
|
||||
for image in old_preview_images:
|
||||
if os.path.splitext(image)[1].endswith(".preview"):
|
||||
a1111_civitai_helper_image = True
|
||||
image_path = os.path.join(base_dirname, image)
|
||||
image_path = join_path(base_dirname, image)
|
||||
os.remove(image_path)
|
||||
|
||||
# save new preview image
|
||||
basename = os.path.splitext(os.path.basename(model_path))[0]
|
||||
extension = f".{content_type.split('/')[1]}"
|
||||
new_preview_path = os.path.join(base_dirname, f"{basename}{extension}")
|
||||
new_preview_path = join_path(base_dirname, f"{basename}{extension}")
|
||||
|
||||
with open(new_preview_path, "wb") as f:
|
||||
f.write(image_file.file.read())
|
||||
@@ -209,7 +220,7 @@ def save_model_preview_image(model_path: str, image_file: Any):
|
||||
"""
|
||||
Keep preview image of a1111_civitai_helper
|
||||
"""
|
||||
new_preview_path = os.path.join(base_dirname, f"{basename}.preview{extension}")
|
||||
new_preview_path = join_path(base_dirname, f"{basename}.preview{extension}")
|
||||
with open(new_preview_path, "wb") as f:
|
||||
f.write(image_file.file.read())
|
||||
|
||||
@@ -243,15 +254,15 @@ def save_model_description(model_path: str, content: Any):
|
||||
# remove old descriptions
|
||||
old_descriptions = get_model_all_descriptions(model_path)
|
||||
for desc in old_descriptions:
|
||||
description_path = os.path.join(base_dirname, desc)
|
||||
description_path = join_path(base_dirname, desc)
|
||||
os.remove(description_path)
|
||||
|
||||
# save new description
|
||||
basename = os.path.splitext(os.path.basename(model_path))[0]
|
||||
extension = ".md"
|
||||
new_desc_path = os.path.join(base_dirname, f"{basename}{extension}")
|
||||
new_desc_path = join_path(base_dirname, f"{basename}{extension}")
|
||||
|
||||
with open(new_desc_path, "w", encoding="utf-8") as f:
|
||||
with open(new_desc_path, "w", encoding="utf-8", newline="") as f:
|
||||
f.write(content)
|
||||
|
||||
|
||||
@@ -272,29 +283,27 @@ def rename_model(model_path: str, new_model_path: str):
|
||||
os.makedirs(new_model_dirname)
|
||||
|
||||
# move model
|
||||
os.rename(model_path, new_model_path)
|
||||
shutil.move(model_path, new_model_path)
|
||||
|
||||
# move preview
|
||||
previews = get_model_all_images(model_path)
|
||||
for preview in previews:
|
||||
preview_path = os.path.join(model_dirname, preview)
|
||||
preview_path = join_path(model_dirname, preview)
|
||||
preview_name = os.path.splitext(preview)[0]
|
||||
preview_ext = os.path.splitext(preview)[1]
|
||||
new_preview_path = (
|
||||
os.path.join(new_model_dirname, new_model_name + preview_ext)
|
||||
join_path(new_model_dirname, new_model_name + preview_ext)
|
||||
if preview_name == model_name
|
||||
else os.path.join(
|
||||
new_model_dirname, new_model_name + ".preview" + preview_ext
|
||||
)
|
||||
else join_path(new_model_dirname, new_model_name + ".preview" + preview_ext)
|
||||
)
|
||||
os.rename(preview_path, new_preview_path)
|
||||
shutil.move(preview_path, new_preview_path)
|
||||
|
||||
# move description
|
||||
description = get_model_description_name(model_path)
|
||||
description_path = os.path.join(model_dirname, description)
|
||||
description_path = join_path(model_dirname, description)
|
||||
if os.path.isfile(description_path):
|
||||
new_description_path = os.path.join(new_model_dirname, f"{new_model_name}.md")
|
||||
os.rename(description_path, new_description_path)
|
||||
new_description_path = join_path(new_model_dirname, f"{new_model_name}.md")
|
||||
shutil.move(description_path, new_description_path)
|
||||
|
||||
|
||||
import pickle
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-model-manager"
|
||||
description = "Manage models: browsing, download and delete."
|
||||
version = "2.0.0"
|
||||
version = "2.0.2"
|
||||
license = "LICENSE"
|
||||
|
||||
[project.urls]
|
||||
|
||||
@@ -72,8 +72,8 @@ const handleCancel = () => {
|
||||
}
|
||||
|
||||
const handleSave = async (data: BaseModel) => {
|
||||
await update(modelContent.value, data)
|
||||
editable.value = false
|
||||
await update(props.model, data)
|
||||
}
|
||||
|
||||
const handleDelete = async () => {
|
||||
|
||||
@@ -29,11 +29,13 @@
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr v-for="item in information" class="h-8 border-b">
|
||||
<tr v-for="item in information" class="h-8 whitespace-nowrap border-b">
|
||||
<td class="border-r bg-gray-300 px-4 dark:bg-gray-800">
|
||||
{{ $t(`info.${item.key}`) }}
|
||||
</td>
|
||||
<td class="break-all px-4">{{ item.display }}</td>
|
||||
<td class="overflow-hidden text-ellipsis break-all px-4">
|
||||
{{ item.display }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -81,7 +83,8 @@ const pathOptions = computed(() => {
|
||||
const information = computed(() => {
|
||||
return Object.values(baseInfo.value).filter((row) => {
|
||||
if (editable.value) {
|
||||
return row.key !== 'fullname'
|
||||
const hiddenKeys = ['fullname', 'pathIndex']
|
||||
return !hiddenKeys.includes(row.key)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="duration-300 group-hover/card:opacity-100">
|
||||
<div class="opacity-0 duration-300 group-hover/card:opacity-100">
|
||||
<div class="flex flex-col gap-4 *:pointer-events-auto">
|
||||
<Button
|
||||
icon="pi pi-plus"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
></textarea>
|
||||
|
||||
<div v-show="!active">
|
||||
<div v-show="editable" class="flex items-center gap-2 text-gray-600">
|
||||
<div v-show="editable" class="mb-4 flex items-center gap-2 text-gray-600">
|
||||
<i class="pi pi-info-circle"></i>
|
||||
<span>
|
||||
{{ $t('tapToChange') }}
|
||||
|
||||
@@ -44,7 +44,7 @@ const [content, modifiers] = defineModel<string, 'trim'>()
|
||||
const inputRef = ref()
|
||||
|
||||
const innerValue = ref(content)
|
||||
const trigger = computed(() => props.updateTrigger ?? 'input')
|
||||
const trigger = computed(() => props.updateTrigger ?? 'change')
|
||||
const updateContent = () => {
|
||||
let value = innerValue.value
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useConfig } from 'hooks/config'
|
||||
import { useLoading } from 'hooks/loading'
|
||||
import { useMarkdown } from 'hooks/markdown'
|
||||
import { request, useRequest } from 'hooks/request'
|
||||
@@ -7,7 +8,7 @@ import { cloneDeep } from 'lodash'
|
||||
import { app } from 'scripts/comfyAPI'
|
||||
import { bytesToSize, formatDate, previewUrlToFile } from 'utils/common'
|
||||
import { ModelGrid } from 'utils/legacy'
|
||||
import { resolveModelTypeLoader } from 'utils/model'
|
||||
import { genModelKey, resolveModelTypeLoader } from 'utils/model'
|
||||
import {
|
||||
computed,
|
||||
inject,
|
||||
@@ -20,7 +21,7 @@ import {
|
||||
} from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
export const useModels = defineStore('models', () => {
|
||||
export const useModels = defineStore('models', (store) => {
|
||||
const { data, refresh } = useRequest<Model[]>('/models', { defaultValue: [] })
|
||||
const { toast, confirm } = useToast()
|
||||
const { t } = useI18n()
|
||||
@@ -28,6 +29,7 @@ export const useModels = defineStore('models', () => {
|
||||
|
||||
const updateModel = async (model: BaseModel, data: BaseModel) => {
|
||||
const formData = new FormData()
|
||||
let oldKey: string | null = null
|
||||
|
||||
// Check current preview
|
||||
if (model.preview !== data.preview) {
|
||||
@@ -45,6 +47,7 @@ export const useModels = defineStore('models', () => {
|
||||
model.fullname !== data.fullname ||
|
||||
model.pathIndex !== data.pathIndex
|
||||
) {
|
||||
oldKey = genModelKey(model)
|
||||
formData.append('type', data.type)
|
||||
formData.append('pathIndex', data.pathIndex.toString())
|
||||
formData.append('fullname', data.fullname)
|
||||
@@ -59,19 +62,25 @@ export const useModels = defineStore('models', () => {
|
||||
method: 'PUT',
|
||||
body: formData,
|
||||
})
|
||||
.catch(() => {
|
||||
.catch((err) => {
|
||||
const error_message = err.message ?? err.error
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: 'Failed to update model',
|
||||
detail: `Failed to update model: ${error_message}`,
|
||||
life: 15000,
|
||||
})
|
||||
throw new Error(error_message)
|
||||
})
|
||||
.finally(() => {
|
||||
loading.hide()
|
||||
})
|
||||
|
||||
await refresh()
|
||||
if (oldKey) {
|
||||
store.dialog.close({ key: oldKey })
|
||||
}
|
||||
|
||||
refresh()
|
||||
}
|
||||
|
||||
const deleteModel = async (model: BaseModel) => {
|
||||
@@ -90,6 +99,7 @@ export const useModels = defineStore('models', () => {
|
||||
severity: 'danger',
|
||||
},
|
||||
accept: () => {
|
||||
const dialogKey = genModelKey(model)
|
||||
loading.show()
|
||||
request(`/model/${model.type}/${model.pathIndex}/${model.fullname}`, {
|
||||
method: 'DELETE',
|
||||
@@ -101,6 +111,7 @@ export const useModels = defineStore('models', () => {
|
||||
detail: `${model.fullname} Deleted`,
|
||||
life: 2000,
|
||||
})
|
||||
store.dialog.close({ key: dialogKey })
|
||||
return refresh()
|
||||
})
|
||||
.then(() => {
|
||||
@@ -118,7 +129,9 @@ export const useModels = defineStore('models', () => {
|
||||
loading.hide()
|
||||
})
|
||||
},
|
||||
reject: () => {},
|
||||
reject: () => {
|
||||
resolve(void 0)
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -191,6 +204,8 @@ const baseInfoKey = Symbol('baseInfo') as InjectionKey<
|
||||
export const useModelBaseInfoEditor = (formInstance: ModelFormInstance) => {
|
||||
const { formData: model, modelData } = formInstance
|
||||
|
||||
const { modelFolders } = useConfig()
|
||||
|
||||
const type = computed({
|
||||
get: () => {
|
||||
return model.value.type
|
||||
@@ -239,6 +254,15 @@ export const useModelBaseInfoEditor = (formInstance: ModelFormInstance) => {
|
||||
key: 'type',
|
||||
formatter: () => modelData.value.type,
|
||||
},
|
||||
{
|
||||
key: 'pathIndex',
|
||||
formatter: () => {
|
||||
const modelType = modelData.value.type
|
||||
const pathIndex = modelData.value.pathIndex
|
||||
const folders = modelFolders.value[modelType] ?? []
|
||||
return `${folders[pathIndex]}`
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'fullname',
|
||||
formatter: (val) => val,
|
||||
|
||||
@@ -32,6 +32,7 @@ const messages = {
|
||||
},
|
||||
info: {
|
||||
type: 'Model Type',
|
||||
pathIndex: 'Directory',
|
||||
fullname: 'File Name',
|
||||
sizeBytes: 'File Size',
|
||||
createdAt: 'Created At',
|
||||
@@ -69,6 +70,7 @@ const messages = {
|
||||
},
|
||||
info: {
|
||||
type: '类型',
|
||||
pathIndex: '目录',
|
||||
fullname: '文件名',
|
||||
sizeBytes: '文件大小',
|
||||
createdAt: '创建时间',
|
||||
|
||||
113
src/style.css
113
src/style.css
@@ -82,26 +82,69 @@
|
||||
|
||||
.markdown-it {
|
||||
font-family: theme('fontFamily.sans');
|
||||
font-size: theme('fontSize.base');
|
||||
line-height: theme('lineHeight.relaxed');
|
||||
word-break: break-word;
|
||||
margin: 0;
|
||||
|
||||
&::before {
|
||||
display: table;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: table;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
> *:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
> *:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: theme('fontSize.2xl');
|
||||
font-weight: theme('fontWeight.bold');
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin-top: theme('margin.4');
|
||||
margin-bottom: theme('margin.4');
|
||||
padding-bottom: theme('padding[2.5]');
|
||||
font-size: 2em;
|
||||
padding-bottom: 0.3em;
|
||||
border-bottom: 1px solid var(--p-surface-700);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: theme('fontSize.xl');
|
||||
font-weight: theme('fontWeight.bold');
|
||||
font-size: 1.5em;
|
||||
padding-bottom: 0.3em;
|
||||
border-bottom: 1px solid var(--p-surface-700);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: theme('fontSize.lg');
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 0.85em;
|
||||
color: var(--p-surface-500);
|
||||
}
|
||||
|
||||
a {
|
||||
@@ -114,8 +157,16 @@
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em 0;
|
||||
p,
|
||||
blockquote,
|
||||
ul,
|
||||
ol,
|
||||
dl,
|
||||
table,
|
||||
pre,
|
||||
details {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
p img {
|
||||
@@ -126,7 +177,6 @@
|
||||
|
||||
ul,
|
||||
ol {
|
||||
margin: 1em 0;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
@@ -135,23 +185,38 @@
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 5px solid #ddd;
|
||||
padding: 10px 20px;
|
||||
margin: 1.5em 0;
|
||||
background: #f9f9f9;
|
||||
padding: 0px 1em;
|
||||
border-left: 0.25em solid var(--p-surface-500);
|
||||
color: var(--p-surface-500);
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
code,
|
||||
pre {
|
||||
background: #f9f9f9;
|
||||
padding: 3px 5px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
blockquote > *:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
blockquote > *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 10px;
|
||||
font-size: 85%;
|
||||
border-radius: 6px;
|
||||
padding: 8px 16px;
|
||||
overflow-x: auto;
|
||||
background: var(--p-dialog-background);
|
||||
filter: invert(10%);
|
||||
}
|
||||
|
||||
pre code,
|
||||
pre tt {
|
||||
display: inline;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
line-height: inherit;
|
||||
word-wrap: normal;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ function dev(): Plugin {
|
||||
fs.mkdirSync(outDirPath)
|
||||
|
||||
const port = server.config.server.port
|
||||
const content = `import "http://127.0.0.1:${port}/src/main.ts";`
|
||||
const content = `import "http://localhost:${port}/src/main.ts";`
|
||||
fs.writeFileSync(path.join(outDirPath, 'manager-dev.js'), content)
|
||||
})
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user