Django 從 0 到 1 打造完整電商平臺:購物車頁面增刪改查商品數(shù)量

IT策士 10余年一線大廠經(jīng)驗,專注 IT 思維、架構(gòu)、職場進階。我會在公眾號、今日頭條持續(xù)發(fā)布最新文章,助你少走彎路。


上一篇我們完成了購物車模型的最終設(shè)計,還跑通了單元測試。今天,模型里的字段將真正“活”起來——我們要實現(xiàn)購物車的完整增刪改查,包括從商品詳情頁一鍵加入購物車、在購物車頁面調(diào)整數(shù)量、勾選結(jié)算、刪除商品,以及全選和合計金額的實時計算。

這篇代碼量不小,前端交互也比較豐富,但每一步我都會把邏輯講透。跟上節(jié)奏,做完這一篇,你的電商項目就已經(jīng)能跑通“選商品 → 加購物車 → 改數(shù)量”的完整閉環(huán)了。


一、需求回顧

我們今天要實現(xiàn)的功能清單:

  1. 加入購物車:在商品詳情頁選中規(guī)格后,點擊“加入購物車”,AJAX 提交,成功后給出提示。

  2. 購物車列表頁

    • 以表格形式展示商品圖片、名稱、規(guī)格、單價、數(shù)量調(diào)整器、小計、勾選框。

    • 支持修改數(shù)量(+/- 按鈕或直接輸入),自動更新小計和合計,且不能超過庫存。

    • 單行勾選/取消勾選,支持全選/取消全選。

    • 勾選商品后,底部合計金額實時更新。

    • 刪除單個商品(帶確認)。

    • 批量刪除勾選商品。

    • 有“去結(jié)算”按鈕,跳轉(zhuǎn)到確認訂單頁(后續(xù)實現(xiàn))。


二、配置 URL 路由

apps/cart/ 下創(chuàng)建 urls.py(如果還沒有):

from django.urls import path
from . import views

app_name = 'cart'

urlpatterns = [
    path('', views.cart_list, name='cart_list'),
    path('add/', views.cart_add, name='cart_add'),
    path('update/<int:item_id>/', views.cart_update, name='cart_update'),
    path('delete/<int:item_id>/', views.cart_delete, name='cart_delete'),
    path('batch_delete/', views.cart_batch_delete, name='cart_batch_delete'),
    path('check/<int:item_id>/', views.cart_check, name='cart_check'),
    path('check_all/', views.cart_check_all, name='cart_check_all'),
]

然后在項目 django_ecommerce/urls.py 中 include:

urlpatterns = [
    # ... 其他路由 ...
    path('cart/', include('apps.cart.urls')),
]

三、編寫視圖

編輯 apps/cart/views.py(新創(chuàng)建該文件):

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.db import transaction
from .models import CartItem
from products.models import SKU


@login_required(login_url='users:login')
def cart_list(request):
    """購物車列表頁"""
    cart_items = CartItem.objects.filter(user=request.user).select_related('sku__spu').prefetch_related('sku__images')

    total_price = sum(item.sku.price * item.quantity for item in cart_items if item.is_checked)
    total_count = sum(1 for item in cart_items if item.is_checked)

    return render(request, 'cart/cart_list.html', {
        'cart_items': cart_items,
        'total_price': total_price,
        'total_count': total_count,
    })


@require_POST
@login_required(login_url='users:login')
def cart_add(request):
    """加入購物車(AJAX)"""
    sku_id = request.POST.get('sku_id')
    quantity = int(request.POST.get('quantity', 1))

    if not sku_id:
        return JsonResponse({'ok': False, 'msg': '參數(shù)錯誤'}, status=400)

    sku = get_object_or_404(SKU, pk=sku_id, is_active=True)

    if quantity > sku.stock:
        return JsonResponse({'ok': False, 'msg': f'庫存不足(僅剩 {sku.stock} 件)'}, status=400)

    # 查找是否已存在該 SKU
    cart_item, created = CartItem.objects.get_or_create(
        user=request.user,
        sku=sku,
        defaults={'quantity': quantity}
    )

    if not created:
        # 已存在,累加數(shù)量
        new_quantity = cart_item.quantity + quantity
        if new_quantity > sku.stock:
            return JsonResponse({'ok': False, 'msg': f'庫存不足(當前已有 {cart_item.quantity} 件,僅剩 {sku.stock} 件)'}, status=400)
        cart_item.quantity = new_quantity
        cart_item.save()

    return JsonResponse({
        'ok': True,
        'msg': '已加入購物車',
        'cart_count': request.user.cart_items.count()
    })


@require_POST
@login_required(login_url='users:login')
def cart_update(request, item_id):
    """更新購物車商品數(shù)量"""
    cart_item = get_object_or_404(CartItem, pk=item_id, user=request.user)

    action = request.POST.get('action')  # 'increase', 'decrease', 'set'
    quantity = request.POST.get('quantity')

    if action == 'increase':
        new_qty = cart_item.quantity + 1
    elif action == 'decrease':
        new_qty = cart_item.quantity - 1
    elif action == 'set' and quantity:
        new_qty = int(quantity)
    else:
        return JsonResponse({'ok': False, 'msg': '參數(shù)錯誤'}, status=400)

    if new_qty < 1:
        return JsonResponse({'ok': False, 'msg': '數(shù)量不能小于1'}, status=400)
    if new_qty > cart_item.sku.stock:
        return JsonResponse({'ok': False, 'msg': f'庫存不足(最多可買 {cart_item.sku.stock} 件)'}, status=400)

    cart_item.quantity = new_qty
    cart_item.save()

    # 重新計算勾選商品的總價
    checked_items = request.user.cart_items.filter(is_checked=True).select_related('sku')
    total_price = sum(item.sku.price * item.quantity for item in checked_items)

    return JsonResponse({
        'ok': True,
        'new_quantity': cart_item.quantity,
        'subtotal': float(cart_item.sku.price * cart_item.quantity),
        'total_price': float(total_price),
    })


@require_POST
@login_required(login_url='users:login')
def cart_delete(request, item_id):
    """刪除單個商品"""
    cart_item = get_object_or_404(CartItem, pk=item_id, user=request.user)
    cart_item.delete()

    # 重新計算
    checked_items = request.user.cart_items.filter(is_checked=True).select_related('sku')
    total_price = sum(item.sku.price * item.quantity for item in checked_items)

    return JsonResponse({
        'ok': True,
        'msg': '已刪除',
        'total_price': float(total_price),
    })


@require_POST
@login_required(login_url='users:login')
def cart_batch_delete(request):
    """批量刪除勾選的商品"""
    item_ids = request.POST.getlist('item_ids[]')
    if item_ids:
        CartItem.objects.filter(pk__in=item_ids, user=request.user).delete()

    checked_items = request.user.cart_items.filter(is_checked=True).select_related('sku')
    total_price = sum(item.sku.price * item.quantity for item in checked_items)

    return JsonResponse({
        'ok': True,
        'msg': '已刪除選中商品',
        'total_price': float(total_price),
    })


@require_POST
@login_required(login_url='users:login')
def cart_check(request, item_id):
    """切換單個商品的勾選狀態(tài)"""
    cart_item = get_object_or_404(CartItem, pk=item_id, user=request.user)
    cart_item.is_checked = not cart_item.is_checked
    cart_item.save(update_fields=['is_checked'])

    checked_items = request.user.cart_items.filter(is_checked=True).select_related('sku')
    total_price = sum(item.sku.price * item.quantity for item in checked_items)

    return JsonResponse({
        'ok': True,
        'is_checked': cart_item.is_checked,
        'total_price': float(total_price),
        'checked_count': checked_items.count(),
        'all_checked': not request.user.cart_items.filter(is_checked=False).exists(),
    })


@require_POST
@login_required(login_url='users:login')
def cart_check_all(request):
    """全選或取消全選"""
    checked = request.POST.get('checked') == 'true'
    request.user.cart_items.update(is_checked=checked)

    total_price = 0.0
    if checked:
        items = request.user.cart_items.select_related('sku')
        total_price = sum(item.sku.price * item.quantity for item in items)

    return JsonResponse({
        'ok': True,
        'total_price': float(total_price),
        'checked_count': request.user.cart_items.filter(is_checked=True).count() if checked else 0,
    })

視圖關(guān)鍵點:

  • 所有操作都通過 login_required 保護。

  • 加入購物車使用 get_or_create,存在則累加數(shù)量,不存在則新建。

  • 數(shù)量修改嚴格校驗庫存上下限。

  • 每次操作后都重新計算總價并返回 JSON,前端可以直接更新顯示。

  • 批量刪除接收前端傳來的 item_ids[] 數(shù)組。


四、創(chuàng)建購物車頁面模板

創(chuàng)建 apps/cart/templates/cart/cart_list.html

{% extends 'base.html' %}
{% load static %}

{% block title %}我的購物車{% endblock %}

{% block content %}
<h3 class="mb-4">?? 我的購物車</h3>

{% if cart_items %}
<div class="card shadow-sm">
    <div class="card-body p-0">
        <table class="table table-hover mb-0" id="cart-table">
            <thead class="table-light">
                <tr>
                    <th style="width: 40px;">
                        <input type="checkbox" id="check-all" {% if total_count == cart_items|length and cart_items %}checked{% endif %}>
                    </th>
                    <th>商品信息</th>
                    <th style="width: 120px;">單價</th>
                    <th style="width: 180px;">數(shù)量</th>
                    <th style="width: 120px;">小計</th>
                    <th style="width: 80px;">操作</th>
                </tr>
            </thead>
            <tbody>
                {% for item in cart_items %}
                <tr id="cart-item-{{ item.id }}">
                    <td>
                        <input type="checkbox" class="item-checkbox" data-item-id="{{ item.id }}" {% if item.is_checked %}checked{% endif %}>
                    </td>
                    <td>
                        <div class="d-flex align-items-center">
                            <img src="{{ item.sku.main_image_url }}" alt="{{ item.sku.name }}" 
                                 style="width: 60px; height: 60px; object-fit: cover;" class="me-3 rounded">
                            <div>
                                <a href="{% url 'products:spu_detail' item.sku.spu.id %}" class="text-decoration-none">
                                    {{ item.sku.name }}
                                </a>
                            </div>
                        </div>
                    </td>
                    <td>¥{{ item.sku.price }}</td>
                    <td>
                        <div class="input-group input-group-sm">
                            <button class="btn btn-outline-secondary btn-minus" data-item-id="{{ item.id }}">?</button>
                            <input type="text" class="form-control text-center quantity-input" 
                                   value="{{ item.quantity }}" data-item-id="{{ item.id }}" 
                                   data-stock="{{ item.sku.stock }}" style="max-width: 60px;">
                            <button class="btn btn-outline-secondary btn-plus" data-item-id="{{ item.id }}">+</button>
                        </div>
                    </td>
                    <td class="subtotal" id="subtotal-{{ item.id }}">
                        ¥{{ item.sku.price|floatformat:2 }}
                    </td>
                    <td>
                        <button class="btn btn-sm btn-outline-danger btn-delete" data-item-id="{{ item.id }}">刪除</button>
                    </td>
                </tr>
                {% endfor %}
            </tbody>
        </table>
    </div>
</div>

<!-- 底部操作欄 -->
<div class="card shadow-sm mt-3">
    <div class="card-body d-flex justify-content-between align-items-center">
        <div>
            <button class="btn btn-outline-danger btn-sm" id="batch-delete-btn">刪除選中</button>
        </div>
        <div class="text-end">
            <span class="me-3">
                已選 <strong id="checked-count">{{ total_count }}</strong> 件,
                合計:<span class="text-danger fs-4 fw-bold" id="total-price">¥{{ total_price|floatformat:2 }}</span>
            </span>
            <a href="#" class="btn btn-danger btn-lg" id="checkout-btn">去結(jié)算</a>
        </div>
    </div>
</div>

{% else %}
<div class="text-center py-5">
    <p class="text-muted fs-5">購物車還是空的哦~</p>
    <a href="{% url 'products:sku_list' %}" class="btn btn-primary">去逛逛</a>
</div>
{% endif %}
{% endblock %}

{% block extra_js %}
<script>
    // 獲取 CSRF Token
    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            const cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                const cookie = cookies[i].trim();
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    const csrftoken = getCookie('csrftoken');

    // 封裝 AJAX POST
    function postJSON(url, data, callback) {
        fetch(url, {
            method: 'POST',
            headers: {
                'X-CSRFToken': csrftoken,
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: new URLSearchParams(data)
        })
        .then(response => response.json())
        .then(callback)
        .catch(error => console.error('Error:', error));
    }

    // 更新頁面上的總價和選中數(shù)量
    function updateSummary(total_price, checked_count) {
        document.getElementById('total-price').textContent = '¥' + total_price.toFixed(2);
        if (checked_count !== undefined) {
            document.getElementById('checked-count').textContent = checked_count;
        }
    }

    // 更新全部勾選框的狀態(tài)
    function updateCheckAll() {
        const allCheckboxes = document.querySelectorAll('.item-checkbox');
        const allChecked = Array.from(allCheckboxes).every(cb => cb.checked);
        document.getElementById('check-all').checked = allChecked;
    }

    // 數(shù)量減少
    document.querySelectorAll('.btn-minus').forEach(btn => {
        btn.addEventListener('click', function() {
            const itemId = this.dataset.itemId;
            const input = document.querySelector(`.quantity-input[data-item-id="${itemId}"]`);
            let qty = parseInt(input.value);
            if (qty <= 1) return;
            postJSON(`/cart/update/${itemId}/`, { action: 'decrease' }, data => {
                if (data.ok) {
                    input.value = data.new_quantity;
                    document.getElementById(`subtotal-${itemId}`).textContent = '¥' + data.subtotal.toFixed(2);
                    updateSummary(data.total_price);
                } else {
                    alert(data.msg);
                }
            });
        });
    });

    // 數(shù)量增加
    document.querySelectorAll('.btn-plus').forEach(btn => {
        btn.addEventListener('click', function() {
            const itemId = this.dataset.itemId;
            const input = document.querySelector(`.quantity-input[data-item-id="${itemId}"]`);
            const stock = parseInt(input.dataset.stock);
            let qty = parseInt(input.value);
            if (qty >= stock) {
                alert('庫存不足');
                return;
            }
            postJSON(`/cart/update/${itemId}/`, { action: 'increase' }, data => {
                if (data.ok) {
                    input.value = data.new_quantity;
                    document.getElementById(`subtotal-${itemId}`).textContent = '¥' + data.subtotal.toFixed(2);
                    updateSummary(data.total_price);
                } else {
                    alert(data.msg);
                }
            });
        });
    });

    // 數(shù)量直接輸入
    document.querySelectorAll('.quantity-input').forEach(input => {
        input.addEventListener('change', function() {
            const itemId = this.dataset.itemId;
            const stock = parseInt(this.dataset.stock);
            let qty = parseInt(this.value);
            if (isNaN(qty) || qty < 1) qty = 1;
            if (qty > stock) qty = stock;
            this.value = qty;
            postJSON(`/cart/update/${itemId}/`, { action: 'set', quantity: qty }, data => {
                if (data.ok) {
                    document.getElementById(`subtotal-${itemId}`).textContent = '¥' + data.subtotal.toFixed(2);
                    updateSummary(data.total_price);
                } else {
                    alert(data.msg);
                }
            });
        });
    });

    // 單個刪除
    document.querySelectorAll('.btn-delete').forEach(btn => {
        btn.addEventListener('click', function() {
            const itemId = this.dataset.itemId;
            if (!confirm('確定要刪除該商品嗎?')) return;
            postJSON(`/cart/delete/${itemId}/`, {}, data => {
                if (data.ok) {
                    document.getElementById(`cart-item-${itemId}`).remove();
                    updateSummary(data.total_price);
                    updateCheckAll();
                    if (document.querySelectorAll('#cart-table tbody tr').length === 0) {
                        location.reload(); // 購物車為空,刷新顯示空狀態(tài)
                    }
                }
            });
        });
    });

    // 單選框勾選
    document.querySelectorAll('.item-checkbox').forEach(cb => {
        cb.addEventListener('change', function() {
            const itemId = this.dataset.itemId;
            postJSON(`/cart/check/${itemId}/`, {}, data => {
                if (data.ok) {
                    updateSummary(data.total_price, data.checked_count);
                    updateCheckAll();
                }
            });
        });
    });

    // 全選/取消全選
    document.getElementById('check-all').addEventListener('change', function() {
        const checked = this.checked;
        postJSON(`/cart/check_all/`, { checked: checked }, data => {
            if (data.ok) {
                updateSummary(data.total_price, data.checked_count);
                document.querySelectorAll('.item-checkbox').forEach(cb => {
                    cb.checked = checked;
                });
            }
        });
    });

    // 批量刪除
    document.getElementById('batch-delete-btn').addEventListener('click', function() {
        const checkedBoxes = document.querySelectorAll('.item-checkbox:checked');
        if (checkedBoxes.length === 0) {
            alert('請選擇要刪除的商品');
            return;
        }
        if (!confirm(`確定要刪除選中的 ${checkedBoxes.length} 件商品嗎?`)) return;
        const itemIds = Array.from(checkedBoxes).map(cb => cb.dataset.itemId);
        postJSON(`/cart/batch_delete/`, { 'item_ids[]': itemIds }, data => {
            if (data.ok) {
                checkedBoxes.forEach(cb => {
                    document.getElementById(`cart-item-${cb.dataset.itemId}`).remove();
                });
                updateSummary(data.total_price, 0);
                updateCheckAll();
                if (document.querySelectorAll('#cart-table tbody tr').length === 0) {
                    location.reload();
                }
            }
        });
    });

    // 小計初始化(模板中的單價默認小計可能不對,頁面加載時計算一下)
    document.querySelectorAll('.subtotal').forEach(td => {
        const row = td.closest('tr');
        const input = row.querySelector('.quantity-input');
        const price = parseFloat(row.querySelector('td:nth-child(3)').textContent.replace('¥', ''));
        const qty = parseInt(input.value);
        td.textContent = '¥' + (price * qty).toFixed(2);
    });
</script>
{% endblock %}

五、完善商品詳情頁的“加入購物車”

打開 apps/products/templates/products/spu_detail.html,需要給“加入購物車”按鈕綁定 AJAX 請求,并獲取當前選中的 SKU ID 和數(shù)量。

在詳情頁的 {% block extra_js %} 中追加以下代碼(在已有的規(guī)格切換邏輯之后):

// 獲取當前選中的 SKU ID
function getCurrentSkuId() {
    const matched = findMatchingSku();
    return matched ? matched.id : null;
}

// 加入購物車按鈕
const addToCartBtn = document.getElementById('add-to-cart-btn');
if (addToCartBtn) {
    addToCartBtn.addEventListener('click', function() {
        const skuId = getCurrentSkuId();
        if (!skuId) {
            alert('請選擇完整的規(guī)格');
            return;
        }
        // 獲取數(shù)量(如果以后有數(shù)量選擇器)
        const quantity = 1;

        fetch('{% url "cart:cart_add" %}', {
            method: 'POST',
            headers: {
                'X-CSRFToken': getCookie('csrftoken'),
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: new URLSearchParams({ sku_id: skuId, quantity: quantity })
        })
        .then(response => response.json())
        .then(data => {
            if (data.ok) {
                alert('已加入購物車!');
                // 可選:更新導(dǎo)航欄購物車數(shù)量徽標
            } else {
                alert(data.msg);
            }
        });
    });
}

// 獲取 CSRF Token(若詳情頁沒有,需增加該函數(shù))
function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

同時,確保模板中按鈕是啟用的(已登錄),不再 disabled:

{% if user.is_authenticated %}
    <button class="btn btn-primary btn-lg" id="add-to-cart-btn">加入購物車</button>
{% else %}
    <a href="{% url 'users:login' %}?next={{ request.path }}" class="btn btn-primary btn-lg">登錄后購買</a>
{% endif %}

六、更新導(dǎo)航欄,顯示購物車數(shù)量

修改 templates/base.html,在導(dǎo)航欄購物車鏈接上加入徽標(利用 user.cart_items.count,需在視圖中傳遞或使用模板 context processor。簡單起見,我們可以使用 Django 模板中直接訪問 user.cart_items.count,但可能增加查詢。更優(yōu)雅的方式是自定義一個 context processor,但現(xiàn)在先簡單處理,僅在有數(shù)據(jù)時展示):

<li class="nav-item">
    <a class="nav-link" href="{% url 'cart:cart_list' %}">
        購物車
        {% if user.is_authenticated and user.cart_items.count > 0 %}
            <span class="badge bg-danger">{{ user.cart_items.count }}</span>
        {% endif %}
    </a>
</li>

七、測試完整流程

啟動服務(wù)器:

python manage.py runserver

7.1 加入購物車測試

  1. 登錄后進入 iPhone 15 詳情頁 /products/spu/1/

  2. 選擇 128GB 午夜色,點擊“加入購物車”

  3. 彈出“已加入購物車!”,導(dǎo)航欄購物車圖標旁出現(xiàn)數(shù)字 1

控制臺輸出:

[25/May/2026 09:30:12] "POST /cart/add/ HTTP/1.1" 200 45

7.2 購物車列表查看

點擊導(dǎo)航欄“購物車”,進入 /cart/

頁面展示:

  • 表格顯示:圖片、iPhone 15 128GB 午夜色、單價 ¥5999.00、數(shù)量 1、小計 ¥5999.00、勾選框已勾選、操作有刪除按鈕。

  • 底部:已選 1 件,合計 ¥5999.00,去結(jié)算按鈕。

終端:

[25/May/2026 09:31:05] "GET /cart/ HTTP/1.1" 200 9867

7.3 修改數(shù)量

點擊 + 按鈕,數(shù)量變?yōu)?2,小計變?yōu)?¥11998.00,合計隨之更新。終端輸出:

[25/May/2026 09:31:30] "POST /cart/update/1/ HTTP/1.1" 200 67

若增加到超過庫存(例如 101),彈出“庫存不足”。

7.4 勾選操作

取消第一個商品的勾選,合計立即變?yōu)?¥0.00,全選框自動取消。終端:

[25/May/2026 09:32:00] "POST /cart/check/1/ HTTP/1.1" 200 78

再次勾選,合計恢復(fù) ¥11998.00,全選框恢復(fù)勾選。

7.5 全選與批量刪除

加入另一個商品(如 Samsung Galaxy S24),購物車有兩個商品,都勾選。點擊“刪除選中”,確認后兩個商品消失,頁面刷新為空購物車狀態(tài)。

[25/May/2026 09:33:10] "POST /cart/batch_delete/ HTTP/1.1" 200 56
[25/May/2026 09:33:10] "GET /cart/ HTTP/1.1" 200 4987

八、總結(jié)與下集預(yù)告

今天我們完成了一個功能豐富、交互流暢的購物車頁面:

  • AJAX 加入購物車,實時反饋;

  • 購物車列表支持數(shù)量增減、直接輸入,庫存校驗嚴格;

  • 單行勾選、全選/取消全選、批量刪除;

  • 所有操作實時更新合計金額,無需刷新頁面;

  • 導(dǎo)航欄購物車數(shù)量徽標。

購物車模塊全線竣工!下一步,用戶就要把購物車里的寶貝變成訂單了。第 18 篇,我們將進入下單流程的鋪墊——訂單模型設(shè)計,回顧訂單表結(jié)構(gòu),梳理訂單狀態(tài)流轉(zhuǎn),為確認訂單頁和提交訂單做好數(shù)據(jù)準備。精彩繼續(xù),明天見!

想了解更多還可以去公眾號、今日頭條搜索「IT策士」,一起升級 IT 思維 !


本文為《Django 從 0 到 1 打造完整電商平臺》系列第 17 篇。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容