Initial commit.
This commit is contained in:
commit
ef812f7fd9
3 changed files with 280 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
.idea
|
||||||
BIN
favicon.png
Normal file
BIN
favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
279
index.html
Normal file
279
index.html
Normal file
|
|
@ -0,0 +1,279 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Проверка наличия льготных препаратов</title>
|
||||||
|
<link rel="icon" type="image/png" href="/favicon.png">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 12px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #195695;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
u {
|
||||||
|
border-bottom: 1px dashed #cccccc;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
.name {
|
||||||
|
background-color: #e6f2ff;
|
||||||
|
text-align: center;
|
||||||
|
color: #195695;
|
||||||
|
}
|
||||||
|
.loading {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
font-style: italic;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.error {
|
||||||
|
color: red;
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.note {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: small;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.search-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
#searchInput {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 220px;
|
||||||
|
max-width: 280px;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
#searchButton {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
background-color: #6d4203;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#searchButton:hover {
|
||||||
|
background-color: #8f6f3f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive behavior for smaller screens */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.search-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchInput {
|
||||||
|
align-self: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchButton {
|
||||||
|
align-self: center;
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: none) {
|
||||||
|
u {
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h2>Проверка наличия льготных препаратов<br/>в аптеках Санкт-Петербурга</h2>
|
||||||
|
|
||||||
|
<div class="search-container">
|
||||||
|
<input type="text" id="searchInput" placeholder="Введите название препарата">
|
||||||
|
<button id="searchButton">Найти</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="content"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function fetchData(name) {
|
||||||
|
document.getElementById('content').innerHTML = '<div class="loading">Загрузка данных...</div>';
|
||||||
|
name = name.replaceAll(' ', '_');
|
||||||
|
fetch(`/api-proxy?operation=getMedicament&filter=${name}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => displayData(processData(data)))
|
||||||
|
.catch(error => showError(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract needed data from JSON
|
||||||
|
function processData(data) {
|
||||||
|
if (data['status'] !== "SUCCESS")
|
||||||
|
return data['errors'];
|
||||||
|
|
||||||
|
const results = data['model']['result'];
|
||||||
|
let processedData = [];
|
||||||
|
|
||||||
|
results.forEach(result => {
|
||||||
|
result['districts'].forEach(district => {
|
||||||
|
district['apothecaries'].forEach(apothecary => {
|
||||||
|
let address = apothecary['address'];
|
||||||
|
const regex = /\d*, [а-яА-Я\-. ]+, (.+) \*.+/;
|
||||||
|
let m;
|
||||||
|
if ((m = regex.exec(address)) !== null)
|
||||||
|
address = m[1];
|
||||||
|
else
|
||||||
|
address = address.substring(0, address.indexOf('*'));
|
||||||
|
|
||||||
|
processedData.push({
|
||||||
|
name: result['name'],
|
||||||
|
apothecary: apothecary['name'] + '<br/><i>' + address + '</i>',
|
||||||
|
countFederal: apothecary['ost1'],
|
||||||
|
countRegional: apothecary['ost2'],
|
||||||
|
timestamp: apothecary['date']
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return processedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the data in a table format
|
||||||
|
function displayData(data) {
|
||||||
|
let htmlContent;
|
||||||
|
|
||||||
|
if (typeof(data) === 'object') {
|
||||||
|
htmlContent = `
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Аптека</th>
|
||||||
|
<th style="width: 75px; text-align: center;">Остаток<br/>(<u title="региональная льгота">рег</u>/<u title="федеральная льгота">фед</u>)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Group consecutive items with same name and generate merged cells
|
||||||
|
if (data.length > 0) {
|
||||||
|
let currentName = data[0].name;
|
||||||
|
let rowCount = 1;
|
||||||
|
let rowStartIndex = 0;
|
||||||
|
|
||||||
|
for (let i = 1; i <= data.length; i++) {
|
||||||
|
if (i < data.length && data[i].name === currentName) {
|
||||||
|
rowCount++;
|
||||||
|
} else {
|
||||||
|
// Generate rows for the current group
|
||||||
|
htmlContent += '<tr><td colspan="2"></td></tr>';
|
||||||
|
htmlContent += `<tr><td colspan="2" class="name"><b>${currentName}</b></td></tr>`;
|
||||||
|
for (let j = rowStartIndex; j < i; j++) {
|
||||||
|
const item = data[j];
|
||||||
|
htmlContent += `
|
||||||
|
<tr>
|
||||||
|
<td>${item.apothecary}</td>
|
||||||
|
<td style="text-align: center;">${item.countRegional} / ${item.countFederal}</td>
|
||||||
|
</tr>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset for next group
|
||||||
|
if (i < data.length) {
|
||||||
|
currentName = data[i].name;
|
||||||
|
rowCount = 1;
|
||||||
|
rowStartIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
htmlContent += `
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
|
|
||||||
|
htmlContent += '<div class="note">Информация получена через <a href="https://eservice.gu.spb.ru/portalFront/resources/portal.html#medicament" target="_blank" style="text-decoration: none;">портал госуслуг Санкт-Петербурга</a>.</div>'
|
||||||
|
}
|
||||||
|
else
|
||||||
|
htmlContent = `<div class="error">${data}</div>`;
|
||||||
|
|
||||||
|
document.getElementById('content').innerHTML = htmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showError(error) {
|
||||||
|
document.getElementById('content').innerHTML = `<div class="error">Ошибка: ${error.message}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function search() {
|
||||||
|
const name = document.getElementById('searchInput').value.trim();
|
||||||
|
if (name) {
|
||||||
|
saveInputValue();
|
||||||
|
fetchData(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save input value to localStorage
|
||||||
|
function saveInputValue() {
|
||||||
|
const name = document.getElementById('searchInput').value;
|
||||||
|
localStorage.setItem('medicamentName', name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore input value from localStorage
|
||||||
|
function restoreInputValue() {
|
||||||
|
const savedValue = localStorage.getItem('medicamentName');
|
||||||
|
if (savedValue) {
|
||||||
|
document.getElementById('searchInput').value = savedValue;
|
||||||
|
return savedValue;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
let name = restoreInputValue();
|
||||||
|
if (name !== null)
|
||||||
|
fetchData(name);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('searchButton').addEventListener('click', search);
|
||||||
|
document.getElementById('searchInput').addEventListener('keypress', (e) => {
|
||||||
|
if (e.key === 'Enter')
|
||||||
|
search();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Reference in a new issue