Доработана работа с пользователями (ввод пароля и отмена автозаполнения) Добавлен логотип блога.

This commit is contained in:
anibilag 2025-03-22 23:51:32 +03:00
parent e4d5029e72
commit 9ba64a453c
6 changed files with 125 additions and 15 deletions

View File

@ -0,0 +1,107 @@
import json
import io
from datetime import datetime
from bs4 import BeautifulSoup
# Файл дампа
input_directory = "D:/__TEMP/____4/__convert"
json_file = "1-2025"
output_file = "2-2025-convert.json"
def main():
try:
f = io.open(input_directory + '/' + json_file + '.json', encoding='utf-8')
records = json.loads(f.read())
except FileNotFoundError:
print("Ошибка: Входной JSON файл не найден.")
return
except json.JSONDecodeError as e:
print(f"Ошибка декодирования JSON: {e}")
return
articles = list()
for item in records:
try:
article = dict()
pre = item['pre']
full = item['full']
article['id'] = item['id']
article['title'] = item['title']
article['content'] = full
article['categoryId'] = item['cat_id']
article['cityId'] = item['city_id']
soup = BeautifulSoup(pre, "html.parser")
# Извлекаем URL изображения
img_tag = soup.find("img")
img_url = img_tag["src"] if img_tag else None
# Удаляем тег <img> из HTML
if img_tag:
img_tag.decompose()
# Удаляем пустые <p> (с пробелами или полностью пустые)
for p in soup.find_all("p"):
if not p.get_text(strip=True): # strip=True убирает пробелы и невидимые символы
p.decompose()
# Извлекаем текст из оставшихся <p>
text_content = " ".join(p.get_text(strip=True) for p in soup.find_all("p"))
if not text_content:
# Находим первый тег <p> и извлекаем текст
soup = BeautifulSoup(full, "html.parser")
first_p = soup.find("p")
text_content = first_p.get_text(strip=True) if first_p else ""
article['excerpt'] = text_content
article['coverImage'] = img_url
article['readTime'] = 2
article['likes'] = 0
article['dislikes'] = 0
article['gallery'] = []
# Разбираем строку в объект datetime
date_obj = datetime.strptime(item['date'], "%d.%m.%Y")
# Преобразуем в нужный формат
formatted_date = date_obj.strftime("%Y-%m-%dT00:00:00Z")
article['publishedAt'] = formatted_date
author = dict()
author['id'] = '41e09d9a-f9c1-44a7-97f4-0be694371e7e'
article['author'] = author
articles.append(article)
except KeyError as e:
print(f"Потерян ключ в записи: {e}")
continue
save_to_json_file(output_file, articles, 'w')
def save_to_file(path, data, mode):
f = open(input_directory + '/' + path, mode)
f.write(data)
f.close()
def save_to_json_file(path, data, mode):
f = io.open(input_directory + '/' + path, encoding='utf-8', mode=mode)
json.dump(data, f, ensure_ascii=False, indent=2)
f.close()
#def create_article:
if __name__ == '__main__':
main()

BIN
public/images/Logo-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 KiB

BIN
public/images/Logo-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 KiB

View File

@ -91,7 +91,7 @@ export function Header() {
to={`/?category=${category}${currentCity ? `&city=${currentCity}` : ''}`}
className={`px-3 py-2 font-medium transition-colors whitespace-nowrap ${
Number(currentCategory) === category
? 'text-base md:text-lg lg:text-xl font-semibold text-blue-600 hover:text-blue-800 underline'
? 'text-base md:text-lg lg:text-xl font-semibold text-blue-600 hover:text-blue-800 bg-gray-200'
: 'text-sm md:text-base lg:text-lg font-medium text-gray-600 hover:text-gray-900'
}`}
>

View File

@ -16,7 +16,7 @@ const initialFormData: UserFormData = {
password: '',
displayName: '',
bio: '',
avatarUrl: ''
avatarUrl: '/images/avatar.jpg'
};
export function UserManagementPage() {
@ -253,7 +253,7 @@ export function UserManagementPage() {
<div className="bg-white rounded-lg max-w-md w-full p-6">
<div className="flex justify-between items-center mb-4">
<h3 className="text-lg font-medium text-gray-900">
{showCreateModal ? 'Создание нового' : 'Редактирование'}
{showCreateModal ? 'Создание нового пользователя' : 'Редактирование'}
</h3>
<button
onClick={() => {
@ -274,7 +274,7 @@ export function UserManagementPage() {
</div>
)}
<form onSubmit={handleSubmit} className="space-y-4">
<form onSubmit={handleSubmit} className="space-y-4" autoComplete="off">
<div>
<label className="block text-sm font-medium text-gray-700">
Аватар
@ -306,6 +306,7 @@ export function UserManagementPage() {
type="text"
value={formData.displayName}
onChange={(e) => setFormData(prev => ({ ...prev, displayName: e.target.value }))}
autoComplete="off"
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
required
/>
@ -319,6 +320,7 @@ export function UserManagementPage() {
type="email"
value={formData.email}
onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value }))}
autoComplete="off"
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
required
/>
@ -326,12 +328,13 @@ export function UserManagementPage() {
<div>
<label className="block text-sm font-medium text-gray-700">
Пароль {showEditModal}
Пароль
</label>
<input
type="password"
value={''}
value={formData.password}
onChange={(e) => setFormData(prev => ({ ...prev, password: e.target.value }))}
autoComplete="new-password"
placeholder={showEditModal ? 'Оставьте пустым, чтобы не менять' : ''}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
required={!showEditModal}

View File

@ -8,7 +8,7 @@ export const userService = {
return response.data;
} catch (error) {
console.error('Ошибка получения списка пользователей:', error);
throw new Error('Ошибка получения списка пользователей');
throw new Error('Сбой при получении списка пользователей');
}
},
@ -17,8 +17,8 @@ export const userService = {
const response = await axios.post('/users', userData);
return response.data;
} catch (error) {
console.error('Error creating user:', error);
throw new Error('Failed to create user');
console.error('Ошибка создания пользователя:', error);
throw new Error('Сбой при создании пользователя');
}
},
@ -27,8 +27,8 @@ export const userService = {
const response = await axios.put(`/users/${userId}`, userData);
return response.data;
} catch (error) {
console.error('Error updating user:', error);
throw new Error('Failed to update user');
console.error('Ошибка редактирования пользователя:', error);
throw new Error('Сбой при редактировании пользователя');
}
},
@ -37,8 +37,8 @@ export const userService = {
const response = await axios.put(`/users/${userId}/permissions`, { permissions });
return response.data;
} catch (error) {
console.error('Error updating user permissions:', error);
throw new Error('Failed to update user permissions');
console.error('Ошибка редактирования прав пользователя:', error);
throw new Error('Сбой при редактировании прав пользователя');
}
},
@ -46,8 +46,8 @@ export const userService = {
try {
await axios.delete(`/users/${userId}`);
} catch (error) {
console.error('Error deleting user:', error);
throw new Error('Failed to delete user');
console.error('Ошибка удаления пользователя:', error);
throw new Error('Сбой при удалении пользователя');
}
}
};