域名 AXUM.RS 将于 2025 年 10 月到期。我们无意再对其进行续费,如果你有意接续这个域名,请与我们取得联系。
  • AXUM.RS 现仅需人民币 3000 元(大写:叁仟元整。接受适度议价
  • 按照行业规则,AXUM.RS 到期后,大概率会进入长时间的赎回期,该期间内,如果你想拥有该域名,将要付出高额的费用
  • 我们已启用 AXUM.EU.ORG 域名,并将持续运营
  • 仅接受微信或支付宝交易
如果你对 AXUM.RS 有兴趣,请和我们进行联系:

存档文章列表

本章将实现存档文章列表功能。注意,本章涉及较多PostgreSQL知识,如果你对相关知识不熟悉,可以先让代码跑起来,再去了解相关知识。

本功能模板文件是templates/frontend/topic_arch.html

视图类

本功能视图类定义在src/view/frontend/topic.rs文件。

handler

// src/handler/frontend/topic.rs
pub async fn archive(
    Extension(state): Extension<Arc<AppState>>,
    Path(dt): Path<String>,
    Query(args): Query<Args>,
) -> Result<HtmlView> {
    let handler_name = "frontend/topic/archive";
    let dt_str = dt.clone();
    let dt = format!("{}01 00:00:00", dt);
    let dt = Local.datetime_from_str(&dt, "%Y年%m月%d %H:%M:%S").map_err(AppError::from).map_err(log_error(handler_name))?;
    let dt = dt.format("%Y-%m-%d %H:%M:%S").to_string();
    let page = args.page();
    let client = get_client(&state).await.map_err(log_error(handler_name))?;
    let list = topic::list_by_arch(&client, page, dt)
        .await
        .map_err(log_error(handler_name))?;
    let cats = category::list(&client)
        .await
        .map_err(log_error(handler_name))?;
    let archives = topic::archive_list(&client)
        .await
        .map_err(log_error(handler_name))?;
    let tmpl = ArchiveList {
        list,
        cats,
        archives,
        page,
        dt:dt_str,
    };
    render(tmpl).map_err(log_error(handler_name))
}

topic::list_by_arch():通过传入的日期时间(每月1日零点,月初),使用 PostgreSQL 计算出月初和月尾的所有文章。

数据库操作

// src/db/topic.rs
pub async fn list_by_arch(
    client: &Client,
    page: u32,
    dt:String,
) -> Result<Paginate<Vec<TopicList>>> {
    let condition = format!("dateline BETWEEN '{}'::timestamp AND '{}'::timestamp + (INTERVAL '1' MONTH) - (INTERVAL '1' SECOND)", &dt, &dt);
    list_by_condition(client, page, Some(&condition), Some(&[])).await
}

假设,dt参数的值是:2022-03-01 00:00:00,那么上述SQL语句可以写为:

SELECT 
	id,title,category_id,summary,hit,dateline,is_del,category_name 
FROM v_topic_cat_list 
WHERE
	is_del=false AND 
	dateline BETWEEN '2022-03-01 00:00:00'::timestamp AND '2022-03-01 00:00:00'::timestamp + (INTERVAL '1' MONTH) - (INTERVAL '1' SECOND)
ORDER BY id DESC
LIMIT 30 OFFSET 0

这里之所以要这样操作,是因为每个月的天数是不一定的,如果使用固定的值,比如30天等,结果会不精确。当然对于博客来说,这种程度的不精确也是可以接受的。现在既然AXUM中文网给出了精确的方案,那自然应该用此方案了。

路由

本功能的路由定义在src/handler/frontend/mod.rs

AppError

/// src/error.rs

#[derive(Debug)]
pub enum AppErrorType {
 		// ...
    Chrono,
}

impl From<chrono::ParseError> for AppError {
    fn from(err: chrono::ParseError) -> Self {
        Self::from_err(Box::new(err), AppErrorType::Chrono)
    }
}

本章代码位于10/存档分支。

要查看完整内容,请先登录