feat: новая функция
This commit is contained in:
@@ -38,7 +38,7 @@ BEGIN
|
||||
|
||||
-- Загружаем данные во временную таблицу
|
||||
COPY tmp_isic_level_names (code_level_tmp, level_name_en_tmp)
|
||||
FROM '/app/db/data/isic_level_names.csv'
|
||||
FROM '/mnt/isic_csv_data/isic_level_names.csv'
|
||||
WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', QUOTE '"');
|
||||
|
||||
-- Вставляем данные в основную таблицу
|
||||
@@ -74,11 +74,11 @@ BEGIN
|
||||
|
||||
-- Загружаем данные во временные таблицы
|
||||
COPY tmp_isic_titles (sort_order_tmp, code_tmp, description_tmp, inclusion_tmp, exclusion_tmp)
|
||||
FROM '/app/db/data/isic_titles.csv'
|
||||
FROM '/mnt/isic_csv_data/isic_titles.csv'
|
||||
WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', QUOTE '"');
|
||||
|
||||
COPY tmp_isic_structure (sort_order_tmp, code_tmp, code_level_tmp, level1_tmp, level2_tmp, level3_tmp, level4_tmp, level5_tmp, level6_tmp)
|
||||
FROM '/app/db/data/isic_structure.csv'
|
||||
FROM '/mnt/isic_csv_data/isic_structure.csv'
|
||||
WITH (FORMAT CSV, HEADER TRUE, DELIMITER ',', QUOTE '"');
|
||||
|
||||
-- Переносим и объединяем данные из временных таблиц в основную таблицу isic_rev4_codes
|
||||
|
||||
@@ -91,7 +91,7 @@ router.get('/codes', async (req, res) => {
|
||||
|
||||
const baseQuerySelect = `
|
||||
SELECT c.code, c.description, c.code_level, c.explanatory_note_inclusion, c.explanatory_note_exclusion,
|
||||
l.level_name_en,
|
||||
l.level_name_en_encrypted as level_name_en,
|
||||
c.level1, c.level2, c.level3, c.level4, c.level5, c.level6
|
||||
FROM isic_rev4_codes c
|
||||
LEFT JOIN isic_rev4_level_names l ON c.code_level = l.code_level
|
||||
|
||||
@@ -273,10 +273,11 @@ onMounted(() => {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: calc(100% - 350px);
|
||||
padding: 0 20px;
|
||||
padding: 0 20px 20px 20px; /* Уменьшаем отступ снизу */
|
||||
background-color: var(--color-white);
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
min-height: 100vh; /* Изменяем на min-height для возможности прокрутки */
|
||||
overflow-y: auto; /* Разрешаем вертикальную прокрутку */
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.main-content.no-right-sidebar {
|
||||
@@ -293,18 +294,7 @@ onMounted(() => {
|
||||
@media (max-width: 768px) {
|
||||
.main-content {
|
||||
max-width: 100%;
|
||||
padding-bottom: 20px; /* Убираем большой отступ, так как панель теперь полноэкранная */
|
||||
}
|
||||
|
||||
.main-content.no-right-sidebar {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.main-content {
|
||||
padding: 0 10px;
|
||||
padding-bottom: 10px; /* Убираем большой отступ */
|
||||
padding-bottom: 10px; /* Уменьшаем отступ для мобильных устройств */
|
||||
}
|
||||
|
||||
.main-content.no-right-sidebar {
|
||||
@@ -312,5 +302,16 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.main-content {
|
||||
padding: 0 10px;
|
||||
padding-bottom: 5px; /* Минимальный отступ для очень маленьких экранов */
|
||||
}
|
||||
|
||||
.main-content.no-right-sidebar {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -583,6 +583,8 @@ async function handleAiReply() {
|
||||
transition: all var(--transition-normal);
|
||||
z-index: 10;
|
||||
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.05);
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.chat-input textarea {
|
||||
@@ -769,7 +771,8 @@ async function handleAiReply() {
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.chat-input {
|
||||
position: static !important;
|
||||
position: sticky !important;
|
||||
bottom: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
padding: 8px 12px !important;
|
||||
background: #f8f8f8 !important;
|
||||
@@ -783,7 +786,8 @@ async function handleAiReply() {
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.chat-input {
|
||||
position: static !important;
|
||||
position: sticky !important;
|
||||
bottom: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
padding: 8px 12px !important;
|
||||
background: #f8f8f8 !important;
|
||||
|
||||
@@ -77,7 +77,10 @@ const pageTitle = computed(() => {
|
||||
return 'Создать новое DLE (Digital Legal Entity)';
|
||||
}
|
||||
if (route.name === 'settings-dle-v2-deploy') {
|
||||
return 'Создать современное DLE v2 (Digital Legal Entity)';
|
||||
return 'Деплой контракта DLE (Digital Legal Entity)';
|
||||
}
|
||||
if (route.name === 'settings-security') {
|
||||
return ''; // Убираем заголовок для страницы безопасности, так как он есть внутри компонента
|
||||
}
|
||||
return 'Настройки';
|
||||
});
|
||||
@@ -119,7 +122,8 @@ onBeforeUnmount(() => {
|
||||
border-radius: var(--block-radius);
|
||||
box-shadow: var(--shadow-md);
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 20px; /* Уменьшаем отступ, так как он уже есть в BaseLayout */
|
||||
min-height: auto; /* Убираем фиксированную высоту */
|
||||
}
|
||||
|
||||
/* Заголовки */
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Российские классификаторы (отображается только для России) -->
|
||||
<div v-if="dleSettings.jurisdiction === '643'">
|
||||
<!-- Классификаторы видов деятельности -->
|
||||
<div v-if="dleSettings.jurisdiction">
|
||||
<div v-if="isLoadingRussianClassifiers" class="loading-section">
|
||||
<p><i class="fas fa-spinner fa-spin"></i> Загрузка российских классификаторов...</p>
|
||||
</div>
|
||||
@@ -196,12 +196,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ОКВЭД - Виды экономической деятельности -->
|
||||
<!-- Виды экономической деятельности -->
|
||||
<div class="form-group okved-section">
|
||||
<label class="form-label okved-title">ОКВЭД (виды экономической деятельности):</label>
|
||||
<label class="form-label okved-title">
|
||||
{{ dleSettings.jurisdiction === '643' ? 'ОКВЭД (виды экономической деятельности)' : 'ISIC (виды экономической деятельности)' }}:
|
||||
</label>
|
||||
|
||||
<!-- Простой 2-уровневый выбор ОКВЭД -->
|
||||
<div class="okved-cascade">
|
||||
<!-- Форма для России (ОКВЭД) -->
|
||||
<div v-if="dleSettings.jurisdiction === '643'" class="okved-cascade">
|
||||
<!-- Уровень 1: Класс (01.11, 01.12...) -->
|
||||
<div class="form-group">
|
||||
<label class="form-label-small">Выберите класс деятельности:</label>
|
||||
@@ -241,6 +243,77 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Форма для других стран (ISIC) -->
|
||||
<div v-else class="isic-cascade">
|
||||
<!-- Уровень 1: Раздел (A, B, C...) -->
|
||||
<div class="form-group">
|
||||
<label class="form-label-small">Выберите раздел деятельности:</label>
|
||||
<select v-model="selectedIsicLevel1" class="form-control" :disabled="isLoadingIsicLevel1">
|
||||
<option value="">-- {{ isLoadingIsicLevel1 ? 'Загрузка разделов...' : 'Выберите раздел' }} --</option>
|
||||
<option
|
||||
v-for="option in isicLevel1Options"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
{{ option.text }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Уровень 2: Группа (01, 02, 03...) -->
|
||||
<div class="form-group" v-if="selectedIsicLevel1">
|
||||
<label class="form-label-small">Выберите группу деятельности:</label>
|
||||
<select v-model="selectedIsicLevel2" class="form-control" :disabled="isLoadingIsicLevel2">
|
||||
<option value="">-- {{ isLoadingIsicLevel2 ? 'Загрузка групп...' : 'Выберите группу' }} --</option>
|
||||
<option
|
||||
v-for="option in isicLevel2Options"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
{{ option.text }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Уровень 3: Класс (011, 012, 013...) -->
|
||||
<div class="form-group" v-if="selectedIsicLevel2">
|
||||
<label class="form-label-small">Выберите класс деятельности:</label>
|
||||
<select v-model="selectedIsicLevel3" class="form-control" :disabled="isLoadingIsicLevel3">
|
||||
<option value="">-- {{ isLoadingIsicLevel3 ? 'Загрузка классов...' : 'Выберите класс' }} --</option>
|
||||
<option
|
||||
v-for="option in isicLevel3Options"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
{{ option.text }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Уровень 4: Подкласс (0111, 0112, 0113...) -->
|
||||
<div class="form-group" v-if="selectedIsicLevel3">
|
||||
<label class="form-label-small">Выберите подкласс деятельности:</label>
|
||||
<select v-model="selectedIsicLevel4" class="form-control" :disabled="isLoadingIsicLevel4">
|
||||
<option value="">-- {{ isLoadingIsicLevel4 ? 'Загрузка подклассов...' : 'Выберите подкласс' }} --</option>
|
||||
<option
|
||||
v-for="option in isicLevel4Options"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
{{ option.text }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Выбранный код ISIC -->
|
||||
<div v-if="currentSelectedIsicText" class="current-isic-selection">
|
||||
<p><strong>Выбранный код:</strong> {{ currentSelectedIsicText }}</p>
|
||||
<button @click="addIsicCode" class="btn btn-success btn-sm" :disabled="!currentSelectedIsicCode">
|
||||
Добавить код деятельности
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Основной код ОКВЭД (оставляем для совместимости) -->
|
||||
<div class="okved-main" style="display: none;">
|
||||
<select v-model="dleSettings.mainOkvedCode" class="form-control">
|
||||
@@ -1117,17 +1190,29 @@ const autoSelectedOktmoInfo = computed(() => {
|
||||
return russianClassifiers.oktmo.find(oktmo => oktmo.code === dleSettings.selectedOktmo);
|
||||
});
|
||||
|
||||
// ===== КАСКАДНАЯ СИСТЕМА ОКВЭД =====
|
||||
// ===== КАСКАДНАЯ СИСТЕМА КЛАССИФИКАТОРОВ =====
|
||||
|
||||
// Состояние для загрузки и опций ОКВЭД
|
||||
// Состояние для загрузки и опций ОКВЭД/ISIC
|
||||
const okvedLevel1Options = ref([]);
|
||||
const okvedLevel2Options = ref([]);
|
||||
const okvedLevel3Options = ref([]);
|
||||
|
||||
// Состояние для загрузки ISIC кодов
|
||||
const isicLevel1Options = ref([]);
|
||||
const isicLevel2Options = ref([]);
|
||||
const isicLevel3Options = ref([]);
|
||||
const isicLevel4Options = ref([]);
|
||||
const okvedLevel4Options = ref([]);
|
||||
|
||||
const isLoadingOkvedLevel1 = ref(false);
|
||||
const isLoadingOkvedLevel2 = ref(false);
|
||||
const isLoadingOkvedLevel3 = ref(false);
|
||||
|
||||
// Состояние загрузки ISIC
|
||||
const isLoadingIsicLevel1 = ref(false);
|
||||
const isLoadingIsicLevel2 = ref(false);
|
||||
const isLoadingIsicLevel3 = ref(false);
|
||||
const isLoadingIsicLevel4 = ref(false);
|
||||
const isLoadingOkvedLevel4 = ref(false);
|
||||
|
||||
// Состояние для КПП кодов
|
||||
@@ -1140,10 +1225,20 @@ const selectedOkvedLevel2 = ref('');
|
||||
const selectedOkvedLevel3 = ref('');
|
||||
const selectedOkvedLevel4 = ref('');
|
||||
|
||||
// Выбранные значения на каждом уровне ISIC
|
||||
const selectedIsicLevel1 = ref('');
|
||||
const selectedIsicLevel2 = ref('');
|
||||
const selectedIsicLevel3 = ref('');
|
||||
const selectedIsicLevel4 = ref('');
|
||||
|
||||
// Текущий выбранный код ОКВЭД
|
||||
const currentSelectedOkvedCode = ref('');
|
||||
const currentSelectedOkvedText = ref('');
|
||||
|
||||
// Текущий выбранный код ISIC
|
||||
const currentSelectedIsicCode = ref('');
|
||||
const currentSelectedIsicText = ref('');
|
||||
|
||||
|
||||
// Функция определения уровня ОКВЭД кода
|
||||
const getOkvedLevel = (code) => {
|
||||
@@ -1156,6 +1251,42 @@ const getOkvedLevel = (code) => {
|
||||
return parts.length + 1; // для более глубоких уровней
|
||||
};
|
||||
|
||||
// Функция для загрузки ISIC кодов определенного уровня
|
||||
const fetchIsicCodes = async (level, parentCode, optionsRef, loadingRef) => {
|
||||
loadingRef.value = true;
|
||||
optionsRef.value = [];
|
||||
|
||||
try {
|
||||
console.log(`[DleDeployForm] Загрузка ISIC уровень ${level}, родитель: ${parentCode || 'root'}`);
|
||||
|
||||
const params = {
|
||||
level: level,
|
||||
limit: 1000 // Увеличиваем лимит для получения всех кодов
|
||||
};
|
||||
|
||||
if (parentCode) {
|
||||
params.parent_code = parentCode;
|
||||
}
|
||||
|
||||
const response = await api.get('/isic/codes', { params });
|
||||
|
||||
if (response.data && response.data.codes) {
|
||||
optionsRef.value = response.data.codes.map(code => ({
|
||||
value: code.code,
|
||||
text: `${code.code} - ${code.description}`
|
||||
}));
|
||||
|
||||
console.log(`[DleDeployForm] Загружено ISIC кодов уровня ${level}: ${optionsRef.value.length}`);
|
||||
} else {
|
||||
console.error('[DleDeployForm] Ошибка ответа API ISIC:', response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[DleDeployForm] Ошибка при загрузке ISIC кодов:', error);
|
||||
} finally {
|
||||
loadingRef.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Функция для загрузки ОКВЭД кодов определенного уровня
|
||||
const fetchOkvedCodes = async (level, parentCode, optionsRef, loadingRef) => {
|
||||
// console.log(`🔍 fetchOkvedCodes вызвана: level=${level}, parentCode=${parentCode || 'root'}`);
|
||||
@@ -1204,6 +1335,45 @@ const fetchOkvedCodes = async (level, parentCode, optionsRef, loadingRef) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Функция для обновления текущего выбранного кода ISIC
|
||||
const updateCurrentIsicSelection = () => {
|
||||
let code = '';
|
||||
let text = '';
|
||||
let optionsToSearch = [];
|
||||
let valueToFind = '';
|
||||
|
||||
// Приоритет: сначала подкласс, потом класс, потом группа, потом раздел
|
||||
if (selectedIsicLevel4.value) {
|
||||
code = selectedIsicLevel4.value;
|
||||
optionsToSearch = isicLevel4Options.value;
|
||||
valueToFind = selectedIsicLevel4.value;
|
||||
} else if (selectedIsicLevel3.value) {
|
||||
code = selectedIsicLevel3.value;
|
||||
optionsToSearch = isicLevel3Options.value;
|
||||
valueToFind = selectedIsicLevel3.value;
|
||||
} else if (selectedIsicLevel2.value) {
|
||||
code = selectedIsicLevel2.value;
|
||||
optionsToSearch = isicLevel2Options.value;
|
||||
valueToFind = selectedIsicLevel2.value;
|
||||
} else if (selectedIsicLevel1.value) {
|
||||
code = selectedIsicLevel1.value;
|
||||
optionsToSearch = isicLevel1Options.value;
|
||||
valueToFind = selectedIsicLevel1.value;
|
||||
}
|
||||
|
||||
if (code && optionsToSearch.length > 0 && valueToFind) {
|
||||
const foundOption = optionsToSearch.find(opt => opt.value === valueToFind);
|
||||
if (foundOption) {
|
||||
text = foundOption.text;
|
||||
} else {
|
||||
text = code;
|
||||
}
|
||||
}
|
||||
|
||||
currentSelectedIsicCode.value = code;
|
||||
currentSelectedIsicText.value = text;
|
||||
};
|
||||
|
||||
// Функция для обновления текущего выбранного кода ОКВЭД
|
||||
const updateCurrentOkvedSelection = () => {
|
||||
let code = '';
|
||||
@@ -1250,6 +1420,69 @@ watch(selectedOkvedLevel2, () => {
|
||||
updateCurrentOkvedSelection();
|
||||
});
|
||||
|
||||
// Watchers для ISIC
|
||||
watch(selectedIsicLevel1, (newVal) => {
|
||||
selectedIsicLevel2.value = '';
|
||||
selectedIsicLevel3.value = '';
|
||||
selectedIsicLevel4.value = '';
|
||||
if (newVal) {
|
||||
fetchIsicCodes(2, newVal, isicLevel2Options, isLoadingIsicLevel2);
|
||||
} else {
|
||||
isicLevel2Options.value = [];
|
||||
isicLevel3Options.value = [];
|
||||
isicLevel4Options.value = [];
|
||||
}
|
||||
updateCurrentIsicSelection();
|
||||
});
|
||||
|
||||
watch(selectedIsicLevel2, (newVal) => {
|
||||
selectedIsicLevel3.value = '';
|
||||
selectedIsicLevel4.value = '';
|
||||
if (newVal) {
|
||||
fetchIsicCodes(3, newVal, isicLevel3Options, isLoadingIsicLevel3);
|
||||
} else {
|
||||
isicLevel3Options.value = [];
|
||||
isicLevel4Options.value = [];
|
||||
}
|
||||
updateCurrentIsicSelection();
|
||||
});
|
||||
|
||||
watch(selectedIsicLevel3, (newVal) => {
|
||||
selectedIsicLevel4.value = '';
|
||||
if (newVal) {
|
||||
fetchIsicCodes(4, newVal, isicLevel4Options, isLoadingIsicLevel4);
|
||||
} else {
|
||||
isicLevel4Options.value = [];
|
||||
}
|
||||
updateCurrentIsicSelection();
|
||||
});
|
||||
|
||||
watch(selectedIsicLevel4, () => {
|
||||
updateCurrentIsicSelection();
|
||||
});
|
||||
|
||||
// Функция добавления выбранного ISIC кода в список
|
||||
const addIsicCode = () => {
|
||||
if (currentSelectedIsicCode.value && currentSelectedIsicText.value) {
|
||||
const alreadyExists = dleSettings.selectedOkved.find(c => c === currentSelectedIsicCode.value);
|
||||
if (!alreadyExists) {
|
||||
dleSettings.selectedOkved.push(currentSelectedIsicCode.value);
|
||||
dleSettings.mainOkvedCode = currentSelectedIsicCode.value; // Обновляем основной код
|
||||
|
||||
// Сбрасываем селекторы для выбора следующего кода
|
||||
selectedIsicLevel1.value = '';
|
||||
selectedIsicLevel2.value = '';
|
||||
selectedIsicLevel3.value = '';
|
||||
selectedIsicLevel4.value = '';
|
||||
// Остальные опции сбросятся через watchers
|
||||
} else {
|
||||
alert('Этот код уже добавлен.');
|
||||
}
|
||||
} else {
|
||||
alert('Код не выбран полностью.');
|
||||
}
|
||||
};
|
||||
|
||||
// Функция добавления выбранного ОКВЭД кода в список
|
||||
const addOkvedCode = () => {
|
||||
if (currentSelectedOkvedCode.value && currentSelectedOkvedText.value) {
|
||||
@@ -1940,7 +2173,59 @@ const loadCountries = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// Функция загрузки российских классификаторов
|
||||
// Функция загрузки классификаторов в зависимости от выбранной страны
|
||||
const loadClassifiers = async () => {
|
||||
isLoadingRussianClassifiers.value = true;
|
||||
try {
|
||||
if (dleSettings.jurisdiction === '643') {
|
||||
// Для России загружаем российские классификаторы
|
||||
console.log('Загружаем российские классификаторы...');
|
||||
|
||||
const response = await api.get('/russian-classifiers/all');
|
||||
|
||||
if (response.data && response.data.success) {
|
||||
const data = response.data.data;
|
||||
russianClassifiers.oktmo = data.oktmo || [];
|
||||
russianClassifiers.okved = data.okved || [];
|
||||
|
||||
console.log('Российские классификаторы загружены:', {
|
||||
oktmo: russianClassifiers.oktmo.length,
|
||||
okved: russianClassifiers.okved.length
|
||||
});
|
||||
|
||||
// Инициализируем каскадную систему ОКВЭД
|
||||
if (russianClassifiers.okved.length > 0) {
|
||||
console.log('🎯 Инициализируем каскадную систему ОКВЭД...');
|
||||
await fetchOkvedCodes(1, null, okvedLevel1Options, isLoadingOkvedLevel1);
|
||||
|
||||
if (selectedOkvedLevel1.value) {
|
||||
await fetchOkvedCodes(2, selectedOkvedLevel1.value, okvedLevel2Options, isLoadingOkvedLevel2);
|
||||
}
|
||||
}
|
||||
|
||||
loadKppCodes();
|
||||
}
|
||||
} else {
|
||||
// Для других стран загружаем ISIC
|
||||
console.log('Загружаем ISIC классификаторы...');
|
||||
|
||||
// Инициализируем каскадную систему ISIC
|
||||
console.log('🎯 Инициализируем каскадную систему ISIC...');
|
||||
await fetchIsicCodes(1, null, isicLevel1Options, isLoadingIsicLevel1);
|
||||
|
||||
if (selectedIsicLevel1.value) {
|
||||
await fetchIsicCodes(2, selectedIsicLevel1.value, isicLevel2Options, isLoadingIsicLevel2);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка при загрузке классификаторов:', error);
|
||||
alert('Не удалось загрузить классификаторы с сервера.');
|
||||
} finally {
|
||||
isLoadingRussianClassifiers.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Функция загрузки российских классификаторов (для совместимости)
|
||||
const loadRussianClassifiers = async () => {
|
||||
isLoadingRussianClassifiers.value = true;
|
||||
try {
|
||||
@@ -2324,9 +2609,9 @@ watch(() => dleSettings.jurisdiction, (newJurisdiction, oldJurisdiction) => {
|
||||
autoSelectedOktmo.value = false;
|
||||
lastApiResult.value = null;
|
||||
|
||||
// Загружаем российские классификаторы при выборе России
|
||||
if (newJurisdiction === '643') {
|
||||
loadRussianClassifiers();
|
||||
// Загружаем классификаторы в зависимости от выбранной страны
|
||||
if (newJurisdiction) {
|
||||
loadClassifiers();
|
||||
}
|
||||
|
||||
// Автосохранение
|
||||
@@ -2840,20 +3125,21 @@ async function submitDeploy() {
|
||||
.explorer-keys-grid { grid-template-columns: 1fr 1fr; }
|
||||
}
|
||||
.settings-panel {
|
||||
padding: var(--block-padding);
|
||||
background-color: var(--color-light);
|
||||
border-radius: var(--radius-md);
|
||||
margin-top: var(--spacing-lg);
|
||||
padding: 0; /* Убираем отступы, так как они уже есть в родительском контейнере */
|
||||
background-color: transparent; /* Убираем фон, так как он уже есть в родительском контейнере */
|
||||
border-radius: 0; /* Убираем скругление углов */
|
||||
margin-top: 0; /* Убираем отступ сверху */
|
||||
animation: fadeIn var(--transition-normal);
|
||||
}
|
||||
|
||||
.settings-block {
|
||||
background: #fff;
|
||||
border-radius: var(--radius-lg, 16px);
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
background: white;
|
||||
border-radius: 12px; /* Согласуем с основными блоками */
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); /* Согласуем тень */
|
||||
border: 1px solid #e9ecef; /* Добавляем границу как у основных блоков */
|
||||
padding: 2rem; /* Увеличиваем отступы */
|
||||
margin-top: 2rem; /* Увеличиваем отступ сверху */
|
||||
margin-bottom: 2rem; /* Увеличиваем отступ снизу */
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
@@ -2878,7 +3164,8 @@ async function submitDeploy() {
|
||||
.form-section h3 {
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.2rem;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600; /* Согласуем с основными заголовками */
|
||||
}
|
||||
|
||||
.form-group {
|
||||
@@ -2910,16 +3197,16 @@ async function submitDeploy() {
|
||||
.form-control {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e9ecef; /* Согласуем с общими стилями */
|
||||
border-radius: 8px; /* Согласуем с кнопками */
|
||||
font-size: 1rem;
|
||||
transition: border-color 0.2s;
|
||||
transition: all 0.2s; /* Добавляем плавный переход для всех свойств */
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.2);
|
||||
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2); /* Согласуем с основными стилями */
|
||||
}
|
||||
|
||||
.address-input-group {
|
||||
@@ -3012,9 +3299,10 @@ async function submitDeploy() {
|
||||
.btn {
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
border-radius: 8px; /* Согласуем с основными кнопками */
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
font-weight: 600; /* Добавляем жирность */
|
||||
transition: all 0.2s;
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
@@ -3029,11 +3317,13 @@ async function submitDeploy() {
|
||||
|
||||
.btn-primary:hover {
|
||||
background: var(--color-primary-dark);
|
||||
transform: translateY(-1px); /* Добавляем эффект hover */
|
||||
}
|
||||
|
||||
.btn-primary:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
transform: none; /* Убираем эффект hover для отключенных кнопок */
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@@ -3606,6 +3896,24 @@ async function submitDeploy() {
|
||||
color: #155724;
|
||||
}
|
||||
|
||||
.current-isic-selection {
|
||||
margin-top: 1rem;
|
||||
padding: 0.75rem;
|
||||
background: #e8f5e8;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #28a745;
|
||||
}
|
||||
|
||||
.current-isic-selection p {
|
||||
margin: 0 0 0.5rem 0;
|
||||
font-weight: 500;
|
||||
color: #155724;
|
||||
}
|
||||
|
||||
.isic-cascade {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.selected-okved-codes {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
@@ -11,51 +11,56 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="security-settings settings-panel">
|
||||
<div class="security-settings">
|
||||
<button class="close-btn" @click="goBack">×</button>
|
||||
<h2>Настройки безопасности и подключения к блокчейну</h2>
|
||||
|
||||
<!-- Заголовок в стиле основной страницы настроек -->
|
||||
<div class="management-header">
|
||||
<div class="header-content">
|
||||
<h1>Настройки безопасности</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-cards">
|
||||
<!-- Блок RPC Провайдеры -->
|
||||
<div class="info-card">
|
||||
<h3>RPC Провайдеры</h3>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Провайдеры:</span>
|
||||
<span class="info-value">{{ securitySettings.rpcConfigs.length > 0 ? `${securitySettings.rpcConfigs.length} настроено` : 'Не настроено' }}</span>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-info" @click="handleRpcDetailsClick">
|
||||
<i class="fas fa-info-circle"></i> Подробнее
|
||||
<!-- Блоки настроек в едином стиле -->
|
||||
<div class="management-blocks">
|
||||
<!-- Столбец 1 -->
|
||||
<div class="blocks-column">
|
||||
<!-- Блок RPC Провайдеры -->
|
||||
<div class="management-block">
|
||||
<h3>RPC Провайдеры</h3>
|
||||
<p>{{ securitySettings.rpcConfigs.length > 0 ? `${securitySettings.rpcConfigs.length} провайдеров настроено` : 'RPC провайдеры не настроены' }}</p>
|
||||
<button class="details-btn" @click="handleRpcDetailsClick">
|
||||
Подробнее
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Блок Аутентификация -->
|
||||
<div class="info-card">
|
||||
<h3>Аутентификация</h3>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Токены:</span>
|
||||
<span class="info-value">{{ securitySettings.authTokens.length > 0 ? `${securitySettings.authTokens.length} настроено` : 'Не настроено' }}</span>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<button class="btn btn-info" @click="showAuthSettings = !showAuthSettings">
|
||||
<i class="fas fa-info-circle"></i> Подробнее
|
||||
<!-- Столбец 2 -->
|
||||
<div class="blocks-column">
|
||||
<!-- Блок Аутентификация -->
|
||||
<div class="management-block">
|
||||
<h3>Аутентификация</h3>
|
||||
<p>{{ securitySettings.authTokens.length > 0 ? `${securitySettings.authTokens.length} токенов настроено` : 'Токены аутентификации не настроены' }}</p>
|
||||
<button class="details-btn" @click="showAuthSettings = !showAuthSettings">
|
||||
Подробнее
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RpcProvidersSettings
|
||||
v-if="showRpcSettings"
|
||||
:rpcConfigs="securitySettings.rpcConfigs"
|
||||
@update="loadSettings"
|
||||
@test="testRpcHandler"
|
||||
/>
|
||||
<AuthTokensSettings
|
||||
v-if="showAuthSettings"
|
||||
:authTokens="securitySettings.authTokens"
|
||||
@update="loadSettings"
|
||||
/>
|
||||
<div v-if="showRpcSettings" class="detail-panel">
|
||||
<RpcProvidersSettings
|
||||
:rpcConfigs="securitySettings.rpcConfigs"
|
||||
@update="loadSettings"
|
||||
@test="testRpcHandler"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="showAuthSettings" class="detail-panel">
|
||||
<AuthTokensSettings
|
||||
:authTokens="securitySettings.authTokens"
|
||||
@update="loadSettings"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Модальное окно "Нет доступа" -->
|
||||
<NoAccessModal
|
||||
@@ -367,82 +372,105 @@ const goBack = () => router.push('/settings');
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.settings-panel {
|
||||
padding: var(--block-padding, 20px);
|
||||
background-color: var(--color-light, #fff);
|
||||
border-radius: var(--radius-md, 8px);
|
||||
margin-top: var(--spacing-lg, 20px);
|
||||
animation: fadeIn var(--transition-normal, 0.3s);
|
||||
.security-settings {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: var(--spacing-lg, 20px);
|
||||
border-bottom: 1px solid var(--color-grey-light, #eee);
|
||||
padding-bottom: var(--spacing-md, 15px);
|
||||
color: var(--color-dark, #333);
|
||||
/* Заголовок в стиле основной страницы настроек */
|
||||
.management-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 2px solid #e9ecef;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-bottom: var(--spacing-md, 15px);
|
||||
color: var(--color-primary, #4caf50);
|
||||
.header-content h1 {
|
||||
margin: 0;
|
||||
color: var(--color-primary);
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-bottom: var(--spacing-sm, 10px);
|
||||
color: var(--color-dark, #333);
|
||||
}
|
||||
|
||||
.settings-cards {
|
||||
/* Блоки настроек в едином стиле */
|
||||
.management-blocks {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: var(--spacing-md, 15px);
|
||||
margin-bottom: var(--spacing-lg, 20px);
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
border: 1px solid var(--color-grey-light, #eee);
|
||||
border-radius: var(--radius-md, 8px);
|
||||
padding: var(--spacing-md, 15px);
|
||||
background-color: white;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
transition: box-shadow 0.3s ease, transform 0.3s ease;
|
||||
.blocks-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.info-card:hover {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
.management-block {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
border: 1px solid #e9ecef;
|
||||
transition: all 0.3s ease;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.management-block:hover {
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
|
||||
transform: translateY(-2px);
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin-bottom: var(--spacing-xs, 5px);
|
||||
.management-block h3 {
|
||||
margin: 0 0 1rem 0;
|
||||
color: var(--color-primary);
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-weight: 500;
|
||||
color: var(--color-primary, #4caf50);
|
||||
margin-right: var(--spacing-sm, 10px);
|
||||
min-width: 80px;
|
||||
.management-block p {
|
||||
margin: 0 0 1.5rem 0;
|
||||
color: #666;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: var(--color-dark, #333);
|
||||
.details-btn {
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 0.75rem 1.5rem;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s;
|
||||
min-width: 120px;
|
||||
flex-shrink: 0;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: var(--spacing-md, 15px);
|
||||
.details-btn:hover {
|
||||
background: var(--color-primary-dark);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.detail-panel {
|
||||
margin-top: var(--spacing-md, 15px);
|
||||
margin-bottom: var(--spacing-lg, 20px);
|
||||
padding: var(--spacing-md, 15px);
|
||||
border: 1px solid var(--color-grey-light, #eee);
|
||||
border-radius: var(--radius-md, 8px);
|
||||
background-color: var(--color-light, #fafafa);
|
||||
margin-top: 3rem; /* Увеличиваем отступ сверху */
|
||||
margin-bottom: 2rem; /* Добавляем отступ снизу */
|
||||
padding: 2rem; /* Увеличиваем внутренние отступы */
|
||||
border: 1px solid #e9ecef;
|
||||
border-radius: 12px; /* Согласуем с основными блоками */
|
||||
background-color: white; /* Белый фон как у основных блоков */
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); /* Добавляем тень */
|
||||
animation: slideDown 0.3s ease;
|
||||
}
|
||||
|
||||
@@ -656,13 +684,41 @@ small {
|
||||
right: 18px;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 2rem;
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
color: #bbb;
|
||||
transition: color 0.2s;
|
||||
color: #666;
|
||||
padding: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transition: all 0.2s;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.close-btn:hover {
|
||||
background: #f0f0f0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Адаптивность */
|
||||
@media (max-width: 1024px) {
|
||||
.management-blocks {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.management-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.header-content h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -62,10 +62,10 @@
|
||||
|
||||
<style scoped>
|
||||
.settings-management {
|
||||
padding: 20px;
|
||||
background-color: var(--color-white);
|
||||
border-radius: var(--radius-lg);
|
||||
min-height: 100vh;
|
||||
padding: 0; /* Убираем отступы, так как они уже есть в родительском контейнере */
|
||||
background-color: transparent; /* Убираем фон, так как он уже есть в родительском контейнере */
|
||||
border-radius: 0; /* Убираем скругление углов */
|
||||
min-height: auto; /* Убираем фиксированную высоту */
|
||||
}
|
||||
|
||||
.management-header {
|
||||
|
||||
Reference in New Issue
Block a user