yggdrasil/src/models/post.rs
xfy 973d6f3d57 feat: add posts, tags database schema and API
- Add migration 002_posts.sql with posts, tags, post_tags tables
- Add Post/Tag/PostStats models with PostStatus enum
- Add posts API with full CRUD:
  - create_post, update_post, delete_post (admin only)
  - get_post_by_slug, list_published_posts (public)
  - list_posts, get_post_stats (admin)
  - list_tags, get_posts_by_tag, search_posts (public)
- Slug auto-generation with uniqueness check
- Server-side markdown rendering with pulldown-cmark
- Auto-summary extraction from markdown
- Soft delete support
2026-06-02 17:33:28 +08:00

58 lines
1.3 KiB
Rust

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PostStatus {
Draft,
Published,
}
impl PostStatus {
#[allow(dead_code)]
pub fn as_str(&self) -> &'static str {
match self {
PostStatus::Draft => "draft",
PostStatus::Published => "published",
}
}
#[allow(dead_code)]
pub fn from_str(s: &str) -> Option<Self> {
match s {
"draft" => Some(PostStatus::Draft),
"published" => Some(PostStatus::Published),
_ => None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Post {
pub id: i32,
pub author_id: i32,
pub title: String,
pub slug: String,
pub summary: Option<String>,
pub content_md: String,
pub content_html: Option<String>,
pub status: PostStatus,
pub published_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub tags: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Tag {
pub id: i32,
pub name: String,
pub post_count: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostStats {
pub total: i64,
pub drafts: i64,
pub published: i64,
}