Files
form-center-front/src/assets/mock/adminapi.ts
T
chenxing d8f1a1fbfa
build / build (push) Successful in 3m8s
feat(t10-admin): 管理员体系前端——应用设置双 tab+单表单管理员+选人组件移植
- AppSettings.vue 应用设置页(基础/字典两 tab);修复 P86:Tabs 写 :value 而受控 prop 是 modelValue,致 ?tab=dicts 深链静默失效,改后深链实拍生效
- UserCheckModal.vue 自 notice 移植(view-ui-plus+ztree,sources 注入式数据源);public/libs 收录 jquery+ztree 本地件(index.html 引用)
- api/module/admin.ts + mock/adminapi.ts + types/admin.ts;AdminListPanel/FormAdminModal 组件
- routes/menuNav/menuRoute/modulePerms 适配管理员菜单与权限位;tree-icon 图标资源
2026-10-15 20:25:39 +08:00

95 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 管理员两表的本地 Mock(vite-plugin-mock,仅 `npm run dev:mock` 生效)。
*
* 用途与背景同 baseapi.ts:本机没有 UserBase 授权数据(执行手册 §5 P1 降级取证先例),
* 角色设置 tab 与「表单管理员」弹窗的两表 CRUD 往返只能在 mock 里实拍。
* 桩刻意把后端三条规则也演一遍,好让冒烟脚本能断言到"前端没有把规则写丢":
* ① 重复添加幂等(不重复建行、不报错);② 校级管理员删到剩 0 拒;③ 写操作回全量列表。
*/
import type { AdminRow } from "@/types/admin";
const ok = (data: unknown) => ({ code: 0, msg: "", data });
const fail = (msg: string) => ({ code: 500, msg, data: null });
let seq = 1;
const schoolAdmins: AdminRow[] = [];
const formAdmins: Record<string, AdminRow[]> = {};
function row(userId: number, userName: string): AdminRow {
return { id: seq++, userId, userName };
}
/** 追加(幂等:已存在的 userId 跳过,姓名快照不覆盖) */
function merge(list: AdminRow[], users: { userId: number; userName: string }[]): AdminRow[] {
for (const item of users || []) {
if (!item || item.userId == null) continue;
if (!list.some((r) => r.userId === Number(item.userId))) {
list.push(row(Number(item.userId), String(item.userName || "")));
}
}
return list;
}
/** 路径里的 id / formUuid:vite-plugin-mock 不保证把 REST 段塞进 query,直接从 url 取最稳 */
function idFrom(url: string): number | null {
const matched = /\/(\d+)(?:\?|$)/.exec(url || "");
return matched ? Number(matched[1]) : null;
}
function formUuidFrom(url: string): string {
const matched = /\/forms\/([\w-]+)\/admins/.exec(url || "");
return matched ? matched[1] : "";
}
export default [
{
url: "/api/form/admin/school-admins",
method: "get",
response: () => ok(schoolAdmins.slice())
},
{
url: "/api/form/admin/school-admins",
method: "post",
response: ({ body }: any) => ok(merge(schoolAdmins, body?.users || []))
},
{
url: "/api/form/admin/school-admins/:id",
method: "delete",
response: ({ url }: any) => {
const id = idFrom(url);
if (schoolAdmins.length <= 1) return fail("本校至少保留一名校级表单管理员,最后一名不可删除");
const index = schoolAdmins.findIndex((r) => r.id === id);
if (index < 0) return fail("校级管理员记录不存在:" + id);
schoolAdmins.splice(index, 1);
return ok(schoolAdmins.slice());
}
},
{
url: "/api/form/admin/forms/:formUuid/admins",
method: "get",
response: ({ url }: any) => ok((formAdmins[formUuidFrom(url)] || []).slice())
},
{
url: "/api/form/admin/forms/:formUuid/admins",
method: "post",
response: ({ url, body }: any) => {
const uuid = formUuidFrom(url);
formAdmins[uuid] = formAdmins[uuid] || [];
return ok(merge(formAdmins[uuid], body?.users || []));
}
},
{
url: "/api/form/admin/forms/:formUuid/admins/:id",
method: "delete",
response: ({ url }: any) => {
const uuid = formUuidFrom(url);
const id = idFrom(url);
const list = formAdmins[uuid] || [];
const index = list.findIndex((r) => r.id === id);
if (index < 0) return fail("表单管理员记录不存在:" + id);
list.splice(index, 1);
return ok(list.slice());
}
}
];