# 工具百宝箱 · 管理后台(qitongxue-admin) Vue 3 + Vite + ant-design-vue v4 + Tailwind 的运营管理端。 ## 接口字段口径(重要 · 防回归) 三端(管理端 / 小程序 / 后端)共享一套**契约冻结**的字段口径,改代码时务必遵守: | 方向 | 口径 | 说明 | | --- | --- | --- | | **请求体(发出去)** | `camelCase` | 如 `levelKey` / `isEnabled` / `moduleKey` / `sortBy`。后端结构体 tag 即 `json:"levelKey"`。 | | **响应体(读回来)** | `snake_case` | 如 `level_key` / `is_enabled` / `module_key` / `usage_count` / `created_at` / `level_expire_at`。 | > `src/api/request.js` 的响应拦截器**不做任何大小写转换**:`code === 0` 时直接 `return result`。 > 因此页面里**读响应字段必须写 snake_case**;写请求字段必须写 **camelCase**。 ### 约定 S1 / S2(跨文件共享) - **S1**:管理端展示层只读响应 `snake_case`;请求体发 `camelCase`。**不引入运行时自动转换层**(会掩盖契约问题)。 - **S2**:表单态(camel)与响应态(snake)之间必须**显式映射**:每页定义 `toForm(record)`(snake → camel)与 `fromForm(form)`(camel → 请求体)。 **严禁 `Object.assign(form, { ...record })` 这种展开式回填** —— `record` 是 snake,`form.levelKey` 会拿到 `undefined`,保存时把 `level_key` 清空。 ### 基线参考 `AdminManage.vue` / `AuditLog.vue` / `QueryLog.vue` / `ImportPreview.vue` / `EventList.vue` / `EnterpriseManage.vue` 读 snake_case 是**正确基线**,请勿「顺手统一」为 camelCase。 ### 示例 ```js // 读响应(snake_case) const res = await levelListApi() modules.value = res?.list || [] modules.value.find((m) => m.module_key === key) // ✅ modules.value.find((m) => m.moduleKey === key) // ❌ 永远 undefined // 写请求(camelCase)+ 显式映射(S2) function toForm(record) { return { id: record.id, levelKey: record.level_key, isEnabled: record.is_enabled } } function fromForm(f) { return { id: f.id, levelKey: f.levelKey, isEnabled: f.isEnabled } } await levelSaveApi(fromForm(form)) ``` ## 开发 ```bash pnpm install pnpm run dev # 本地开发 pnpm run build # 生产构建 ```