news 2026/9/14 14:30:27

Django构建汽车美容行业网站:从项目搭建到业务建模实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Django构建汽车美容行业网站:从项目搭建到业务建模实战

简介:这份源码包面向汽车美容行业线上转型需求,提供基于Django框架的完整网站设计与实现方案,适合Web开发学习者、行业从业者及需要快速搭建预约服务平台的开发者参考。项目涵盖车辆美容预约、服务套餐选择、技师团队展示、在线支付、会员管理、客户反馈与数据分析等核心业务模块,前后端逻辑清晰。压缩包共66个文件,其中55个Python文件负责视图、模型、中间件及工具函数等后端逻辑,7个XML配置文件用于数据库、缓存与中间件等运行参数设定,另有Git忽略文件、Idea工程文件与说明文档,整体68KB,目录结构按应用模块划分,便于按需查阅。目前已有276人学习下载。通过该项目可掌握Django框架下的模型设计、路由配置、用户交互及前后端协作思路,也能借鉴汽车美容业务的功能拆解方式,是一份兼具实战价值与教学意义的源码案例。

1. 汽车美容行业网站设计为什么选 Django 而不是展示型 CMS

汽车美容门店的官网需求,往往被误当成一个展示页:几个服务项目、几张效果图、一个预约电话就完事。但真到上线交付,就会发现数据是活的——车型档案要跟会员绑定、施工单要关联美容师提成、洗车/打蜡/镀晶的价格随时调、高峰期预约要排班。这类状态多、关系密、还要给店长做后台录入的业务,展示型 CMS 撑不住,纯前端静态站更撑不住。Django 的立项逻辑就在这里:自带 ORM 和 migration,模型改完直接同步数据库;自带 Admin 后台,不写一行前端就能让店员录入项目和订单;自带认证和权限,会员登录、员工分权是现成能力。这也解释了为什么检索“python django搭建web项目”“django创建app”的源码包里,汽车美容、汽修、健身房这类垂直行业占了相当大的比例——它们是典型的 Model 密集业务,天然适合 MTV 架构。源码交付的价值在于拿回去就能跑,而不是重新搭框架。

2. 搭建 Django 项目骨架与美容网站的基础 settings

2.1 先定项目结构:一个业务拆两个 app

拿到“汽车美容行业网站设计源码”,第一件要做的不是写 models,而是把 Django 项目目录立起来。行业源码常见的败笔是把所有 model 塞进一个 app,几百行代码堆在 models.py 里,后续改需求时牵一发动全身。我的做法是按业务域拆开:customer管客户、车辆和会员等级,shop管服务项目、预约和工单,Django 自带的auth管后台员工账号,三者通过外键关联,边界清楚。

python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install django mysqlclient pillow django-simpleui django-admin startproject beauty_salon . python manage.py startapp customer python manage.py startapp shop

这段命令里值得说的是依赖选择:mysqlclient是生产环境连接 MySQL 的常用驱动;pillow用于服务项目图标、案例效果图的 ImageField 处理;django-simpleui属于后加的 Admin 美化组件,装不装都能跑,装上之后admin界面更接近管理后台审美。先装好再创建项目,省得回头补包。Windows 上如果mysqlclient编译报错,常见的替代方案是换用pymysql,并在项目的__init__.py里调用pymysql.install_as_MySQLdb(),但对新手来说,本地开发直接用默认 SQLite 起步,生产再切 MySQL,路径更平滑。

2.2 settings 里与汽车美容业务直接相关的 6 处配置

项目目录生成后,beauty_salon/settings.py是第一个要动刀的文件。默认配置跑通没问题,但离“可交付的源码”还差几步。

# beauty_salon/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'simpleui', # admin 界面美化,放在 admin 前 'customer', 'shop', ] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'beauty_salon', 'USER': 'root', 'PASSWORD': 'your_password', 'HOST': '127.0.0.1', 'PORT': '3306', 'CONN_MAX_AGE': 60, 'OPTIONS': {'charset': 'utf8mb4'}, } } TIME_ZONE = 'Asia/Shanghai' USE_TZ = True MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media' LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/'

参数说明按重要程度排:数据库DATABASESOPTIONS指定utf8mb4是为了让车牌号、英文大小写、中文备注都能正常存取,汽车美容订单里经常混着“VIP”“京A·12345”这类混合字符,默认utf8在索引和排序上会有兼容问题。CONN_MAX_AGE = 60表示 MySQL 连接在请求结束后保留 60 秒,省去重复握手开销,业务量不大的美容门店站,这个值已经够用。TIME_ZONEAsia/Shanghai是因为预约时间是以门店本地时钟为准,如果保留默认 UTC,订单里的施工时间会整体偏移 8 小时。MEDIA_ROOT指向上传文件落地目录,汽车美容的效果图、施工前后对比照都从这里读写。LOGIN_URLLOGIN_REDIRECT_URL是 Django 认证机制的默认跳转,会员与后台登录都需要它们。这些配置项在交付时都需要提供样例和注释,否则接手的人不知道哪几个值必须改。

2.3 路由与静态资源的最小可用配置

配好 settings 后,根路由beauty_salon/urls.py需要把两个 app 的 URL 挂进去,同时补上开发环境的媒体文件服务。这一步漏掉,Admin 后台会显示正常但上传的图片全都 404。

# beauty_salon/urls.py from django.contrib import admin from django.urls import path, include from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('', include('customer.urls')), path('', include('shop.urls')), ] if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

这段代码的逻辑是:include把各 app 的 URLconf 按前缀挂到根路由,不用app_name的话项目小也能跑,但我习惯在每个 app 的 urls.py 里定义app_name,方便模板里写shop:service_list这类命名空间;static(settings.MEDIA_URL, document_root=...)只在DEBUG=True时生效,生产环境必须交给 nginx,源码交付说明里要强调这一点。到这里项目骨架已经能被python manage.py runserver启动,下一步才是把汽车美容的业务实体建模出来。

3. 汽车美容核心业务实体在 Django models 里的数据建模

3.1 客户、车辆、会员等级:一对多的关系怎么建

汽车美容行业的特点是一人多车。客户可能家里两台车、公司三台车,洗车卡绑定在车牌上还是绑定在客户上,业务上经常争论。我的建模原则是:会员等级、储值余额这类资产挂在Customer上,车辆档案单独建Car,通过外键指向客户,并且用related_name='cars'让反向查询读起来像英语句子。

# customer/models.py from django.db import models class Customer(models.Model): MEMBER_CHOICES = [ ('normal', '普通客户'), ('silver', '银卡会员'), ('gold', '金卡会员'), ] name = models.CharField('姓名', max_length=32) phone = models.CharField('手机号', max_length=11, unique=True) level = models.CharField('会员等级', max_length=16, choices=MEMBER_CHOICES, default='normal') balance = models.DecimalField('储值余额', max_digits=10, decimal_places=2, default=0) created_at = models.DateTimeField('建档时间', auto_now_add=True) def __str__(self): return f'{self.name}({self.phone})' class Car(models.Model): customer = models.ForeignKey(Customer, on_delete=models.CASCADE, verbose_name='车主', related_name='cars') plate_no = models.CharField('车牌号', max_length=16, unique=True) brand = models.CharField('品牌', max_length=32) model_name = models.CharField('车型', max_length=32, blank=True) mileage = models.IntegerField('当前里程(km)', default=0) def __str__(self): return f'{self.plate_no} {self.brand}'

字段选择体现的是业务约束:phoneunique=True是因为门店系统靠手机号识别客户,重复建档会导致储值对不上;balanceDecimalField而不是FloatField,因为浮点数在金额累加时会出现 0.1+0.2=0.30000000000000004 的精度问题,流水和余额都不能接受这种误差;on_delete=models.CASCADE表示删客户时连带删车辆档案,实际交付时客户有消费记录,我不会用 CASCADE,而是会改成PROTECT或软删除字段,这个属于交付前根据需求调整的地方。related_name='cars'让代码里可以直接写customer.cars.all(),比默认的car_set可读性好得多。

3.2 服务项目与预约:多对多用中间表而不是自动建表

服务项目和预约的关系是典型的多对多:一次预约可以做精洗加打蜡,也可以做镀晶加内饰养护。Django 的ManyToManyField可以直接建关联表,但汽车美容场景里,预约明细还需要记录“分配给哪个美容师”“现场实收多少钱”,这些字段挂在自动生成的关联表上很别扭,所以我会显式建中间模型AppointmentItem

# shop/models.py from django.db import models from customer.models import Customer, Car class ServiceItem(models.Model): CATEGORY_CHOICES = [ ('wash', '洗车'), ('beauty', '美容'), ('maintain', '养护'), ] name = models.CharField('项目名称', max_length=64) category = models.CharField('分类', max_length=16, choices=CATEGORY_CHOICES, default='wash') price = models.DecimalField('标准价', max_digits=8, decimal_places=2) duration = models.IntegerField('预计工时(分钟)', default=30) icon = models.ImageField('图标', upload_to='service/', blank=True) def __str__(self): return self.name class Appointment(models.Model): STATUS_CHOICES = [ ('pending', '待确认'), ('confirmed', '已确认'), ('done', '已完成'), ('canceled', '已取消'), ] customer = models.ForeignKey(Customer, on_delete=models.CASCADE, verbose_name='预约客户') car = models.ForeignKey(Car, on_delete=models.CASCADE, verbose_name='预约车辆') appoint_time = models.DateTimeField('预约时间') status = models.CharField('状态', max_length=16, choices=STATUS_CHOICES, default='pending') remark = models.TextField('备注', blank=True) created_at = models.DateTimeField('提交时间', auto_now_add=True) class AppointmentItem(models.Model): appointment = models.ForeignKey(Appointment, on_delete=models.CASCADE, related_name='items') service = models.ForeignKey(ServiceItem, on_delete=models.PROTECT) quantity = models.PositiveIntegerField('数量', default=1) sale_price = models.DecimalField('实收单价', max_digits=8, decimal_places=2) employee = models.ForeignKey('Employee', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='施工美容师')

这段设计有几个关键决策。AppointmentItem.sale_price是给“实收单价”留的快照字段,因为服务项目调价后,历史预约不能跟着变,查询时优先取sale_price而不是service.priceon_delete=models.PROTECT放在ServiceItem上,防止有人手滑删掉一个仍有预约记录关联的项目。employee = models.ForeignKey('Employee', ...)用了字符串引用而不是直接写类名,是为了避免和后面定义的Employee产生导入顺序问题。Appointment里冗余存了car,虽然通过 customer 也能查到,但预约时明确指定车辆是业务刚需,门店要安排工位和美容师,不能模棱两可。

3.3 查询与删除对象:N+1 问题的基本解法

models 建完之后,业务查询和删除要特别注意性能。汽车美容的预约列表常常按客户姓名搜索,ORM 直接遍历会引发 N+1 次查询:先查 10 条预约,每条预约又查一次客户、车辆、明细,页面响应能慢上一倍。Django 的解法是select_relatedprefetch_related,前者用于外键的单表 JOIN,后者用于多对多和反向关联。

# shop/views.py 中查询预约列表 from django.db import transaction appointments = Appointment.objects.select_related( 'customer', 'car' ).prefetch_related('items__service').filter( status='pending' ) # 删除对象:批量取消一周前的草稿预约 with transaction.atomic(): deleted, _ = Appointment.objects.filter( status='canceled', created_at__lt='2025-01-01' ).delete()

select_related('customer', 'car')会生成一条带 LEFT JOIN 的 SQL,把外键对象一次取回;.prefetch_related('items__service')则生成两条独立查询,再在内存里组装,适合跨关系表的集合。删除操作里transaction.atomic()是关键,预约删除可能连带明细删除,如果中途出错,事务回滚能保证主表和子表数据一致。delete()返回的元组(total_deleted, detail_dict)里,第一个元素是所有对象的总删除数,适合写进操作日志。这里提醒一点:生产环境很少真正delete()用户数据,常用做法是加is_activeis_archived字段做软删除,避免误删后无法恢复。

4. 视图与模板联动:让服务列表和预约在页面里流转

4.1 用类视图展示服务项目,带搜索和分页

汽车美容门店的服务项目通常 20 到 50 个,列表页不能一次全铺开,客户需要能搜“镀晶”“打蜡”这种关键词。Django 的ListView配合get_queryset重写是最省力的方案,比手写HttpResponse+ 分页逻辑干净得多。

# shop/views.py from django.views.generic import ListView from .models import ServiceItem class ServiceListView(ListView): model = ServiceItem template_name = 'shop/service_list.html' context_object_name = 'services' paginate_by = 9 def get_queryset(self): qs = super().get_queryset() keyword = self.request.GET.get('q', '').strip() if keyword: qs = qs.filter(name__icontains=keyword) return qs

这里的参数逻辑是:paginate_by = 9对应门店常见的三列布局,一页 9 个项目视觉上最整齐;context_object_name指定模板里循环变量的名字,模板写{% for s in services %},而不是默认的object_list,语义更直观;get_querysetname__icontains=keyword是大小写不敏感的模糊匹配,搜索“镀晶”能匹配“全车镀晶”“玻璃镀晶”。模板侧需要手动渲染分页控件,ListView只把page_obj传给模板,样式要自己写。

<!-- shop/templates/shop/service_list.html --> <div class="service-grid"> {% for s in services %} <div class="service-card"> <h3><a href="{% url 'shop:service_detail' s.pk %}">{{ s.name }}</a></h3> <p>分类:{{ s.get_category_display }} | {{ s.duration }} 分钟</p> <p class="price">¥{{ s.price }}</p> </div> {% empty %} <p>暂无可预约的服务项目</p> {% endfor %} </div> <div class="pagination"> {% if page_obj.has_previous %} <a href="?q={{ request.GET.q }}&page={{ page_obj.previous_page_number }}">上一页</a> {% endif %} <span>{{ page_obj.number }} / {{ page_obj.paginator.num_pages }}</span> {% if page_obj.has_next %} <a href="?q={{ request.GET.q }}&page={{ page_obj.next_page_number }}">下一页</a> {% endif %} </div>

模板里s.get_category_display会把 models 里定义的('wash', '洗车')转换成中文“洗车”,这是 Django choices 字段自带的展示方法。分页链接里带上?q={{ request.GET.q }}是为了翻页时不丢失搜索关键词,这是个高频踩坑点:不带上 q 参数,第二页就会回到全量列表。这个模板片段可以直接搬进源码交付包里,只需要补上对应的 CSS。

4.2 预约提交:POST 表单、redirect 和 messages 传数据

预约表单是汽车美容站的核心交互。用户选择服务项目、填车牌和预约时间,提交后跳转到一个“预约成功”的提示页,同时给店长后台生成一条待确认记录。这里我使用 Django 的CreateView配合messages框架实现重定向传数据,代码量最少且符合 Django 的请求-重定向-响应模式。

# shop/views.py from django.contrib import messages from django.urls import reverse_lazy from django.views.generic import CreateView from .models import Appointment from .forms import AppointmentForm class AppointmentCreateView(CreateView): model = Appointment form_class = AppointmentForm template_name = 'shop/appointment_form.html' success_url = reverse_lazy('shop:service_list') def form_valid(self, form): form.instance.customer = self.request.user.customer messages.success(self.request, '预约已提交,等待门店电话确认') return super().form_valid(form)

这段代码中,form.instance.customer在表单里不展示、由视图自动填充,避免用户伪造别人的预约;这里的写法是把它直接挂在登录用户的 Customer 外键上。messages.success写入一条一次性消息,Django 在下一个请求的模板里可以通过{% if messages %}渲染出来。与重定向搭配时,消息会先存入 session,页面刷新后自动清除,不会出现刷新还在提示的尴尬。成功地址reverse_lazy而不是reverse,是因为类属性在模块加载时就求值,reverse_lazy延迟到请求时解析 URL,这两个 API 的差异也是源码评审时经常被问到的点。

这里顺带说明“django 前后端分离”的边界:汽车美容行业网站设计源码走的是服务端渲染路线,模板直接输出 HTML,好处是 SEO 友好、交付简单、不需要 CORS 和 token 管理;只有当网站需要承接小程序或 App 的 API 请求时,才有必要拆出 Django REST Framework 做前后端分离。一个会话型业务站点强行分离,反而会让源码包复杂度翻倍。

4.3 URL 命名与模板反向解析对照

URLconf 是源码里最长被忽略但又最容易乱的部分。我按功能模块把路由分组,统一用app_namepath name做命名空间。下面是 shop app 的 URL 配置,也是模板里{% url 'shop:xxx' %}的对照表。

# shop/urls.py from django.urls import path from . import views app_name = 'shop' urlpatterns = [ path('', views.ServiceListView.as_view(), name='service_list'), path('service/<int:pk>/', views.ServiceDetailView.as_view(), name='service_detail'), path('appointment/new/', views.AppointmentCreateView.as_view(), name='appointment_create'), path('appointments/', views.AppointmentListView.as_view(), name='appointment_list'), ]
URL 表达式name作用
''service_list首页服务项目列表 + 搜索
service/<int:pk>/service_detail项目详情,含施工说明
appointment/new/appointment_create提交预约表单
appointments/appointment_list当前用户的历史预约列表

这里的int:pk是 Django 路径转换器,只匹配整数,访问/service/abc/直接 404,省得在视图里自己try/except校验参数。命名空间shop:加上去之后,即使后续再加一个orderapp 有同名 URL,模板里也互不冲突。源码交付时,这份 URL 表通常会写进 README,它决定了接手者能否快速定位功能对应的代码文件。

5. Django admin 定制、源码整理与上线排错

5.1 admin 界面美化与列表页高频配置项

汽车美容网站交付后,真正每天登录后台的是门店店长,不是程序员。店长电脑分辨率普遍不高,鼠标操作也慢,默认 Django admin 是能用,但list_display不配置的话,订单列表只会显示对象字符串,完全没法检索。实际操作里我会给每个核心 model 都写 admin 注册,并利用django-simpleui优化列表和表单的视觉密度。

# shop/admin.py from django.contrib import admin from .models import ServiceItem, Appointment, AppointmentItem @admin.register(ServiceItem) class ServiceItemAdmin(admin.ModelAdmin): list_display = ('name', 'category', 'price', 'duration') list_filter = ('category',) search_fields = ('name',) list_per_page = 20 @admin.register(Appointment) class AppointmentAdmin(admin.ModelAdmin): list_display = ('appoint_time', 'customer', 'car', 'status') list_filter = ('status', 'appoint_time') search_fields = ('customer__name', 'car__plate_no') inlines = [AppointmentItemInline]

list_display里的statusprice直接显示字段值,店长不用点进详情就能确认预约、核对金额;search_fields = ('customer__name', 'car__plate_no')是跨表搜索,写的是 Django 的双下划线语法,ORM 会 JOIN 到客户表和车辆表查询,注意这里的customer__namecustomername必须和 model 字段完全一致,写成customer_name会报字段错误。list_filter左侧筛选栏会按日期和状态下钻,这是店长每天早上看“今天预约”的操作入口。AppointmentItemInline是预约明细的行内编辑,在预约编辑页直接增删项目,比跳转子页面快得多。这些配置配合 simpleui 后,后台整体质感接近市面上的商业管理软件。

运行前执行迁移命令,缺了这步 admin 页面会直接 500:

python manage.py makemigrations customer shop python manage.py migrate python manage.py createsuperuser python manage.py collectstatic

collectstatic是部署前必做的一步,Django admin 的 CSS、JS 会复制到STATIC_ROOT指定的目录,如果跳过,线上后台会变成没有样式的纯文字页面。DEBUG=False之后,只有执行过collectstatic,静态资源才能被 nginx 正确 serve。

5.2 源码交付的常见坑与排错表

交付源码包时,踩坑记录通常比功能说明更值钱。下面这几项是“django 项目”落地里几乎必遇到的,我把现象和处置方案做成对照,可以直接写进交付文档。

现象根因处置
mysqlclient安装报错缺少 MySQL 客户端编译依赖Linux 装libmysqlclient-dev,Windows 用 pymysql 替代
admin 后台无样式未执行collectstaticSTATIC_ROOT未配置配置STATIC_ROOT并运行 collectstatic
上传图片 404MEDIA_URL路由没挂在 urls.py 里static()追加,或交给 nginx alias
保存时间差 8 小时TIME_ZONE默认 UTC改为Asia/Shanghai,并确保 MySQL 连接串 timezone 一致
预约列表查询慢N+1 查询列表视图加select_related/prefetch_related

排错表的作用是让接手者不必从头读源码,“django install mysqlclient”这类问题在真机部署时几乎人人都会遇到。在看到报错黑窗时直接对表查根因,比读一屏 traceback 快得多。

5.3 一个值得写进源码包的验证技巧:自定义 management command 造演示数据

最后给一个源码交付时非常讨巧的做法:写一个 Django 自定义命令,一键生成演示数据。门店老板验收系统时,最想知道的是“你的系统有数据是啥样”,而不会接受一个空荡荡的后台。

# shop/management/commands/seed_demo.py import random from django.core.management.base import BaseCommand from django.utils import timezone from customer.models import Customer, Car from shop.models import ServiceItem, Appointment class Command(BaseCommand): help = '生成演示客户、车辆和预约数据' def add_arguments(self, parser): parser.add_argument('--customers', type=int, default=10) def handle(self, *args, **options): count = options['customers'] for i in range(count): customer, _ = Customer.objects.get_or_create( phone=f'1380000{i:04d}', defaults={'name': f'演示客户{i}'} ) Car.objects.get_or_create( plate_no=f'京A{i:04d}', defaults={'customer': customer, 'brand': '大众', 'mileage': 20000} ) services = list(ServiceItem.objects.all()) if services: Appointment.objects.create( customer=Customer.objects.first(), car=Car.objects.first(), appoint_time=timezone.now() + timezone.timedelta(hours=2), status='pending', ) self.stdout.write(self.style.SUCCESS(f'已生成 {count} 位演示客户'))

这个命令的实用点在于:BaseCommandadd_arguments使用 argparse 语法,调用方可以执行python manage.py seed_demo --customers 30控制生成量;get_or_create保证命令可重复执行而不产生重复脏数据;self.style.SUCCESS是 Django 内置的控制台绿色输出。配合一个空的测试库,交付前跑manage.py migrate && manage.py seed_demo && manage.py runserver,一个新环境从裸机到完整后台 demo 数据只需要三分钟。验收人员第一次打开 admin 界面看到的不是空白列表,而是带客户姓名、车牌号和待确认订单的页面,这个第一印象往往直接决定源码包能不能过验收,验完自行再刷一遍即可清空演示数据。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 14:29:49

Claude Code 配 TaoToken:GLM Coding Plan 的 Base URL 和 Key 这样改

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 14:29:35

STM32C552高精度ADC电压采集实战指南

1. 项目概述&#xff1a;为什么STM32C552的ADC电压采集值得深挖&#xff1f; 你手头有一块STM32C552开发板&#xff0c;想测个电池电压、传感器输出或者电源轨状态&#xff0c;结果发现——采出来的数值跳得像心电图&#xff0c;滤波加了还是漂&#xff0c;DMA一开数据就错位&a…

作者头像 李华
网站建设 2026/9/14 14:27:02

同一把 TaoToken Key,MarsCode 从 Doubao-1.5-pro 切到 DeepSeek-R1

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 14:26:29

五颗芯片打造工业设备监测与远程IO控制终端,双MCU架构全解析

前阵子做项目选型&#xff0c;手头同时到了一批芯片&#xff1a;TLE7272-2D、GD32F427VGT6、STM32F417ZGT6、MCP4631-503E/ST、GRX350A3BC160。乍一看这就是一张“购物车清单”&#xff0c;但把它们铺到原理图工作区后我发现&#xff0c;这五颗器件刚好能组成一套完整的智能系统…

作者头像 李华
网站建设 2026/9/14 14:26:18

ASP.NET MVC 5学生宿舍管理系统开发实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华