Files

55 lines
2.2 KiB
Markdown
Raw Permalink Normal View History

2026-09-29 10:58:25 +08:00
# 工具百宝箱 · 管理后台(qitongxue-admin)
2025-04-24 13:39:24 +08:00
2026-09-29 10:58:25 +08:00
Vue 3 + Vite + ant-design-vue v4 + Tailwind 的运营管理端。
2025-04-24 13:39:24 +08:00
2026-09-29 10:58:25 +08:00
## 接口字段口径(重要 · 防回归)
三端(管理端 / 小程序 / 后端)共享一套**契约冻结**的字段口径,改代码时务必遵守:
| 方向 | 口径 | 说明 |
| --- | --- | --- |
| **请求体(发出去)** | `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 # 生产构建
```