user.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  6. <title>ArozOS - New User</title>
  7. <script src="script/jquery.min.js"></script>
  8. <script src="script/ao_module.js"></script>
  9. <script src="script/applocale.js"></script>
  10. <style>
  11. * { box-sizing: border-box; margin: 0; padding: 0; }
  12. #uu-root {
  13. --uu-text: #202124;
  14. --uu-body: #3c4043;
  15. --uu-dim: #5f6368;
  16. --uu-muted: #9aa0a6;
  17. --uu-sep: #dadce0;
  18. --uu-bg: #f8f9fa;
  19. --uu-card-bg: #ffffff;
  20. --uu-input-border: #dadce0;
  21. --uu-input-focus: #1967d2;
  22. --uu-accent: #1a73e8;
  23. --uu-accent-press: #1558b0;
  24. --uu-danger: #d93025;
  25. font-family: 'Google Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  26. font-size: 14px;
  27. -webkit-font-smoothing: antialiased;
  28. color: var(--uu-body);
  29. background: var(--uu-bg);
  30. min-height: 100vh;
  31. }
  32. #uu-root.dark {
  33. --uu-text: #e8eaed;
  34. --uu-body: #bdc1c6;
  35. --uu-dim: #9aa0a6;
  36. --uu-muted: #5f6368;
  37. --uu-sep: #3c4043;
  38. --uu-bg: #202124;
  39. --uu-card-bg: #292a2d;
  40. --uu-input-border: #5f6368;
  41. --uu-input-focus: #8ab4f8;
  42. --uu-accent: #8ab4f8;
  43. --uu-accent-press: #aecbfa;
  44. --uu-danger: #f28b82;
  45. }
  46. body { background: var(--uu-bg); }
  47. /* ── Layout ── */
  48. #uu-outer {
  49. min-height: 100vh;
  50. display: flex;
  51. align-items: center;
  52. justify-content: center;
  53. padding: 24px 16px;
  54. }
  55. /* ── Card ── */
  56. #uu-card {
  57. width: 100%;
  58. max-width: 450px;
  59. background: var(--uu-card-bg);
  60. border-radius: 8px;
  61. border: 1px solid var(--uu-sep);
  62. box-shadow: 0 1px 4px rgba(0,0,0,0.08);
  63. overflow: hidden;
  64. }
  65. #uu-root.dark #uu-card {
  66. box-shadow: 0 1px 4px rgba(0,0,0,0.40);
  67. }
  68. /* ── Header ── */
  69. #uu-hero {
  70. padding: 32px 40px 22px;
  71. display: flex;
  72. flex-direction: column;
  73. align-items: flex-start;
  74. border-bottom: 1px solid var(--uu-sep);
  75. }
  76. #uu-hero-icon { display: none; }
  77. #uu-hero-title {
  78. font-size: 24px;
  79. font-weight: 400;
  80. color: var(--uu-text);
  81. line-height: 1.25;
  82. letter-spacing: 0;
  83. }
  84. #uu-hero-sub {
  85. font-size: 13px;
  86. color: var(--uu-dim);
  87. margin-top: 8px;
  88. line-height: 1.5;
  89. }
  90. /* ── Form body ── */
  91. #uu-body { padding: 24px 40px 32px; }
  92. .uu-field { margin-bottom: 20px; }
  93. .uu-label {
  94. display: block;
  95. font-size: 13px;
  96. font-weight: 400;
  97. color: var(--uu-dim);
  98. margin-bottom: 6px;
  99. }
  100. .uu-req { color: var(--uu-danger); margin-left: 2px; }
  101. .uu-input {
  102. width: 100%;
  103. padding: 9px 12px;
  104. border-radius: 4px;
  105. border: 1px solid var(--uu-input-border);
  106. background: transparent;
  107. color: var(--uu-text);
  108. font-family: inherit;
  109. font-size: 14px;
  110. outline: none;
  111. transition: border-color 0.15s, box-shadow 0.15s;
  112. appearance: none;
  113. -webkit-appearance: none;
  114. }
  115. .uu-input::placeholder { color: var(--uu-muted); }
  116. .uu-input:focus {
  117. border-color: var(--uu-input-focus);
  118. box-shadow: 0 0 0 1px var(--uu-input-focus);
  119. }
  120. .uu-input.error {
  121. border-color: var(--uu-danger);
  122. box-shadow: 0 0 0 1px var(--uu-danger);
  123. }
  124. select.uu-input {
  125. background-color: var(--uu-card-bg);
  126. background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%235f6368' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  127. background-repeat: no-repeat;
  128. background-position: right 12px center;
  129. padding-right: 32px;
  130. cursor: pointer;
  131. }
  132. /* ── Error alert ── */
  133. #uu-err {
  134. display: none;
  135. background: rgba(217,48,37,0.06);
  136. border: 1px solid rgba(217,48,37,0.20);
  137. border-radius: 4px;
  138. padding: 10px 12px;
  139. margin-bottom: 16px;
  140. font-size: 13px;
  141. color: var(--uu-danger);
  142. }
  143. #uu-root.dark #uu-err {
  144. background: rgba(242,139,130,0.08);
  145. border-color: rgba(242,139,130,0.28);
  146. }
  147. /* ── Required note ── */
  148. #uu-note {
  149. font-size: 12px;
  150. color: var(--uu-muted);
  151. margin-bottom: 20px;
  152. }
  153. /* ── Divider ── */
  154. .uu-divider {
  155. height: 1px;
  156. background: var(--uu-sep);
  157. margin-bottom: 20px;
  158. }
  159. /* ── Actions ── */
  160. #uu-actions {
  161. display: flex;
  162. justify-content: flex-end;
  163. align-items: center;
  164. gap: 8px;
  165. }
  166. .uu-btn {
  167. display: inline-flex;
  168. align-items: center;
  169. justify-content: center;
  170. gap: 5px;
  171. padding: 9px 24px;
  172. border-radius: 4px;
  173. border: none;
  174. font-family: inherit;
  175. font-size: 14px;
  176. font-weight: 500;
  177. cursor: pointer;
  178. outline: none;
  179. background: transparent;
  180. color: var(--uu-accent);
  181. transition: background 0.12s;
  182. white-space: nowrap;
  183. user-select: none;
  184. -webkit-tap-highlight-color: transparent;
  185. }
  186. .uu-btn:hover { background: rgba(26,115,232,0.08); }
  187. .uu-btn:active { background: rgba(26,115,232,0.14); }
  188. #uu-root.dark .uu-btn:hover { background: rgba(138,180,248,0.10); }
  189. #uu-root.dark .uu-btn:active { background: rgba(138,180,248,0.16); }
  190. .uu-btn.primary {
  191. background: var(--uu-accent);
  192. color: #ffffff;
  193. box-shadow: 0 1px 2px rgba(0,0,0,0.10);
  194. }
  195. .uu-btn.primary:hover { background: var(--uu-accent-press); }
  196. .uu-btn.primary:active { opacity: 0.88; }
  197. </style>
  198. </head>
  199. <body>
  200. <div id="uu-root">
  201. <div id="uu-outer">
  202. <div id="uu-card">
  203. <div id="uu-hero">
  204. <div id="uu-hero-icon">
  205. <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
  206. <circle cx="12" cy="8" r="4" stroke="currentColor" stroke-width="1.6"/>
  207. <path d="M4 20c0-3.314 3.582-6 8-6s8 2.686 8 6" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
  208. </svg>
  209. </div>
  210. <div>
  211. <div id="uu-hero-title" locale="user/title">New User</div>
  212. <div id="uu-hero-sub" locale="user/subtitle">Fill in the following information to create an account.</div>
  213. </div>
  214. </div>
  215. <div id="uu-body">
  216. <div class="uu-field">
  217. <label class="uu-label" for="username">
  218. <span locale="user/username">Username</span><span class="uu-req">*</span>
  219. </label>
  220. <input id="username" class="uu-input" type="text" autocomplete="username">
  221. </div>
  222. <div class="uu-field">
  223. <label class="uu-label" for="magic">
  224. <span locale="user/password">Password</span><span class="uu-req">*</span>
  225. </label>
  226. <input id="magic" class="uu-input" type="password" autocomplete="new-password">
  227. </div>
  228. <div class="uu-field">
  229. <label class="uu-label" for="repeatMagic">
  230. <span locale="user/confirm-pw">Confirm Password</span><span class="uu-req">*</span>
  231. </label>
  232. <input id="repeatMagic" class="uu-input" type="password" autocomplete="new-password">
  233. </div>
  234. <div class="uu-field">
  235. <label class="uu-label" for="usergroups">
  236. <span locale="user/group">User Group</span>
  237. </label>
  238. <select id="usergroups" class="uu-input">
  239. <option locale="user/loading">Loading&#8230;</option>
  240. </select>
  241. </div>
  242. <div id="uu-note"><span class="uu-req">*</span> <span locale="user/required-note">This field is required</span></div>
  243. <div id="uu-err"></div>
  244. <div class="uu-divider"></div>
  245. <div id="uu-actions">
  246. <button id="cancelbtn" class="uu-btn" onclick="cancel()" style="display:none;" locale="user/cancel">Cancel</button>
  247. <button class="uu-btn primary" onclick="createUser()" locale="user/create">Create</button>
  248. </div>
  249. </div>
  250. </div>
  251. </div>
  252. </div>
  253. <script>
  254. /* ── Theme (best-effort — page may be public) ── */
  255. try {
  256. if (typeof ao_module_getSystemThemeColor === 'function') {
  257. ao_module_getSystemThemeColor(function(c) {
  258. document.getElementById('uu-root').classList.toggle('dark', c !== 'whiteTheme');
  259. });
  260. } else {
  261. var _t = (typeof preferredTheme !== 'undefined' ? preferredTheme : null) ||
  262. (parent && typeof parent.preferredTheme !== 'undefined' ? parent.preferredTheme : null);
  263. if (_t) document.getElementById('uu-root').classList.toggle('dark', _t === 'dark' || _t === 'darkTheme');
  264. }
  265. } catch(e) {}
  266. /* ── Locale (best-effort — user may not be logged in) ── */
  267. try {
  268. if (typeof NewAppLocale === 'function') {
  269. var uuLocale = NewAppLocale();
  270. uuLocale.init('locale/user.json', function() {
  271. uuLocale.translate();
  272. });
  273. }
  274. } catch(e) {}
  275. /* ── Load user groups ── */
  276. $.get("system/permission/listgroup", function(data) {
  277. $("#usergroups").empty();
  278. for (var i = 0; i < data.length; i++) {
  279. $("#usergroups").append('<option value="' + escHtml(data[i]) + '">' + escHtml(data[i]) + '</option>');
  280. }
  281. });
  282. /* ── Show cancel button if running inside desktop ── */
  283. try {
  284. if (!(!parent.isDesktopMode)) {
  285. $("#cancelbtn").show();
  286. }
  287. } catch(e) {}
  288. /* ── Enter key submits ── */
  289. $("input").on("keydown", function(event) {
  290. if (event.keyCode === 13) {
  291. event.preventDefault();
  292. createUser();
  293. }
  294. });
  295. /* ── Create user ── */
  296. function createUser() {
  297. var username = $("#username").val().trim();
  298. var password = $("#magic").val();
  299. var repeat = $("#repeatMagic").val();
  300. var usergroup = $("#usergroups").val();
  301. var valid = true;
  302. /* Clear previous errors */
  303. $(".uu-input").removeClass("error");
  304. $("#uu-err").hide();
  305. if (username === "") {
  306. $("#username").addClass("error");
  307. valid = false;
  308. }
  309. if (password === "") {
  310. $("#magic").addClass("error");
  311. $("#repeatMagic").addClass("error");
  312. valid = false;
  313. } else if (password !== repeat) {
  314. $("#repeatMagic").addClass("error");
  315. valid = false;
  316. }
  317. if (!valid) return;
  318. $.post("system/auth/register", { username: username, password: password, group: usergroup })
  319. .done(function(data) {
  320. if (!data.includes("Error")) {
  321. $.get("system/auth/checkLogin", function(loggedIn) {
  322. if (loggedIn == true) {
  323. try {
  324. if (!(!parent.isDesktopMode)) {
  325. ao_module_parentCallback(true);
  326. parent.closeFwProcess($(window.frameElement).parent().parent().attr("windowId"));
  327. return;
  328. }
  329. } catch(e) {}
  330. window.location.href = "SystemAO/closeTabInsturction.html";
  331. } else {
  332. window.location.href = "/login.html";
  333. }
  334. });
  335. } else {
  336. $("#uu-err").text(data).slideDown('fast');
  337. }
  338. });
  339. }
  340. function cancel() {
  341. try {
  342. if (!(!parent.isDesktopMode)) {
  343. parent.closeFwProcess($(window.frameElement).parent().parent().attr("windowId"));
  344. }
  345. } catch(e) {}
  346. }
  347. function escHtml(s) {
  348. return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
  349. }
  350. </script>
  351. </body>
  352. </html>