safety-eval-service-frontend/.cursor/skills/specs/11-接口与数据层规范/02-接口定义规范/SKILL.md

7.2 KiB
Raw Permalink Blame History

name description
jjb-declare-request 定义 JJB 接口定义规范。在使用 declareRequest、Action 命名、Loading 状态或 resetModelState 时使用。必须参考 MD/d.ts 文档。

接口与数据层规范

接口定义规范 (declareRequest)

所有接口必须通过 declareRequest 进行声明。该方法通过字符串 DSL 实现请求配置与数据处理。

必须严格参考对应 MD 文档或 d.ts 文件!

基本语法

declareRequest(
  a?: string,  // 参数1Loading 状态标识(可选)
  b: string,    // 参数2请求表达式必填
  c?: string   // 参数3响应数据处理表达式可选
)

参数说明

参数 类型 必填 说明
a string 请求时绑定的 Loading 状态标识,例如 "loading""confirmLoading"
b string 请求表达式,格式:Method [> @] URL,支持完整 http[s] 路径
c string 响应数据处理表达式,用于从响应结果中取值并赋给目标字段

定义示例

import { declareRequest } from '@cqsjjb/jjb-dva-runtime';

// 示例1获取试卷列表完整参数
export const getExamResDataAction = declareRequest(
  'examResDataLoading', // 参数1Loading 状态字段名
  'Get > /com-train/exams', // 参数2请求方法 > 接口路径
  'examResData: [] | res.data || [] & examResDataTotal: 0 | res.totalCount || 0' // 参数3数据映射与默认值
);

// 示例2仅定义请求省略参数1和参数3
export const getUserInfoAction = declareRequest(
  'Get > /api/user/{id}' // 仅必填参数
);

// 示例3POST 请求使用 @ 标记
export const createUserAction = declareRequest(
  'createUserLoading',
  'Post > @/api/user', // @ 标记忽略 request 包裹层
  'userId: "" | res.data.id || ""'
);

命名格式

[name]Action 统一使用 小驼峰 (camelCase) 命名

⚠️ 禁止使用的关键字

禁止使用以下关键字作为 Action 名称,这些是 Connect 装饰器注入的保留字段和方法,使用会导致冲突异常:

  • dispatchDva dispatch 方法
  • resetModelState:重置模型状态方法
  • dispatchModelAction:手动调用 Action 方法
  • getModelState:获取模型状态方法
  • props:命名空间对应的 props 对象
  • models:所有连接的模型对象
  • action:通用 Action 标识(避免冲突)

错误示例

import { declareRequest } from '@cqsjjb/jjb-dva-runtime';

// ❌ 错误:使用了保留关键字
export const dispatch = declareRequest('Get > /api/user');
export const resetModelState = declareRequest('Get > /api/user');
export const dispatchModelAction = declareRequest('Get > /api/user');
export const getModelState = declareRequest('Get > /api/user');
export const props = declareRequest('Get > /api/user');
export const models = declareRequest('Get > /api/user');
export const action = declareRequest('Get > /api/user');

正确示例

import { declareRequest } from '@cqsjjb/jjb-dva-runtime';

// ✅ 正确:使用符合规范的命名
export const fetchUserAction = declareRequest('Get > /api/user');
export const getUserListAction = declareRequest('Get > /api/users');
export const createUserAction = declareRequest('Post > @/api/user');
export const updateUserAction = declareRequest('Put > @/api/user/{id}');

请求表达式规范

  • 格式Method [> @] URL

  • 支持的 HTTP 方法

    • GetGET 请求
    • PostPOST 请求
    • PutPUT 请求
    • DeleteDELETE 请求
    • PatchPATCH 请求
  • @ 标记说明

    • 作用:忽略请求体中 request 对象的包裹层,直接传递数据

    • 限制Get 请求不能使用 @,其他请求方法可选

    • 示例

      // ✅ POST 请求使用 @,忽略 request 包裹
      'Post > @/api/user'
      
      // ❌ GET 请求禁止使用 @
      'Get > @/api/user/{id}'  // 错误写法
      
  • URL 路径规范

    • 普通路径:例如 /api/xxx/list

    • 模板插值:支持占位符 {},调用时会替换为参数值

      // 示例URL 模板插值
      'Get > /api/user/{id}'  // 调用时 {id} 会被替换为实际参数值
      
    • 完整 HTTP 路径:支持完整的 http[s] 路径

    • 请求格式限制仅支持 application/json 格式,其他格式不支持

响应表达式规范

  • 格式targetField: defaultValue | expression & ...

  • 组成部分

    • targetField:目标字段名称

    • defaultValue:当结果为空时的默认值

    • expression:从响应对象中获取数据的 JS 表达式

    • &:支持多个字段连接

    • res:固定上下文对象,表示响应结果

  • 示例

    // 示例:多字段映射
    'dataSource: [] | res.data || [] & total: 0 | res.total || 0'
    

    表示:

    • 将结果赋值给 dataSource,默认值为 [],优先取 res.data,如果为空则取 []

    • & 连接下一个字段

    • 将结果赋值给 total,默认值为 0,优先取 res.total,如果为空则取 0

  • AI 约束必须根据后端返回结构精确配置此映射

使用规则总结

  1. @ 标记限制Get 请求不能用 @,其他请求方法可选

  2. URL 模板插值:支持路径模板插值 {id},调用时自动替换

  3. 参数可选性:参数 aLoading 状态、c响应处理可选不写也能正常工作

  4. 请求格式:仅支持 application/json 格式

Loading 状态管理规范

⚠️ 重要约束:当 declareRequest 定义的接口 Action 在弹窗、抽屉等可关闭组件中使用时,必须在组件销毁时调用 resetModelState 重置对应的 loading 字段

问题说明

declareRequest 定义的接口 Action 会自动管理 loading 状态(如 loadingconfirmLoadingsubmitLoading。但在以下场景中loading 状态可能无法自动重置:

  • 接口请求异常中断
  • 弹窗/抽屉在请求过程中被关闭
  • 组件卸载时请求仍在进行

这会导致 loading 状态一直保持为 true,下次打开组件时仍然显示加载状态,影响用户体验。

解决方案

在组件销毁时(如弹窗的 onCancelafterCloseuseEffect 清理函数),调用 resetModelState 重置对应的 loading 字段。

示例

import { useEffect } from 'react';
import { Connect } from '@cqsjjb/jjb-dva-runtime';
import { NS_USER } from '~/enumerate/namespace';

function UserModal({ createUserAction, resetModelState, modalOpen }) {
  useEffect(() => {
    if (!modalOpen) {
      // ✅ 弹窗关闭时重置 loading 状态
      resetModelState(NS_USER, { confirmLoading: false });
    }
  }, [modalOpen]);

  // ... 其他代码
}

export default Connect([NS_USER], true)(UserModal);

相关规范