from django.contrib import admin from django.utils.html import format_html from django.db.models import Sum from unfold.admin import ModelAdmin, TabularInline from unfold.decorators import display from .models import ESP32Config, Order, Salesperson, WeChatPayConfig, Service, ARService, ProductFeature import qrcode from io import BytesIO import base64 # 自定义后台标题 admin.site.site_header = "量迹AI硬件销售管理后台" admin.site.site_title = "量迹AI后台" admin.site.index_title = "欢迎使用量迹AI管理系统" class ProductFeatureInline(TabularInline): model = ProductFeature extra = 1 fields = ('title', 'description', 'icon_name', 'icon_image', 'icon_url', 'order') @admin.register(WeChatPayConfig) class WeChatPayConfigAdmin(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(ModelAdmin): list_display = ('name', 'chip_type', 'price', 'has_camera', 'has_microphone') list_filter = ('chip_type', 'has_camera') search_fields = ('name', 'description') inlines = [ProductFeatureInline] 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(ModelAdmin): list_display = ('title', 'created_at') search_fields = ('title', 'description') fieldsets = ( ('基本信息', { 'fields': ('title', 'description', 'color') }), ('价格与交付', { 'fields': ('price', 'unit', 'delivery_time', 'delivery_content') }), ('图标', { 'fields': ('icon', 'icon_url'), 'description': '图标上传和URL二选一,优先使用URL' }), ('详情页图片', { 'fields': ('detail_image', 'detail_image_url'), 'description': '图片上传和URL二选一,优先使用URL' }), ('详细内容', { 'fields': ('features',) }), ) @admin.register(ARService) class ARServiceAdmin(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(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 @display(description="累计销售额 (已支付)", ordering='_total_sales') 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}" 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}" @display(description="推广链接") def view_promotion_url(self, obj): url = self.promotion_url(obj) return format_html('打开推广链接', url) def promotion_url_display(self, obj): return self.promotion_url(obj) promotion_url_display.short_description = "完整推广链接" @display(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) fieldsets = ( ('基本信息', { 'fields': ('name', 'code') }), ('推广工具', { 'fields': ('promotion_url_display', 'promotion_qr_code') }), ('业绩统计', { 'fields': ('total_sales_display',) }), ) @admin.register(Order) class OrderAdmin(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',) }), )