feat: cover

This commit is contained in:
2025-12-10 20:50:48 +08:00
parent 9ad8d9d7e9
commit 116efcdf93
6 changed files with 80 additions and 11 deletions

View File

@@ -156,8 +156,8 @@ export const i18nData = {
"Cloudflare Turnstile Secret Key": "Cloudflare Turnstile 密钥",
"If the cloudflare turnstile keys are not empty, the turnstile will be used for register and download.":
"如果设置了 Cloudflare Turnstile 密钥,将在注册和下载时启用验证",
"The first image will be used as the cover image":
"第一张图片将用作封面图片",
"You can select a cover image using the radio button in the Cover column":
"您可以使用封面列中的单选按钮选择封面图片",
"Please enter a search keyword": "请输入搜索关键词",
"Searching...": "搜索中...",
"Create Tag": "创建标签",
@@ -425,8 +425,8 @@ export const i18nData = {
"Cloudflare Turnstile Secret Key": "Cloudflare Turnstile 密鑰",
"If the cloudflare turnstile keys are not empty, the turnstile will be used for register and download.":
"如果設置了 Cloudflare Turnstile 密鑰,將在註冊和下載時啟用驗證",
"The first image will be used as the cover image":
"第一張圖片將用作封面圖片",
"You can select a cover image using the radio button in the Cover column":
"您可以使用封面列中的單選按鈕選擇封面圖片",
"Please enter a search keyword": "請輸入搜尋關鍵字",
"Searching...": "搜尋中...",
"Create Tag": "創建標籤",

View File

@@ -48,6 +48,7 @@ export interface CreateResourceParams {
tags: number[];
article: string;
images: number[];
cover_id?: number;
gallery: number[];
gallery_nsfw: number[];
characters: CharacterParams[];
@@ -94,6 +95,7 @@ export interface ResourceDetails {
releaseDate?: string;
tags: Tag[];
images: Image[];
coverId?: number;
files: RFile[];
author: User;
views: number;

View File

@@ -29,6 +29,7 @@ export default function EditResourcePage() {
const [tags, setTags] = useState<Tag[]>([]);
const [article, setArticle] = useState<string>("");
const [images, setImages] = useState<number[]>([]);
const [coverId, setCoverId] = useState<number | undefined>(undefined);
const [links, setLinks] = useState<{ label: string; url: string }[]>([]);
const [galleryImages, setGalleryImages] = useState<number[]>([]);
const [galleryNsfw, setGalleryNsfw] = useState<number[]>([]);
@@ -59,6 +60,7 @@ export default function EditResourcePage() {
setTags(data.tags);
setArticle(data.article);
setImages(data.images.map((i) => i.id));
setCoverId(data.coverId);
setLinks(data.links ?? []);
setGalleryImages(data.gallery ?? []);
setGalleryNsfw(data.galleryNsfw ?? []);
@@ -106,6 +108,7 @@ export default function EditResourcePage() {
tags: tags.map((tag) => tag.id),
article: article,
images: images,
cover_id: coverId,
links: links,
gallery: galleryImages,
gallery_nsfw: galleryNsfw,
@@ -328,7 +331,7 @@ export default function EditResourcePage() {
"Images will not be displayed automatically, you need to reference them in the description",
)}
</p>
<p>{t("The first image will be used as the cover image")}</p>
<p>{t("You can select a cover image using the radio button in the Cover column")}</p>
</div>
</div>
<div
@@ -339,6 +342,7 @@ export default function EditResourcePage() {
<tr>
<td>{t("Preview")}</td>
<td>{"Markdown"}</td>
<td>{t("Cover")}</td>
<td>{t("Gallery")}</td>
<td>{"Nsfw"}</td>
<td>{t("Action")}</td>
@@ -368,6 +372,15 @@ export default function EditResourcePage() {
<MdContentCopy />
</button>
</td>
<td>
<input
type="radio"
name="cover"
className="radio radio-accent"
checked={coverId === image}
onChange={() => setCoverId(image)}
/>
</td>
<td>
<input
type="checkbox"
@@ -409,6 +422,9 @@ export default function EditResourcePage() {
const newImages = [...images];
newImages.splice(index, 1);
setImages(newImages);
if (coverId === id) {
setCoverId(undefined);
}
network.deleteImage(id);
}}
>

View File

@@ -28,6 +28,7 @@ export default function PublishPage() {
const [tags, setTags] = useState<Tag[]>([]);
const [article, setArticle] = useState<string>("");
const [images, setImages] = useState<number[]>([]);
const [coverId, setCoverId] = useState<number | undefined>(undefined);
const [links, setLinks] = useState<{ label: string; url: string }[]>([]);
const [galleryImages, setGalleryImages] = useState<number[]>([]);
const [galleryNsfw, setGalleryNsfw] = useState<number[]>([]);
@@ -48,6 +49,7 @@ export default function PublishPage() {
setTags(data.tags || []);
setArticle(data.article || "");
setImages(data.images || []);
setCoverId(data.cover_id || undefined);
setLinks(data.links || []);
setGalleryImages(data.gallery || []);
setGalleryNsfw(data.gallery_nsfw || []);
@@ -64,6 +66,7 @@ export default function PublishPage() {
tags: tags,
article: article,
images: images,
cover_id: coverId,
links: links,
gallery: galleryImages,
gallery_nsfw: galleryNsfw,
@@ -73,7 +76,7 @@ export default function PublishPage() {
const dataString = JSON.stringify(data);
localStorage.setItem("publish_data", dataString);
}
}, [altTitles, article, images, tags, title, links, galleryImages, galleryNsfw, characters, releaseDate]);
}, [altTitles, article, images, coverId, tags, title, links, galleryImages, galleryNsfw, characters, releaseDate]);
const navigate = useNavigate();
const { t } = useTranslation();
@@ -120,6 +123,7 @@ export default function PublishPage() {
tags: tags.map((tag) => tag.id),
article: article,
images: images,
cover_id: coverId,
links: links,
gallery: galleryImages,
gallery_nsfw: galleryNsfw,
@@ -344,7 +348,7 @@ export default function PublishPage() {
"Images will not be displayed automatically, you need to reference them in the description",
)}
</p>
<p>{t("The first image will be used as the cover image")}</p>
<p>{t("You can select a cover image using the radio button in the Cover column")}</p>
</div>
</div>
<div
@@ -355,7 +359,8 @@ export default function PublishPage() {
<tr>
<td>{t("Preview")}</td>
<td>{"Markdown"}</td>
<td>{"Gallery"}</td>
<td>{t("Cover")}</td>
<td>{t("Gallery")}</td>
<td>{"Nsfw"}</td>
<td>{t("Action")}</td>
</tr>
@@ -384,6 +389,15 @@ export default function PublishPage() {
<MdContentCopy />
</button>
</td>
<td>
<input
type="radio"
name="cover"
className="radio radio-accent"
checked={coverId === image}
onChange={() => setCoverId(image)}
/>
</td>
<td>
<input
type="checkbox"
@@ -425,6 +439,9 @@ export default function PublishPage() {
const newImages = [...images];
newImages.splice(index, 1);
setImages(newImages);
if (coverId === id) {
setCoverId(undefined);
}
network.deleteImage(id);
}}
>