Skip to content

Latest commit

 

History

History
240 lines (166 loc) · 7.99 KB

File metadata and controls

240 lines (166 loc) · 7.99 KB

easy-qfnu-api-go 开发规范 (v2.0)

1. 工程目录结构 (Project Layout)

本项目遵循 Go 社区标准工程结构,并结合 embed 特性实现了前后端一体化打包。注意:文件命名已简化,去除了 _service_handler 后缀。

easy-qfnu-api-go/
├── api/                    # 【接口层】Handler 处理函数
│   └── v1/                 # API 版本控制
│       └── grade.go        # 成绩相关接口 (原 grade_handler.go)
├── common/                 # 【公共层】通用工具
│   ├── logger/             # 日志配置 (slog + lumberjack)
│   └── response/           # 统一响应封装 (泛型支持)
├── middleware/             # 【中间件】全局拦截器 (CORS, Auth, Logger)
├── model/                  # 【模型层】数据结构定义 (Struct)
│   └── grade.go            # 成绩结构体 & 请求参数定义
├── service/                # 【逻辑层】业务逻辑、爬虫、解析
│   ├── client.go           # 统一的 Resty 客户端工厂 (含 upstream 拦截)
│   └── grade.go            # 成绩业务逻辑 (原 grade_service.go)
├── web/                    # 【前端源码】(编译时嵌入二进制)
│   ├── templates/          # HTML 模板
│   │   ├── layouts/        # 布局 (base.html)
│   │   └── grade.html      # 功能页
│   └── static/             # 静态资源
│       ├── js/
│       │   ├── api/        # API 封装 (request.js, grade.js)
│       │   └── pages/      # 页面逻辑
│       └── css/            # 自定义样式
├── logs/                   # 【运行时】日志文件目录 (自动生成)
├── go.mod                  # 依赖管理
└── main.go                 # 程序入口 (路由注册、静态资源挂载)


2. 接口交互协议 (API Protocol)

  • 传输协议: HTTP/1.1

  • 请求方式:

  • 查询数据统一使用 GET (参数放 Query String)。

  • 提交操作使用 POST (参数放 JSON Body)。

  • 响应格式: 统一使用 application/json; charset=utf-8


3. 请求规范 (Request Standards)

3.1 鉴权 (Authentication)

本系统采用 Header 鉴权

参数名 位置 必填 说明 示例
Authorization Header 教务系统的完整 Cookie 字符串 JSESSIONID=...

3.2 中间件拦截

后端已启用 middleware.AuthRequired

  • 如果请求未携带 Authorization,接口将直接返回 401 状态码,业务逻辑不会执行。
  • Handler 写法: 不需要手动判断 Authorization 是否为空,直接从 Context 获取:
Authorization := c.GetString("Authorization")

4. 响应规范 (Response Standards)

使用了 Go 泛型 (Generics) 进行封装。

4.1 统一结构定义

// common/response/response.go
type Response[T any] struct {
    Code int    `json:"code"` // 0:成功, 非0:错误码
    Msg  string `json:"msg"`  // 提示信息
    Data T      `json:"data"` // 泛型数据
}

4.2 Handler 调用示例

// 成功 (自动推导类型)
response.Success(c, data)

// 失败 (显式指定 any)
response.FailWithCode[any](c, response.CodeAuthExpired, "Cookie 已失效")

5. 日志规范 (Logging)

本项目使用 log/slog 标准库配合 lumberjack 进行日志管理。

  • 初始化: 在 main.go 启动时调用 logger.InitLogger

  • 输出策略:

  • 控制台: 彩色文本 (Tint),方便开发调试。

  • 文件: JSON 格式,按大小切割,保留历史备份。

  • 文件命名: logs/easy-qfnu-api-{时间戳}.log (每次启动独立文件)。

使用示例:

import "log/slog"

slog.Info("抓取成绩成功", "term", "2024-1", "count", 10)
slog.Error("解析失败", "err", err)

6. 后端开发流程 (Backend Workflow)

新增功能(如:查询课表)步骤:

  1. Model: model/schedule.go (定义结构体 & ScheduleRequest)。
  2. Service: service/schedule.go (定义 FetchSchedule,使用 NewJwcClient 创建请求)。
  3. API: api/v1/schedule.go (定义 GetSchedule,绑定参数,调用 Service)。
  4. Router: 在 main.goapiGroup 中注册路由。

7. 前端开发规范 (Frontend Standards)

7.1 技术栈

技术 说明 引入方式
TailwindCSS CSS 框架 CLI 编译,输出到 /static/css/tailwind.css
Alpine.js 轻量级响应式框架 <script defer src="https://unpkg.com/alpinejs@3/dist/cdn.min.js"></script>
Axios HTTP 请求库 <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Go Template 服务端模板渲染 内置

TailwindCSS CLI 使用说明

# 安装 TailwindCSS CLI
npm install -D tailwindcss

# 初始化配置文件
npx tailwindcss init

# 开发模式(监听文件变化)
npx tailwindcss -i ./web/static/css/input.css -o ./web/static/css/tailwind.css --watch

# 生产模式(压缩输出)
npx tailwindcss -i ./web/static/css/input.css -o ./web/static/css/tailwind.css --minify

7.2 Cookie 隐私保护 UI

为了保护用户隐私(截图分享时),Cookie 输入框必须实现 “自动模糊,聚焦清晰” 的效果。

HTML 实现 (Tailwind 类名):

<textarea
  class="... transition-all duration-300 blur-[4px] focus:blur-none hover:blur-none opacity-60 focus:opacity-100 ..."></textarea>

7.2 API 请求封装 (request.js)

严禁在响应拦截器中直接写 window.location.href = '/login',这会导致死循环刷新。

正确逻辑:

service.interceptors.response.use((response) => {
  const res = response.data;
  if (res.code !== 0) {
    // 1. 优先弹窗提示
    vant.showToast(res.msg);

    // 2. 特殊处理 Cookie 失效 (401)
    if (res.code === 401) {
      localStorage.removeItem("qfnu_cookie");
      // 可选:仅在非登录页时才跳转,或只提示不跳转
      // if (window.location.pathname !== '/login') { ... }
    }
    return Promise.reject(new Error(res.msg));
  }
  return res.data; // 直接返回 data 字段
});

7.3 前端目录挂载

前端资源通过 embed 打包进 Go 二进制文件。

  • HTML 模板: 使用 r.LoadHTMLGlob 加载。
  • 静态资源: 使用 http.FS 配合 r.NoRoute 托管,解决 SPA 路由刷新 404 问题。

8. 错误码定义 (Error Codes)

请维护 common/response/code.go

常量名 Code 说明
CodeSuccess 0 成功
CodeServerBusy 1 通用错误/系统繁忙
CodeInvalidParam 1001 参数绑定失败
CodeAuthExpired 401 Authorization 过期/未登录
CodeTargetError 502 教务系统无响应

9. 命名规范 (Naming)

  • 文件名: 全小写,下划线分隔,不带后缀

  • service/grade.go

  • service/grade_service.go

  • Go 变量: 驼峰命名 (gradeList)。

  • JSON 字段: 蛇形命名 (course_name)。

  • 前端 API: window.GradeApi (挂载在 window 对象上,方便模板调用)。


10. 部署说明 (Deployment)

由于使用了 embed,本项目编译后为单文件部署

  1. 编译: go build -o qfnu-app.exe
  2. 运行: 直接运行 .exe 文件即可,无需携带 web 目录。
  3. 日志: 程序会自动在运行目录下生成 logs 文件夹。