from django.contrib import admin
from django.utils.html import format_html
from django.db.models import Sum
from .models import ESP32Config, Order, Salesperson, WeChatPayConfig, Service, ARService
import qrcode
from io import BytesIO
import base64
# 自定义后台标题
admin.site.site_header = "量迹AI硬件销售管理后台"
admin.site.site_title = "量迹AI后台"
admin.site.index_title = "欢迎使用量迹AI管理系统"
@admin.register(WeChatPayConfig)
class WeChatPayConfigAdmin(admin.ModelAdmin):
list_display = ('app_id', 'mch_id', 'is_active', 'notify_url')
list_filter = ('is_active',)
search_fields = ('app_id', 'mch_id')
fieldsets = (
('基本配置', {
'fields': ('app_id', 'mch_id', 'is_active')
}),
('安全配置', {
'fields': ('api_key', 'app_secret')
}),
('回调配置', {
'fields': ('notify_url',)
}),
)
@admin.register(ESP32Config)
class ESP32ConfigAdmin(admin.ModelAdmin):
list_display = ('name', 'chip_type', 'price', 'has_camera', 'has_microphone')
list_filter = ('chip_type', 'has_camera')
search_fields = ('name', 'description')
fieldsets = (
('基本信息', {
'fields': ('name', 'price', 'description')
}),
('硬件参数', {
'fields': ('chip_type', 'flash_size', 'ram_size', 'has_camera', 'has_microphone')
}),
('详情页图片', {
'fields': ('detail_image', 'detail_image_url'),
'description': '图片上传和URL二选一,优先使用URL'
}),
)
@admin.register(Service)
class ServiceAdmin(admin.ModelAdmin):
list_display = ('title', 'created_at')
search_fields = ('title', 'description')
fieldsets = (
('基本信息', {
'fields': ('title', 'description', 'color')
}),
('图标', {
'fields': ('icon', 'icon_url'),
'description': '图标上传和URL二选一,优先使用URL'
}),
('详情页图片', {
'fields': ('detail_image', 'detail_image_url'),
'description': '图片上传和URL二选一,优先使用URL'
}),
('详细内容', {
'fields': ('features',)
}),
)
@admin.register(ARService)
class ARServiceAdmin(admin.ModelAdmin):
list_display = ('title', 'created_at')
search_fields = ('title', 'description')
fieldsets = (
('基本信息', {
'fields': ('title', 'description')
}),
('封面/长图', {
'fields': ('cover_image', 'cover_image_url'),
'description': '图片上传和URL二选一,优先使用URL'
}),
)
@admin.register(Salesperson)
class SalespersonAdmin(admin.ModelAdmin):
list_display = ('name', 'code', 'total_sales', 'view_promotion_url')
search_fields = ('name', 'code')
readonly_fields = ('promotion_qr_code', 'promotion_url_display', 'total_sales_display')
def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.annotate(
_total_sales=Sum('orders__total_price', default=0)
)
return queryset
def total_sales(self, obj):
# 仅计算已支付的订单
paid_sales = obj.orders.filter(status='paid').aggregate(total=Sum('total_price'))['total']
return f"¥{paid_sales or 0:.2f}"
total_sales.short_description = "累计销售额 (已支付)"
total_sales.admin_order_field = '_total_sales'
def total_sales_display(self, obj):
return self.total_sales(obj)
total_sales_display.short_description = "累计销售额 (已支付)"
def promotion_url(self, obj):
# 假设前端部署在 localhost:5173,生产环境需配置
base_url = "http://localhost:5173"
return f"{base_url}/?ref={obj.code}"
def view_promotion_url(self, obj):
url = self.promotion_url(obj)
return format_html('打开推广链接', url)
view_promotion_url.short_description = "推广链接"
def promotion_url_display(self, obj):
return self.promotion_url(obj)
promotion_url_display.short_description = "完整推广链接"
def promotion_qr_code(self, obj):
if not obj.code:
return "请先保存以生成二维码"
url = self.promotion_url(obj)
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(url)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
buffer = BytesIO()
img.save(buffer, format="PNG")
img_str = base64.b64encode(buffer.getvalue()).decode()
return format_html('
', img_str)
promotion_qr_code.short_description = "推广二维码"
fieldsets = (
('基本信息', {
'fields': ('name', 'code')
}),
('推广工具', {
'fields': ('promotion_url_display', 'promotion_qr_code')
}),
('业绩统计', {
'fields': ('total_sales_display',)
}),
)
@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
list_display = ('id', 'customer_name', 'config', 'total_price', 'status', 'salesperson', 'created_at')
list_filter = ('status', 'salesperson', 'created_at')
search_fields = ('id', 'customer_name', 'phone_number', 'wechat_trade_no')
readonly_fields = ('total_price', 'created_at', 'wechat_trade_no')
fieldsets = (
('订单信息', {
'fields': ('config', 'quantity', 'total_price', 'status', 'created_at')
}),
('客户信息', {
'fields': ('customer_name', 'phone_number', 'shipping_address')
}),
('销售归属', {
'fields': ('salesperson',)
}),
('支付信息', {
'fields': ('wechat_trade_no',)
}),
)