Skip to main content

tdm_server_rust/web/
questionnaire_controller.rs

1//! 接稿意愿问卷接口 (Questionnaire Controller)
2//!
3//! 问卷提交和查询。
4//! 对应 Java QuestionnaireController。
5
6use crate::utils::query_deserialize::de_opt_i32;
7use crate::{
8    common::AppJson,
9    app::AppState, common::result::ResultBody, entity::questionnaire::Questionnaire,
10    error::ApiResult, service::questionnaire_service::QuestionnaireService,
11};
12use axum::{
13    extract::{Path, Query, State},
14    routing::get,
15    Router,
16};
17use serde::Deserialize;
18
19/// 问卷列表查询参数
20#[derive(Debug, Deserialize)]
21#[serde(rename_all = "camelCase")]
22pub struct QuestionnaireListQuery {
23    /// 岗位 ID
24    #[serde(default, deserialize_with = "de_opt_i32")]
25    pub post_id: Option<i32>,
26    /// 接稿意愿
27    #[serde(default, deserialize_with = "de_opt_i32")]
28    pub willingness: Option<i32>,
29    /// 篇幅偏好
30    pub length: Option<String>,
31    /// 出稿频率
32    #[serde(default, deserialize_with = "de_opt_i32")]
33    pub frequency: Option<i32>,
34    /// 组员 ID
35    #[serde(default, deserialize_with = "de_opt_i32")]
36    pub member_id: Option<i32>,
37}
38
39/// 问卷路由(挂载于 `/api/questionnaires`)
40pub fn routes() -> Router<AppState> {
41    Router::new().route("/", get(list_questionnaires)).route(
42        "/:memberId",
43        get(get_questionnaire).post(submit_questionnaire),
44    )
45}
46
47/// 问卷列表
48#[tracing::instrument(skip_all, level = "info")]
49pub async fn list_questionnaires(
50    State(state): State<AppState>,
51    Query(q): Query<QuestionnaireListQuery>,
52) -> ApiResult<ResultBody<Vec<Questionnaire>>> {
53    let data = QuestionnaireService::list_all(
54        &state,
55        q.post_id,
56        q.willingness,
57        q.length,
58        q.frequency,
59        q.member_id,
60    )
61    .await?;
62    Ok(ResultBody::success_data(data))
63}
64
65/// 获取组员问卷
66#[tracing::instrument(skip_all, level = "info")]
67pub async fn get_questionnaire(
68    State(state): State<AppState>,
69    Path(member_id): Path<i32>,
70) -> ApiResult<ResultBody<Option<Questionnaire>>> {
71    let data = QuestionnaireService::get_by_member_id(&state, member_id).await?;
72    Ok(ResultBody::success_data(data))
73}
74
75/// 提交/更新问卷
76#[tracing::instrument(skip_all, level = "info")]
77pub async fn submit_questionnaire(
78    State(state): State<AppState>,
79    Path(member_id): Path<i32>,
80    AppJson(body): AppJson<Questionnaire>,
81) -> ApiResult<ResultBody<Questionnaire>> {
82    let data = QuestionnaireService::submit(&state, member_id, body).await?;
83    Ok(ResultBody::success_data(data))
84}