Show SCUM player identifiers and login IP
This commit is contained in:
@@ -198,20 +198,20 @@ function renderSurfaceBody(e: ReactLike["createElement"], pageKey: string, data:
|
||||
|
||||
function playersSurface(e: ReactLike["createElement"], data: SCUMSurfaceData, input: SCUMPageContext, view: ViewState) {
|
||||
const search = view.playerSearch.trim().toLowerCase();
|
||||
const players = data.players.filter((player) => matchesText(player, search, "displayName", "playerName", "gamePlayerId", "playerId", "steamId", "squadName") && (view.playerStatus === "all" || (view.playerStatus === "online") === playerOnline(player)));
|
||||
const players = data.players.filter((player) => matchesText(player, search, "displayName", "playerName", "gamePlayerId", "playerId", "userProfileId", "profileId", "steamId", "squadName", "lastLoginIp", "loginIp", "ipAddress", "ip") && (view.playerStatus === "all" || (view.playerStatus === "online") === playerOnline(player)));
|
||||
const onlineCount = data.players.filter(playerOnline).length;
|
||||
const selectedPlayer = data.players.find((player) => playerKey(player) === view.playerPanel.playerId);
|
||||
return e("div", { className: "console-record-list scum-surface" },
|
||||
e("div", { className: "resource-filter-bar scum-filter-bar" },
|
||||
labeledField(e, "搜索用户", e("input", { type: "search", value: view.playerSearch, "aria-label": "搜索用户", placeholder: "名称 / Steam ID / 队伍", onChange: (event: InputEvent) => view.setPlayerSearch(inputValue(event)) })),
|
||||
labeledField(e, "搜索用户", e("input", { type: "search", value: view.playerSearch, "aria-label": "搜索用户", placeholder: "名称 / UUID / Steam ID / 登录 IP / 队伍", onChange: (event: InputEvent) => view.setPlayerSearch(inputValue(event)) })),
|
||||
labeledField(e, "在线状态", e("select", { value: view.playerStatus, "aria-label": "在线状态", onChange: (event: InputEvent) => view.setPlayerStatus(inputValue(event)) }, e("option", { value: "all" }, "全部状态"), e("option", { value: "online" }, "在线"), e("option", { value: "offline" }, "离线/未知"))),
|
||||
e("span", { className: "scum-online-summary" }, "在线用户 ", e("strong", null, `${onlineCount} / ${data.players.length}`)),
|
||||
players.length !== data.players.length ? e("span", { className: "page-status" }, `当前显示 ${players.length} 人`) : null
|
||||
),
|
||||
e("div", { className: "provider-table-wrap scum-table-wrap" },
|
||||
e("table", { className: "resource-table scum-user-table" },
|
||||
e("thead", null, e("tr", null, ["用户名", "队伍", "状态", "最后活动", "操作"].map((label) => e("th", { key: label, scope: "col" }, label)))),
|
||||
e("tbody", null, players.length ? players.map((player, index) => playerTableRow(e, player, index, data, input, view)) : e("tr", null, e("td", { colSpan: 5 }, e("p", { className: "page-status" }, "没有符合筛选条件的真实用户记录。"))))
|
||||
e("thead", null, e("tr", null, ["用户名", "UUID / Steam", "渣币", "登录 IP", "队伍", "状态", "最后活动", "操作"].map((label) => e("th", { key: label, scope: "col" }, label)))),
|
||||
e("tbody", null, players.length ? players.map((player, index) => playerTableRow(e, player, index, data, input, view)) : e("tr", null, e("td", { colSpan: 8 }, e("p", { className: "page-status" }, "没有符合筛选条件的真实用户记录。"))))
|
||||
)
|
||||
),
|
||||
selectedPlayer && view.playerPanel.kind !== "closed" ? playerDrawer(e, selectedPlayer, data, input, view) : null
|
||||
@@ -220,12 +220,17 @@ function playersSurface(e: ReactLike["createElement"], data: SCUMSurfaceData, in
|
||||
|
||||
function playerTableRow(e: ReactLike["createElement"], player: RecordMap, index: number, data: SCUMSurfaceData, input: SCUMPageContext, view: ViewState) {
|
||||
const name = textField(player, "displayName", "playerName", "name") || textField(player, "gamePlayerId", "playerId", "steamId") || "未知用户";
|
||||
const uuid = textField(player, "gamePlayerId", "playerId", "userProfileId", "profileId") || "未同步";
|
||||
const steamId = textField(player, "steamId", "providerId");
|
||||
const open = (kind: PlayerPanelKind) => { view.setPlayerPanel({ kind, playerId: playerKey(player) }); if (kind === "attributes") view.setAttributeDrafts(playerAttributeDrafts(player)); };
|
||||
return e("tr", { key: idOf(player, `player-${index}`) },
|
||||
e("td", null, e("strong", null, name)),
|
||||
e("td", null, e("span", { className: "provider-id" }, uuid), steamId ? e("span", { className: "provider-id" }, `Steam ${steamId}`) : null),
|
||||
e("td", null, e("strong", null, numField(player, "normalBalance", "moneyBalance")), e("span", { className: "provider-id" }, `Gold ${numField(player, "goldBalance")}`)),
|
||||
e("td", null, e("span", { className: "provider-id" }, textField(player, "lastLoginIp", "loginIp", "ipAddress", "ip") || "未同步")),
|
||||
e("td", null, e("span", null, textField(player, "squadName", "squadId") || "未加入"), e("span", { className: "provider-id" }, textField(player, "squadId") ? `ID ${textField(player, "squadId")}` : "")),
|
||||
e("td", null, e("span", { className: `status-pill ${playerOnline(player) ? "status-active" : "status-disabled"}` }, playerOnline(player) ? "在线" : "离线/未知"), e("span", { className: "provider-id" }, numField(player, "pingMs") === "--" ? "" : `${numField(player, "pingMs")} ms`)),
|
||||
e("td", null, userDateField(player, "lastSeenAt", "lastLoginObservedAt", "onlineObservedAt", "updatedAt")),
|
||||
e("td", null, userDateField(player, "lastSeenAt", "lastLoginTime", "lastLoginAt", "lastLoginObservedAt", "onlineObservedAt", "updatedAt")),
|
||||
e("td", { className: "provider-actions-cell" }, playerActionMenu(e, player, view, open))
|
||||
);
|
||||
}
|
||||
@@ -254,9 +259,11 @@ function playerDrawer(e: ReactLike["createElement"], player: RecordMap, data: SC
|
||||
e("div", { className: "panel-header" }, e("div", null, e("h2", null, title), e("span", { className: "provider-id" }, `${name} · Steam ${textField(player, "steamId", "providerId") || "未同步"}`)), e("button", { type: "button", className: "drawer-close", onClick: close }, "关闭")),
|
||||
e("div", { className: "console-record-meta scum-player-overview" },
|
||||
e("span", null, `Profile ${textField(player, "userProfileId", "profileId") || "未同步"}`),
|
||||
e("span", null, `UUID ${textField(player, "gamePlayerId", "playerId") || "未同步"}`),
|
||||
e("span", null, `登录 IP ${textField(player, "lastLoginIp", "loginIp", "ipAddress", "ip") || "未同步"}`),
|
||||
e("span", null, `网络相关 ${shortHash(textField(player, "networkCorrelation")) || "未同步"}`),
|
||||
e("span", null, `Fame ${numField(player, "famePoints")}`),
|
||||
e("span", null, `Cash ${numField(player, "normalBalance", "moneyBalance")} · Gold ${numField(player, "goldBalance")}`),
|
||||
e("span", null, `渣币 ${numField(player, "normalBalance", "moneyBalance")} · Gold ${numField(player, "goldBalance")}`),
|
||||
e("span", null, `上次登录 ${userDateField(player, "lastLoginTime", "lastLoginAt", "lastLoginObservedAt")}`)),
|
||||
content
|
||||
)
|
||||
@@ -304,7 +311,7 @@ function playerItemsPanel(e: ReactLike["createElement"], player: RecordMap) {
|
||||
|
||||
function playerHistoryPanel(e: ReactLike["createElement"], player: RecordMap, data: SCUMSurfaceData) {
|
||||
const rows = playerRecords(data.activityEvents, player).filter((row) => ["login", "logout", "scum.login", "scum.logout"].includes(textField(row, "eventType", "type").toLowerCase()));
|
||||
return e("div", { className: "console-record-list" }, e("p", { className: "dialog-description" }, "登录历史来自插件声明的 SCUM 登录日志投影;网络字段只显示不可逆相关性哈希。"), e("div", { className: "console-row-list" }, rows.length ? rows.map((row, index) => e("div", { key: idOf(row, `history-${index}`), className: "console-row" }, e("span", null, textField(row, "eventType", "type") || "登录事件"), e("strong", null, dateField(row, "occurredAt", "observedAt", "createdAt")), e("strong", null, shortHash(textField(row, "networkCorrelation")) || textField(row, "reason") || "无网络字段"))) : e("p", { className: "page-status" }, "没有该用户的真实登录历史。")));
|
||||
return e("div", { className: "console-record-list" }, e("p", { className: "dialog-description" }, "登录历史来自插件声明的 SCUM 登录日志投影。"), e("div", { className: "console-row-list" }, rows.length ? rows.map((row, index) => e("div", { key: idOf(row, `history-${index}`), className: "console-row" }, e("span", null, textField(row, "eventType", "type") || "登录事件"), e("strong", null, dateField(row, "occurredAt", "observedAt", "createdAt")), e("strong", null, textField(row, "lastLoginIp", "loginIp", "ipAddress", "ip") || shortHash(textField(row, "networkCorrelation")) || textField(row, "reason") || "无网络字段"))) : e("p", { className: "page-status" }, "没有该用户的真实登录历史。")));
|
||||
}
|
||||
|
||||
function playerTrajectoryPanel(e: ReactLike["createElement"], player: RecordMap, data: SCUMSurfaceData) {
|
||||
|
||||
Reference in New Issue
Block a user