// VL_VERSION:4.2.13
// @meta component summary:"用户中心实例与项目绑定管理（UC-007A）- 实例注册表 + 项目->用户中心中心化绑定的唯一换绑入口" keywords:(["多用户中心","项目绑定","bindingSource","admin"])
<Section-AdminBindingsPage "root"> containerType:col min-height:"0"

# Frontend Public Props

# Frontend Public Events

# Frontend Public Methods
METHOD ReloadAll();RETURN {success:BOOL}
-$loading = true
-<ServiceDomain-UserCenterService "ucService">.ListUserCenters() -> _c
-IF _c.success
--$centers = _c.centers
-<ServiceDomain-UserCenterService "ucService">.ListProjectBindings() -> _b
-IF _b.success
--$bindings = _b.bindings
-<ServiceDomain-UserCenterService "ucService">.ListBindingHistory("", 50) -> _h
-IF _h.success
--$history = _h.changes
-$loading = false
-RETURN {success:true}

# Frontend Global Vars
$centers([{}]) = []
$bindings([{}]) = []
$loading(BOOL) = false
$infoMessage(STRING) = ""
$errorMessage(STRING) = ""
$newProjectId(STRING) = ""
$newCenterCode(STRING) = ""
$newNote(STRING) = ""
$saving(BOOL) = false
$history([{}]) = []
$ucEditOpen(BOOL) = false
$ucCode(STRING) = ""
$ucName(STRING) = ""
$ucANid(STRING) = ""
$ucAUrl(STRING) = ""
$ucBNid(STRING) = ""
$ucBUrl(STRING) = ""
$ucSaving(BOOL) = false

# Frontend Tree
<ServiceDomain-UserCenterService "ucService">
-<Service-ListUserCenters> params:() returns:(success(BOOL),centers([{}]))
-<Service-ListProjectBindings> params:() returns:(success(BOOL),bindings([{}]))
-<Service-EnsureDefaultUserCenter> params:() returns:(success(BOOL),message(STRING),action(STRING),userCenterCode(STRING))
-<Service-UpsertUserCenter> params:(userCenterCode(STRING),displayName(STRING),userCenterBackendNid(INT),userCenterFrontendUrl(STRING),permissionCenterBackendNid(INT),permissionCenterFrontendUrl(STRING)) returns:(success(BOOL),message(STRING),action(STRING))
-<Service-SetDefaultUserCenter> params:(userCenterCode(STRING)) returns:(success(BOOL),message(STRING))
-<Service-DisableUserCenter> params:(userCenterCode(STRING)) returns:(success(BOOL),message(STRING))
-<Service-UpsertProjectBinding> params:(projectId(STRING),env(STRING),userCenterCode(STRING),note(STRING)) returns:(success(BOOL),message(STRING),action(STRING))
-<Service-DisableProjectBinding> params:(projectId(STRING),env(STRING)) returns:(success(BOOL),message(STRING))
-<Service-ListBindingHistory> params:(projectId(STRING),limit(INT)) returns:(success(BOOL),changes([{}]))
<Col-Root> width:"100%" flex:"1" min-height:"0" padding:"32px" gap:"24px"
-<Col-Header> width:"100%" gap:"4px"
--<Text-Title> value:"用户中心实例与项目绑定" style:"caption" size:"lg"
--<Text-Hint> value:"组织可有多个用户中心实例；项目形成中心化绑定后，换绑只能在本页完成，项目自身配置不得覆盖。解析顺序：项目绑定 > 项目配置 nid > 默认用户中心。" style:"muted" size:"sm"
-<If-InfoM> conditions:($infoMessage != "")
--<Col-InfoBox> width:"100%" padding:"8px 12px" sk.bg:"#f0fdf4" border:"1px solid #bbf7d0"
---<Text-Info> value:$infoMessage style:"caption" size:"sm" sk.fg:"#15803d"
-<If-ErrM> conditions:($errorMessage != "")
--<Col-ErrBox> width:"100%" padding:"8px 12px" sk.bg:"#fef2f2" border:"1px solid #fecaca"
---<Text-Err> value:$errorMessage style:"hint" size:"sm" sk.fg:"#b91c1c"
-<Col-CentersPanel> width:"100%" border:"1px solid #ebedf1"
--<Row-CPH> width:"100%" padding:"12px 16px" align-items:"center" gap:"12px" sk.borderBottom:"1px solid #ebedf1" sk.bg:"#fafafa"
---<Text-CPT> value:("用户中心实例（" + $centers.length + "）") style:"caption" size:"sm" flex:"1"
---<Button-EnsureDefault> value:"注册当前部署为默认实例" style:"primary|filled|default|sm|actionable" min-height:"28px"
---<Button-UcNew> value:"手动新建实例" style:"neutral|outlined|default|sm|actionable" min-height:"28px"
--<Row-CCH> width:"100%" padding:"10px 16px" gap:"12px" align-items:"center" sk.borderBottom:"1px solid #ebedf1" sk.bg:"#fafafa"
---<Text-CH1> value:"实例" flex:"2" style:"muted" size:"xs"
---<Text-CH3> value:"用户中心后端" min-width:"110px" style:"muted" size:"xs"
---<Text-CH4> value:"权限中心后端" min-width:"110px" style:"muted" size:"xs"
---<Text-CH5> value:"默认" min-width:"60px" style:"muted" size:"xs"
---<Text-CH6> value:"状态" min-width:"70px" style:"muted" size:"xs"
---<Text-CH7> value:"操作" min-width:"150px" style:"muted" size:"xs"
--<If-CEmpty> conditions:($centers.length == 0)
---<Text-CEmpty> value:"暂无实例。点击右上按钮把当前部署注册为默认用户中心。" padding:"16px" style:"hint" size:"sm"
--<For-Centers> sourceArray:$centers loopVar:[_c,_cIdx]
---<Row-CItem> width:"100%" padding:"10px 16px" gap:"12px" align-items:"center" sk.borderBottom:"1px solid #f1f3f5"
----<Col-CNameCell> flex:"2" gap:"1px" min-width:"0"
-----<Text-CN> value:(_c.displayName ? _c.displayName : "(未命名实例)") style:"body" size:"sm"
-----<Text-CC> value:("编码 " + _c.userCenterCode) style:"hint" size:"xs"
----<Text-CA> value:("" + _c.userCenterBackendNid) min-width:"110px" style:"muted" size:"sm"
----<Text-CB> value:("" + _c.permissionCenterBackendNid) min-width:"110px" style:"muted" size:"sm"
----<Row-CDCell> min-width:"60px" align-items:"center"
-----<If-CDef> conditions:(_c.isDefault == true)
------<Row-CDTag> sk.bg:"#e8eeff" padding:"2px 8px" radius:"sm"
-------<Text-CDTagT> value:"默认" style:"body" size:"xs" sk.fg:"#2549d6"
----<Row-CSCell> min-width:"70px" align-items:"center"
-----<Row-CSTag> sk.bg:(_c.status == "active" ? "#e6f4ea" : "#eef0f3") padding:"2px 8px" radius:"sm"
------<Text-CSTagT> value:(_c.status == "active" ? "启用" : "已停用") style:"body" size:"xs" sk.fg:(_c.status == "active" ? "#1a7f37" : "#5b6472")
----<Row-CAct> min-width:"150px" gap:"6px"
-----<Button-UcEdit> value:"编辑" style:"primary|ghost|default|sm|actionable" min-height:"26px"
-----<If-UcCanDefault> conditions:(_c.isDefault != true && _c.status == "active")
------<Button-UcSetDefault> value:"设默认" style:"success|ghost|default|sm|actionable" min-height:"26px"
-----<If-UcCanDisable> conditions:(_c.isDefault != true && _c.status == "active")
------<Button-UcDisable> value:"停用" style:"danger|ghost|default|sm|actionable" min-height:"26px"
-<Col-BindPanel> width:"100%" border:"1px solid #ebedf1"
--<Row-BPH> width:"100%" padding:"12px 16px" align-items:"center" gap:"12px" sk.borderBottom:"1px solid #ebedf1" sk.bg:"#fafafa"
---<Text-BPT> value:("项目绑定（" + $bindings.length + "）") style:"caption" size:"sm" flex:"1"
---<Button-Reload> value:"刷新" style:"neutral|outlined|default|sm|actionable" min-height:"28px"
--<Row-NewBind> width:"100%" padding:"12px 16px" gap:"8px" align-items:"center" sk.borderBottom:"1px solid #ebedf1"
---<Input-NewPid> style:"neutral|outlined|default|sm" value:$newProjectId placeholder:"项目 ID（如 ProjectAccessTest）" flex:"1" min-height:"32px"
---<Input-NewCode> style:"neutral|outlined|default|sm" value:$newCenterCode placeholder:"用户中心编码（如 default）" min-width:"180px" min-height:"32px"
---<Input-NewNote> style:"neutral|outlined|default|sm" value:$newNote placeholder:"备注（可选）" flex:"1" min-height:"32px"
---<Button-Bind> value:($saving == true ? "保存中..." : "绑定/换绑") style:"primary|filled|default|sm|actionable" min-height:"32px" min-width:"90px"
--<Row-BCH> width:"100%" padding:"10px 16px" gap:"12px" align-items:"center" sk.borderBottom:"1px solid #ebedf1" sk.bg:"#fafafa"
---<Text-BH1> value:"项目 ID" flex:"1" style:"muted" size:"xs"
---<Text-BH2> value:"环境" min-width:"80px" style:"muted" size:"xs"
---<Text-BH3> value:"用户中心编码" min-width:"140px" style:"muted" size:"xs"
---<Text-BH4> value:"状态" min-width:"70px" style:"muted" size:"xs"
---<Text-BH5> value:"操作人" min-width:"90px" style:"muted" size:"xs"
---<Text-BH6> value:"操作" min-width:"80px" style:"muted" size:"xs"
--<If-BEmpty> conditions:($bindings.length == 0)
---<Text-BEmpty> value:"暂无项目绑定。未绑定的项目按其配置 nid 或默认用户中心解析。" padding:"16px" style:"hint" size:"sm"
--<For-Bindings> sourceArray:$bindings loopVar:[_b,_bIdx]
---<Row-BItem> width:"100%" padding:"10px 16px" gap:"12px" align-items:"center" sk.borderBottom:"1px solid #f1f3f5"
----<Text-BP> value:_b.projectId flex:"1" style:"caption" size:"sm"
----<Text-BE> value:_b.env min-width:"80px" style:"muted" size:"sm"
----<Text-BC> value:_b.userCenterCode min-width:"140px" style:"caption" size:"sm"
----<If-BActive> conditions:(_b.status == "active")
-----<Text-BSa> value:"生效" min-width:"70px" style:"caption" size:"sm" sk.fg:"#15803d"
----<If-BDisabled> conditions:(_b.status != "active")
-----<Text-BSd> value:"已解绑" min-width:"70px" style:"muted" size:"sm"
----<Text-BBy> value:(_b.boundBy ? _b.boundBy : "-") min-width:"90px" style:"muted" size:"sm"
----<Row-BAct> min-width:"80px" gap:"6px"
-----<If-BCanDisable> conditions:(_b.status == "active")
------<Button-Unbind> value:"解绑" style:"danger|ghost|default|sm|actionable" min-height:"26px"
-<If-UcEdit> conditions:($ucEditOpen == true)
--<Col-UcMask> position:"absolute" top:"0" left:"0" width:"100%" height:"100%" align-items:"center" justify-content:"center" sk.bg:"rgba(0,0,0,0.32)" z-index:"200"
---<Col-UcDialog> width:"560px" sk.bg:"#ffffff" border:"1px solid #ebedf1"
----<Row-UcDH> width:"100%" padding:"12px 16px" align-items:"center" gap:"12px" sk.borderBottom:"1px solid #ebedf1" sk.bg:"#fafafa"
-----<Text-UcDT> value:"新建/编辑用户中心实例" style:"caption" size:"sm" flex:"1"
-----<Button-UcDClose> value:"×" style:"neutral|ghost|default|sm|actionable" min-width:"28px" min-height:"28px"
----<Col-UcDB> width:"100%" padding:"16px" gap:"10px"
-----<Row-UcTip> width:"100%" padding:"8px 12px" style:"warning|soft|passive" radius:"sm"
------<Text-UcTip> value:"多数情况下用上方「注册当前部署为默认实例」即可自动登记，无需手填编号与地址。此处仅用于一个组织有多套用户中心实例的高级场景。" style:"body" size:"xs"
-----<Row-UcR1> width:"100%" gap:"12px" align-items:"center"
------<Text-UcL1> value:"实例编码 / 名称" min-width:"140px" style:"muted" size:"sm"
------<Input-UcCode> style:"neutral|outlined|default|sm" value:$ucCode placeholder:"实例编码（已存在则编辑并恢复启用）" flex:"1" min-height:"32px"
------<Input-UcName> style:"neutral|outlined|default|sm" value:$ucName placeholder:"实例显示名" flex:"1" min-height:"32px"
-----<Row-UcR2> width:"100%" gap:"12px" align-items:"center"
------<Text-UcL2> value:"用户中心后端 / 前端地址" min-width:"140px" style:"muted" size:"sm"
------<Input-UcANid> style:"neutral|outlined|default|sm" value:$ucANid placeholder:"用户中心后端 nid，如 12206000" min-width:"180px" min-height:"32px"
------<Input-UcAUrl> style:"neutral|outlined|default|sm" value:$ucAUrl placeholder:"用户中心前端地址" flex:"1" min-height:"32px"
-----<Row-UcR3> width:"100%" gap:"12px" align-items:"center"
------<Text-UcL3> value:"权限中心后端 / 前端地址" min-width:"140px" style:"muted" size:"sm"
------<Input-UcBNid> style:"neutral|outlined|default|sm" value:$ucBNid placeholder:"权限中心后端 nid，如 12206040" min-width:"180px" min-height:"32px"
------<Input-UcBUrl> style:"neutral|outlined|default|sm" value:$ucBUrl placeholder:"权限中心前端地址" flex:"1" min-height:"32px"
----<Row-UcDF> width:"100%" padding:"12px 16px" gap:"8px" justify-content:"flex-end" sk.borderTop:"1px solid #ebedf1" sk.bg:"#fafafa"
-----<Button-UcDCancel> value:"取消" style:"neutral|outlined|default|sm|actionable" min-height:"30px" min-width:"72px"
-----<Button-UcDSave> value:($ucSaving == true ? "保存中..." : "保存") style:"primary|filled|default|sm|actionable" min-height:"30px" min-width:"72px"
-<Col-HistPanel> width:"100%" border:"1px solid #ebedf1"
--<Row-HPH> width:"100%" padding:"12px 16px" align-items:"center" gap:"12px" sk.borderBottom:"1px solid #ebedf1" sk.bg:"#fafafa"
---<Text-HPT> value:("换绑历史（最近 " + $history.length + " 条）") style:"caption" size:"sm" flex:"1"
--<Row-HCH> width:"100%" padding:"10px 16px" gap:"12px" align-items:"center" sk.borderBottom:"1px solid #ebedf1" sk.bg:"#fafafa"
---<Text-HH1> value:"时间" min-width:"160px" style:"muted" size:"xs"
---<Text-HH2> value:"项目 ID" flex:"1" style:"muted" size:"xs"
---<Text-HH3> value:"动作" min-width:"70px" style:"muted" size:"xs"
---<Text-HH4> value:"从 → 到" flex:"1" style:"muted" size:"xs"
---<Text-HH5> value:"操作人" min-width:"90px" style:"muted" size:"xs"
--<If-HEmpty> conditions:($history.length == 0)
---<Col-HEmpty> width:"100%" align-items:"center" justify-content:"center" padding:"40px 16px" gap:"6px"
----<Text-HEmptyT> value:"还没有换绑记录" style:"caption" size:"md"
----<Text-HEmptyD> value:"项目完成绑定或换绑后，操作记录会显示在这里。" style:"muted" size:"sm"
--<For-Hist> sourceArray:$history loopVar:[_h,_hIdx]
---<Row-HItem> width:"100%" padding:"10px 16px" gap:"12px" align-items:"center" sk.borderBottom:"1px solid #f1f3f5"
----<Text-HT> value:(_h._create ? ("" + _h._create) : "-") min-width:"160px" style:"muted" size:"sm"
----<Text-HP> value:_h.projectId flex:"1" style:"caption" size:"sm"
----<Text-HA> value:(_h.action == "bind" ? "绑定" : (_h.action == "rebind" ? "换绑" : "解绑")) min-width:"70px" style:"caption" size:"sm"
----<Text-HFT> value:((_h.fromCode != "" ? _h.fromCode : "（无）") + " → " + (_h.toCode != "" ? _h.toCode : "（无）")) flex:"1" style:"muted" size:"sm"
----<Text-HO> value:(_h.operatorId ? _h.operatorId : "-") min-width:"90px" style:"muted" size:"sm"

# Frontend Event Handlers
<Section-AdminBindingsPage "root">.@init()
-ReloadAll() -> _r

<Button-Reload>.@click()
-ReloadAll() -> _r

<Button-EnsureDefault>.@click()
-<ServiceDomain-UserCenterService "ucService">.EnsureDefaultUserCenter() -> _r
-IF !_r.success
--$errorMessage = _r.message
--RETURN
-$errorMessage = ""
-$infoMessage = (_r.action == "insert" ? "已注册默认用户中心 " : "已刷新默认用户中心 ") + _r.userCenterCode
-ReloadAll() -> _r2

<Input-NewPid>.@change(value)
-$newProjectId = value

<Input-NewCode>.@change(value)
-$newCenterCode = value

<Input-NewNote>.@change(value)
-$newNote = value

<Button-Bind>.@click()
-IF $saving == true
--RETURN
-IF $newProjectId == "" || $newCenterCode == ""
--$errorMessage = "请填写项目 ID 和用户中心编码。"
--RETURN
-$saving = true
-<ServiceDomain-UserCenterService "ucService">.UpsertProjectBinding($newProjectId, "preview", $newCenterCode, $newNote) -> _r
-$saving = false
-IF !_r.success
--$errorMessage = _r.message
--RETURN
-$errorMessage = ""
-$infoMessage = (_r.action == "insert" ? ("已绑定 " + $newProjectId) : ("已换绑 " + $newProjectId))
-$newProjectId = ""
-$newNote = ""
-ReloadAll() -> _r2

<Button-Unbind>.@click()
-<ServiceDomain-UserCenterService "ucService">.DisableProjectBinding(_b.projectId, _b.env) -> _r
-IF !_r.success
--$errorMessage = _r.message
--RETURN
-$errorMessage = ""
-$infoMessage = "已解绑 " + _b.projectId
-ReloadAll() -> _r2

<Button-UcNew>.@click()
-$ucEditOpen = true
-$ucCode = ""
-$ucName = ""
-$ucANid = ""
-$ucAUrl = ""
-$ucBNid = ""
-$ucBUrl = ""

<Button-UcEdit>.@click()
-$ucEditOpen = true
-$ucCode = _c.userCenterCode
-$ucName = _c.displayName ? _c.displayName : ""
-$ucANid = "" + _c.userCenterBackendNid
-$ucAUrl = _c.userCenterFrontendUrl ? _c.userCenterFrontendUrl : ""
-$ucBNid = "" + _c.permissionCenterBackendNid
-$ucBUrl = _c.permissionCenterFrontendUrl ? _c.permissionCenterFrontendUrl : ""

<Button-UcSetDefault>.@click()
-<ServiceDomain-UserCenterService "ucService">.SetDefaultUserCenter(_c.userCenterCode) -> _r
-IF !_r.success
--$errorMessage = _r.message
--RETURN
-$errorMessage = ""
-$infoMessage = "默认用户中心已切换为 " + _c.userCenterCode
-ReloadAll() -> _r2

<Button-UcDisable>.@click()
-<SysUI>.showModal("停用用户中心实例", "停用后绑定到该实例的业务项目将无法正常解析用户中心，确定停用？") -> _cfm
-IF !_cfm.confirm
--RETURN
-<ServiceDomain-UserCenterService "ucService">.DisableUserCenter(_c.userCenterCode) -> _r
-IF !_r.success
--$errorMessage = _r.message
--RETURN
-$errorMessage = ""
-$infoMessage = "已停用实例 " + _c.userCenterCode
-ReloadAll() -> _r2

<Button-UcDClose>.@click()
-$ucEditOpen = false

<Button-UcDCancel>.@click()
-$ucEditOpen = false

<Input-UcCode>.@change(value)
-$ucCode = value

<Input-UcName>.@change(value)
-$ucName = value

<Input-UcANid>.@change(value)
-$ucANid = value

<Input-UcAUrl>.@change(value)
-$ucAUrl = value

<Input-UcBNid>.@change(value)
-$ucBNid = value

<Input-UcBUrl>.@change(value)
-$ucBUrl = value

<Button-UcDSave>.@click()
-IF $ucSaving == true
--RETURN
-IF $ucCode == "" || $ucANid == ""
--$errorMessage = "请填写用户中心编码与用户中心后端 nid。"
--RETURN
-$ucSaving = true
-<ServiceDomain-UserCenterService "ucService">.UpsertUserCenter($ucCode, $ucName, ($ucANid * 1), $ucAUrl, ($ucBNid != "" ? ($ucBNid * 1) : 0), $ucBUrl) -> _r
-$ucSaving = false
-IF !_r.success
--$errorMessage = _r.message
--RETURN
-$ucEditOpen = false
-$errorMessage = ""
-$infoMessage = (_r.action == "insert" ? "已注册实例 " : "已更新实例 ") + $ucCode
-ReloadAll() -> _r2

# Frontend Internal Methods

# Frontend Pipeline Funcs

</Section-AdminBindingsPage>
