Spaces:
Running
Running
图像提示词图像上传支持9张
Browse files- models.py +4 -0
- router_prompts.py +32 -0
models.py
CHANGED
|
@@ -277,6 +277,8 @@ class PromptCreate(BaseModel):
|
|
| 277 |
cover_image: str # 封面图
|
| 278 |
media_type: str = "image" # "image" 或 "video"(示例媒体类型)
|
| 279 |
video_url: Optional[str] = None # 示例视频 URL(仅 media_type=video)
|
|
|
|
|
|
|
| 280 |
price: int = 0 # 定价(0=免费)
|
| 281 |
tags: Optional[List[str]] = None # 自定义标签(最多10个,每个≤12字)
|
| 282 |
|
|
@@ -289,6 +291,8 @@ class PromptUpdate(BaseModel):
|
|
| 289 |
cover_image: Optional[str] = None
|
| 290 |
media_type: Optional[str] = None
|
| 291 |
video_url: Optional[str] = None
|
|
|
|
|
|
|
| 292 |
price: Optional[int] = None
|
| 293 |
tags: Optional[List[str]] = None
|
| 294 |
|
|
|
|
| 277 |
cover_image: str # 封面图
|
| 278 |
media_type: str = "image" # "image" 或 "video"(示例媒体类型)
|
| 279 |
video_url: Optional[str] = None # 示例视频 URL(仅 media_type=video)
|
| 280 |
+
images: Optional[List[str]] = None # 图像提示词图片列表(最多9张,首张为封面)
|
| 281 |
+
is_original: bool = False # 原创作品标记
|
| 282 |
price: int = 0 # 定价(0=免费)
|
| 283 |
tags: Optional[List[str]] = None # 自定义标签(最多10个,每个≤12字)
|
| 284 |
|
|
|
|
| 291 |
cover_image: Optional[str] = None
|
| 292 |
media_type: Optional[str] = None
|
| 293 |
video_url: Optional[str] = None
|
| 294 |
+
images: Optional[List[str]] = None # 图像提示词图片列表(最多9张,首张为封面)
|
| 295 |
+
is_original: Optional[bool] = None # 原创作品标记
|
| 296 |
price: Optional[int] = None
|
| 297 |
tags: Optional[List[str]] = None
|
| 298 |
|
router_prompts.py
CHANGED
|
@@ -54,6 +54,23 @@ MAX_CATEGORY_LEN = 8
|
|
| 54 |
MAX_CATEGORY_PER_TYPE = 30
|
| 55 |
MAX_TAGS = 10 # 单个提示词最多标签数
|
| 56 |
MAX_TAG_LEN = 12 # 单个标签最大字数
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
|
| 59 |
def calculate_tx_hash(tx_id, account, tx_type, amount, prev_hash):
|
|
@@ -352,6 +369,9 @@ async def create_prompt(prompt: PromptCreate, current_user: str = Depends(requir
|
|
| 352 |
# 未上传示例视频时降级为图片展示
|
| 353 |
media_type = "image"
|
| 354 |
|
|
|
|
|
|
|
|
|
|
| 355 |
new_prompt = {
|
| 356 |
"id": f"prompt_{int(time.time())}_{uuid.uuid4().hex[:6]}",
|
| 357 |
"prompt_type": prompt.prompt_type,
|
|
@@ -362,6 +382,8 @@ async def create_prompt(prompt: PromptCreate, current_user: str = Depends(requir
|
|
| 362 |
"cover_image": prompt.cover_image,
|
| 363 |
"media_type": media_type,
|
| 364 |
"video_url": video_url,
|
|
|
|
|
|
|
| 365 |
"price": price,
|
| 366 |
"author": current_user,
|
| 367 |
"created_at": int(time.time()),
|
|
@@ -441,11 +463,21 @@ async def update_prompt(prompt_id: str, update_data: PromptUpdate, current_user:
|
|
| 441 |
return False
|
| 442 |
prompt["media_type"] = update_data.media_type
|
| 443 |
if update_data.media_type == "image":
|
|
|
|
| 444 |
prompt["video_url"] = None
|
| 445 |
if update_data.video_url is not None:
|
| 446 |
prompt["video_url"] = update_data.video_url
|
| 447 |
if update_data.video_url:
|
| 448 |
prompt["media_type"] = "video"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 449 |
if update_data.tags is not None:
|
| 450 |
prompt["tags"] = _sanitize_tags(update_data.tags)
|
| 451 |
result_holder["prompt"] = prompt
|
|
|
|
| 54 |
MAX_CATEGORY_PER_TYPE = 30
|
| 55 |
MAX_TAGS = 10 # 单个提示词最多标签数
|
| 56 |
MAX_TAG_LEN = 12 # 单个标签最大字数
|
| 57 |
+
MAX_IMAGES = 9 # 图像提示词最多图片数(与讨论区一致)
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def _sanitize_images(images) -> list:
|
| 61 |
+
"""清洗图片列表:过滤非法元素,最多 MAX_IMAGES 张"""
|
| 62 |
+
if not isinstance(images, list):
|
| 63 |
+
return []
|
| 64 |
+
cleaned = []
|
| 65 |
+
for url in images:
|
| 66 |
+
if not isinstance(url, str):
|
| 67 |
+
continue
|
| 68 |
+
u = url.strip()
|
| 69 |
+
if u:
|
| 70 |
+
cleaned.append(u)
|
| 71 |
+
if len(cleaned) >= MAX_IMAGES:
|
| 72 |
+
break
|
| 73 |
+
return cleaned
|
| 74 |
|
| 75 |
|
| 76 |
def calculate_tx_hash(tx_id, account, tx_type, amount, prev_hash):
|
|
|
|
| 369 |
# 未上传示例视频时降级为图片展示
|
| 370 |
media_type = "image"
|
| 371 |
|
| 372 |
+
# 图像提示词的图片列表(首张即封面);视频提示词不保留图片列表
|
| 373 |
+
images = _sanitize_images(prompt.images) if media_type == "image" else []
|
| 374 |
+
|
| 375 |
new_prompt = {
|
| 376 |
"id": f"prompt_{int(time.time())}_{uuid.uuid4().hex[:6]}",
|
| 377 |
"prompt_type": prompt.prompt_type,
|
|
|
|
| 382 |
"cover_image": prompt.cover_image,
|
| 383 |
"media_type": media_type,
|
| 384 |
"video_url": video_url,
|
| 385 |
+
"images": images,
|
| 386 |
+
"is_original": bool(prompt.is_original),
|
| 387 |
"price": price,
|
| 388 |
"author": current_user,
|
| 389 |
"created_at": int(time.time()),
|
|
|
|
| 463 |
return False
|
| 464 |
prompt["media_type"] = update_data.media_type
|
| 465 |
if update_data.media_type == "image":
|
| 466 |
+
# 图像类型不保留视频(与 create 逻辑一致)
|
| 467 |
prompt["video_url"] = None
|
| 468 |
if update_data.video_url is not None:
|
| 469 |
prompt["video_url"] = update_data.video_url
|
| 470 |
if update_data.video_url:
|
| 471 |
prompt["media_type"] = "video"
|
| 472 |
+
# 类型变更后补正关联字段(pydantic 无法区分未传与 null,统一在此收尾)
|
| 473 |
+
if prompt.get("media_type") == "image":
|
| 474 |
+
prompt["video_url"] = None
|
| 475 |
+
else:
|
| 476 |
+
prompt["images"] = []
|
| 477 |
+
if update_data.images is not None:
|
| 478 |
+
prompt["images"] = _sanitize_images(update_data.images)
|
| 479 |
+
if update_data.is_original is not None:
|
| 480 |
+
prompt["is_original"] = bool(update_data.is_original)
|
| 481 |
if update_data.tags is not None:
|
| 482 |
prompt["tags"] = _sanitize_tags(update_data.tags)
|
| 483 |
result_holder["prompt"] = prompt
|