292 lines
14 KiB
HTML
292 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html xmlns:th="http://www.thymeleaf.org">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>公告管理 - 商家后台</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
|
|
</head>
|
|
<body>
|
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
|
<div class="container-fluid">
|
|
<a class="navbar-brand" href="/merchant/dashboard.html">
|
|
<i class="bi bi-shop"></i> 商家后台
|
|
</a>
|
|
<div class="navbar-nav ms-auto">
|
|
<a class="nav-link" href="/merchant/dashboard.html">首页</a>
|
|
<a class="nav-link" href="/merchant/products.html">商品管理</a>
|
|
<a class="nav-link" href="/merchant/orders.html">订单管理</a>
|
|
<a class="nav-link" href="/merchant/inventory.html">库存管理</a>
|
|
<a class="nav-link" href="/merchant/statistics.html">数据统计</a>
|
|
<a class="nav-link active" href="/merchant/announcements.html">公告管理</a>
|
|
<a class="nav-link" href="/merchant/messages.html">留言管理</a>
|
|
<a class="nav-link" href="/merchant/reviews.html">评价管理</a>
|
|
<a class="nav-link" href="/merchant/users.html">用户管理</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="container mt-4 mb-5">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h2><i class="bi bi-megaphone"></i> 公告管理</h2>
|
|
<button class="btn btn-primary" onclick="showAddAnnouncementModal()">
|
|
<i class="bi bi-plus-circle"></i> 新增公告
|
|
</button>
|
|
</div>
|
|
<div class="card shadow-sm">
|
|
<div class="card-body">
|
|
<div id="announcementsList"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 添加/编辑公告模态框 -->
|
|
<div class="modal fade" id="announcementModal" tabindex="-1">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="announcementModalTitle">新增公告</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="announcementForm">
|
|
<input type="hidden" id="announcementId">
|
|
<div class="mb-3">
|
|
<label for="title" class="form-label">标题 <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control" id="title" required>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="type" class="form-label">类型</label>
|
|
<select class="form-control" id="type">
|
|
<option value="ACTIVITY">活动</option>
|
|
<option value="NOTICE">通知</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="content" class="form-label">内容 <span class="text-danger">*</span></label>
|
|
<textarea class="form-control" id="content" rows="5" required></textarea>
|
|
</div>
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="status" checked>
|
|
<label class="form-check-label" for="status">
|
|
发布
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
|
<button type="button" class="btn btn-primary" onclick="saveAnnouncement()">保存</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="/static/js/sidebar-replacer.js"></script>
|
|
<script src="/static/js/ui-enhancements.js"></script>
|
|
<script>
|
|
// 检查登录状态
|
|
async function checkLogin() {
|
|
try {
|
|
const response = await fetch('/merchant/profile', {
|
|
credentials: 'include'
|
|
});
|
|
const data = await response.json();
|
|
if (data.code !== 200 || !data.data) {
|
|
window.location.href = '/merchant/login.html';
|
|
return false;
|
|
}
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
window.location.href = '/merchant/login.html';
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 加载公告列表
|
|
async function loadAnnouncements() {
|
|
try {
|
|
const response = await fetch('/merchant/announcements', {
|
|
credentials: 'include'
|
|
});
|
|
const data = await response.json();
|
|
|
|
const container = document.getElementById('announcementsList');
|
|
|
|
if (data.code === 200 && data.data) {
|
|
const announcements = data.data || [];
|
|
|
|
if (announcements.length === 0) {
|
|
container.innerHTML = '<div class="alert alert-info">暂无公告,请点击"新增公告"按钮添加</div>';
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = `
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>标题</th>
|
|
<th>类型</th>
|
|
<th>状态</th>
|
|
<th>创建时间</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
${announcements.map(announcement => `
|
|
<tr>
|
|
<td><strong>${announcement.title || ''}</strong></td>
|
|
<td><span class="badge ${announcement.type === 'ACTIVITY' ? 'bg-warning' : 'bg-info'}">${announcement.type === 'ACTIVITY' ? '活动' : '通知'}</span></td>
|
|
<td>
|
|
<span class="badge ${announcement.status === 1 ? 'bg-success' : 'bg-secondary'}">
|
|
${announcement.status === 1 ? '已发布' : '已下架'}
|
|
</span>
|
|
</td>
|
|
<td>${announcement.createTime ? new Date(announcement.createTime).toLocaleString('zh-CN') : '-'}</td>
|
|
<td>
|
|
<div class="btn-group btn-group-sm">
|
|
<button class="btn btn-outline-primary" onclick="editAnnouncement(${announcement.id})" title="编辑">
|
|
<i class="bi bi-pencil"></i>
|
|
</button>
|
|
<button class="btn btn-outline-danger" onclick="deleteAnnouncement(${announcement.id})" title="删除">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
`).join('')}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
`;
|
|
} else {
|
|
container.innerHTML = '<div class="alert alert-warning">加载公告列表失败:' + (data.message || '未知错误') + '</div>';
|
|
}
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
document.getElementById('announcementsList').innerHTML = '<div class="alert alert-danger">加载公告列表失败,请刷新页面重试</div>';
|
|
}
|
|
}
|
|
|
|
// 显示添加公告模态框
|
|
function showAddAnnouncementModal() {
|
|
document.getElementById('announcementModalTitle').textContent = '新增公告';
|
|
document.getElementById('announcementId').value = '';
|
|
document.getElementById('announcementForm').reset();
|
|
document.getElementById('status').checked = true;
|
|
const modal = new bootstrap.Modal(document.getElementById('announcementModal'));
|
|
modal.show();
|
|
}
|
|
|
|
// 编辑公告
|
|
async function editAnnouncement(announcementId) {
|
|
try {
|
|
const response = await fetch(`/merchant/announcements/${announcementId}`, {
|
|
credentials: 'include'
|
|
});
|
|
const data = await response.json();
|
|
|
|
if (data.code === 200 && data.data) {
|
|
const announcement = data.data;
|
|
document.getElementById('announcementModalTitle').textContent = '编辑公告';
|
|
document.getElementById('announcementId').value = announcement.id;
|
|
document.getElementById('title').value = announcement.title || '';
|
|
document.getElementById('type').value = announcement.type || 'NOTICE';
|
|
document.getElementById('content').value = announcement.content || '';
|
|
document.getElementById('status').checked = announcement.status === 1;
|
|
|
|
const modal = new bootstrap.Modal(document.getElementById('announcementModal'));
|
|
modal.show();
|
|
} else {
|
|
alert('加载公告信息失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
alert('加载公告信息失败');
|
|
}
|
|
}
|
|
|
|
// 保存公告
|
|
async function saveAnnouncement() {
|
|
const announcementId = document.getElementById('announcementId').value;
|
|
const announcementData = {
|
|
title: document.getElementById('title').value,
|
|
type: document.getElementById('type').value,
|
|
content: document.getElementById('content').value,
|
|
status: document.getElementById('status').checked ? 1 : 0
|
|
};
|
|
|
|
if (!announcementData.title || !announcementData.content) {
|
|
UIEnhancements.showWarning('请填写完整信息');
|
|
return;
|
|
}
|
|
|
|
const saveBtn = document.querySelector('#announcementModal .btn-primary');
|
|
|
|
try {
|
|
const url = announcementId ? `/merchant/announcements/${announcementId}` : '/merchant/announcements';
|
|
const method = announcementId ? 'PUT' : 'POST';
|
|
|
|
const { data } = await UIEnhancements.enhancedFetch(url, {
|
|
method: method,
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
credentials: 'include',
|
|
body: JSON.stringify(announcementData),
|
|
button: saveBtn
|
|
});
|
|
|
|
if (data.code === 200) {
|
|
UIEnhancements.showSuccess(announcementId ? '公告已更新' : '公告已发布');
|
|
const modal = bootstrap.Modal.getInstance(document.getElementById('announcementModal'));
|
|
modal.hide();
|
|
loadAnnouncements();
|
|
} else {
|
|
UIEnhancements.showError(data.message || '保存失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
UIEnhancements.showError('保存失败,请稍后重试');
|
|
}
|
|
}
|
|
|
|
// 删除公告
|
|
async function deleteAnnouncement(announcementId) {
|
|
const confirmed = await UIEnhancements.confirmAction('确定要删除该公告吗?', '确认删除');
|
|
if (!confirmed) return;
|
|
|
|
try {
|
|
const { data } = await UIEnhancements.enhancedFetch(`/merchant/announcements/${announcementId}`, {
|
|
method: 'DELETE',
|
|
credentials: 'include'
|
|
});
|
|
|
|
if (data.code === 200) {
|
|
UIEnhancements.showSuccess('公告已删除');
|
|
loadAnnouncements();
|
|
} else {
|
|
UIEnhancements.showError(data.message || '删除失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
UIEnhancements.showError('删除失败,请稍后重试');
|
|
}
|
|
}
|
|
|
|
// 页面加载
|
|
checkLogin().then(isLoggedIn => {
|
|
if (isLoggedIn) {
|
|
loadAnnouncements();
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|