@stalfh233/omc-fake-platform 0.4.72 → 0.4.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/state.d.ts +46 -0
- package/dist/state.js +8 -0
- package/dist/workflow.js +233 -2
- package/package.json +2 -2
package/dist/state.d.ts
CHANGED
|
@@ -298,6 +298,52 @@ export interface FakeState {
|
|
|
298
298
|
reportPages: Map<string, FakeReportPage>;
|
|
299
299
|
/** R1-report: BI dashboards keyed by objectId (= the report page id). */
|
|
300
300
|
biDashboards: Map<string, FakeBiDashboard>;
|
|
301
|
+
/** Organization writes: role groups / roles / members (recId) / scopes. */
|
|
302
|
+
orgGroups: Map<string, {
|
|
303
|
+
id: string;
|
|
304
|
+
name: string;
|
|
305
|
+
code: string | null;
|
|
306
|
+
parentId: string | null;
|
|
307
|
+
}>;
|
|
308
|
+
orgRoles: Map<string, {
|
|
309
|
+
id: string;
|
|
310
|
+
name: string;
|
|
311
|
+
code: string | null;
|
|
312
|
+
roleGroupId: string;
|
|
313
|
+
roleGroupName: string | null;
|
|
314
|
+
roleType: string;
|
|
315
|
+
corpId: string;
|
|
316
|
+
remarks?: string | null;
|
|
317
|
+
}>;
|
|
318
|
+
orgMembers: Map<string, {
|
|
319
|
+
roleId: string;
|
|
320
|
+
userId: string;
|
|
321
|
+
name: string;
|
|
322
|
+
unitType: string;
|
|
323
|
+
ouScope: Record<string, unknown>[];
|
|
324
|
+
}>;
|
|
325
|
+
/** Organization departments/users (writes added 2026-10-22). */
|
|
326
|
+
orgDepartments: Map<string, {
|
|
327
|
+
id: string;
|
|
328
|
+
name: string;
|
|
329
|
+
parentId: string | null;
|
|
330
|
+
managerId: string | null;
|
|
331
|
+
enabled: boolean;
|
|
332
|
+
sortKey: number | null;
|
|
333
|
+
remarks: string | null;
|
|
334
|
+
}>;
|
|
335
|
+
orgUsers: Map<string, {
|
|
336
|
+
id: string;
|
|
337
|
+
name: string;
|
|
338
|
+
username: string;
|
|
339
|
+
departmentId: string;
|
|
340
|
+
mobile: string | null;
|
|
341
|
+
email: string | null;
|
|
342
|
+
status: string;
|
|
343
|
+
active: boolean;
|
|
344
|
+
roleIds: string[];
|
|
345
|
+
deptIds?: string[];
|
|
346
|
+
}>;
|
|
301
347
|
workflows: Map<string, FakeWorkflow>;
|
|
302
348
|
workItems: Map<string, FakeWorkItem>;
|
|
303
349
|
dataRows: Map<string, Record<string, unknown>>;
|
package/dist/state.js
CHANGED
|
@@ -50,6 +50,14 @@ export function createFakeState(options = {}) {
|
|
|
50
50
|
listViews: new Map(),
|
|
51
51
|
reportPages: new Map(),
|
|
52
52
|
biDashboards: new Map(),
|
|
53
|
+
// Seeded with the static 默认 group the role/list face advertises; a new
|
|
54
|
+
// group must not reuse that id (or the delete guard mistakes the seed role
|
|
55
|
+
// for a member of the caller's group).
|
|
56
|
+
orgGroups: new Map([["grp-1", { id: "grp-1", name: "默认", code: "SYS_1000000", parentId: null }]]),
|
|
57
|
+
orgDepartments: new Map(),
|
|
58
|
+
orgUsers: new Map(),
|
|
59
|
+
orgRoles: new Map(),
|
|
60
|
+
orgMembers: new Map(),
|
|
53
61
|
workflows: new Map(),
|
|
54
62
|
workItems: new Map(),
|
|
55
63
|
dataRows: new Map(),
|
package/dist/workflow.js
CHANGED
|
@@ -349,8 +349,30 @@ export const workflowRoute = (ctx, input) => {
|
|
|
349
349
|
{ id: "grp-1", name: "默认", code: "SYS_1000000", children: [{ id: "role-lead", name: "部门负责人", code: "SYS260630023816197", roleType: "SYS", corpId: "corp-1" }] },
|
|
350
350
|
{ id: "role-finance", name: "财务负责人", code: "SYS260515031207258", roleType: "SYS", corpId: "corp-1" },
|
|
351
351
|
];
|
|
352
|
-
case "/api/api/organization/department/tree":
|
|
353
|
-
|
|
352
|
+
case "/api/api/organization/department/tree": {
|
|
353
|
+
// Platform semantics (1.1.25): no deptIds → roots; deptIds=<id> → that
|
|
354
|
+
// department's WHOLE SUBTREE, not one level.
|
|
355
|
+
const all = [
|
|
356
|
+
{ id: "dept-1", name: "总所", code: "1", corpId: "corp-1", parentId: null },
|
|
357
|
+
{ id: "dept-2", name: "业务部", code: "1_1", corpId: "corp-1", parentId: "dept-1" },
|
|
358
|
+
...[...ctx.state.orgDepartments.values()].map((dept) => ({ id: dept.id, name: dept.name, code: null, corpId: "corp-1", parentId: dept.parentId })),
|
|
359
|
+
];
|
|
360
|
+
const requested = String(q.deptIds ?? "");
|
|
361
|
+
if (requested === "")
|
|
362
|
+
return { departmentList: all.filter((dept) => dept.parentId === null) };
|
|
363
|
+
const subtree = [];
|
|
364
|
+
const queue = [requested];
|
|
365
|
+
while (queue.length > 0) {
|
|
366
|
+
const current = queue.shift();
|
|
367
|
+
for (const dept of all) {
|
|
368
|
+
if (dept.parentId !== current || subtree.some((seen) => seen.id === dept.id))
|
|
369
|
+
continue;
|
|
370
|
+
subtree.push(dept);
|
|
371
|
+
queue.push(dept.id);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return { departmentList: subtree };
|
|
375
|
+
}
|
|
354
376
|
case "/api/api/organization/user/search": {
|
|
355
377
|
// UserController.search: @RequestBody {wd,page,size} → PageVO<UserVO>.
|
|
356
378
|
const wd = String(body.wd ?? "");
|
|
@@ -364,6 +386,215 @@ export const workflowRoute = (ctx, input) => {
|
|
|
364
386
|
const size = Number(body.size ?? 100);
|
|
365
387
|
return { totalElements: users.length, totalPages: size > 0 ? Math.ceil(users.length / size) : 0, content: users.slice(page * size, page * size + size) };
|
|
366
388
|
}
|
|
389
|
+
case "/api/api/organization/department/add": {
|
|
390
|
+
if (!body.name)
|
|
391
|
+
return businessRefusal(10005, "部门名称不能为空");
|
|
392
|
+
if (typeof body.deptType !== "number")
|
|
393
|
+
return businessRefusal(10009, "类型转换异常");
|
|
394
|
+
const id = `dept-${ctx.state.orgDepartments.size + 10}`;
|
|
395
|
+
const dept = { id, name: String(body.name), parentId: body.parentId ? String(body.parentId) : null, managerId: body.managerId ? String(body.managerId) : null, enabled: body.enabled !== false, sortKey: body.sortKey === undefined ? null : Number(body.sortKey), remarks: body.remarks ? String(body.remarks) : null };
|
|
396
|
+
ctx.state.orgDepartments.set(id, dept);
|
|
397
|
+
return dept;
|
|
398
|
+
}
|
|
399
|
+
case "/api/api/organization/department/modefied": {
|
|
400
|
+
const dept = ctx.state.orgDepartments.get(String(body.id ?? ""));
|
|
401
|
+
if (!dept)
|
|
402
|
+
return businessRefusal(10011, "部门不存在");
|
|
403
|
+
Object.assign(dept, {
|
|
404
|
+
...(body.name !== undefined ? { name: String(body.name) } : {}),
|
|
405
|
+
...(body.parentId !== undefined ? { parentId: body.parentId === null ? null : String(body.parentId) } : {}),
|
|
406
|
+
...(body.managerId !== undefined ? { managerId: body.managerId === null ? null : String(body.managerId) } : {}),
|
|
407
|
+
...(body.enabled !== undefined ? { enabled: body.enabled === true } : {}),
|
|
408
|
+
...(body.sortKey !== undefined ? { sortKey: body.sortKey === null ? null : Number(body.sortKey) } : {}),
|
|
409
|
+
...(body.remarks !== undefined ? { remarks: body.remarks === null ? null : String(body.remarks) } : {}),
|
|
410
|
+
});
|
|
411
|
+
return dept;
|
|
412
|
+
}
|
|
413
|
+
case "/api/api/organization/department/get_dept_info": {
|
|
414
|
+
const dept = ctx.state.orgDepartments.get(String(q.deptId ?? ""));
|
|
415
|
+
if (!dept)
|
|
416
|
+
return businessRefusal(10011, "部门不存在");
|
|
417
|
+
return dept;
|
|
418
|
+
}
|
|
419
|
+
case "/api/api/organization/department/strike_out": {
|
|
420
|
+
const deptId = String(q.id ?? "");
|
|
421
|
+
// Platform guards (live 1.1.25): children → 200009, users → 200002.
|
|
422
|
+
// dept-1 carries the static child dept-2 in the tree face.
|
|
423
|
+
if (deptId === "dept-1" || [...ctx.state.orgDepartments.values()].some((dept) => dept.parentId === deptId))
|
|
424
|
+
return businessRefusal(200009, "部门下面存在子部门,不能删除!");
|
|
425
|
+
if ([...ctx.state.orgUsers.values()].some((user) => user.departmentId === deptId))
|
|
426
|
+
return businessRefusal(200002, "部门下面存在用户,不能删除!");
|
|
427
|
+
ctx.state.orgDepartments.delete(deptId);
|
|
428
|
+
return true;
|
|
429
|
+
}
|
|
430
|
+
case "/api/api/organization/department/list_user": {
|
|
431
|
+
const deptId = String(q.deptId ?? "");
|
|
432
|
+
const users = [...ctx.state.orgUsers.values()].filter((user) => user.departmentId === deptId);
|
|
433
|
+
return users.map((user) => ({ id: user.id, name: user.name, username: user.username, mobile: user.mobile }));
|
|
434
|
+
}
|
|
435
|
+
case "/api/api/organization/user/add": {
|
|
436
|
+
for (const key of ["userLabelIds", "userManagerConfigList"]) {
|
|
437
|
+
// Platform NPEs on null (UserHelper.dealUserLabel:428) — the tool fills
|
|
438
|
+
// them, and the fake reproduces the failure so the guard is testable.
|
|
439
|
+
if (body[key] === null || body[key] === undefined)
|
|
440
|
+
return businessRefusal(50000, "服务异常");
|
|
441
|
+
}
|
|
442
|
+
const deptId = String(body.departmentId ?? "");
|
|
443
|
+
if (!ctx.state.orgDepartments.has(deptId) && deptId !== "dept-1" && deptId !== "dept-2")
|
|
444
|
+
return businessRefusal(201011, "用户的部门不存在!");
|
|
445
|
+
if (!body.username)
|
|
446
|
+
return businessRefusal(10005, "账号不能为空");
|
|
447
|
+
const id = `user-${ctx.state.orgUsers.size + 10}`;
|
|
448
|
+
const user = { id, name: String(body.name ?? ""), username: String(body.username), departmentId: deptId, mobile: body.mobile ? String(body.mobile) : null, email: body.email ? String(body.email) : null, status: String(body.status ?? "ENABLE"), active: body.active !== false, roleIds: Array.isArray(body.roleIds) ? body.roleIds : [] };
|
|
449
|
+
ctx.state.orgUsers.set(id, user);
|
|
450
|
+
return user;
|
|
451
|
+
}
|
|
452
|
+
case "/api/api/organization/user/info": {
|
|
453
|
+
const user = ctx.state.orgUsers.get(String(q.id ?? ""));
|
|
454
|
+
if (!user)
|
|
455
|
+
return businessRefusal(10011, "用户不存在");
|
|
456
|
+
return { ...user, deptIds: [], userLabelIds: [], userManagerConfigList: [] };
|
|
457
|
+
}
|
|
458
|
+
case "/api/api/organization/user/modify": {
|
|
459
|
+
const user = ctx.state.orgUsers.get(String(body.id ?? ""));
|
|
460
|
+
if (!user)
|
|
461
|
+
return businessRefusal(10011, "用户不存在");
|
|
462
|
+
if (!Array.isArray(body.deptIds))
|
|
463
|
+
return businessRefusal(50000, "服务异常");
|
|
464
|
+
Object.assign(user, {
|
|
465
|
+
...(body.name !== undefined ? { name: String(body.name) } : {}),
|
|
466
|
+
...(body.departmentId !== undefined ? { departmentId: String(body.departmentId) } : {}),
|
|
467
|
+
...(body.mobile !== undefined ? { mobile: body.mobile === null ? null : String(body.mobile) } : {}),
|
|
468
|
+
...(body.email !== undefined ? { email: body.email === null ? null : String(body.email) } : {}),
|
|
469
|
+
...(body.status !== undefined ? { status: String(body.status) } : {}),
|
|
470
|
+
...(body.active !== undefined ? { active: body.active === true } : {}),
|
|
471
|
+
...(Array.isArray(body.roleIds) ? { roleIds: body.roleIds } : {}),
|
|
472
|
+
...(Array.isArray(body.deptIds) ? { deptIds: body.deptIds } : {}),
|
|
473
|
+
});
|
|
474
|
+
return user;
|
|
475
|
+
}
|
|
476
|
+
case "/api/api/organization/user/strike_out": {
|
|
477
|
+
ctx.state.orgUsers.delete(String(q.id ?? ""));
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
case "/api/api/organization/user/departments": {
|
|
481
|
+
const user = ctx.state.orgUsers.get(String(q.id ?? ""));
|
|
482
|
+
if (!user)
|
|
483
|
+
return [];
|
|
484
|
+
const dept = ctx.state.orgDepartments.get(user.departmentId);
|
|
485
|
+
return [{ deptId: user.departmentId, deptName: dept?.name ?? user.departmentId, isMain: true }];
|
|
486
|
+
}
|
|
487
|
+
case "/api/api/organization/role/add_role_group": {
|
|
488
|
+
const id = `grp-${ctx.state.orgGroups.size + 1}`;
|
|
489
|
+
ctx.state.orgGroups.set(id, { id, name: String(body.roleGroupName ?? ""), code: body.code ? String(body.code) : null, parentId: body.parentId ? String(body.parentId) : null });
|
|
490
|
+
return { roleGroupId: id, roleGroupName: body.roleGroupName, code: ctx.state.orgGroups.get(id).code, corpId: body.corpId ?? "other" };
|
|
491
|
+
}
|
|
492
|
+
case "/api/api/organization/role/add_role": {
|
|
493
|
+
const groupId = String(body.roleGroupId ?? "");
|
|
494
|
+
if (!groupId)
|
|
495
|
+
return businessRefusal(10005, "角色组不能为空");
|
|
496
|
+
if (groupId !== "grp-1" && !ctx.state.orgGroups.has(groupId))
|
|
497
|
+
return businessRefusal(10011, "角色组不存在");
|
|
498
|
+
const id = `role-${ctx.state.orgRoles.size + 1}`;
|
|
499
|
+
ctx.state.orgRoles.set(id, { id, name: String(body.roleName ?? ""), code: body.code ? String(body.code) : null, roleGroupId: groupId, roleGroupName: body.roleGroupName ? String(body.roleGroupName) : null, roleType: String(body.roleType ?? "SYS"), corpId: String(body.corpId ?? "other") });
|
|
500
|
+
return { roleId: id, roleName: body.roleName, code: ctx.state.orgRoles.get(id).code, roleGroupId: groupId, roleGroupName: body.roleGroupName ?? null, roleType: body.roleType ?? "SYS", corpId: body.corpId ?? "other" };
|
|
501
|
+
}
|
|
502
|
+
case "/api/api/organization/role/get": {
|
|
503
|
+
const role = ctx.state.orgRoles.get(String(q.roleId ?? ""));
|
|
504
|
+
if (!role)
|
|
505
|
+
return businessRefusal(10011, "角色不存在");
|
|
506
|
+
const remarks = role.remarks ?? null;
|
|
507
|
+
return { roleId: role.id, roleName: role.name, name: role.name, code: role.code, roleGroupId: role.roleGroupId, groupId: role.roleGroupId, roleGroupName: role.roleGroupName, roleType: role.roleType, corpId: role.corpId, remarks };
|
|
508
|
+
}
|
|
509
|
+
case "/api/api/organization/role/modify_role": {
|
|
510
|
+
const role = ctx.state.orgRoles.get(String(body.roleId ?? ""));
|
|
511
|
+
if (!role)
|
|
512
|
+
return businessRefusal(10011, "角色不存在");
|
|
513
|
+
role.name = body.roleName === undefined ? role.name : String(body.roleName);
|
|
514
|
+
role.code = body.code === undefined ? role.code : String(body.code);
|
|
515
|
+
// role/get answers RoleModel (name/groupId/remarks), not RoleVO — keep the
|
|
516
|
+
// stored shape aligned so a readback never invents a field.
|
|
517
|
+
if (body.remarks !== undefined)
|
|
518
|
+
role.remarks = body.remarks === null ? null : String(body.remarks);
|
|
519
|
+
if (body.roleGroupId !== undefined)
|
|
520
|
+
role.roleGroupId = String(body.roleGroupId);
|
|
521
|
+
return { roleId: role.id };
|
|
522
|
+
}
|
|
523
|
+
case "/api/api/organization/role/add_role_user": {
|
|
524
|
+
const roleId = String(body.roleId ?? "");
|
|
525
|
+
if (!roleId)
|
|
526
|
+
return businessRefusal(10005, "角色不能为空");
|
|
527
|
+
const rows = Array.isArray(body.userIds) ? body.userIds : [];
|
|
528
|
+
for (const row of rows) {
|
|
529
|
+
const userId = String(row.id ?? "");
|
|
530
|
+
if (!userId)
|
|
531
|
+
continue;
|
|
532
|
+
ctx.state.orgMembers.set(`${roleId}#${userId}`, { roleId, userId, name: String(row.name ?? userId), unitType: String(row.unitType ?? "3"), ouScope: [] });
|
|
533
|
+
}
|
|
534
|
+
return true;
|
|
535
|
+
}
|
|
536
|
+
case "/api/api/organization/role/strike_out_role_user": {
|
|
537
|
+
// Body {roleId,userIds}, NOT query ids (live 1.1.25 answers 10009 when the
|
|
538
|
+
// body is missing).
|
|
539
|
+
const roleId = String(body.roleId ?? "");
|
|
540
|
+
const userIds = Array.isArray(body.userIds) ? body.userIds : [];
|
|
541
|
+
if (userIds.length === 0)
|
|
542
|
+
return businessRefusal(10009, "Required request body is missing");
|
|
543
|
+
for (const id of userIds)
|
|
544
|
+
ctx.state.orgMembers.delete(`${roleId}#${String(id)}`);
|
|
545
|
+
return { undeletableLabelUsers: [], deletedUsers: userIds.map((id) => ({ id })) };
|
|
546
|
+
}
|
|
547
|
+
case "/api/api/organization/role/strike_out_role": {
|
|
548
|
+
const ids = String(q.ids ?? "").split(",").filter((value) => value !== "");
|
|
549
|
+
for (const roleId of ids) {
|
|
550
|
+
if ([...ctx.state.orgMembers.values()].some((member) => member.roleId === roleId))
|
|
551
|
+
return businessRefusal(-1, "角色下已经包含用户数据!");
|
|
552
|
+
ctx.state.orgRoles.delete(roleId);
|
|
553
|
+
}
|
|
554
|
+
return ids.map((roleId) => ({ roleId }));
|
|
555
|
+
}
|
|
556
|
+
case "/api/api/organization/role/strike_out_role_group": {
|
|
557
|
+
const ids = String(q.ids ?? "").split(",").filter((value) => value !== "");
|
|
558
|
+
for (const groupId of ids) {
|
|
559
|
+
if ([...ctx.state.orgRoles.values()].some((role) => role.roleGroupId === groupId))
|
|
560
|
+
return businessRefusal(-1, "角色组下已经包含角色数据!");
|
|
561
|
+
ctx.state.orgGroups.delete(groupId);
|
|
562
|
+
}
|
|
563
|
+
return ids.map((roleGroupId) => ({ roleGroupId }));
|
|
564
|
+
}
|
|
565
|
+
case "/api/api/organization/user/dept_transfer": {
|
|
566
|
+
const sourceDept = String(body.sourceDept ?? "");
|
|
567
|
+
const targetDept = String(body.targetDept ?? "");
|
|
568
|
+
if (!sourceDept || !targetDept)
|
|
569
|
+
return businessRefusal(50000, "服务异常");
|
|
570
|
+
const ids = Array.isArray(body.userIds) ? body.userIds : [];
|
|
571
|
+
for (const id of ids) {
|
|
572
|
+
const user = ctx.state.orgUsers.get(String(id));
|
|
573
|
+
if (!user)
|
|
574
|
+
continue;
|
|
575
|
+
if (user.departmentId === sourceDept)
|
|
576
|
+
user.departmentId = targetDept;
|
|
577
|
+
}
|
|
578
|
+
return JSON.stringify(ids);
|
|
579
|
+
}
|
|
580
|
+
case "/api/api/organization/role/users": {
|
|
581
|
+
const roleId = String(q.roleId ?? "");
|
|
582
|
+
const members = [...ctx.state.orgMembers.values()].filter((member) => member.roleId === roleId);
|
|
583
|
+
const page = Number(q.page ?? 0);
|
|
584
|
+
const size = Number(q.size ?? 500);
|
|
585
|
+
return { totalElements: members.length, totalPages: size > 0 ? Math.ceil(members.length / size) : 0, content: members.slice(page * size, page * size + size).map((member) => ({ id: member.userId, name: member.name, unitType: member.unitType, departmentId: "dept-1" })) };
|
|
586
|
+
}
|
|
587
|
+
case "/api/api/organization/role/get_ouscope": {
|
|
588
|
+
const member = ctx.state.orgMembers.get(`${String(q.roleId ?? "")}#${String(q.userId ?? "")}`);
|
|
589
|
+
return member ? member.ouScope : [];
|
|
590
|
+
}
|
|
591
|
+
case "/api/api/organization/role/update_ouscope": {
|
|
592
|
+
const member = ctx.state.orgMembers.get(`${String(body.roleId ?? "")}#${String(body.userId ?? "")}`);
|
|
593
|
+
if (!member)
|
|
594
|
+
return businessRefusal(10011, "角色成员不存在");
|
|
595
|
+
member.ouScope = Array.isArray(body.ouScopeList) ? body.ouScopeList : [];
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
367
598
|
default:
|
|
368
599
|
return NOT_HANDLED;
|
|
369
600
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stalfh233/omc-fake-platform",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.74",
|
|
4
4
|
"description": "OMC 的内存假 CloudPivot 平台(wire 接缝的第二个适配器)+ HTTP 假服务器——@stalfh233/omc-cli 的测试与 bench 基准基座",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"build": "tsc --project tsconfig.build.json"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"omc-core": "0.4.
|
|
21
|
+
"omc-core": "0.4.74"
|
|
22
22
|
},
|
|
23
23
|
"engines": {
|
|
24
24
|
"node": ">=22.13"
|