wangzhibo
2026-05-09 53418655c061ac26f66058253f39200aced1ab1d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
@model LoginViewModel
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>登录 - Board</title>
  <link rel="stylesheet" href="@Model.BasePath/static/style.css" />
</head>
<body class="page-login">
  <main class="card">
    <h1>Board 门户</h1>
    <p class="muted">请使用域账号登录</p>
    <form id="loginForm" class="form" autocomplete="on">
      <label>
        <span>用户名</span>
        <input type="text" name="username" required autofocus />
      </label>
      <label>
        <span>密码</span>
        <input type="password" name="password" required />
      </label>
      <p id="loginError" class="error" hidden></p>
      <button type="submit" class="btn primary login-submit">登录</button>
    </form>
    <div class="login-winauth">
      <button type="button" class="btn winauth" id="btnWinAuth">一键登录(Windows 集成)</button>
    </div>
  </main>
  <script>
    (function () {
      const params = new URLSearchParams(location.search);
      const basePath = "@Model.BasePath";
      const next = params.get("next") || (basePath + "/");
      const form = document.getElementById("loginForm");
      const err = document.getElementById("loginError");
      const negotiateErr = params.get("negotiate_error");
      if (negotiateErr) {
        err.textContent = negotiateErr;
        err.hidden = false;
        const clean = new URLSearchParams();
        const n = params.get("next");
        if (n) clean.set("next", n);
        const qs = clean.toString();
        history.replaceState({}, "", basePath + "/login" + (qs ? "?" + qs : ""));
      }
      form.addEventListener("submit", async (e) => {
        e.preventDefault();
        err.hidden = true;
        const fd = new FormData(form);
        const body = {
          username: fd.get("username"),
          password: fd.get("password"),
          next: next.startsWith(basePath + "/") ? next : (basePath + "/"),
        };
        const res = await fetch(basePath + "/api/login", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          credentials: "include",
          body: JSON.stringify(body),
        });
        const data = await res.json().catch(() => ({}));
        if (!res.ok || !data.ok) {
          err.textContent = data.error || "登录失败";
          err.hidden = false;
          return;
        }
        location.href = data.redirect || (basePath + "/");
      });
 
      document.getElementById("btnWinAuth").addEventListener("click", () => {
        err.hidden = true;
        const nextSafe = next.startsWith(basePath + "/") ? next : (basePath + "/");
        const q = new URLSearchParams({ next: nextSafe });
        location.href = basePath + "/api/winauth/negotiate?" + q.toString();
      });
    })();
  </script>
</body>
</html>