初始化鸿蒙应用展示平台项目 - 前后端分离架构
This commit is contained in:
246
templates/credits_management.html
Executable file
246
templates/credits_management.html
Executable file
@@ -0,0 +1,246 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'admin_nav.html' %}
|
||||
|
||||
<div class="admin-container">
|
||||
<div class="admin-content">
|
||||
<div class="admin-card">
|
||||
<div class="card-header">
|
||||
<div class="header-left">
|
||||
<i class="fas fa-award"></i>
|
||||
<h3>鸣谢管理</h3>
|
||||
</div>
|
||||
</div>
|
||||
<form onsubmit="submitAddCreditForm(event, this)" class="admin-form" enctype="multipart/form-data">
|
||||
<div class="form-group">
|
||||
<label for="credit-name">姓名</label>
|
||||
<input type="text" id="credit-name" name="name" placeholder="请输入姓名" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="credit-avatar">头像</label>
|
||||
<div class="file-input-wrapper">
|
||||
<input type="file" id="credit-avatar" name="avatar" accept="image/*">
|
||||
<label for="credit-avatar" class="file-input-label">
|
||||
<i class="fas fa-cloud-upload-alt"></i>
|
||||
<span>选择文件</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="avatar-url">或输入头像URL</label>
|
||||
<input type="url" id="avatar-url" name="avatar_url" placeholder="http://example.com/avatar.png">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="credit-link">链接</label>
|
||||
<input type="url" id="credit-link" name="link" placeholder="http://example.com">
|
||||
</div>
|
||||
<button type="submit" class="btn-primary">
|
||||
<i class="fas fa-plus"></i> 添加鸣谢
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="credits-list">
|
||||
{% for credit in credits %}
|
||||
<div class="credit-item">
|
||||
<img src="{{ credit.avatar_url }}" alt="{{ credit.name }}" class="credit-avatar">
|
||||
<div class="credit-info">
|
||||
<h4>{{ credit.name }}</h4>
|
||||
<a href="{{ credit.link }}" target="_blank">{{ credit.link }}</a>
|
||||
</div>
|
||||
<div class="credit-controls">
|
||||
<button onclick="editCredit({{ credit.id }}, '{{ credit.name }}', '{{ credit.avatar_url }}', '{{ credit.link }}')" class="btn-edit">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
<button onclick="deleteCredit({{ credit.id }})" class="btn-delete">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function submitAddCreditForm(event, form) {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(form);
|
||||
|
||||
fetch('{{ url_for("add_credit") }}', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
showNotification(data.message, 'success');
|
||||
form.reset();
|
||||
location.reload();
|
||||
} else {
|
||||
showNotification(data.error, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
showNotification('操作失败,请重试', 'error');
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function editCredit(id, name, avatarUrl, link) {
|
||||
const form = document.querySelector('.admin-form');
|
||||
form.querySelector('#credit-name').value = name;
|
||||
form.querySelector('#credit-link').value = link;
|
||||
form.querySelector('#avatar-url').value = avatarUrl;
|
||||
form.querySelector('#credit-avatar').value = ''; // 清空文件输入
|
||||
form.onsubmit = function(event) {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(form);
|
||||
formData.append('id', id);
|
||||
|
||||
fetch('{{ url_for("edit_credit") }}', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
showNotification(data.message, 'success');
|
||||
location.reload();
|
||||
} else {
|
||||
showNotification(data.error, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
showNotification('操作失败,请重试', 'error');
|
||||
console.error('Error:', error);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function deleteCredit(id) {
|
||||
if (confirm('确定要删除这个鸣谢吗?')) {
|
||||
fetch(`{{ url_for('delete_credit', credit_id=0) }}`.replace('0', id), {
|
||||
method: 'POST'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
showNotification(data.message, 'success');
|
||||
location.reload();
|
||||
} else {
|
||||
showNotification(data.error, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
showNotification('删除失败,请重试', 'error');
|
||||
console.error('Error:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showNotification(message, type = 'success') {
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `notification ${type}`;
|
||||
notification.textContent = message;
|
||||
|
||||
Object.assign(notification.style, {
|
||||
position: 'fixed',
|
||||
bottom: '20px',
|
||||
right: '20px',
|
||||
padding: '10px 20px',
|
||||
borderRadius: '4px',
|
||||
backgroundColor: type === 'success' ? '#4CAF50' : '#f44336',
|
||||
color: 'white',
|
||||
zIndex: '1000',
|
||||
opacity: '0',
|
||||
transform: 'translateY(20px)',
|
||||
transition: 'all 0.3s ease'
|
||||
});
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
notification.offsetHeight;
|
||||
|
||||
notification.style.opacity = '1';
|
||||
notification.style.transform = 'translateY(0)';
|
||||
|
||||
setTimeout(() => {
|
||||
notification.style.opacity = '0';
|
||||
notification.style.transform = 'translateY(20px)';
|
||||
setTimeout(() => notification.remove(), 300);
|
||||
}, 3000);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.credits-list {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.credit-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 20px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.credit-avatar {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.credit-info {
|
||||
flex: 1;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.credit-info h4 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.credit-info a {
|
||||
font-size: 16px;
|
||||
color: #007AFF;
|
||||
text-decoration: none;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.credit-info a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.credit-controls {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.btn-edit, .btn-delete {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: #666;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-edit:hover {
|
||||
color: #007AFF;
|
||||
}
|
||||
|
||||
.btn-delete:hover {
|
||||
color: #ff3b30;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user