1fa62d10e13d75b6349bbe455cb4c407e4701fcd
工具百宝箱 · 管理后台(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。
示例
// 读响应(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))
开发
pnpm install
pnpm run dev # 本地开发
pnpm run build # 生产构建
Description
Languages
Vue
83.4%
JavaScript
11.4%
CSS
4.9%
HTML
0.3%