fix CRM contacts

This commit is contained in:
root
2026-01-18 19:19:03 +03:00
parent 77f76c8c28
commit 308c684aa2
6 changed files with 122 additions and 655 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ document.addEventListener("DOMContentLoaded", function () {
const body = document.body;
// Базовая функция для получения base URL (объявляем ДО использования)
const baseUrl = '{{ base_url("/") }}'.replace(/\/+$/, '');
const baseUrl = '/'.replace(/\/+$/, '');
if (sidebarToggle) {
// Обработчик клика
+53 -26
View File
@@ -24,6 +24,16 @@ class ContactsManager {
this.loadContacts();
}
/**
* Получить заголовки запроса
*/
getHeaders() {
return {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
};
}
/**
* Загрузить список контактов
*/
@@ -31,9 +41,8 @@ class ContactsManager {
try {
const response = await fetch(`${this.apiUrl}/list/${this.clientId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'same-origin',
headers: this.getHeaders(),
body: JSON.stringify({})
});
@@ -106,6 +115,7 @@ class ContactsManager {
* Отобразить одну строку контакта
*/
renderRow(contact) {
const escapedId = this.escapeJs(contact.id);
return `
<tr data-id="${contact.id}" class="contact-row">
<td>
@@ -129,29 +139,27 @@ class ContactsManager {
value="${this.escapeHtml(contact.position || '')}" style="display: none;" placeholder="Должность">
</td>
<td class="text-end">
<div class="contact-actions">
<div class="btn-group contact-actions">
<button type="button" class="btn btn-outline-primary btn-sm"
onclick="contactsManager.edit(${contact.id})" title="Редактировать">
onclick="contactsManager.edit('${escapedId}')" title="Редактировать">
<i class="fa-solid fa-pen"></i>
</button>
<button type="button" class="btn btn-outline-danger btn-sm"
onclick="contactsManager.remove(${contact.id})" title="Удалить">
onclick="contactsManager.remove('${escapedId}')" title="Удалить">
<i class="fa-solid fa-trash"></i>
</button>
</div>
<div class="edit-actions" style="display: none;">
<div class="btn-group edit-actions" style="display: none;">
<button type="button" class="btn btn-outline-success btn-sm"
onclick="contactsManager.save(${contact.id})" title="Сохранить">
onclick="contactsManager.save('${escapedId}')" title="Сохранить">
<i class="fa-solid fa-check"></i>
</button>
<button type="button" class="btn btn-outline-secondary btn-sm"
onclick="contactsManager.cancel(${contact.id})" title="Отмена">
onclick="contactsManager.cancel('${escapedId}')" title="Отмена">
<i class="fa-solid fa-times"></i>
</button>
</div>
</td>
</tr>
`;
</td>`;
}
/**
@@ -225,18 +233,16 @@ class ContactsManager {
// Создание нового
response = await fetch(`${this.apiUrl}/store`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'same-origin',
headers: this.getHeaders(),
body: JSON.stringify(data)
});
} else {
// Обновление существующего
response = await fetch(`${this.apiUrl}/update/${contactId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'same-origin',
headers: this.getHeaders(),
body: JSON.stringify(data)
});
}
@@ -245,13 +251,15 @@ class ContactsManager {
if (result.success) {
// Обновляем локальный массив
const index = this.contacts.findIndex(c => c.id === contactId);
// contactId может быть строкой из data-id, а c.id - числом из БД
const contactIdStr = String(contactId);
const index = this.contacts.findIndex(c => String(c.id) === contactIdStr);
if (index !== -1) {
if (result.item) {
// Обновляем с реальным ID от сервера
this.contacts[index] = { ...data, id: result.item.id };
} else {
this.contacts[index] = data;
this.contacts[index] = { ...data, id: contactId };
}
}
@@ -270,9 +278,10 @@ class ContactsManager {
* Отменить редактирование
*/
cancel(contactId) {
if (contactId.toString().startsWith('new_')) {
const contactIdStr = String(contactId);
if (contactIdStr.startsWith('new_')) {
// Удаляем новую строку
this.contacts = this.contacts.filter(c => c.id !== contactId);
this.contacts = this.contacts.filter(c => String(c.id) !== contactIdStr);
this.render();
} else {
// Перезагружаем данные
@@ -291,16 +300,17 @@ class ContactsManager {
try {
const response = await fetch(`${this.apiUrl}/delete/${contactId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'same-origin',
headers: this.getHeaders(),
body: JSON.stringify({})
});
const result = await response.json();
if (result.success) {
this.contacts = this.contacts.filter(c => c.id !== contactId);
// contactId может быть строкой, а c.id - числом
const contactIdStr = String(contactId);
this.contacts = this.contacts.filter(c => String(c.id) !== contactIdStr);
this.render();
this.showSuccess(result.message || 'Контакт удалён');
} else {
@@ -361,6 +371,23 @@ class ContactsManager {
div.textContent = text;
return div.innerHTML;
}
/**
* Экранирование для JavaScript строки
*/
escapeJs(text) {
if (!text) return '';
// Приводим к строке, так как id может быть числом
const str = String(text);
return str
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(/"/g, '\\"')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/</g, '\\x3c')
.replace(/>/g, '\\x3e');
}
}
// Инициализация при загрузке страницы