Опубликовано через кнопку

This commit is contained in:
Aset 2026-08-12 07:39:53 +00:00
parent bcc0954b2a
commit 4caccb36c5
4 changed files with 77 additions and 9 deletions

View File

@ -24,12 +24,22 @@
<button type="submit" class="btn btn-primary btn-block">Кіру</button> <button type="submit" class="btn btn-primary btn-block">Кіру</button>
</form> </form>
<button type="button" class="btn btn-ghost btn-block" id="forgotBtn" style="margin-top:10px">Құпия сөзді ұмыттыңыз ба?</button> <button type="button" class="btn btn-ghost btn-block" id="forgotBtn" style="margin-top:10px">Құпия сөзді ұмыттыңыз ба?</button>
<button type="button" class="btn btn-cyan btn-block" id="registerBtn" style="margin-top:8px">Тіркелу</button>
<div id="recoverBox" class="hidden" style="margin-top:14px"> <div id="recoverBox" class="hidden" style="margin-top:14px">
<div class="login-sub">Логиніңізді жазыңыз — жаңа құпия сөз беріледі</div> <div class="login-sub">Логиніңізді жазыңыз — жаңа құпия сөз беріледі</div>
<input type="text" id="recoverLogin" placeholder="Логин (жеке нөміріңіз)"> <input type="text" id="recoverLogin" placeholder="Логин (жеке нөміріңіз)">
<button type="button" class="btn btn-primary btn-block" id="recoverGo" style="margin-top:10px">Жаңа құпия сөз алу</button> <button type="button" class="btn btn-primary btn-block" id="recoverGo" style="margin-top:10px">Жаңа құпия сөз алу</button>
<div id="recoverMsg" class="login-error"></div> <div id="recoverMsg" class="login-error"></div>
</div> </div>
<div id="registerBox" class="hidden" style="margin-top:14px">
<div class="login-sub">Аты-жөніңізді, жеке нөміріңізді және құпия сөзді жазып тіркеліңіз</div>
<input type="text" id="regName" placeholder="Аты-жөні">
<input type="tel" id="regPhone" placeholder="Телефон нөмірі (+7 7XX XXX XX XX)" style="margin-top:8px">
<input type="text" id="regLogin" inputmode="numeric" placeholder="Логин (жеке нөміріңіз)" style="margin-top:8px">
<input type="password" id="regPass" placeholder="Құпия сөз (ағылшын әріптерімен)" style="margin-top:8px">
<button type="button" class="btn btn-cyan btn-block" id="regGo" style="margin-top:10px">Тіркелу</button>
<div id="regMsg" class="login-error"></div>
</div>
<p class="login-hint">Демо: админ — 1001 / Admin123 · қызметкер — 2001 / Worker123</p> <p class="login-hint">Демо: админ — 1001 / Admin123 · қызметкер — 2001 / Worker123</p>
</div> </div>
</div> </div>

View File

@ -175,6 +175,45 @@ function lsSet(k, v) { localStorage.setItem("qcom_" + k, JSON.stringify(v)); }
/* ---------------- КІРУ ---------------- */ /* ---------------- КІРУ ---------------- */
document.getElementById("forgotBtn").addEventListener("click", function () { document.getElementById("forgotBtn").addEventListener("click", function () {
document.getElementById("recoverBox").classList.toggle("hidden"); document.getElementById("recoverBox").classList.toggle("hidden");
document.getElementById("registerBox").classList.add("hidden");
});
document.getElementById("registerBtn").addEventListener("click", function () {
document.getElementById("registerBox").classList.toggle("hidden");
document.getElementById("recoverBox").classList.add("hidden");
});
document.getElementById("regGo").addEventListener("click", async function () {
var name = document.getElementById("regName").value.trim();
var phone = document.getElementById("regPhone").value.trim();
var login = document.getElementById("regLogin").value.trim();
var pass = document.getElementById("regPass").value.trim();
var msg = document.getElementById("regMsg");
if (!name || !login || !pass) { msg.textContent = "Аты-жөнін, логинді және құпия сөзді толтырыңыз"; return; }
var res = await apiPost("/api/register", { name: name, login: login, password: pass, phone: phone });
if (res.ok) {
state.user = res.user;
state.token = res.token;
await loadServerData();
enterApp();
return;
}
if (res.offline) {
if (MOCK_USERS.find(function (u) { return u.login === login; })) {
msg.textContent = "Мұндай логин бар (демо-режим)";
return;
}
MOCK_USERS.push({ login: login, password: pass, name: name, phone: phone, role: "user" });
state.user = { login: login, name: name, role: "user" };
state.offline = true;
state.content = MOCK_CONTENT;
state.complaints = lsGet("complaints", []);
state.testResults = lsGet("testResults", []);
state.directMessages = lsGet("directMessages", []);
enterApp();
return;
}
msg.textContent = res.error || "Қате";
}); });
document.getElementById("recoverGo").addEventListener("click", async function () { document.getElementById("recoverGo").addEventListener("click", async function () {
@ -685,7 +724,9 @@ async function renderUsers(el) {
html += '<div><label>Логин (жеке нөмір)</label><input id="uLogin" placeholder="Мысалы: 2004"></div>'; html += '<div><label>Логин (жеке нөмір)</label><input id="uLogin" placeholder="Мысалы: 2004"></div>';
html += '<div><label>Аты-жөні</label><input id="uName" placeholder="Аты-жөні"></div>'; html += '<div><label>Аты-жөні</label><input id="uName" placeholder="Аты-жөні"></div>';
html += '</div><div class="grid grid-2">'; html += '</div><div class="grid grid-2">';
html += '<div><label>Телефон нөмірі</label><input id="uPhone" placeholder="+7 7XX XXX XX XX"></div>';
html += '<div><label>Құпия сөз</label><input id="uPass" placeholder="Ағылшын әріптерімен"></div>'; html += '<div><label>Құпия сөз</label><input id="uPass" placeholder="Ағылшын әріптерімен"></div>';
html += '</div><div class="grid grid-2">';
html += '<div><label>Рөлі</label><select id="uRole"><option value="user">Қызметкер</option><option value="admin">Админ (комплаенс)</option></select></div>'; html += '<div><label>Рөлі</label><select id="uRole"><option value="user">Қызметкер</option><option value="admin">Админ (комплаенс)</option></select></div>';
html += '</div>'; html += '</div>';
html += '<button class="btn btn-primary" style="margin-top:14px" onclick="addUser()">Қосу</button>'; html += '<button class="btn btn-primary" style="margin-top:14px" onclick="addUser()">Қосу</button>';
@ -705,9 +746,10 @@ async function loadUsersList() {
if (!r.ok) return; if (!r.ok) return;
users = r.data; users = r.data;
} }
var html = '<div class="card"><table><thead><tr><th>Логин</th><th>Аты-жөні</th><th>Рөл</th><th>Құпия сөз</th><th></th></tr></thead><tbody>'; var html = '<div class="card"><table><thead><tr><th>Логин</th><th>Аты-жөні</th><th>Телефон</th><th>Рөл</th><th>Құпия сөз</th><th></th></tr></thead><tbody>';
users.forEach(function (u) { users.forEach(function (u) {
html += "<tr><td><b>" + esc(u.login) + "</b></td><td>" + esc(u.name) + "</td>"; html += "<tr><td><b>" + esc(u.login) + "</b></td><td>" + esc(u.name) + "</td>";
html += "<td>" + esc(u.phone || "") + "</td>";
html += '<td>' + (u.role === "admin" ? "Админ" : "Қызметкер") + "</td>"; html += '<td>' + (u.role === "admin" ? "Админ" : "Қызметкер") + "</td>";
html += '<td><span class="pass-row"><span class="pass-text">' + esc(u.password) + '</span>'; html += '<td><span class="pass-row"><span class="pass-text">' + esc(u.password) + '</span>';
html += '<button class="btn btn-sm btn-ghost" onclick="resetUserPass(\'' + esc(u.login) + '\')">Ауыстыру</button></span></td>'; html += '<button class="btn btn-sm btn-ghost" onclick="resetUserPass(\'' + esc(u.login) + '\')">Ауыстыру</button></span></td>';
@ -720,21 +762,23 @@ async function loadUsersList() {
async function addUser() { async function addUser() {
var login = document.getElementById("uLogin").value.trim(); var login = document.getElementById("uLogin").value.trim();
var name = document.getElementById("uName").value.trim(); var name = document.getElementById("uName").value.trim();
var phone = document.getElementById("uPhone").value.trim();
var pass = document.getElementById("uPass").value.trim(); var pass = document.getElementById("uPass").value.trim();
var role = document.getElementById("uRole").value; var role = document.getElementById("uRole").value;
var msg = document.getElementById("uMsg"); var msg = document.getElementById("uMsg");
if (!login || !name || !pass) { msg.innerHTML = '<div class="msg err">Барлық өрістерді толтырыңыз</div>'; return; } if (!login || !name || !pass) { msg.innerHTML = '<div class="msg err">Барлық өрістерді толтырыңыз</div>'; return; }
if (state.offline) { if (state.offline) {
MOCK_USERS.push({ login: login, name: name, password: pass, role: role }); MOCK_USERS.push({ login: login, name: name, phone: phone, password: pass, role: role });
msg.innerHTML = '<div class="msg ok">✅ Қосылды (демо)</div>'; msg.innerHTML = '<div class="msg ok">✅ Қосылды (демо)</div>';
loadUsersList(); loadUsersList();
return; return;
} }
var res = await apiPost("/api/users", { login: login, name: name, password: pass, role: role }); var res = await apiPost("/api/users", { login: login, name: name, phone: phone, password: pass, role: role });
if (res.ok) { if (res.ok) {
msg.innerHTML = '<div class="msg ok">✅ Қызметкер қосылды</div>'; msg.innerHTML = '<div class="msg ok">✅ Қызметкер қосылды</div>';
document.getElementById("uLogin").value = ""; document.getElementById("uLogin").value = "";
document.getElementById("uName").value = ""; document.getElementById("uName").value = "";
document.getElementById("uPhone").value = "";
document.getElementById("uPass").value = ""; document.getElementById("uPass").value = "";
loadUsersList(); loadUsersList();
} else msg.innerHTML = '<div class="msg err">' + esc(res.error || "Қате") + "</div>"; } else msg.innerHTML = '<div class="msg err">' + esc(res.error || "Қате") + "</div>";

View File

@ -75,11 +75,25 @@ http.createServer(async (req, res) => {
return send(res, 200, { ok: true, password: newPass, name: u.name }); return send(res, 200, { ok: true, password: newPass, name: u.name });
} }
// ---------- ТІРКЕЛУ ----------
if (req.method === "POST" && url === "/api/register") {
const b = await body(req);
if (!b.login || !b.name || !b.password) return send(res, 400, { ok: false, error: "Аты-жөні, логин және құпия сөз міндетті" });
const users = loadUsers();
if (users.find((x) => x.login === String(b.login))) return send(res, 400, { ok: false, error: "Мұндай логин бар, басқа нөмір жазыңыз" });
users.push({ login: String(b.login), password: String(b.password), name: String(b.name), phone: String(b.phone || ""), role: "user" });
saveUsers(users);
const token = crypto.randomBytes(24).toString("hex");
const nu = users[users.length - 1];
sessions.set(token, nu);
return send(res, 200, { ok: true, token, user: publicUser(nu) });
}
// ---------- АККАУНТТАРДЫ БАСҚАРУ (админ) ---------- // ---------- АККАУНТТАРДЫ БАСҚАРУ (админ) ----------
if (req.method === "GET" && url === "/api/users") { if (req.method === "GET" && url === "/api/users") {
if (user.role !== "admin") return send(res, 403, { ok: false, error: "Құқық жоқ" }); if (user.role !== "admin") return send(res, 403, { ok: false, error: "Құқық жоқ" });
return send(res, 200, { ok: true, data: loadUsers().map((x) => ({ return send(res, 200, { ok: true, data: loadUsers().map((x) => ({
login: x.login, name: x.name, role: x.role, password: x.password, login: x.login, name: x.name, role: x.role, password: x.password, phone: x.phone || "",
})) }); })) });
} }
@ -89,7 +103,7 @@ http.createServer(async (req, res) => {
if (!b.login || !b.name || !b.password) return send(res, 400, { ok: false, error: "Логин, аты-жөні және құпия сөз міндетті" }); if (!b.login || !b.name || !b.password) return send(res, 400, { ok: false, error: "Логин, аты-жөні және құпия сөз міндетті" });
const users = loadUsers(); const users = loadUsers();
if (users.find((x) => x.login === String(b.login))) return send(res, 400, { ok: false, error: "Мұндай логин бар" }); if (users.find((x) => x.login === String(b.login))) return send(res, 400, { ok: false, error: "Мұндай логин бар" });
users.push({ login: String(b.login), password: String(b.password), name: String(b.name), role: b.role === "admin" ? "admin" : "user" }); users.push({ login: String(b.login), password: String(b.password), name: String(b.name), phone: String(b.phone || ""), role: b.role === "admin" ? "admin" : "user" });
saveUsers(users); saveUsers(users);
return send(res, 200, { ok: true }); return send(res, 200, { ok: true });
} }

View File

@ -1,6 +1,6 @@
[ [
{ "login": "1001", "password": "Admin123", "name": "Асет (Комплаенс офицер)", "role": "admin" }, { "login": "1001", "password": "Admin123", "name": "Асет (Комплаенс офицер)", "phone": "+7 (777) 100-10-01", "role": "admin" },
{ "login": "2001", "password": "Worker123", "name": "Айгүл Серікқызы", "role": "user" }, { "login": "2001", "password": "Worker123", "name": "Айгүл Серікқызы", "phone": "+7 (777) 200-10-01", "role": "user" },
{ "login": "2002", "password": "Worker123", "name": "Бауыржан Нұрланұлы", "role": "user" }, { "login": "2002", "password": "Worker123", "name": "Бауыржан Нұрланұлы", "phone": "+7 (777) 200-10-02", "role": "user" },
{ "login": "2003", "password": "Worker123", "name": "Дана Қайратқызы", "role": "user" } { "login": "2003", "password": "Worker123", "name": "Дана Қайратқызы", "phone": "+7 (777) 200-10-03", "role": "user" }
] ]