feat(ai-studio): clarify hosted model tiers

This commit is contained in:
chengma
2026-07-11 14:49:39 +08:00
parent 2c6ed87201
commit 03916dea55
10 changed files with 342 additions and 42 deletions
+12 -4
View File
@@ -7,7 +7,7 @@ import os
from PySide6.QtCore import QMimeData
from PySide6.QtWidgets import QListWidget, QListWidgetItem
from ... import accounts, appconfig, db, image_studio, image_studio_export, prompts
from ... import accounts, appconfig, cmhub_models, db, image_studio, image_studio_export, prompts
from .. import file_manager
from ..widgets import *
from ..workers import (
@@ -278,6 +278,7 @@ class ImageStudioTab(QWidget):
self._build_ui()
self._connect_signals()
self._refresh_model_hint()
self.refresh_accounts()
self.refresh_templates()
self.refresh_projects()
@@ -434,7 +435,7 @@ class ImageStudioTab(QWidget):
form.addRow("比例", self.aspect_combo)
layout.addLayout(form)
self.billing_label = QLabel("cmhub 托管模型:扣点以返回结果为准")
self.billing_label = QLabel("cmhub 托管默认档:扣点以返回结果为准")
self.billing_label.setObjectName("imageStudioBillingLabel")
self.billing_label.setWordWrap(True)
layout.addWidget(self.billing_label)
@@ -1045,7 +1046,7 @@ class ImageStudioTab(QWidget):
self.progress_bar.setRange(0, count)
self.progress_bar.setValue(0)
self.log_view.clear()
self._append_log(f"[AI工场] 本轮生图开始:{count} 张,来源 cmhub 托管模型")
self._append_log(f"[AI工场] 本轮生图开始:{count} 张,使用 {self._cmhub_image_model_summary()}")
worker = ImageStudioGenerateJobsWorker(
self.current_project.id,
source.id,
@@ -1189,7 +1190,7 @@ class ImageStudioTab(QWidget):
self.progress_bar.setRange(0, total)
self.progress_bar.setValue(done)
if payload.get("points_balance") is not None:
text = f"cmhub 托管模型:余额 {payload.get('points_balance')}"
text = f"{self._cmhub_image_model_summary()};余额 {payload.get('points_balance')}"
if payload.get("points_cost") is not None:
text += f",本张扣点 {payload.get('points_cost')}"
self.billing_label.setText(text)
@@ -1339,6 +1340,13 @@ class ImageStudioTab(QWidget):
scrollbar = self.log_view.verticalScrollBar()
scrollbar.setValue(scrollbar.maximum())
def _refresh_model_hint(self):
self.billing_label.setText(self._cmhub_image_model_summary())
def _cmhub_image_model_summary(self):
alias = appconfig.cmhub_config(self.config).get("image_alias", "")
return cmhub_models.configured_alias_summary(alias)
def _message(self, title, text):
box = QMessageBox(self)
box.setWindowTitle(str(title or "提示"))
+3 -27
View File
@@ -7,6 +7,7 @@ import os
from ... import ai as ai_module
from ... import chrome
from ... import cmhub_models
from ..widgets import *
from ..workers import AIModelTestWorker as _RealAIModelTestWorker
from ..workers import CMHubSettingsWorker as _RealCMHubSettingsWorker
@@ -1250,7 +1251,8 @@ class SettingsTab(QWidget):
alias = str(model.get("alias") or "").strip()
if not alias or alias in added:
continue
combo.addItem(self._cmhub_alias_label(model), alias)
combo.addItem(cmhub_models.alias_label(model), alias)
combo.setItemData(combo.count() - 1, cmhub_models.alias_tooltip(model), Qt.ToolTipRole)
added.add(alias)
if selected and selected not in added:
combo.addItem(f"{selected}(已保存)", selected)
@@ -1272,32 +1274,6 @@ class SettingsTab(QWidget):
items.append(model)
return items
def _cmhub_alias_label(self, model):
alias = str(model.get("alias") or "").strip()
price_text = self._cmhub_price_text(model.get("prices"))
parts = [alias]
if price_text:
parts.append(price_text)
if model.get("requires_image"):
parts.append("需参考图")
return " · ".join(parts)
def _cmhub_price_text(self, prices):
if not isinstance(prices, list):
return ""
parts = []
for item in prices[:3]:
if not isinstance(item, dict):
continue
cost = item.get("points_cost")
if cost is None:
cost = item.get("cost")
if cost is None:
continue
resolution = item.get("resolution") or item.get("name") or ""
parts.append(f"{resolution}:{cost}点" if resolution else f"{cost}点")
return "/".join(parts)
def _cmhub_alias_count(self, operation):
combo = self.cmhub_title_alias_combo if operation == "title" else self.cmhub_image_alias_combo
return sum(1 for index in range(combo.count()) if combo.itemData(index))
+12 -1
View File
@@ -57,7 +57,7 @@ def _format_image_studio_event(event):
if result:
prefix += f":{result}"
if detail:
prefix += f",{diagnostics.redact_log_text(detail)}"
prefix += f",{_image_studio_user_detail(detail)}"
if event.get("points_cost") is not None:
prefix += f",扣点 {event.get('points_cost')}"
if event.get("points_balance") is not None:
@@ -65,6 +65,17 @@ def _format_image_studio_event(event):
return prefix
def _image_studio_user_detail(detail):
text = diagnostics.redact_log_text(str(detail or "")).replace("\r", " ").replace("\n", " ").strip()
text = _USER_LOG_URL_RE.sub("[链接已隐藏]", text)
text = _USER_LOG_PATH_RE.sub("[接口路径已隐藏]", text)
text = text.replace("GET [链接已隐藏]", "请求 cmhub")
text = text.replace("POST [链接已隐藏]", "请求 cmhub")
if len(text) > 180:
return text[:177] + "..."
return text
class ImageStudioPullImagesWorker(BaseWorker):
"""Read Shopee main image URLs for one AI studio project in background."""