处理中...';
+ button.disabled = true;
+
+ fetch(`/payment/simulate_success/${paymentSn}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ }
+ })
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ return response.json();
+ })
+ .then(data => {
+ if (data.success) {
+ showAlert('模拟支付成功!', 'success');
+ setTimeout(() => {
+ showPaymentSuccess();
+ }, 1000);
+ } else {
+ showAlert(data.message || '模拟支付失败', 'error');
+ button.innerHTML = originalText;
+ button.disabled = false;
+ }
+ })
+ .catch(error => {
+ console.error('模拟支付错误:', error);
+ showAlert('模拟支付失败', 'error');
+ button.innerHTML = originalText;
+ button.disabled = false;
+ });
+}
+
+// 模拟支付失败
+function simulatePaymentFail() {
+ const paymentSn = document.querySelector('[data-payment-sn]')?.dataset.paymentSn;
+
+ if (!paymentSn) {
+ showAlert('支付信息获取失败', 'error');
+ return;
+ }
+
+ showConfirm('确定要模拟支付失败吗?这将导致订单支付失败。', () => {
+ // 显示处理中状态
+ const button = event.target;
+ const originalText = button.innerHTML;
+ button.innerHTML = '
处理中...';
+ button.disabled = true;
+
+ fetch(`/payment/simulate_fail/${paymentSn}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
})
- .then(response => response.json())
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ return response.json();
+ })
.then(data => {
if (data.success) {
- showAlert('模拟支付成功', 'success');
+ showAlert('模拟支付失败!', 'warning');
setTimeout(() => {
- showPaymentSuccess();
+ showPaymentFail();
}, 1000);
} else {
- showAlert(data.message, 'error');
+ showAlert(data.message || '模拟操作失败', 'error');
+ button.innerHTML = originalText;
+ button.disabled = false;
}
})
.catch(error => {
- showAlert('模拟支付失败', 'error');
+ console.error('模拟支付失败错误:', error);
+ showAlert('模拟操作失败', 'error');
+ button.innerHTML = originalText;
+ button.disabled = false;
});
- }
+ });
+}
+
+// 兼容旧版本的模拟支付函数
+function simulatePayment() {
+ simulatePaymentSuccess();
}
diff --git a/app/static/js/product_detail.js b/app/static/js/product_detail.js
index a94a72e..be38f49 100644
--- a/app/static/js/product_detail.js
+++ b/app/static/js/product_detail.js
@@ -22,8 +22,67 @@ document.addEventListener('DOMContentLoaded', function() {
if (typeof loadCartCount === 'function') {
loadCartCount();
}
+
+ // 添加浏览历史记录
+ if (window.isLoggedIn && window.productId) {
+ addBrowseHistory(window.productId);
+ }
+
+ // 检查收藏状态
+ if (window.isLoggedIn && window.productId) {
+ checkFavoriteStatus(window.productId);
+ }
});
+// 添加浏览历史记录
+function addBrowseHistory(productId) {
+ fetch('/history/add', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ product_id: productId
+ })
+ })
+ .then(response => response.json())
+ .then(data => {
+ // 静默添加,不需要用户感知
+ console.log('浏览历史记录已添加');
+ })
+ .catch(error => {
+ console.error('添加浏览历史失败:', error);
+ });
+}
+
+// 检查收藏状态
+function checkFavoriteStatus(productId) {
+ fetch(`/favorite/check/${productId}`)
+ .then(response => response.json())
+ .then(data => {
+ if (data.success) {
+ updateFavoriteButton(data.is_favorited);
+ }
+ })
+ .catch(error => {
+ console.error('检查收藏状态失败:', error);
+ });
+}
+
+// 更新收藏按钮状态
+function updateFavoriteButton(isFavorited) {
+ const favoriteBtn = document.querySelector('[onclick="addToFavorites()"]');
+ if (favoriteBtn) {
+ if (isFavorited) {
+ favoriteBtn.innerHTML = '
已收藏';
+ favoriteBtn.className = 'btn btn-outline-danger';
+ } else {
+ favoriteBtn.innerHTML = '
收藏商品';
+ favoriteBtn.className = 'btn btn-outline-secondary';
+ }
+ }
+}
+
// 规格选择
function selectSpec(button) {
const specName = button.getAttribute('data-spec-name');
@@ -231,6 +290,68 @@ function buyNow() {
// 收藏商品
function addToFavorites() {
- // TODO: 实现收藏功能
- alert('收藏功能开发中...');
+ if (!window.isLoggedIn) {
+ if (confirm('请先登录后再收藏,是否前往登录?')) {
+ window.location.href = '/auth/login?next=' + encodeURIComponent(window.location.pathname);
+ }
+ return;
+ }
+
+ // 确保获取到商品ID
+ const productId = window.productId || window.currentProductId;
+ if (!productId) {
+ alert('获取商品信息失败,请刷新页面重试');
+ return;
+ }
+
+ console.log('收藏商品ID:', productId); // 调试信息
+
+ const favoriteBtn = document.querySelector('[onclick="addToFavorites()"]');
+ const isFavorited = favoriteBtn && favoriteBtn.innerHTML.includes('已收藏');
+
+ // 临时禁用按钮
+ if (favoriteBtn) {
+ favoriteBtn.disabled = true;
+ favoriteBtn.innerHTML = '
处理中...';
+ }
+
+ fetch('/favorite/toggle', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ product_id: parseInt(productId)
+ })
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.success) {
+ showSuccessMessage(data.message);
+ updateFavoriteButton(data.is_favorited);
+ } else {
+ alert(data.message);
+ }
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ alert('操作失败,请稍后再试');
+ })
+ .finally(() => {
+ // 恢复按钮状态
+ if (favoriteBtn) {
+ favoriteBtn.disabled = false;
+ }
+ });
+}
+
+// 显示成功消息
+function showSuccessMessage(message) {
+ // 这里可以使用Toast或其他方式显示消息
+ if (typeof showToast === 'function') {
+ showToast(message, 'success');
+ } else {
+ // 简单的成功提示
+ alert(message);
+ }
}
diff --git a/app/static/js/review.js b/app/static/js/review.js
new file mode 100644
index 0000000..9182326
--- /dev/null
+++ b/app/static/js/review.js
@@ -0,0 +1,646 @@
+// 评价功能 JavaScript
+
+document.addEventListener('DOMContentLoaded', function() {
+ initializeReviewForm();
+ initializeImageUpload();
+});
+
+// 初始化评价表单
+function initializeReviewForm() {
+ const starRating = document.getElementById('starRating');
+ const ratingInput = document.getElementById('rating');
+ const ratingText = document.getElementById('ratingText');
+ const reviewForm = document.getElementById('reviewForm');
+
+ if (starRating) {
+ const stars = starRating.querySelectorAll('.star');
+ const ratingTexts = {
+ 1: '很差',
+ 2: '较差',
+ 3: '一般',
+ 4: '满意',
+ 5: '非常满意'
+ };
+
+ let currentRating = 0; // 当前选中的评分
+
+ // 初始化:设置所有星星为空心
+ stars.forEach(star => {
+ star.textContent = '☆'; // 空心星星
+ });
+
+ // 星级点击事件
+ stars.forEach((star, index) => {
+ star.addEventListener('click', function() {
+ const rating = index + 1;
+ setRating(rating);
+ });
+
+ // 鼠标悬停事件
+ star.addEventListener('mouseenter', function() {
+ const rating = index + 1;
+ showHoverStars(rating);
+
+ // 显示临时评分文字
+ const tempText = ratingTexts[rating] || '请选择评分';
+ ratingText.textContent = tempText;
+ ratingText.style.backgroundColor = '#ff6b35';
+ ratingText.style.color = 'white';
+ ratingText.style.borderColor = '#ff6b35';
+ });
+ });
+
+ // 鼠标离开星级评分区域
+ starRating.addEventListener('mouseleave', function() {
+ showSelectedStars(currentRating);
+
+ // 恢复原来的评分文字
+ if (currentRating > 0) {
+ ratingText.textContent = ratingTexts[currentRating];
+ ratingText.classList.add('selected');
+ ratingText.style.backgroundColor = '#ff6b35';
+ ratingText.style.color = 'white';
+ ratingText.style.borderColor = '#ff6b35';
+ } else {
+ ratingText.textContent = '请选择评分';
+ ratingText.classList.remove('selected');
+ ratingText.style.backgroundColor = '#f8f9fa';
+ ratingText.style.color = '#666';
+ ratingText.style.borderColor = '#e9ecef';
+ }
+ });
+
+ // 设置评分
+ function setRating(rating) {
+ currentRating = rating;
+ ratingInput.value = rating;
+ ratingText.textContent = ratingTexts[rating] || '请选择评分';
+ ratingText.classList.add('selected');
+ ratingText.style.backgroundColor = '#ff6b35';
+ ratingText.style.color = 'white';
+ ratingText.style.borderColor = '#ff6b35';
+ showSelectedStars(rating);
+ }
+
+ // 显示悬停状态的星星
+ function showHoverStars(rating) {
+ stars.forEach((star, index) => {
+ star.classList.remove('filled');
+ if (index < rating) {
+ star.textContent = '★'; // 实心星星
+ star.classList.add('filled');
+ } else {
+ star.textContent = '☆'; // 空心星星
+ }
+ });
+ }
+
+ // 显示选中状态的星星
+ function showSelectedStars(rating) {
+ stars.forEach((star, index) => {
+ star.classList.remove('filled');
+ if (index < rating) {
+ star.textContent = '★'; // 实心星星
+ star.classList.add('filled');
+ } else {
+ star.textContent = '☆'; // 空心星星
+ }
+ });
+ }
+ }
+
+ // 表单提交
+ if (reviewForm) {
+ reviewForm.addEventListener('submit', function(e) {
+ e.preventDefault();
+ submitReview();
+ });
+ }
+}
+
+// 初始化图片上传
+function initializeImageUpload() {
+ const uploadArea = document.getElementById('uploadArea');
+ const imageInput = document.getElementById('imageInput');
+ const uploadedImages = document.getElementById('uploadedImages');
+
+ if (!uploadArea || !imageInput) return;
+
+ let uploadedImageUrls = [];
+
+ // 点击上传区域
+ uploadArea.addEventListener('click', function() {
+ imageInput.click();
+ });
+
+ // 拖拽上传
+ uploadArea.addEventListener('dragover', function(e) {
+ e.preventDefault();
+ this.style.borderColor = '#007bff';
+ });
+
+ uploadArea.addEventListener('dragleave', function(e) {
+ e.preventDefault();
+ this.style.borderColor = '#ddd';
+ });
+
+ uploadArea.addEventListener('drop', function(e) {
+ e.preventDefault();
+ this.style.borderColor = '#ddd';
+
+ const files = Array.from(e.dataTransfer.files);
+ handleFiles(files);
+ });
+
+ // 文件选择
+ imageInput.addEventListener('change', function() {
+ const files = Array.from(this.files);
+ handleFiles(files);
+ });
+
+ // 处理文件上传
+ function handleFiles(files) {
+ if (uploadedImageUrls.length + files.length > 5) {
+ showAlert('最多只能上传5张图片', 'warning');
+ return;
+ }
+
+ files.forEach(file => {
+ if (!file.type.startsWith('image/')) {
+ showAlert('只能上传图片文件', 'warning');
+ return;
+ }
+
+ if (file.size > 5 * 1024 * 1024) {
+ showAlert('图片大小不能超过5MB', 'warning');
+ return;
+ }
+
+ uploadImage(file);
+ });
+ }
+
+ // 上传图片到服务器
+ function uploadImage(file) {
+ const formData = new FormData();
+ formData.append('file', file);
+
+ // 显示上传进度
+ const previewElement = createImagePreview(URL.createObjectURL(file), true);
+ uploadedImages.appendChild(previewElement);
+
+ fetch('/review/upload_image', {
+ method: 'POST',
+ body: formData
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.success) {
+ // 更新预览元素
+ const img = previewElement.querySelector('img');
+ img.src = data.url;
+ // 强制设置图片样式
+ forceImageStyles(img);
+ previewElement.classList.remove('uploading');
+ previewElement.dataset.url = data.url;
+ uploadedImageUrls.push(data.url);
+ } else {
+ showAlert(data.message || '图片上传失败', 'error');
+ previewElement.remove();
+ }
+ })
+ .catch(error => {
+ showAlert('图片上传失败', 'error');
+ previewElement.remove();
+ });
+ }
+
+ // 创建图片预览元素
+ function createImagePreview(src, isUploading = false) {
+ const div = document.createElement('div');
+ div.className = `image-preview ${isUploading ? 'uploading' : ''}`;
+
+ // 强制设置容器样式
+ div.style.cssText = `
+ position: relative !important;
+ width: 80px !important;
+ height: 80px !important;
+ max-width: 80px !important;
+ max-height: 80px !important;
+ min-width: 80px !important;
+ min-height: 80px !important;
+ border-radius: 8px !important;
+ overflow: hidden !important;
+ border: 2px solid #e9ecef !important;
+ flex-shrink: 0 !important;
+ flex-grow: 0 !important;
+ display: inline-block !important;
+ box-sizing: border-box !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ vertical-align: top !important;
+ `;
+
+ const img = document.createElement('img');
+ img.src = src;
+ img.alt = '评价图片';
+
+ // 强制设置图片样式
+ forceImageStyles(img);
+
+ const removeBtn = document.createElement('button');
+ removeBtn.className = 'remove-btn';
+ removeBtn.innerHTML = '×';
+ removeBtn.type = 'button';
+ removeBtn.style.cssText = `
+ position: absolute !important;
+ top: 2px !important;
+ right: 2px !important;
+ background: rgba(255, 255, 255, 0.9) !important;
+ border: none !important;
+ border-radius: 50% !important;
+ width: 20px !important;
+ height: 20px !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: center !important;
+ cursor: pointer !important;
+ font-size: 12px !important;
+ color: #dc3545 !important;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.2) !important;
+ z-index: 10 !important;
+ `;
+
+ removeBtn.onclick = function() {
+ const url = div.dataset.url;
+ if (url) {
+ uploadedImageUrls = uploadedImageUrls.filter(u => u !== url);
+ }
+ div.remove();
+ };
+
+ div.appendChild(img);
+ div.appendChild(removeBtn);
+
+ return div;
+ }
+
+ // 强制设置图片样式的函数
+ function forceImageStyles(img) {
+ img.style.cssText = `
+ display: block !important;
+ width: 80px !important;
+ height: 80px !important;
+ max-width: 80px !important;
+ max-height: 80px !important;
+ min-width: 80px !important;
+ min-height: 80px !important;
+ object-fit: cover !important;
+ border-radius: 6px !important;
+ box-sizing: border-box !important;
+ position: relative !important;
+ top: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ border: none !important;
+ outline: none !important;
+ background: none !important;
+ vertical-align: top !important;
+ flex-shrink: 0 !important;
+ flex-grow: 0 !important;
+ `;
+
+ // 图片加载完成后再次强制设置样式
+ img.onload = function() {
+ forceImageStyles(this);
+ };
+ }
+
+ // 获取上传的图片URL列表
+ window.getUploadedImages = function() {
+ return uploadedImageUrls;
+ };
+}
+
+// 提交评价
+function submitReview() {
+ const submitBtn = document.getElementById('submitBtn');
+ const orderId = document.getElementById('orderId').value;
+ const productId = document.getElementById('productId').value;
+ const rating = document.getElementById('rating').value;
+ const content = document.getElementById('content').value;
+ const isAnonymous = document.getElementById('isAnonymous').checked;
+
+ // 验证
+ if (!rating) {
+ showAlert('请选择评分', 'warning');
+ return;
+ }
+
+ // 禁用提交按钮
+ submitBtn.disabled = true;
+ submitBtn.innerHTML = '
提交中...';
+
+ const data = {
+ order_id: parseInt(orderId),
+ product_id: parseInt(productId),
+ rating: parseInt(rating),
+ content: content.trim(),
+ is_anonymous: isAnonymous,
+ images: window.getUploadedImages ? window.getUploadedImages() : []
+ };
+
+ fetch('/review/submit', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(data)
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.success) {
+ showAlert(data.message, 'success');
+ setTimeout(() => {
+ window.location.href = `/order/detail/${orderId}`;
+ }, 1500);
+ } else {
+ showAlert(data.message, 'error');
+ }
+ })
+ .catch(error => {
+ showAlert('提交失败,请重试', 'error');
+ })
+ .finally(() => {
+ // 恢复提交按钮
+ submitBtn.disabled = false;
+ submitBtn.innerHTML = '
提交评价';
+ });
+}
+
+// 加载商品评价列表(用于商品详情页)
+function loadProductReviews(productId, page = 1, rating = null) {
+ const reviewsContainer = document.getElementById('reviewsContainer');
+ if (!reviewsContainer) return;
+
+ const params = new URLSearchParams({
+ page: page
+ });
+
+ if (rating) {
+ params.append('rating', rating);
+ }
+
+ reviewsContainer.innerHTML = '
加载中...
';
+
+ fetch(`/review/product/${productId}?${params}`)
+ .then(response => response.json())
+ .then(data => {
+ if (data.success) {
+ renderReviews(data);
+ } else {
+ reviewsContainer.innerHTML = '
加载失败
';
+ }
+ })
+ .catch(error => {
+ reviewsContainer.innerHTML = '
加载失败
';
+ });
+}
+
+// 渲染评价列表
+function renderReviews(data) {
+ const reviewsContainer = document.getElementById('reviewsContainer');
+ if (!reviewsContainer) return;
+
+ let html = '';
+
+ // 评价统计
+ if (data.stats) {
+ html += renderReviewStats(data.stats);
+ }
+
+ // 评价筛选
+ html += renderReviewFilter();
+
+ // 评价列表
+ if (data.reviews && data.reviews.length > 0) {
+ data.reviews.forEach(review => {
+ html += renderReviewItem(review);
+ });
+
+ // 分页
+ if (data.pagination && data.pagination.pages > 1) {
+ html += renderPagination(data.pagination);
+ }
+ } else {
+ html += '
暂无评价
';
+ }
+
+ reviewsContainer.innerHTML = html;
+}
+
+// 渲染评价统计
+function renderReviewStats(stats) {
+ const goodRate = stats.good_rate || 0;
+ const totalReviews = stats.total_reviews || 0;
+
+ let html = `
+
+
+
+
${goodRate}%
+
好评率 (${totalReviews}条评价)
+
+
+ `;
+
+ for (let i = 5; i >= 1; i--) {
+ const count = stats.rating_stats[i] || 0;
+ const percentage = totalReviews > 0 ? (count / totalReviews * 100) : 0;
+
+ html += `
+
+ `;
+ }
+
+ html += `
+
+
+
+ `;
+
+ return html;
+}
+
+// 渲染评价筛选
+function renderReviewFilter() {
+ return `
+
+
+
+
+
+
+ `;
+}
+
+// 渲染单个评价 - 修复图片和头像问题
+function renderReviewItem(review) {
+ let html = `
+
+
+ `;
+
+ if (review.user_avatar) {
+ // 用户头像 - 添加内联样式强制约束尺寸
+ html += `

`;
+ } else {
+ html += `
+
+
`;
+ }
+
+ html += `
+
+
${review.username}
+
${new Date(review.created_at).toLocaleDateString()}
+
+
+
+
+ ${review.rating_stars}
+ ${review.rating}分
+
+ `;
+
+ if (review.content) {
+ html += `
${review.content}
`;
+ }
+
+ if (review.images && review.images.length > 0) {
+ html += '
';
+ review.images.forEach(imageUrl => {
+ // 评价图片 - 使用特殊的类名和内联样式确保图片尺寸正确
+ html += `

`;
+ });
+ html += '
';
+ }
+
+ html += '
';
+
+ return html;
+}
+
+// 渲染分页
+function renderPagination(pagination) {
+ if (pagination.pages <= 1) return '';
+
+ let html = '
';
+
+ return html;
+}
+
+// 筛选评价
+function filterReviews(rating) {
+ // 更新筛选按钮状态
+ const filterButtons = document.querySelectorAll('.reviews-filter .btn');
+ filterButtons.forEach(btn => btn.classList.remove('active'));
+ event.target.classList.add('active');
+
+ // 重新加载评价
+ loadProductReviews(window.currentProductId, 1, rating);
+}
+
+// 显示图片模态框
+function showImageModal(imageUrl) {
+ const modal = document.getElementById('imageModal');
+ const modalImage = document.getElementById('modalImage');
+
+ if (modal && modalImage) {
+ modalImage.src = imageUrl;
+ new bootstrap.Modal(modal).show();
+ }
+}
+
+// 显示提示信息
+function showAlert(message, type = 'info') {
+ // 创建警告框
+ const alertDiv = document.createElement('div');
+ alertDiv.className = `alert alert-${type === 'error' ? 'danger' : type} alert-dismissible fade show position-fixed`;
+ alertDiv.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
+ alertDiv.innerHTML = `
+ ${message}
+
+ `;
+
+ // 添加到页面
+ document.body.appendChild(alertDiv);
+
+ // 自动消失
+ setTimeout(() => {
+ if (alertDiv.parentNode) {
+ alertDiv.remove();
+ }
+ }, 5000);
+}
+
+// 全局变量,用于存储当前商品ID
+window.currentProductId = null;
diff --git a/app/templates/admin/base.html b/app/templates/admin/base.html
index 2e75765..51e055b 100644
--- a/app/templates/admin/base.html
+++ b/app/templates/admin/base.html
@@ -45,8 +45,8 @@
-
+
订单管理
diff --git a/app/templates/admin/logs.html b/app/templates/admin/logs.html
new file mode 100644
index 0000000..3de58a9
--- /dev/null
+++ b/app/templates/admin/logs.html
@@ -0,0 +1,245 @@
+{% extends "admin/base.html" %}
+
+{% block title %}操作日志 - 太白购物商城管理后台{% endblock %}
+
+{% block page_title %}操作日志{% endblock %}
+{% block page_description %}查看系统操作日志,监控用户和管理员行为{% endblock %}
+
+{% block extra_css %}
+
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+
{{ logs.total }}
+
总日志数
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ logs.items | selectattr('user_type', 'equalto', 1) | list | length }}
+
用户操作
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ logs.items | selectattr('user_type', 'equalto', 2) | list | length }}
+
管理员操作
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ today_logs_count }}
+
今日操作
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 时间 |
+ 操作者 |
+ 操作类型 |
+ 操作内容 |
+ IP地址 |
+ 用户代理 |
+
+
+
+ {% if logs.items %}
+ {% for log in logs.items %}
+
+
+ {{ log.created_at.strftime('%Y-%m-%d') if log.created_at else '-' }}
+ {{ log.created_at.strftime('%H:%M:%S') if log.created_at else '' }}
+ |
+
+
+
+ {{ '管理员' if log.user_type == 2 else '用户' }}
+
+ #{{ log.user_id or '-' }}
+
+ |
+
+ {{ log.action }}
+ |
+
+
+ {% if log.resource_type %}
+ {{ log.resource_type }}
+ {% if log.resource_id %}
+ #{{ log.resource_id }}
+ {% endif %}
+ {% else %}
+ -
+ {% endif %}
+
+ |
+
+ {{ log.ip_address or '-' }}
+ |
+
+
+ {% if log.user_agent %}
+
+ {{ log.user_agent[:50] }}{% if log.user_agent|length > 50 %}...{% endif %}
+
+ {% else %}
+ -
+ {% endif %}
+
+ |
+
+ {% endfor %}
+ {% else %}
+
+
+
+
+ 暂无操作日志
+ {% if user_type or action %}
+ 尝试调整筛选条件
+ {% endif %}
+
+ |
+
+ {% endif %}
+
+
+
+
+
+ {% if logs.pages > 1 %}
+
+ {% endif %}
+
+
+{% endblock %}
+
+{% block extra_js %}
+
+{% endblock %}
diff --git a/app/templates/admin/order_detail.html b/app/templates/admin/order_detail.html
new file mode 100644
index 0000000..260aaf0
--- /dev/null
+++ b/app/templates/admin/order_detail.html
@@ -0,0 +1,426 @@
+{% extends "admin/base.html" %}
+
+{% block title %}订单详情 - 太白购物商城管理后台{% endblock %}
+
+{% block page_title %}订单详情{% endblock %}
+{% block page_description %}订单号:{{ order.order_sn }}{% endblock %}
+
+{% block extra_css %}
+
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+
+ 订单号: |
+ {{ order.order_sn }} |
+
+
+ 用户信息: |
+
+ {{ order.user.username }}
+ {% if order.user.phone %}
+ {{ order.user.phone }}
+ {% endif %}
+ |
+
+
+ 订单状态: |
+
+ {{ order.get_status_text() }}
+ |
+
+
+ 支付方式: |
+
+ {% if order.payment_method %}
+ {{ order.payment_method }}
+ {% else %}
+ 未设置
+ {% endif %}
+ |
+
+
+
+
+
+
+ 创建时间: |
+ {{ order.created_at.strftime('%Y-%m-%d %H:%M:%S') }} |
+
+ {% if order.shipped_at %}
+
+ 发货时间: |
+ {{ order.shipped_at.strftime('%Y-%m-%d %H:%M:%S') }} |
+
+ {% endif %}
+ {% if order.received_at %}
+
+ 收货时间: |
+ {{ order.received_at.strftime('%Y-%m-%d %H:%M:%S') }} |
+
+ {% endif %}
+
+ 配送方式: |
+ {{ order.shipping_method or '标准配送' }} |
+
+
+
+
+
+ {% if order.remark %}
+
+
订单备注:
+
{{ order.remark }}
+
+ {% endif %}
+
+
+
+
+
+
+
+ {% set receiver = order.get_receiver_info() %}
+ {% if receiver %}
+
+
+
+
+ 收货人: |
+ {{ receiver.receiver_name }} |
+
+
+ 联系电话: |
+ {{ receiver.receiver_phone }} |
+
+
+
+
+
+
+ 收货地址: |
+ {{ receiver.full_address }} |
+
+ {% if receiver.postal_code %}
+
+ 邮政编码: |
+ {{ receiver.postal_code }} |
+
+ {% endif %}
+
+
+
+ {% else %}
+
暂无收货信息
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+ 商品信息 |
+ 单价 |
+ 数量 |
+ 小计 |
+
+
+
+ {% for item in order.order_items %}
+
+
+
+ {% if item.product_image %}
+ 
+ {% endif %}
+
+ {{ item.product_name }}
+ {% if item.spec_combination %}
+ {{ item.spec_combination }}
+ {% endif %}
+ {% if item.sku_code %}
+ SKU: {{ item.sku_code }}
+ {% endif %}
+
+
+ |
+ ¥{{ "%.2f"|format(item.price) }} |
+ {{ item.quantity }} |
+ ¥{{ "%.2f"|format(item.total_price) }} |
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 商品总额: |
+ ¥{{ "%.2f"|format(order.total_amount) }} |
+
+
+ 运费: |
+ ¥{{ "%.2f"|format(order.shipping_fee) }} |
+
+
+ 实付金额: |
+ ¥{{ "%.2f"|format(order.actual_amount) }} |
+
+
+
+
+
+
+ {% if payment %}
+
+
+
+
+
+ 支付流水号: |
+ {{ payment.payment_sn }} |
+
+
+ 支付状态: |
+
+
+ {{ payment.get_status_text() }}
+
+ |
+
+ {% if payment.paid_at %}
+
+ 支付时间: |
+ {{ payment.paid_at.strftime('%Y-%m-%d %H:%M:%S') }} |
+
+ {% endif %}
+ {% if payment.third_party_sn %}
+
+ 第三方流水号: |
+ {{ payment.third_party_sn }} |
+
+ {% endif %}
+
+
+
+ {% endif %}
+
+
+ {% if shipping_info %}
+
+
+
+
+
+ 物流公司: |
+ {{ shipping_info.shipping_company }} |
+
+
+ 快递单号: |
+ {{ shipping_info.tracking_number }} |
+
+
+ 物流状态: |
+
+
+ {% if shipping_info.shipping_status == 1 %}已发货
+ {% elif shipping_info.shipping_status == 2 %}运输中
+ {% elif shipping_info.shipping_status == 3 %}已送达
+ {% endif %}
+
+ |
+
+
+
+
+ {% endif %}
+
+
+
+
+
+
+ {% if order.status == 2 %}
+
+ {% endif %}
+
+ {% if order.status in [2, 3] %}
+
+ {% endif %}
+
+ {% if order.can_cancel() %}
+
+ {% endif %}
+
+
+ 返回列表
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
+
+{% block extra_js %}
+
+{% endblock %}
diff --git a/app/templates/admin/orders.html b/app/templates/admin/orders.html
index e69de29..fd308be 100644
--- a/app/templates/admin/orders.html
+++ b/app/templates/admin/orders.html
@@ -0,0 +1,365 @@
+{% extends "admin/base.html" %}
+
+{% block title %}订单管理 - 太白购物商城管理后台{% endblock %}
+
+{% block page_title %}订单管理{% endblock %}
+{% block page_description %}管理系统中的所有订单{% endblock %}
+
+{% block extra_css %}
+
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+
{{ order_stats.get(0, {}).get('count', 0) + order_stats.get(1, {}).get('count', 0) + order_stats.get(2, {}).get('count', 0) + order_stats.get(3, {}).get('count', 0) + order_stats.get(4, {}).get('count', 0) + order_stats.get(5, {}).get('count', 0) + order_stats.get(6, {}).get('count', 0) + order_stats.get(7, {}).get('count', 0) }}
+
总订单
+
+
+
+
+
+
+
{{ order_stats.get(1, {}).get('count', 0) }}
+
待支付
+
+
+
+
+
+
+
{{ order_stats.get(2, {}).get('count', 0) }}
+
待发货
+
+
+
+
+
+
+
{{ order_stats.get(3, {}).get('count', 0) }}
+
待收货
+
+
+
+
+
+
+
{{ order_stats.get(5, {}).get('count', 0) }}
+
已完成
+
+
+
+
+
+
+
{{ order_stats.get(6, {}).get('count', 0) }}
+
已取消
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if orders.items %}
+
+
+
+
+ 订单号 |
+ 用户信息 |
+ 订单金额 |
+ 订单状态 |
+ 支付方式 |
+ 创建时间 |
+ 操作 |
+
+
+
+ {% for order in orders.items %}
+
+
+ {{ order.order_sn }}
+ ID: {{ order.id }}
+ |
+
+ {{ order.user.username }}
+ {% if order.user.phone %}
+ {{ order.user.phone }}
+ {% endif %}
+ |
+
+ ¥{{ "%.2f"|format(order.actual_amount) }}
+ {% if order.shipping_fee > 0 %}
+ 含运费: ¥{{ "%.2f"|format(order.shipping_fee) }}
+ {% endif %}
+ |
+
+ {{ order.get_status_text() }}
+ |
+
+ {% if order.payment_method %}
+ {{ order.payment_method }}
+ {% else %}
+ 未设置
+ {% endif %}
+ |
+
+ {{ order.created_at.strftime('%Y-%m-%d') }}
+ {{ order.created_at.strftime('%H:%M:%S') }}
+ |
+
+
+
+ 详情
+
+
+ {% if order.status == 2 %}
+
+ {% endif %}
+
+ {% if order.status in [2, 3] %}
+
+ {% endif %}
+
+ {% if order.can_cancel() %}
+
+ {% endif %}
+
+ |
+
+ {% endfor %}
+
+
+
+
+
+ {% if orders.pages > 1 %}
+
+ {% endif %}
+
+ {% else %}
+
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
+
+{% block extra_js %}
+
+{% endblock %}
diff --git a/app/templates/admin/users.html b/app/templates/admin/users.html
index e69de29..0ace774 100644
--- a/app/templates/admin/users.html
+++ b/app/templates/admin/users.html
@@ -0,0 +1,279 @@
+{% extends "admin/base.html" %}
+
+{% block title %}用户管理 - 太白购物商城管理后台{% endblock %}
+
+{% block page_title %}用户管理{% endblock %}
+{% block page_description %}管理系统用户,查看用户信息和状态{% endblock %}
+
+{% block extra_css %}
+
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ users.total }}
+
总用户数
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ users.items | selectattr('status', 'equalto', 1) | list | length }}
+
正常用户
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ users.items | selectattr('status', 'equalto', 0) | list | length }}
+
禁用用户
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ week_new_users }}
+
本周新增
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 用户ID |
+ 用户信息 |
+ 联系方式 |
+ 注册时间 |
+ 状态 |
+ 操作 |
+
+
+
+ {% if users.items %}
+ {% for user in users.items %}
+
+
+ #{{ user.id }}
+ |
+
+
+
+ {% if user.avatar_url %}
+ 
+ {% else %}
+
+
+
+ {% endif %}
+
+
+ {{ user.username }}
+ {% if user.nickname %}
+ {{ user.nickname }}
+ {% endif %}
+
+
+ |
+
+
+ {% if user.email %}
+ {{ user.email }}
+ {% endif %}
+ {% if user.phone %}
+ {{ user.phone }}
+ {% endif %}
+ {% if not user.email and not user.phone %}
+ 未设置
+ {% endif %}
+
+ |
+
+ {{ user.created_at.strftime('%Y-%m-%d') if user.created_at else '-' }}
+ {{ user.created_at.strftime('%H:%M:%S') if user.created_at else '' }}
+ |
+
+
+ {{ '正常' if user.status == 1 else '禁用' }}
+
+ |
+
+
+
+
+
+ |
+
+ {% endfor %}
+ {% else %}
+
+
+
+
+ 暂无用户数据
+ {% if search or status %}
+ 尝试调整搜索条件
+ {% endif %}
+
+ |
+
+ {% endif %}
+
+
+
+
+
+ {% if users.pages > 1 %}
+
+ {% endif %}
+
+
+
+
+
+
+{% endblock %}
+
+{% block extra_js %}
+
+{% endblock %}
diff --git a/app/templates/base.html b/app/templates/base.html
index ef39781..deca345 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -4,10 +4,14 @@
{% block title %}太白购物商城{% endblock %}
+
+
-
- {% block styles %}{% endblock %}
+
+
+
+ {% block head %}{% endblock %}
@@ -29,23 +33,12 @@
全部商品
-
-
- 商品分类
-
-
-
-
-
- {% with messages = get_flashed_messages(with_categories=true) %}
- {% if messages %}
-