mirror of
https://github.com/wgh136/nysoure.git
synced 2025-12-16 07:51:14 +00:00
Compare commits
5 Commits
ddd856529b
...
5a5c2edfda
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a5c2edfda | |||
| d860bdf06a | |||
| a3de195eca | |||
| 6cabff8f8d | |||
| 78f6130b23 |
@@ -263,6 +263,7 @@ export const i18nData = {
|
||||
"Optional": "可选",
|
||||
"Download": "下载",
|
||||
"Notifications": "通知",
|
||||
"Release Date": "发售日期",
|
||||
},
|
||||
},
|
||||
"zh-TW": {
|
||||
@@ -529,6 +530,7 @@ export const i18nData = {
|
||||
"Optional": "可選",
|
||||
"Download": "下載",
|
||||
"Notifications": "通知",
|
||||
"Release Date": "發售日期",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@ export interface CreateResourceParams {
|
||||
title: string;
|
||||
alternative_titles: string[];
|
||||
links: RLink[];
|
||||
release_date?: string;
|
||||
tags: number[];
|
||||
article: string;
|
||||
images: number[];
|
||||
@@ -77,6 +78,7 @@ export interface Resource {
|
||||
id: number;
|
||||
title: string;
|
||||
created_at: string;
|
||||
release_date?: string;
|
||||
tags: Tag[];
|
||||
image?: Image;
|
||||
author: User;
|
||||
@@ -89,6 +91,7 @@ export interface ResourceDetails {
|
||||
links: RLink[];
|
||||
article: string;
|
||||
createdAt: string;
|
||||
releaseDate?: string;
|
||||
tags: Tag[];
|
||||
images: Image[];
|
||||
files: RFile[];
|
||||
|
||||
@@ -25,6 +25,7 @@ import CharacterEditer, { FetchVndbCharactersButton } from "../components/charac
|
||||
export default function EditResourcePage() {
|
||||
const [title, setTitle] = useState<string>("");
|
||||
const [altTitles, setAltTitles] = useState<string[]>([]);
|
||||
const [releaseDate, setReleaseDate] = useState<string | undefined>(undefined);
|
||||
const [tags, setTags] = useState<Tag[]>([]);
|
||||
const [article, setArticle] = useState<string>("");
|
||||
const [images, setImages] = useState<number[]>([]);
|
||||
@@ -61,6 +62,7 @@ export default function EditResourcePage() {
|
||||
setLinks(data.links ?? []);
|
||||
setGalleryImages(data.gallery ?? []);
|
||||
setGalleryNsfw(data.galleryNsfw ?? []);
|
||||
setReleaseDate(data.releaseDate ?? undefined);
|
||||
setCharacters(data.characters ?? []);
|
||||
setLoading(false);
|
||||
} else {
|
||||
@@ -108,6 +110,7 @@ export default function EditResourcePage() {
|
||||
gallery: galleryImages,
|
||||
gallery_nsfw: galleryNsfw,
|
||||
characters: characters,
|
||||
release_date: releaseDate,
|
||||
});
|
||||
if (res.success) {
|
||||
setSubmitting(false);
|
||||
@@ -194,6 +197,14 @@ export default function EditResourcePage() {
|
||||
{t("Add Alternative Title")}
|
||||
</button>
|
||||
<div className={"h-2"}></div>
|
||||
<p className={"my-1"}>{t("Release Date")}</p>
|
||||
<input
|
||||
type="date"
|
||||
className="input"
|
||||
value={releaseDate || ""}
|
||||
onChange={(e) => setReleaseDate(e.target.value || undefined)}
|
||||
/>
|
||||
<div className={"h-4"}></div>
|
||||
<p className={"my-1"}>{t("Links")}</p>
|
||||
<div className={"flex flex-col"}>
|
||||
{links.map((link, index) => {
|
||||
|
||||
@@ -24,6 +24,7 @@ import CharacterEditer, { FetchVndbCharactersButton } from "../components/charac
|
||||
export default function PublishPage() {
|
||||
const [title, setTitle] = useState<string>("");
|
||||
const [altTitles, setAltTitles] = useState<string[]>([]);
|
||||
const [releaseDate, setReleaseDate] = useState<string | undefined>(undefined);
|
||||
const [tags, setTags] = useState<Tag[]>([]);
|
||||
const [article, setArticle] = useState<string>("");
|
||||
const [images, setImages] = useState<number[]>([]);
|
||||
@@ -43,9 +44,14 @@ export default function PublishPage() {
|
||||
const data = JSON.parse(oldData);
|
||||
setTitle(data.title || "");
|
||||
setAltTitles(data.alternative_titles || []);
|
||||
setReleaseDate(data.release_date || undefined);
|
||||
setTags(data.tags || []);
|
||||
setArticle(data.article || "");
|
||||
setImages(data.images || []);
|
||||
setLinks(data.links || []);
|
||||
setGalleryImages(data.gallery || []);
|
||||
setGalleryNsfw(data.gallery_nsfw || []);
|
||||
setCharacters(data.characters || []);
|
||||
} catch (e) {
|
||||
console.error("Failed to parse publish_data from localStorage", e);
|
||||
}
|
||||
@@ -58,11 +64,16 @@ export default function PublishPage() {
|
||||
tags: tags,
|
||||
article: article,
|
||||
images: images,
|
||||
links: links,
|
||||
gallery: galleryImages,
|
||||
gallery_nsfw: galleryNsfw,
|
||||
characters: characters,
|
||||
release_date: releaseDate,
|
||||
};
|
||||
const dataString = JSON.stringify(data);
|
||||
localStorage.setItem("publish_data", dataString);
|
||||
}
|
||||
}, [altTitles, article, images, tags, title]);
|
||||
}, [altTitles, article, images, tags, title, links, galleryImages, galleryNsfw, characters, releaseDate]);
|
||||
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
@@ -105,6 +116,7 @@ export default function PublishPage() {
|
||||
const res = await network.createResource({
|
||||
title: title,
|
||||
alternative_titles: altTitles,
|
||||
release_date: releaseDate,
|
||||
tags: tags.map((tag) => tag.id),
|
||||
article: article,
|
||||
images: images,
|
||||
@@ -201,6 +213,14 @@ export default function PublishPage() {
|
||||
{t("Add Alternative Title")}
|
||||
</button>
|
||||
<div className={"h-2"}></div>
|
||||
<p className={"my-1"}>{t("Release Date")}</p>
|
||||
<input
|
||||
type="date"
|
||||
className="input"
|
||||
value={releaseDate || ""}
|
||||
onChange={(e) => setReleaseDate(e.target.value || undefined)}
|
||||
/>
|
||||
<div className={"h-4"}></div>
|
||||
<p className={"my-1"}>{t("Links")}</p>
|
||||
<div className={"flex flex-col"}>
|
||||
{links.map((link, index) => {
|
||||
|
||||
@@ -209,6 +209,14 @@ export default function ResourcePage() {
|
||||
</h2>
|
||||
);
|
||||
})}
|
||||
{
|
||||
resource.releaseDate ? (
|
||||
<div className={"px-4 py-1 text-sm text-gray-600 dark:text-gray-400 flex items-center"}>
|
||||
<MdOutlineAccessTime size={18} className={"inline-block mr-1"} />
|
||||
{t("Release Date")}: {resource.releaseDate.split("T")[0]}
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
<button
|
||||
onClick={() => {
|
||||
navigate(
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"nysoure/server/dao"
|
||||
"nysoure/server/middleware"
|
||||
"time"
|
||||
|
||||
"nysoure/server/search"
|
||||
|
||||
@@ -20,10 +23,40 @@ func rebuildSearchIndex(c fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
func updateResourceReleaseDate(c fiber.Ctx) error {
|
||||
type Request struct {
|
||||
ResourceID uint `json:"resource_id"`
|
||||
ReleaseDate string `json:"release_date"`
|
||||
}
|
||||
var req Request
|
||||
if err := c.Bind().JSON(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid request body: " + err.Error(),
|
||||
})
|
||||
}
|
||||
date, err := time.Parse("2006-01-02", req.ReleaseDate)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid date format: " + err.Error(),
|
||||
})
|
||||
}
|
||||
err = dao.UpdateResourceReleaseDate(req.ResourceID, date)
|
||||
if err != nil {
|
||||
slog.Error("Failed to update release date", "error", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Failed to update release date",
|
||||
})
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"message": "Release date updated successfully",
|
||||
})
|
||||
}
|
||||
|
||||
func AddDevAPI(router fiber.Router) {
|
||||
devGroup := router.Group("/dev")
|
||||
devGroup.Use(middleware.DevMiddleware())
|
||||
{
|
||||
devGroup.Post("/rebuild_search_index", rebuildSearchIndex)
|
||||
devGroup.Post("/update_resource_release_date", updateResourceReleaseDate)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,3 +704,14 @@ func GetResourceOwnerID(resourceID uint) (uint, error) {
|
||||
}
|
||||
return uid, nil
|
||||
}
|
||||
|
||||
func UpdateResourceReleaseDate(resourceID uint, releaseDate time.Time) error {
|
||||
result := db.Model(&model.Resource{}).Where("id = ?", resourceID).Update("release_date", releaseDate)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return model.NewNotFoundError("Resource not found")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ type Resource struct {
|
||||
Title string
|
||||
AlternativeTitles []string `gorm:"serializer:json"`
|
||||
Links []Link `gorm:"serializer:json"`
|
||||
ReleaseDate *time.Time
|
||||
Article string
|
||||
Images []Image `gorm:"many2many:resource_images;"`
|
||||
Tags []Tag `gorm:"many2many:resource_tags;"`
|
||||
@@ -35,6 +36,7 @@ type ResourceView struct {
|
||||
ID uint `json:"id"`
|
||||
Title string `json:"title"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ReleaseDate *time.Time `json:"release_date,omitempty"`
|
||||
Tags []TagView `json:"tags"`
|
||||
Image *ImageView `json:"image"`
|
||||
Author UserView `json:"author"`
|
||||
@@ -47,6 +49,7 @@ type ResourceDetailView struct {
|
||||
Links []Link `json:"links"`
|
||||
Article string `json:"article"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
ReleaseDate *time.Time `json:"releaseDate,omitempty"`
|
||||
Tags []TagView `json:"tags"`
|
||||
Images []ImageView `json:"images"`
|
||||
Files []FileView `json:"files"`
|
||||
@@ -84,6 +87,7 @@ func (r *Resource) ToView() ResourceView {
|
||||
ID: r.ID,
|
||||
Title: r.Title,
|
||||
CreatedAt: r.CreatedAt,
|
||||
ReleaseDate: r.ReleaseDate,
|
||||
Tags: tags,
|
||||
Image: image,
|
||||
Author: r.User.ToView(),
|
||||
@@ -115,6 +119,7 @@ func (r *Resource) ToDetailView() ResourceDetailView {
|
||||
Links: r.Links,
|
||||
Article: r.Article,
|
||||
CreatedAt: r.CreatedAt,
|
||||
ReleaseDate: r.ReleaseDate,
|
||||
Tags: tags,
|
||||
Images: images,
|
||||
Files: files,
|
||||
|
||||
@@ -30,6 +30,7 @@ type ResourceParams struct {
|
||||
Title string `json:"title" binding:"required"`
|
||||
AlternativeTitles []string `json:"alternative_titles"`
|
||||
Links []model.Link `json:"links"`
|
||||
ReleaseDate string `json:"release_date"`
|
||||
Tags []uint `json:"tags"`
|
||||
Article string `json:"article"`
|
||||
Images []uint `json:"images"`
|
||||
@@ -101,11 +102,20 @@ func CreateResource(uid uint, params *ResourceParams) (uint, error) {
|
||||
ImageID: imageID,
|
||||
}
|
||||
}
|
||||
var date *time.Time
|
||||
if params.ReleaseDate != "" {
|
||||
parsedDate, err := time.Parse("2006-01-02", params.ReleaseDate)
|
||||
if err != nil {
|
||||
return 0, model.NewRequestError("Invalid release date format, expected YYYY-MM-DD")
|
||||
}
|
||||
date = &parsedDate
|
||||
}
|
||||
r := model.Resource{
|
||||
Title: params.Title,
|
||||
AlternativeTitles: params.AlternativeTitles,
|
||||
Article: params.Article,
|
||||
Links: params.Links,
|
||||
ReleaseDate: date,
|
||||
Images: images,
|
||||
Tags: tags,
|
||||
UserID: uid,
|
||||
@@ -529,10 +539,20 @@ func UpdateResource(uid, rid uint, params *ResourceParams) error {
|
||||
}
|
||||
}
|
||||
|
||||
var date *time.Time
|
||||
if params.ReleaseDate != "" {
|
||||
parsedDate, err := time.Parse("2006-01-02", params.ReleaseDate)
|
||||
if err != nil {
|
||||
return model.NewRequestError("Invalid release date format, expected YYYY-MM-DD")
|
||||
}
|
||||
date = &parsedDate
|
||||
}
|
||||
|
||||
r.Title = params.Title
|
||||
r.AlternativeTitles = params.AlternativeTitles
|
||||
r.Article = params.Article
|
||||
r.Links = params.Links
|
||||
r.ReleaseDate = date
|
||||
r.Gallery = gallery
|
||||
r.GalleryNsfw = nsfw
|
||||
r.Characters = characters
|
||||
|
||||
Reference in New Issue
Block a user