Доработана работа с пользователями (ввод пароля и отмена автозаполнения) Добавлен логотип блога.
This commit is contained in:
parent
e4d5029e72
commit
9ba64a453c
107
.import/mysql_json_convert.py
Normal file
107
.import/mysql_json_convert.py
Normal 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
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
BIN
public/images/Logo-4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 951 KiB |
@ -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'
|
||||
}`}
|
||||
>
|
||||
|
@ -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}
|
||||
|
@ -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('Сбой при удалении пользователя');
|
||||
}
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user