#!/usr/bin/env bash set -euo pipefail API="http://127.0.0.1:8080/api" extract_id() { sed -n -E 's/.*"id":([0-9]+).*/\1/p'; } # 使用变量承载 JSON,避免直接使用管道导致的 broken pipe get_menu_id_by_parent_and_path(){ local parent_id="$1"; local path="$2" local MENUS MENUS=$(curl -s -X GET "$API/menus" -H "$H_AUTH") echo "$MENUS" | P="$path" PID="$parent_id" python3 - <<'PY' import json,sys,os try: data=json.load(sys.stdin) except Exception: sys.exit(0) menus=data.get("data", []) P=os.environ.get("P") PID=os.environ.get("PID") try: pid_int=None if PID in (None, "", "null") else int(PID) except Exception: pid_int=None for m in menus: if m.get("path")==P and ((pid_int is None and m.get("parent_id") is None) or (pid_int is not None and m.get("parent_id")==pid_int)): print(m.get("id"), end="") break PY } get_menu_id_by_parent_and_name(){ local parent_id="$1"; local name="$2" local MENUS MENUS=$(curl -s -X GET "$API/menus" -H "$H_AUTH") echo "$MENUS" | N="$name" PID="$parent_id" python3 - <<'PY' import json,sys,os try: data=json.load(sys.stdin) except Exception: sys.exit(0) menus=data.get("data", []) N=os.environ.get("N") PID=os.environ.get("PID") try: pid_int=None if PID in (None, "", "null") else int(PID) except Exception: pid_int=None for m in menus: if m.get("name")==N and ((pid_int is None and m.get("parent_id") is None) or (pid_int is not None and m.get("parent_id")==pid_int)): print(m.get("id"), end="") break PY } create_or_get_menu(){ # parent_id name type path component icon order_no [visible] [status] [keep_alive] local parent_id="$1"; local name="$2"; local mtype="$3"; local path="$4"; local component="$5"; local icon="$6"; local order_no="$7"; local visible="${8:-true}"; local status="${9:-1}"; local keep_alive="${10:-true}" local id="" if [ -n "$path" ]; then id=$(get_menu_id_by_parent_and_path "$parent_id" "$path") || true; fi if [ -z "$id" ]; then id=$(get_menu_id_by_parent_and_name "$parent_id" "$name") || true; fi if [ -n "$id" ]; then echo "$id"; return 0; fi # 规范化可选字段为 JSON 合法值 local j_parent j_path j_comp j_icon j_order if [ -n "${parent_id:-}" ]; then j_parent="$parent_id"; else j_parent="null"; fi if [ -n "${path:-}" ]; then j_path="\"$path\""; else j_path="null"; fi if [ -n "${component:-}" ]; then j_comp="\"$component\""; else j_comp="null"; fi if [ -n "${icon:-}" ]; then j_icon="\"$icon\""; else j_icon="null"; fi j_order="${order_no:-0}" local payload payload=$(cat < 根) orders[rid]=list(reversed(order)) print(json.dumps({"keep": keep_id, "dups": duplicates, "orders": orders})) PY ) local KEEP_ID; KEEP_ID=$(echo "$JSON" | sed -n -E 's/.*"keep":"?([0-9]+)"?.*/\1/p') local DUPS; DUPS=$(echo "$JSON" | sed -n -E 's/.*"dups":\[([^\]]*)\].*/\1/p' | tr -d '" ') if [ -n "${DUPS:-}" ]; then echo "[INFO] 发现重复根菜单: $ROOT_NAME (type=$ROOT_TYPE),保留ID=$KEEP_ID,待清理: [$DUPS]" # 逐个根依次删除其子树 for rid in $(echo "$DUPS" | tr ',' ' '); do local ORDER; ORDER=$(echo "$JSON" | RID="$rid" python3 - <<'PY' import json,sys,os obj=json.load(sys.stdin) rid=os.environ.get("RID") print(",".join(obj.get("orders", {}).get(rid, [])), end="") PY ) for id in $(echo "$ORDER" | tr ',' ' '); do # 逐个删除(叶优先),失败重试一次 RES=$(curl -s -X DELETE "$API/menus/$id" -H "$H_AUTH" || true) echo "$RES" | grep -q '"code":0' || { sleep 0.2 RES=$(curl -s -X DELETE "$API/menus/$id" -H "$H_AUTH" || true) echo "$RES" | grep -q '"code":0' || echo "[WARN] 删除菜单失败(id=$id): $RES" } done done echo "[OK] 已清理 $ROOT_NAME 重复根菜单" fi } # 如数据库已存在相同根菜单,先做去重清理 cleanup_duplicate_roots "演示-系统管理" 0 || true cleanup_duplicate_roots "系统管理" 1 || true # 2) Create demo menus(可通过环境变量 SKIP_DEMO=1 跳过) if [ "${SKIP_DEMO:-0}" != "1" ]; then # 幂等:优先查找已存在的“演示-系统管理”,否则创建(基于 Python 解析) MENUS_JSON=$(curl -s -X GET "$API/menus" -H "$H_AUTH") DEMO_ROOT_ID=$(echo "$MENUS_JSON" | python3 - <<'PY' import json,sys try: data=json.load(sys.stdin) menus=data.get("data", []) except Exception: menus=[] for m in menus: if m.get("name")=="演示-系统管理" and m.get("type")==0 and m.get("parent_id") is None: print(m.get("id"), end="") break PY ) if [ -z "${DEMO_ROOT_ID:-}" ]; then DEMO_ROOT_JSON=$(printf '{"name":"演示-系统管理","type":0,"order_no":100,"visible":true,"status":1}' | curl -s -X POST "$API/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) DEMO_ROOT_ID=$(echo "$DEMO_ROOT_JSON" | extract_id) fi if [ -z "${DEMO_ROOT_ID:-}" ]; then echo "[ERROR] 创建/获取 演示-系统管理 根菜单失败"; exit 1; fi USERS_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-用户管理" 1 "/demo/users" "Users" "" 10) ROLES_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-角色管理" 1 "/demo/roles" "Roles" "" 20) MENUS_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-菜单管理" 1 "/demo/menus" "Menus" "" 30) PERMS_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-权限管理" 1 "/demo/perms" "Permissions" "" 40) DEPT_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-部门管理" 1 "/demo/departments" "Departments" "" 50) POS_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-岗位管理" 1 "/demo/positions" "Positions" "" 60) echo "[OK] 演示菜单准备完成: ROOT=$DEMO_ROOT_ID USERS=$USERS_ID ROLES=$ROLES_ID MENUS=$MENUS_ID PERMS=$PERMS_ID DEPT=$DEPT_ID POS=$POS_ID" else echo "[INFO] 已设置 SKIP_DEMO=1,跳过演示菜单创建" fi # [INFO] 演示菜单已通过幂等逻辑创建/获取,避免重复 # 3) Create demo role TS=$(date +%s) ROLE_NAME="演示-经理-${TS}" ROLE_CODE="demo_manager_${TS}" ROLE_JSON=$(printf '{"name":"%s","code":"%s","status":1}' "$ROLE_NAME" "$ROLE_CODE" | curl -s -X POST "$API/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) ROLE_ID=$(echo "$ROLE_JSON" | extract_id); if [ -z "$ROLE_ID" ]; then echo "[ERROR] 创建角色失败: $ROLE_JSON"; exit 1; fi echo "[OK] 创建角色成功: $ROLE_NAME (id=$ROLE_ID)" # 4) Bind menus to the role IDS="" for v in "${USERS_ID:-}" "${ROLES_ID:-}" "${MENUS_ID:-}" "${PERMS_ID:-}" "${DEPT_ID:-}" "${POS_ID:-}"; do if [ -n "$v" ]; then if [ -n "$IDS" ]; then IDS="$IDS,$v"; else IDS="$v"; fi fi done if [ -n "$IDS" ]; then BIND_MENU_JSON=$(printf '{"ids":[%s]}' "$IDS" | curl -s -X PUT "$API/roles/$ROLE_ID/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) echo "$BIND_MENU_JSON" | grep -q '"code":0' || { echo "[ERROR] 绑定角色菜单失败: $BIND_MENU_JSON"; exit 1; } echo "[OK] 绑定角色菜单成功" else echo "[WARN] 无可绑定的演示菜单,跳过绑定" fi # 5) Create a user and bind the role USER_NAME="alice_${TS}" USER_PASS="Password@123" USER_JSON=$(printf '{"username":"%s","password":"%s","nickname":"Alice","status":1}' "$USER_NAME" "$USER_PASS" | curl -s -X POST "$API/users" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) USER_ID=$(echo "$USER_JSON" | extract_id); if [ -z "$USER_ID" ]; then echo "[ERROR] 创建用户失败: $USER_JSON"; exit 1; fi echo "[OK] 创建用户成功: $USER_NAME (id=$USER_ID)" BIND_ROLE_JSON=$(printf '{"ids":[%s]}' "$ROLE_ID" | curl -s -X PUT "$API/users/$USER_ID/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) echo "$BIND_ROLE_JSON" | grep -q '"code":0' || { echo "[ERROR] 绑定用户角色失败: $BIND_ROLE_JSON"; exit 1; } echo "[OK] 绑定用户角色成功" # 5b) Bind demo role to admin and verify menus ADMIN_JSON=$(curl -s -X GET "$API/users?page=1&page_size=50&keyword=admin" -H "$H_AUTH") ADMIN_ID=$(echo "$ADMIN_JSON" | sed -n -E 's/.*"id":([0-9]+).*"username":"admin".*/\1/p') if [ -z "$ADMIN_ID" ]; then echo "[WARN] 未找到 admin 用户ID" else BIND_ADMIN_JSON=$(printf '{"ids":[%s]}' "$ROLE_ID" | curl -s -X PUT "$API/users/$ADMIN_ID/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) echo "$BIND_ADMIN_JSON" | grep -q '"code":0' && echo "[OK] 已为 admin 绑定演示角色(id=$ROLE_ID)" || echo "[WARN] 为 admin 绑定角色可能失败: $BIND_ADMIN_JSON" MENUS_ADMIN=$(curl -s -X GET "$API/auth/menus" -H "$H_AUTH") echo "[RESULT] Admin 可见菜单响应: $MENUS_ADMIN" fi # 6) Login as new user and fetch menus LOGIN2_JSON=$(printf '{"username":"%s","password":"%s"}' "$USER_NAME" "$USER_PASS" | curl -s -X POST "$API/auth/login" -H "Content-Type: application/json" --data-binary @-) TOKEN2=$(echo "$LOGIN2_JSON" | sed -n -E 's/.*"access_token":"([^\"]*)".*/\1/p') if [ -z "$TOKEN2" ]; then echo "[ERROR] 新用户登录失败: $LOGIN2_JSON"; exit 1; fi MENUS2=$(curl -s -X GET "$API/auth/menus" -H "Authorization: Bearer $TOKEN2") echo "[RESULT] 新用户可见菜单响应: $MENUS2" # 7) Check permissions and seed defaults if empty PERMS_LIST=$(curl -s -X GET "$API/permissions?page=1&page_size=100" -H "$H_AUTH") || true PERMS_TOTAL=$(echo "$PERMS_LIST" | sed -n -E 's/.*"total":([0-9]+).*/\1/p') || true [ -z "${PERMS_TOTAL:-}" ] && PERMS_TOTAL=0 echo "[RESULT] 当前权限总数: $PERMS_TOTAL" if [ "$PERMS_TOTAL" = "0" ]; then echo "[INFO] 权限为空,开始初始化默认权限" curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"users:view","name":"用户查看","description":"查看用户"}' >/dev/null || true curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"users:edit","name":"用户编辑","description":"编辑用户"}' >/dev/null || true curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"roles:view","name":"角色查看","description":"查看角色"}' >/dev/null || true curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"roles:edit","name":"角色编辑","description":"编辑角色"}' >/dev/null || true curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"menus:view","name":"菜单查看","description":"查看菜单"}' >/dev/null || true curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"menus:edit","name":"菜单编辑","description":"编辑菜单"}' >/dev/null || true curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"permissions:view","name":"权限查看","description":"查看权限"}' >/dev/null || true curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"permissions:edit","name":"权限编辑","description":"编辑权限"}' >/dev/null || true curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"departments:view","name":"部门查看","description":"查看部门"}' >/dev/null || true curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"departments:edit","name":"部门编辑","description":"编辑部门"}' >/dev/null || true PERMS_LIST=$(curl -s -X GET "$API/permissions?page=1&page_size=100" -H "$H_AUTH") || true PERMS_TOTAL=$(echo "$PERMS_LIST" | sed -n -E 's/.*"total":([0-9]+).*/\1/p') || true [ -z "${PERMS_TOTAL:-}" ] && PERMS_TOTAL=0 echo "[RESULT] 初始化后权限总数: $PERMS_TOTAL" fi echo "[SUMMARY] DEMO_ROOT=${DEMO_ROOT_ID:-} USERS=${USERS_ID:-} ROLES=${ROLES_ID:-} MENUS=${MENUS_ID:-} PERMS=${PERMS_ID:-} ROLE=$ROLE_ID USER=$USER_ID USERNAME=$USER_NAME" # 8) Seed formal "系统管理" menus and Super Admin role # 获取或创建 系统管理 根菜单:查找时不依赖字段顺序 MENUS_JSON=$(curl -s -X GET "$API/menus" -H "$H_AUTH") SYS_ROOT_ID=$(echo "$MENUS_JSON" | python3 - <<'PY' import json,sys try: data=json.load(sys.stdin) menus=data.get("data", []) except Exception: menus=[] for m in menus: if m.get("name")=="系统管理" and m.get("type")==1 and m.get("parent_id") is None: print(m.get("id"), end="") break PY ) if [ -z "${SYS_ROOT_ID:-}" ]; then SYS_ROOT_JSON=$(printf '{"name":"系统管理","type":1,"icon":"SettingOutlined","order_no":10,"visible":true,"status":1}' | curl -s -X POST "$API/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) SYS_ROOT_ID=$(echo "$SYS_ROOT_JSON" | extract_id) fi if [ -z "${SYS_ROOT_ID:-}" ]; then echo "[ERROR] 创建/获取 系统管理 根菜单失败"; exit 1; fi # helper to create child menu under 系统管理 create_menu_under_sys(){ local name="$1"; local path="$2"; local component="$3"; local icon="$4"; local order_no="$5" local id id=$(get_menu_id_by_parent_and_path "$SYS_ROOT_ID" "$path") || true if [ -z "$id" ]; then id=$(get_menu_id_by_parent_and_name "$SYS_ROOT_ID" "$name") || true; fi if [ -n "$id" ]; then echo "$id"; return 0; fi id=$(create_or_get_menu "$SYS_ROOT_ID" "$name" 1 "$path" "$component" "$icon" "$order_no") echo "$id" } USERS2_ID=$(create_menu_under_sys "用户管理" "/users" "Users" "UserOutlined" 20); [ -z "$USERS2_ID" ] && echo "[WARN] 用户管理 菜单ID获取失败" ROLES2_ID=$(create_menu_under_sys "角色管理" "/roles" "Roles" "TeamOutlined" 30); [ -z "$ROLES2_ID" ] && echo "[WARN] 角色管理 菜单ID获取失败" MENUS2_ID=$(create_menu_under_sys "菜单管理" "/menus" "Menus" "AppstoreOutlined" 40); [ -z "$MENUS2_ID" ] && echo "[WARN] 菜单管理 菜单ID获取失败" PERMS2_ID=$(create_menu_under_sys "权限管理" "/permissions" "Permissions" "KeyOutlined" 50); [ -z "$PERMS2_ID" ] && echo "[WARN] 权限管理 菜单ID获取失败" DEPTS2_ID=$(create_menu_under_sys "部门管理" "/departments" "Departments" "AppstoreOutlined" 60); [ -z "$DEPTS2_ID" ] && echo "[WARN] 部门管理 菜单ID获取失败" POSITIONS2_ID=$(create_menu_under_sys "岗位管理" "/positions" "Positions" "IdcardOutlined" 65); [ -z "$POSITIONS2_ID" ] && echo "[WARN] 岗位管理 菜单ID获取失败" echo "[OK] 正式系统菜单准备完成: ROOT=$SYS_ROOT_ID USERS=$USERS2_ID ROLES=$ROLES2_ID MENUS=$MENUS2_ID PERMS=$PERMS2_ID DEPTS=$DEPTS2_ID POSITIONS=$POSITIONS2_ID" # 工具函数:根据 parent_id + perms 查找或创建按钮菜单(使用 Python 解析) create_or_get_button(){ local parent_id="$1"; local name="$2"; local perms="$3"; local order_no="${4:-0}" local id MENUS MENUS=$(curl -s -X GET "$API/menus" -H "$H_AUTH") id=$(echo "$MENUS" | PERM="$perms" PID="$parent_id" python3 - <<'PY' import json,sys,os try: data=json.load(sys.stdin) menus=data.get("data", []) except Exception: menus=[] PERM=os.environ.get("PERM") PID=os.environ.get("PID") pid_int=None try: pid_int=int(PID) except Exception: pass for m in menus: if m.get("type")==3 and m.get("perms")==PERM and m.get("parent_id")==pid_int: print(m.get("id"), end="") break PY ) || true if [ -n "$id" ]; then echo "$id"; return 0; fi local resp; resp=$(printf '{"parent_id":%s,"name":"%s","type":3,"order_no":%s,"visible":false,"status":1,"keep_alive":false,"perms":"%s"}' \ "$parent_id" "$name" "${order_no:-0}" "$perms" | curl -s -X POST "$API/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) id=$(echo "$resp" | extract_id) echo "$id" } # 为系统管理下添加按钮权限(幂等) [ -n "${USERS2_ID:-}" ] && { create_or_get_button "$USERS2_ID" "新增" "system:user:create" 10 >/dev/null || true create_or_get_button "$USERS2_ID" "编辑" "system:user:update" 20 >/dev/null || true create_or_get_button "$USERS2_ID" "重置密码" "system:user:reset" 30 >/dev/null || true create_or_get_button "$USERS2_ID" "删除" "system:user:delete" 40 >/dev/null || true create_or_get_button "$USERS2_ID" "分配岗位" "system:user:assignPosition" 50 >/dev/null || true } [ -n "${ROLES2_ID:-}" ] && { create_or_get_button "$ROLES2_ID" "新增" "system:role:create" 10 >/dev/null || true create_or_get_button "$ROLES2_ID" "编辑" "system:role:update" 20 >/dev/null || true create_or_get_button "$ROLES2_ID" "分配菜单" "system:role:assign" 30 >/dev/null || true create_or_get_button "$ROLES2_ID" "删除" "system:role:delete" 40 >/dev/null || true } [ -n "${MENUS2_ID:-}" ] && { create_or_get_button "$MENUS2_ID" "新增" "system:menu:create" 10 >/dev/null || true create_or_get_button "$MENUS2_ID" "编辑" "system:menu:update" 20 >/dev/null || true create_or_get_button "$MENUS2_ID" "删除" "system:menu:delete" 30 >/dev/null || true } [ -n "${POSITIONS2_ID:-}" ] && { create_or_get_button "$POSITIONS2_ID" "新增" "system:position:create" 10 >/dev/null || true create_or_get_button "$POSITIONS2_ID" "编辑" "system:position:update" 20 >/dev/null || true create_or_get_button "$POSITIONS2_ID" "删除" "system:position:delete" 30 >/dev/null || true } # 9) Create Super Admin role if not exists (code=super_admin) SUPER_JSON=$(curl -s -X GET "$API/roles?page=1&page_size=100&keyword=super_admin" -H "$H_AUTH") SUPER_ROLE_ID=$(echo "$SUPER_JSON" | sed -n -E 's/.*"id":([0-9]+).*"code":"super_admin".*/\1/p') if [ -z "${SUPER_ROLE_ID:-}" ]; then SUPER_CREATE_JSON=$(printf '{"name":"超级管理员","code":"super_admin","status":1}' | curl -s -X POST "$API/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) SUPER_ROLE_ID=$(echo "$SUPER_CREATE_JSON" | extract_id) fi if [ -z "${SUPER_ROLE_ID:-}" ]; then echo "[ERROR] 创建/获取 超级管理员 角色失败"; exit 1; fi echo "[OK] 超级管理员 角色ID=$SUPER_ROLE_ID" # 10) Bind ALL menus to Super Admin (幂等) ALL_MENU_IDS=$(curl -s -X GET "$API/menus" -H "$H_AUTH" | python3 - <<'PY' import json,sys try: data=json.load(sys.stdin) menus=data.get("data", []) except Exception: menus=[] ids=[str(m.get("id")) for m in menus if isinstance(m.get("id"), int)] print(",".join(ids), end="") PY ) BIND_SUPER_JSON=$(printf '{"ids":[%s]}' "$ALL_MENU_IDS" | curl -s -X PUT "$API/roles/$SUPER_ROLE_ID/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) echo "$BIND_SUPER_JSON" | grep -q '"code":0' || { echo "[ERROR] 绑定全部菜单到 超级管理员 失败: $BIND_SUPER_JSON"; exit 1; } echo "[OK] 已将全部菜单绑定到 超级管理员 角色" # 11) Assign Super Admin role to admin (保留演示角色) if [ -z "${ADMIN_ID:-}" ]; then ADMIN_JSON=$(curl -s -X GET "$API/users?page=1&page_size=50&keyword=admin" -H "$H_AUTH") ADMIN_ID=$(echo "$ADMIN_JSON" | sed -n -E 's/.*"id":([0-9]+).*"username":"admin".*/\1/p') fi if [ -n "${ADMIN_ID:-}" ]; then CUR_ROLES_JSON=$(curl -s -X GET "$API/users/$ADMIN_ID/roles" -H "$H_AUTH") NEW_ROLE_IDS=$(echo "$CUR_ROLES_JSON" | SUPER_ROLE_ID="$SUPER_ROLE_ID" python3 -c 'import json,sys,os try: data=json.load(sys.stdin) except Exception: data={} ids=[] for it in data.get("data", []): try: i=int(it.get("id")) s=str(i) if s not in ids: ids.append(s) except Exception: pass sid=os.environ.get("SUPER_ROLE_ID") if sid and sid not in ids: ids.append(sid) print("".join([",".join(ids)]), end="")') if [ -z "$NEW_ROLE_IDS" ]; then NEW_ROLE_IDS="$SUPER_ROLE_ID"; fi ASSIGN_ADMIN_JSON=$(printf '{"ids":[%s]}' "$NEW_ROLE_IDS" | curl -s -X PUT "$API/users/$ADMIN_ID/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-) echo "$ASSIGN_ADMIN_JSON" | grep -q '"code":0' && echo "[OK] 已为 admin 分配 超级管理员 角色(id=$SUPER_ROLE_ID) 合并现有角色: [$NEW_ROLE_IDS]" || echo "[WARN] 为 admin 分配 超级管理员 可能失败: $ASSIGN_ADMIN_JSON" MENUS_ADMIN2=$(curl -s -X GET "$API/auth/menus" -H "$H_AUTH") echo "[RESULT] Admin 可见菜单(包含正式菜单): $MENUS_ADMIN2" else echo "[WARN] 未能获取 admin 用户ID,跳过角色分配" fi echo "[SUMMARY] DEMO_ROOT=${DEMO_ROOT_ID:-} USERS=${USERS_ID:-} ROLES=${ROLES_ID:-} MENUS=${MENUS_ID:-} PERMS=${PERMS_ID:-}"