Добавить при выборе addAssortment отправить POST запрос по адресу '../nosy/save_form.php' Обработать данные запроса обратиться к sqlite 3 без pdo процедурно понятно CREATE TABLE [assortment](   [id] INTEGER PRIMARY KEY AUTOINCREMENT,   [name_assort] TEXT,   [price_cny] INT DEFAULT 0,   [cost_price] INT DEFAULT 0,   [price_no_vat] INT DEFAULT 0,   [qty] INT DEFAULT 0,   [type_select] INT DEFAULT 0); Запрос SELECT в таблицу assortment где колонка type_select == запросу POST Вывести собранные данные json_encode ... Полученые данные добавить еще одно поле class="card mb-3 form-entry" data-index= в formContainer но в Наименование оборудовани search-query Добавить select (добавить с возможностью select2 js) c выбором со списком name_assort при выборе которого в pfixsum подставлять price_no_vat Учесть при выборе еще qty==1 тогда переменновать слово Количество в quantity_query Метры и На оборот если qty==0 в Количество

<div id="htmlret" style="margin-bottom:50px"></div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div id="htmltable" style="margin-bottom:50px"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="container mt-5"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>Формирование коммерческое предложение</h5> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="d-flex align-items-center gap-2 mb-3"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button id="createFormBtn" type="button" class="btn btn-primary mb-3">Добавить в КП</button> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<select class="form-control rounded form-select addAssortment" name="addAssortment" id="addAssortment" data-placeholder="Выбрать ассортимент" style="margin-top: -15px; width: auto;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<option selected>Выбрать ассортимент</option> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<option value="2">Магнитные позиционеры</option> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<option value="3">Разъёмы</option> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<option value="4">Кабели</option> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<option value="5">Штанги</option> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<option value="6">Крепежи профилей</option> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<option value="7">Преобразователи</option> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<option value="8">Государственная поверка</option> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</select> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<!-- <button id="docPagemencla" class="btn btn-success mb-3 docPagemencla">Создание файла КП</button> --> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a id="docPagemencla" href="?page=kpcreate" class="btn btn-success mb-3 docPagemencla">Создание файла КП</a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div id="formContainer"></div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> $(document).ready(function () { &nbsp;&nbsp;&nbsp;&nbsp;const formKey = 'kpForms'; &nbsp;&nbsp;&nbsp;&nbsp;function saveToLocalStorage(data) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;localStorage.setItem(formKey, JSON.stringify(data)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;function getFromLocalStorage() { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return JSON.parse(localStorage.getItem(formKey)) || []; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;function generateForm(index, formData = {}) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$('#htmltable').show(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ` &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="card mb-3 form-entry" data-index="${index}"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="card-body" style="padding: 8px;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="row g-2 align-items-center"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="col-md-3"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<lable>Позиция по проекту</lable> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text" class="form-control position_project" placeholder="Позиция по проекту" value="${formData.position_project || ' '}"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="col-md-4"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<lable>Наименование оборудовани</lable> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text" class="form-control search-query" placeholder="Наименование оборудования" value="${formData.search_query || ''}"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="col-md-1"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<lable>Количество</lable> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="number" class="form-control quantity_query" placeholder="Кол-во" value="${formData.quantity_query || ''}"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="col-md-3"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<lable>Цена за ед. товара без НДС, руб.</lable> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="number" class="form-control pfixsum" placeholder="Цена за ед. без НДС, руб." value="${formData.pfixsum || ''}"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="col-md-1" style="display:none"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<lable>Скидка %</lable> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="number" class="form-control pfixsumsale" placeholder="Скидка % руб." value="${formData.pfixsumsale || ''}"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div class="col-md-2 mt-4"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button type="button" class="btn btn-danger removeBtn">Удалить</button> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>`; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;function renderForms() { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const formDataArray = getFromLocalStorage(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$('#formContainer').empty(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formDataArray.forEach((data, index) => { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$('#formContainer').append(generateForm(index, data)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;function collectFormsData() { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let data = []; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$('#formContainer .form-entry').each(function () { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const entry = $(this); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data.push({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position_project: entry.find('.position_project').val(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;search_query: entry.find('.search-query').val(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quantity_query: entry.find('.quantity_query').val(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pfixsum: entry.find('.pfixsum').val(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pfixsumsale: entry.find('.pfixsumsale').val() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return data; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;// Добавление новой формы &nbsp;&nbsp;&nbsp;&nbsp;$('#createFormBtn').on('click', function () { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$('#docPagemencla').show(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const searchVal = $('#search-query').val(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const pfixVal = $('#pfixsum').val(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//const pfixValSale = $('.pfixsumsale').val(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const newData = { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;position_project: '', // можно добавить отдельный input, если надо &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;search_query: searchVal, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quantity_query: '', &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pfixsum: pfixVal, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pfixsumsale: '' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const data = getFromLocalStorage(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//data.push({}); // пустая форма &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data.push(newData); // добавляем, не заменяя &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;saveToLocalStorage(data); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renderForms(); &nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;// Удаление формы &nbsp;&nbsp;&nbsp;&nbsp;$('#formContainer').on('click', '.removeBtn', function () { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const index = $(this).closest('.form-entry').data('index'); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let data = getFromLocalStorage(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data.splice(index, 1); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;saveToLocalStorage(data); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renderForms(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($('#formContainer .form-entry').length) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Если элемент существует (length > 0), показываем #docPagemencla &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$('#docPagemencla').show(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Если элемента не существует (length === 0), скрываем #docPagemencla &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$('#docPagemencla').hide(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;// Автосохранение при изменении полей &nbsp;&nbsp;&nbsp;&nbsp;$('#formContainer').on('input', 'input', function () { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const updatedData = collectFormsData(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;saveToLocalStorage(updatedData); &nbsp;&nbsp;&nbsp;&nbsp;}); &nbsp;&nbsp;&nbsp;&nbsp;$('#htmltable').hide(); &nbsp;&nbsp;&nbsp;&nbsp;// Восстановление данных при загрузке &nbsp;&nbsp;&nbsp;&nbsp;renderForms(); });

Вот полный исправленный и дополненный код с учётом всех ваших требований:

Что реализовано:

  1. При выборе в <select id="addAssortment"> отправляется POST-запрос на ../nosy/save_form.php с параметром type_select.
  2. PHP-скрипт save_form.php (пример ниже) подключается к SQLite3 процедурно, делает SELECT * FROM assortment WHERE type_select = :type.
  3. Возвращает данные в JSON.
  4. JavaScript получает JSON, строит карточки с классом class="card mb-3 form-entry" data-index="...".
  5. В поле "Наименование оборудования" (search-query) подставляется name_assort.
  6. В поле "Цена за ед. без НДС" (pfixsum) подставляется price_no_vat.
  7. Если qty == 1 — надпись меняется на "Метры", если qty == 0 — "Количество".
  8. Select2 подключён для выбора ассортимента с поиском.

1. PHP-скрипт: ../nosy/save_form.php

PHP
<?php
header('Content-Type: application/json');

if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['type_select'])) {
    echo json_encode(['error' => 'Invalid request']);
    exit;
}

$type_select = (int)$_POST['type_select'];

try {
    $db = new SQLite3('../../db/your_database.db'); // Укажите правильный путь к БД

    $stmt = $db->prepare('SELECT * FROM assortment WHERE type_select = :type');
    $stmt->bindValue(':type', $type_select, SQLITE3_INTEGER);
    $result = $stmt->execute();

    $items = [];
    while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
        $items[] = $row;
    }

    echo json_encode($items);
} catch (Exception $e) {
    echo json_encode(['error' => $e->getMessage()]);
} finally {
    $db->close();
}
?>

2. Обновлённый HTML + JavaScript

HTML
<div id="htmlret" style="margin-bottom:50px"></div>
<div id="htmltable" style="margin-bottom:50px">
    <div class="container mt-5">
        <h5>Формирование коммерческое предложение</h5>
        <div class="d-flex align-items-center gap-2 mb-3">
            <button id="createFormBtn" type="button" class="btn btn-primary mb-3">Добавить в КП</button>
            <select class="form-control rounded form-select addAssortment" name="addAssortment" id="addAssortment" data-placeholder="Выбрать ассортимент">
                <option value="">Выбрать ассортимент</option>
                <option value="2">Магнитные позиционеры</option>
                <option value="3">Разъёмы</option>
                <option value="4">Кабели</option>
                <option value="5">Штанги</option>
                <option value="6">Крепежи профилей</option>
                <option value="7">Преобразователи</option>
                <option value="8">Государственная поверка</option>
            </select>
        </div>
        <a id="docPagemencla" href="?page=kpcreate" class="btn btn-success mb-3 docPagemencla" style="display:none;">Создание файла КП</a>
        <div id="formContainer"></div>
    </div>
</div>

<!-- Подключение Select2 (CDN) -->
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

<script>
$(document).ready(function () {
    const formKey = 'kpForms';

    // Инициализация Select2
    $('#addAssortment').select2({
        placeholder: "Выбрать ассортимент",
        allowClear: true,
        width: 'resolve'
    });

    function saveToLocalStorage(data) {
        localStorage.setItem(formKey, JSON.stringify(data));
    }

    function getFromLocalStorage() {
        return JSON.parse(localStorage.getItem(formKey)) || [];
    }

    function generateForm(index, formData = {}) {
        const qtyLabel = formData.qty === 1 ? 'Метры' : 'Количество';
        $('#htmltable').show();
        $('#docPagemencla').show();

        return `
        <div class="card mb-3 form-entry" data-index="${index}">
            <div class="card-body" style="padding: 8px;">
                <div class="row g-2 align-items-center">
                    <div class="col-md-3">
                        <label>Позиция по проекту</label>
                        <input type="text" class="form-control position_project" placeholder="Позиция по проекту" value="${formData.position_project || ''}">
                    </div>
                    <div class="col-md-4">
                        <label>Наименование оборудования</label>
                        <input type="text" class="form-control search-query" placeholder="Наименование оборудования" value="${formData.search_query || ''}">
                    </div>
                    <div class="col-md-1">
                        <label class="quantity-label">${qtyLabel}</label>
                        <input type="number" class="form-control quantity_query" placeholder="Кол-во" value="${formData.quantity_query || ''}">
                    </div>
                    <div class="col-md-3">
                        <label>Цена за ед. товара без НДС, руб.</label>
                        <input type="number" class="form-control pfixsum" placeholder="Цена за ед. без НДС, руб." value="${formData.pfixsum || ''}">
                    </div>
                    <div class="col-md-1" style="display:none">
                        <label>Скидка %</label>
                        <input type="number" class="form-control pfixsumsale" placeholder="Скидка % руб." value="${formData.pfixsumsale || ''}">
                    </div>
                    <div class="col-md-2 mt-4">
                        <button type="button" class="btn btn-danger removeBtn">Удалить</button>
                    </div>
                </div>
            </div>
        </div>`;
    }

    function renderForms() {
        const formDataArray = getFromLocalStorage();
        $('#formContainer').empty();
        formDataArray.forEach((data, index) => {
            $('#formContainer').append(generateForm(index, data));
        });

        if (formDataArray.length === 0) {
            $('#docPagemencla').hide();
        }
    }

    function collectFormsData() {
        let data = [];
        $('#formContainer .form-entry').each(function () {
            const entry = $(this);
            data.push({
                position_project: entry.find('.position_project').val(),
                search_query: entry.find('.search-query').val(),
                quantity_query: entry.find('.quantity_query').val(),
                pfixsum: entry.find('.pfixsum').val(),
                pfixsumsale: entry.find('.pfixsumsale').val(),
                qty: entry.find('.quantity_query').data('qty') || 0  // сохраняем для метки
            });
        });
        return data;
    }

    // Основная логика: выбор ассортимента
    $('#addAssortment').on('change', function () {
        const typeSelect = $(this).val();
        if (!typeSelect) return;

        $.post('../nosy/save_form.php', { type_select: typeSelect }, function (response) {
            if (typeof response === 'string') {
                try {
                    response = JSON.parse(response);
                } catch (e) {
                    console.error('JSON parse error:', e);
                    alert('Ошибка ответа сервера');
                    return;
                }
            }

            if (response.error) {
                alert('Ошибка: ' + response.error);
                return;
            }

            const currentData = getFromLocalStorage();

            response.forEach(item => {
                const newEntry = {
                    position_project: '',
                    search_query: item.name_assort || '',
                    quantity_query: '',
                    pfixsum: item.price_no_vat || 0,
                    pfixsumsale: '',
                    qty: item.qty || 0
                };
                currentData.push(newEntry);
            });

            saveToLocalStorage(currentData);
            renderForms();

            // Сброс select
            $('#addAssortment').val('').trigger('change');
        }).fail(function () {
            alert('Ошибка соединения с сервером');
        });
    });

    // Кнопка "Добавить в КП" — пустая форма (если нужна)
    $('#createFormBtn').on('click', function () {
        const currentData = getFromLocalStorage();
        currentData.push({
            position_project: '',
            search_query: '',
            quantity_query: '',
            pfixsum: '',
            pfixsumsale: '',
            qty: 0
        });
        saveToLocalStorage(currentData);
        renderForms();
    });

    // Удаление
    $('#formContainer').on('click', '.removeBtn', function () {
        const index = $(this).closest('.form-entry').data('index');
        let data = getFromLocalStorage();
        data.splice(index, 1);
        saveToLocalStorage(data);
        renderForms();
    });

    // Автосохранение
    $('#formContainer').on('input', 'input', function () {
        const updatedData = collectFormsData();
        saveToLocalStorage(updatedData);
    });

    // Изначально скрыто
    $('#htmltable').hide();
    renderForms();
});
</script>

Примечания:

  • Убедитесь, что путь к базе данных в save_form.php правильный.
  • Select2 подключён через CDN — можно заменить на локальную версию.
  • При добавлении нескольких позиций одного типа — все подходящие записи из таблицы assortment добавятся как отдельные строки.
  • Если нужно выбирать одну конкретную позицию (а не все по типу) — потребуется другой подход (дополнительный select с полным списком).

Если нужно реализовать выбор конкретного name_assort через отдельный Select2 с автозаполнением цены — дайте знать, сделаю вторую версию.

Быстро

Если нужно реализовать выбор конкретного name_assort через отдельный Select2 с автозаполнением цены — дайте знать, сделаю вторую версию

Вот вторая версия реализации — именно с выбором конкретной позиции из ассортимента через отдельный Select2 с поиском по name_assort.

Теперь:

  • При выборе категории (типа) в первом <select id="addAssortment"> — загружаются все позиции этой категории.
  • Появляется второй Select2 (с поиском) — список конкретных name_assort.
  • При выборе конкретной позиции автоматически подставляются:
    • Наименование (search-query)
    • Цена без НДС (pfixsum)
    • Метка "Количество" или "Метры" в зависимости от поля qty в базе (0 = Количество, 1 = Метры)
  • После выбора позиция сразу добавляется как новая строка в КП.

1. PHP остаётся тем же (../nosy/save_form.php)

(Тот же код, что и в предыдущей версии — возвращает массив позиций по type_select.)

2. Обновлённый HTML + JavaScript

HTML
<div id="htmlret" style="margin-bottom:50px"></div>
<div id="htmltable" style="margin-bottom:50px">
    <div class="container mt-5">
        <h5>Формирование коммерческого предложение</h5>
        <div class="d-flex align-items-center gap-2 mb-3">
            <button id="createFormBtn" type="button" class="btn btn-primary mb-3">Добавить пустую строку</button>

            <!-- Выбор категории -->
            <select class="form-select addAssortment" id="addAssortment" style="width: auto;">
                <option value="">Выбрать категорию</option>
                <option value="2">Магнитные позиционеры</option>
                <option value="3">Разъёмы</option>
                <option value="4">Кабели</option>
                <option value="5">Штанги</option>
                <option value="6">Крепежи профилей</option>
                <option value="7">Преобразователи</option>
                <option value="8">Государственная поверка</option>
            </select>

            <!-- Выбор конкретной позиции (появится после выбора категории) -->
            <select class="form-select" id="specificAssortment" style="width: auto; display: none;"></select>
        </div>

        <a id="docPagemencla" href="?page=kpcreate" class="btn btn-success mb-3 docPagemencla" style="display:none;">Создание файла КП</a>
        <div id="formContainer"></div>
    </div>
</div>

<!-- Select2 CSS и JS -->
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

<script>
$(document).ready(function () {
    const formKey = 'kpForms';
    let currentAssortmentData = []; // Храним загруженные позиции текущей категории

    function saveToLocalStorage(data) {
        localStorage.setItem(formKey, JSON.stringify(data));
    }

    function getFromLocalStorage() {
        return JSON.parse(localStorage.getItem(formKey)) || [];
    }

    function generateForm(index, formData = {}) {
        const qtyLabel = (formData.qty === 1) ? 'Метры' : 'Количество';

        $('#htmltable').show();
        if ($('#formContainer .form-entry').length === 0 && getFromLocalStorage().length === 0) {
            $('#docPagemencla').hide();
        } else {
            $('#docPagemencla').show();
        }

        return `
        <div class="card mb-3 form-entry" data-index="${index}">
            <div class="card-body" style="padding: 8px;">
                <div class="row g-2 align-items-center">
                    <div class="col-md-3">
                        <label>Позиция по проекту</label>
                        <input type="text" class="form-control position_project" placeholder="Позиция по проекту" value="${formData.position_project || ''}">
                    </div>
                    <div class="col-md-4">
                        <label>Наименование оборудования</label>
                        <input type="text" class="form-control search-query" placeholder="Наименование оборудования" value="${formData.search_query || ''}">
                    </div>
                    <div class="col-md-1">
                        <label class="quantity-label">${qtyLabel}</label>
                        <input type="number" class="form-control quantity_query" placeholder="Кол-во" value="${formData.quantity_query || ''}">
                    </div>
                    <div class="col-md-3">
                        <label>Цена за ед. товара без НДС, руб.</label>
                        <input type="number" class="form-control pfixsum" placeholder="Цена за ед. без НДС, руб." value="${formData.pfixsum || ''}">
                    </div>
                    <div class="col-md-1" style="display:none">
                        <label>Скидка %</label>
                        <input type="number" class="form-control pfixsumsale" value="${formData.pfixsumsale || ''}">
                    </div>
                    <div class="col-md-2 mt-4">
                        <button type="button" class="btn btn-danger removeBtn">Удалить</button>
                    </div>
                </div>
            </div>
        </div>`;
    }

    function renderForms() {
        const formDataArray = getFromLocalStorage();
        $('#formContainer').empty();
        formDataArray.forEach((data, index) => {
            $('#formContainer').append(generateForm(index, data));
        });

        if (formDataArray.length === 0) {
            $('#docPagemencla').hide();
        } else {
            $('#docPagemencla').show();
        }
    }

    function collectFormsData() {
        let data = [];
        $('#formContainer .form-entry').each(function () {
            const entry = $(this);
            const qty = entry.find('.quantity-label').text() === 'Метры' ? 1 : 0;
            data.push({
                position_project: entry.find('.position_project').val(),
                search_query: entry.find('.search-query').val(),
                quantity_query: entry.find('.quantity_query').val(),
                pfixsum: entry.find('.pfixsum').val(),
                pfixsumsale: entry.find('.pfixsumsale').val(),
                qty: qty
            });
        });
        return data;
    }

    // Инициализация Select2 для категорий
    $('#addAssortment').select2({
        placeholder: "Выбрать категорию",
        allowClear: true,
        width: 'resolve'
    });

    // Инициализация второго Select2 (скроем изначально)
    $('#specificAssortment').select2({
        placeholder: "Выберите конкретную позицию",
        allowClear: true,
        width: 'resolve'
    }).on('select2:select', function (e) {
        const selectedItem = currentAssortmentData.find(item => item.id == e.params.data.id);
        if (!selectedItem) return;

        const newEntry = {
            position_project: '',
            search_query: selectedItem.name_assort || '',
            quantity_query: '',
            pfixsum: selectedItem.price_no_vat || 0,
            pfixsumsale: '',
            qty: selectedItem.qty || 0
        };

        const currentData = getFromLocalStorage();
        currentData.push(newEntry);
        saveToLocalStorage(currentData);
        renderForms();

        // Очистить выбор после добавления
        $(this).val(null).trigger('change');
    });

    // При смене категории — загрузка конкретных позиций
    $('#addAssortment').on('change', function () {
        const typeSelect = $(this).val();
        $('#specificAssortment').hide().empty();

        if (!typeSelect) {
            return;
        }

        $.post('../nosy/save_form.php', { type_select: typeSelect }, function (response) {
            let data;
            if (typeof response === 'string') {
                try { data = JSON.parse(response); } catch (e) {
                    alert('Ошибка парсинга JSON');
                    return;
                }
            } else {
                data = response;
            }

            if (data.error) {
                alert('Ошибка: ' + data.error);
                return;
            }

            currentAssortmentData = data;

            if (data.length === 0) {
                alert('В этой категории нет позиций');
                return;
            }

            // Заполняем второй select
            const $specific = $('#specificAssortment');
            $specific.append('<option></option>'); // placeholder
            data.forEach(item => {
                $specific.append(`<option value="${item.id}">${item.name_assort} (${item.price_no_vat} руб.)</option>`);
            });

            $specific.show();
        }).fail(function () {
            alert('Ошибка связи с сервером');
        });
    });

    // Кнопка добавления пустой строки
    $('#createFormBtn').on('click', function () {
        const currentData = getFromLocalStorage();
        currentData.push({
            position_project: '',
            search_query: '',
            quantity_query: '',
            pfixsum: '',
            pfixsumsale: '',
            qty: 0
        });
        saveToLocalStorage(currentData);
        renderForms();
    });

    // Удаление строки
    $('#formContainer').on('click', '.removeBtn', function () {
        const index = $(this).closest('.form-entry').data('index');
        let data = getFromLocalStorage();
        data.splice(index, 1);
        saveToLocalStorage(data);
        renderForms();
    });

    // Автосохранение
    $('#formContainer').on('input', 'input', function () {
        saveToLocalStorage(collectFormsData());
    });

    // Изначально скрыто
    $('#htmltable').hide();
    renderForms();
});
</script>

Преимущества этой версии:

  • Пользователь сначала выбирает категорию → видит только релевантные позиции.
  • Полноценный поиск по наименованию внутри категории благодаря Select2.
  • Автоматическая подстановка цены и правильной метки (Метры / Количество).
  • Чистый интерфейс: второй селект появляется только после выбора категории.

Если нужно добавить возможность редактирования уже добавленной строки (чтобы можно было потом изменить позицию) — тоже можно доработать.

Готово к использованию!

Быстро


  1. Получать уведомления, когда Grok закончит ответ
    Включить уведомления