build / build (push) Successful in 3m8s
- 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 图标资源
95 lines
3.6 KiB
TypeScript
95 lines
3.6 KiB
TypeScript
/**
|
||
* 管理员两表的本地 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());
|
||
}
|
||
}
|
||
];
|