×
微信咨询
微信二维码

长按图片识别添加或保存到相册

产品服务 帮助文档

来团科技商品多规格排序系统架构设计文档

来团科技商品多规格排序系统采用紧凑排序算法与独立排序表设计,实现规格组与规格值多层级排序,保证后台、API、小程序三端排序一致,避免SKU匹配失败,并通过Redis缓存优化高并发查询性能。

文档版本:v1.0.0 by 来团科技
创建日期:2026-03-22
项目:lt-store-pro 多商户商城系统
框架:ThinkPHP 8.0 + Vue.js + 微信小程序


一、需求背景

1.1 业务场景

商城系统中,商品规格(SKU)的排序功能直接影响用户购物体验:

  1. 后台管理需求:商家后台编辑商品时,需要对多规格组、规格值进行自定义排序
  2. 前台展示需求:小程序/APP展示商品时,需要按商家设定的顺序呈现规格选项
  3. 数据一致性需求:前后端排序规则必须一致,否则SKU匹配失败

1.2 核心挑战

挑战点 描述
多层级排序 规格组 → 规格值,两层排序关系
商品级自定义 每个商品的规格排序可以不同
前后端一致性 后台、API、小程序三端排序必须统一
高并发场景 秒杀/活动期间规格查询性能要求高
可扩展性 未来可能支持第三级分类排序

二、技术方案总览

2.1 核心设计思想

┌─────────────────────────────────────────────────────────────────┐
│                        架构分层设计                              │
├─────────────────────────────────────────────────────────────────┤
│  Controller层  │  接收排序请求,参数校验,调用Service              │
├─────────────────────────────────────────────────────────────────┤
│  Service层    │  排序业务逻辑,事务管理,排序算法实现             │
├─────────────────────────────────────────────────────────────────┤
│  Model层      │  数据访问,缓存管理,查询优化                     │
├─────────────────────────────────────────────────────────────────┤
│  Repository层 │  数据仓储模式,抽象数据操作(可选)               │
└─────────────────────────────────────────────────────────────────┘

2.2 排序策略选型

方案对比

方案 描述 优点 缺点 推荐指数
方案A:紧凑排序 使用整数序号,相邻序号间隔10 查询高效,插入方便 移动多个时需批量更新 ⭐⭐⭐⭐⭐
方案B:稀疏排序 使用浮点数/字符串 插入时无需移动 查询需额外排序,跨数据库兼容差 ⭐⭐⭐
方案C:链表形式 prev/next指针 移动无需更新其他记录 查询需递归,跨表关联复杂 ⭐⭐

技术选型:方案A(紧凑排序)

选型依据:

  1. 性能优先:整数比较在数据库索引中效率最高
  2. 批量更新友好:间隔10的策略允许少量中间插入,只需更新2-3条记录
  3. 跨数据库兼容:纯整数字段,任何数据库都支持
  4. 缓存友好:Redis Sorted Set 可直接映射

三、数据库设计

3.1 新建表:商品规格排序表

-- 商品规格排序主表(存储规格组的排序)
CREATE TABLE `ltshop_goods_spec_sort` (
    `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    `goods_id` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '商品ID',
    `spec_id` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '规格组ID',
    `sort` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '规格组排序值',
    `wxapp_id` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '小程序ID',
    `create_time` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '创建时间',
    `update_time` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '更新时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_goods_spec` (`goods_id`, `spec_id`, `wxapp_id`),
    KEY `idx_goods_sort` (`goods_id`, `sort`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品规格组排序表';

-- 商品规格值排序表(存储规格值在商品内的排序)
CREATE TABLE `ltshop_goods_spec_value_sort` (
    `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    `goods_id` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '商品ID',
    `spec_id` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '规格组ID',
    `spec_value_id` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '规格值ID',
    `sort` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '规格值排序值',
    `wxapp_id` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '小程序ID',
    `create_time` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '创建时间',
    `update_time` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '更新时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_goods_spec_value` (`goods_id`, `spec_id`, `spec_value_id`, `wxapp_id`),
    KEY `idx_goods_spec_sort` (`goods_id`, `spec_id`, `sort`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品规格值排序表';

3.2 表设计优势分析

特性 说明
分离存储 规格组排序和规格值排序分离,互不影响
唯一索引 (goods_id, spec_id, wxapp_id) 确保同一商品同规格只有一条记录
查询优化 联合索引支持 WHERE goods_id = ? ORDER BY sort 的有序查询
无冗余 排序表独立,不影响原有业务表结构
可扩展 如需支持分类排序,可新建 ltshop_category_spec_sort 表

3.3 索引设计说明

-- 规格组排序查询(按商品ID查所有规格组)
EXPLAIN SELECT * FROM ltshop_goods_spec_sort
WHERE goods_id = 10001
ORDER BY sort ASC;

-- 规格值排序查询(按商品ID+规格组查所有规格值)
EXPLAIN SELECT * FROM ltshop_goods_spec_value_sort
WHERE goods_id = 10001 AND spec_id = 10023
ORDER BY sort ASC;

四、核心算法设计

4.1 排序算法:紧凑间隔算法

算法原理

初始状态:规格A(sort=10) → 规格B(sort=20) → 规格C(sort=30)
     ↓
插入新规格D到B和C之间
     ↓
重新计算:D=25,B和C不动(如果25还在间隔内)
     ↓
如果超出间隔(如插入10个新规格),则触发重排:
     ↓
重排后:A(10) → B(20) → D(30) → C(40)

算法实现

/**
 * 商品规格排序服务
 * Class GoodsSpecSortService
 */
class GoodsSpecSortService
{
    private const SORT_STEP = 10;      // 排序间隔
    private const SORT_INIT = 10;      // 初始排序值
    private const REBALANCE_THRESHOLD = 3; // 重排阈值(剩余间隔不足3时触发重排)

    /**
     * 批量保存规格组排序
     * @param int $goodsId 商品ID
     * @param array $specIds 规格组ID数组(按排序顺序)
     * @param int $wxappId 小程序ID
     * @return bool
     */
    public function saveSpecGroupSort(int $goodsId, array $specIds, int $wxappId): bool
    {
        $model = new GoodsSpecSort();
        $time = time();

        // 开启事务
        $model->startTrans();
        try {
            // 1. 检查是否需要重排
            $existing = $model->where('goods_id', $goodsId)
                ->where('wxapp_id', $wxappId)
                ->order('sort', 'asc')
                ->select()
                ->toArray();

            // 2. 计算新的排序值
            $sortData = [];
            $sort = self::SORT_INIT;
            foreach ($specIds as $specId) {
                $sortData[$specId] = $sort;
                $sort += self::SORT_STEP;
            }

            // 3. 检查是否需要重排(间隔不足)
            $needsRebalance = $this->checkNeedsRebalance($existing, $sortData);

            if ($needsRebalance) {
                // 触发重排,重新分配所有排序值
                $sortData = $this->rebalance($specIds);
            }

            // 4. 批量插入/更新
            $insertData = [];
            foreach ($sortData as $specId => $sort) {
                $insertData[] = [
                    'goods_id' => $goodsId,
                    'spec_id' => $specId,
                    'sort' => $sort,
                    'wxapp_id' => $wxappId,
                    'create_time' => $time,
                    'update_time' => $time,
                ];
            }

            // 使用 REPLACE INTO 实现插入或更新
            $model->replaceAll($insertData);

            $model->commit();
            return true;
        } catch (Exception $e) {
            $model->rollback();
            throw $e;
        }
    }

    /**
     * 检查是否需要重排
     */
    private function checkNeedsRebalance(array $existing, array $newData): bool
    {
        if (empty($existing)) {
            return false;
        }

        // 检查新排序是否与现有排序冲突
        $existingSorts = array_column($existing, 'sort', 'spec_id');
        foreach ($newData as $specId => $newSort) {
            if (isset($existingSorts[$specId])) {
                // spec_id 已存在,检查排序值差距
                if (abs($existingSorts[$specId] - $newSort) >= self::REBALANCE_THRESHOLD) {
                    return true;
                }
            }
        }

        // 检查是否有重复排序值
        $sortCounts = array_count_values(array_column($existing, 'sort'));
        foreach ($sortCounts as $count) {
            if ($count > 1) {
                return true;
            }
        }

        return false;
    }

    /**
     * 重排所有规格组排序
     */
    private function rebalance(array $specIds): array
    {
        $sortData = [];
        $sort = self::SORT_INIT;
        foreach ($specIds as $specId) {
            $sortData[$specId] = $sort;
            $sort += self::SORT_STEP;
        }
        return $sortData;
    }
}

4.2 查询算法:多层级排序

排序查询流程

1. 查询规格组排序(ltshop_goods_spec_sort)
       ↓
2. 查询规格值排序(ltshop_goods_spec_value_sort)
       ↓
3. 与规格关系表(ltshop_goods_spec_rel)联合查询
       ↓
4. 按 sort 字段排序返回

查询实现

/**
 * 获取商品规格数据(带排序)
 * @param int $goodsId 商品ID
 * @param int $wxappId 小程序ID
 * @return array
 */
public function getGoodsSpecData(int $goodsId, int $wxappId): array
{
    // 1. 查询规格组排序
    $specSortList = (new GoodsSpecSort())
        ->where('goods_id', $goodsId)
        ->where('wxapp_id', $wxappId)
        ->column('sort', 'spec_id');

    // 2. 查询规格值排序
    $valueSortList = (new GoodsSpecValueSort())
        ->where('goods_id', $goodsId)
        ->where('wxapp_id', $wxappId)
        ->select()
        ->toArray();

    // 构建 spec_id => [value_id => sort] 的映射
    $valueSortMap = [];
    foreach ($valueSortList as $item) {
        $valueSortMap[$item['spec_id']][$item['spec_value_id']] = $item['sort'];
    }

    // 3. 查询规格关系数据
    $specRelList = (new GoodsSpecRel())
        ->with(['spec', 'specValue'])
        ->where('goods_id', $goodsId)
        ->where('wxapp_id', $wxappId)
        ->select()
        ->toArray();

    // 4. 按排序组装数据
    $specAttrData = [];
    foreach ($specRelList as $item) {
        $specId = $item['spec_id'];
        $specValueId = $item['spec_value_id'];

        // 获取排序值(默认为0,按spec_id和value_id排序)
        $groupSort = $specSortList[$specId] ?? 0;
        $valueSort = $valueSortMap[$specId][$specValueId] ?? 0;

        // 构建排序键(用于多级排序)
        $sortKey = sprintf('%05d_%05d_%05d', $groupSort, $specId, $valueSort);

        $specAttrData[$sortKey] = [
            'group_id' => $specId,
            'group_name' => $item['spec']['spec_name'],
            'spec_items' => [],
            'group_sort' => $groupSort,
        ];
    }

    // 5. 按sortKey排序并构建spec_items
    ksort($specAttrData);

    $result = [];
    $groupMap = [];
    foreach ($specAttrData as $sortKey => $item) {
        if (!isset($groupMap[$item['group_id']])) {
            $groupMap[$item['group_id']] = count($result);
            $result[] = [
                'group_id' => $item['group_id'],
                'group_name' => $item['group_name'],
                'spec_items' => [],
                'group_sort' => $item['group_sort'],
            ];
        }

        // 查找对应的spec_value并添加
        foreach ($specRelList as $relItem) {
            if ($relItem['spec_id'] == $item['group_id']) {
                $valueSort = $valueSortMap[$item['group_id']][$relItem['spec_value_id']] ?? 0;
                $result[$groupMap[$item['group_id']]]['spec_items'][] = [
                    'item_id' => $relItem['spec_value_id'],
                    'spec_value' => $relItem['spec_value']['spec_value'],
                    'value_sort' => $valueSort,
                ];
            }
        }
    }

    // 6. 对spec_items按value_sort排序
    foreach ($result as &$group) {
        usort($group['spec_items'], function($a, $b) {
            return $a['value_sort'] - $b['value_sort'];
        });
    }

    return $result;
}

五、API接口设计

5.1 批量更新规格排序

POST /api/goods/sortSpec

请求参数:

{
    "goods_id": 10001,
    "spec_data": [
        {
            "spec_id": 10023,
            "value_data": [
                {"spec_value_id": 10025, "sort": 10},
                {"spec_value_id": 10026, "sort": 20}
            ]
        },
        {
            "spec_id": 10024,
            "value_data": [
                {"spec_value_id": 10027, "sort": 10}
            ]
        }
    ]
}

响应示例:

{
    "code": 1,
    "msg": "排序已保存",
    "data": null
}

5.2 获取商品规格排序

GET /api/goods/getSpecSort?goods_id=10001

响应示例:

{
    "code": 1,
    "msg": "success",
    "data": {
        "spec_sort": {
            "10023": 10,
            "10024": 20
        },
        "value_sort": {
            "10023": {
                "10025": 10,
                "10026": 20
            },
            "10024": {
                "10027": 10
            }
        }
    }
}

六、前端实现

6.1 规格组拖拽排序(Vue组件)

// components/goods/spec/GroupSortable.vue
<template>
    <div class="spec-group-list">
        <div
            v-for="(group, index) in specGroups"
            :key="group.spec_id"
            class="spec-group-item"
            :data-index="index"
        >
            <div class="drag-handle">
                <i class="iconfont icon-drag"></i>
            </div>
            <div class="group-content">
                <span class="group-name">{{ group.spec_name }}</span>
                <spec-value-sortable
                    :spec-id="group.spec_id"
                    :values="group.values"
                    @sort-change="onValueSortChange"
                />
            </div>
        </div>
    </div>
</template>

<script>
import Sortable from 'sortablejs';
import SpecValueSortable from './ValueSortable.vue';

export default {
    name: 'GroupSortable',
    components: { SpecValueSortable },
    props: {
        goodsId: { type: Number, required: true },
        specGroups: { type: Array, default: () => [] }
    },
    emits: ['sort-change'],
    data() {
        return {
            sortable: null
        };
    },
    mounted() {
        this.initSortable();
    },
    beforeUnmount() {
        this.sortable && this.sortable.destroy();
    },
    methods: {
        initSortable() {
            const el = this.$el;
            this.sortable = new Sortable(el, {
                animation: 150,
                handle: '.drag-handle',
                ghostClass: 'sortable-ghost',
                onEnd: this.handleDragEnd
            });
        },
        handleDragEnd(evt) {
            const { oldIndex, newIndex } = evt;
            if (oldIndex === newIndex) return;

            // 移动数组元素
            const movedGroup = this.specGroups.splice(oldIndex, 1)[0];
            this.specGroups.splice(newIndex, 0, movedGroup);

            // 触发保存
            this.saveSort();
        },
        saveSort() {
            const specData = this.specGroups.map((group, index) => ({
                spec_id: group.spec_id,
                sort: (index + 1) * 10,
                value_data: group.values.map((v, vIndex) => ({
                    spec_value_id: v.spec_value_id,
                    sort: (vIndex + 1) * 10
                }))
            }));

            this.$api.post('/goods/sortSpec', {
                goods_id: this.goodsId,
                spec_data: specData
            }).then(res => {
                if (res.code !== 1) {
                    this.$message.error(res.msg);
                }
            });
        },
        onValueSortChange(specId, newValues) {
            const group = this.specGroups.find(g => g.spec_id === specId);
            if (group) {
                group.values = newValues;
            }
            this.saveSort();
        }
    }
};
</script>

6.2 规格值拖拽排序

// components/goods/spec/ValueSortable.vue
<template>
    <div class="spec-value-list">
        <div
            v-for="value in values"
            :key="value.spec_value_id"
            class="spec-value-item"
            :data-id="value.spec_value_id"
        >
            <span class="drag-handle">
                <i class="iconfont icon-drag"></i>
            </span>
            <span class="value-name">{{ value.spec_value }}</span>
        </div>
    </div>
</template>

<script>
import Sortable from 'sortablejs';

export default {
    name: 'ValueSortable',
    props: {
        specId: { type: Number, required: true },
        values: { type: Array, default: () => [] }
    },
    emits: ['sort-change'],
    data() {
        return {
            sortable: null
        };
    },
    mounted() {
        this.initSortable();
    },
    beforeUnmount() {
        this.sortable && this.sortable.destroy();
    },
    methods: {
        initSortable() {
            const el = this.$el;
            this.sortable = new Sortable(el, {
                animation: 150,
                handle: '.drag-handle',
                ghostClass: 'sortable-ghost',
                onEnd: this.handleDragEnd
            });
        },
        handleDragEnd(evt) {
            const { oldIndex, newIndex } = evt;
            if (oldIndex === newIndex) return;

            // 移动数组元素
            const movedValue = this.values.splice(oldIndex, 1)[0];
            this.values.splice(newIndex, 0, movedValue);

            // 通知父组件
            this.$emit('sort-change', this.specId, [...this.values]);
        }
    }
};
</script>

七、缓存策略

7.1 Redis缓存设计

/**
 * 规格排序缓存服务
 * Class SpecSortCacheService
 */
class SpecSortCacheService
{
    private const CACHE_KEY_SPEC = 'goods_spec_sort:%d:%d';  // goods_id:wxapp_id
    private const CACHE_KEY_VALUE = 'goods_value_sort:%d:%d:%d';  // goods_id:spec_id:wxapp_id
    private const CACHE_TTL = 86400; // 24小时

    /**
     * 获取规格组排序缓存
     */
    public function getSpecSortCache(int $goodsId, int $wxappId): ?array
    {
        $key = sprintf(self::CACHE_KEY_SPEC, $goodsId, $wxappId);
        $cache = Cache::get($key);
        return $cache ?: null;
    }

    /**
     * 设置规格组排序缓存
     */
    public function setSpecSortCache(int $goodsId, int $wxappId, array $data): void
    {
        $key = sprintf(self::CACHE_KEY_SPEC, $goodsId, $wxappId);
        Cache::set($key, $data, self::CACHE_TTL);
    }

    /**
     * 获取规格值排序缓存
     */
    public function getValueSortCache(int $goodsId, int $specId, int $wxappId): ?array
    {
        $key = sprintf(self::CACHE_KEY_VALUE, $goodsId, $specId, $wxappId);
        $cache = Cache::get($key);
        return $cache ?: null;
    }

    /**
     * 设置规格值排序缓存
     */
    public function setValueSortCache(int $goodsId, int $specId, int $wxappId, array $data): void
    {
        $key = sprintf(self::CACHE_KEY_VALUE, $goodsId, $specId, $wxappId);
        Cache::set($key, $data, self::CACHE_TTL);
    }

    /**
     * 清除商品排序缓存
     */
    public function clearGoodsSortCache(int $goodsId, int $wxappId): void
    {
        $specKey = sprintf(self::CACHE_KEY_SPEC, $goodsId, $wxappId);
        Cache::delete($specKey);

        // 清除所有规格值的缓存(模糊匹配)
        $pattern = sprintf('goods_value_sort:%d:*:%d', $goodsId, $wxappId);
        $keys = Cache::tag('goods_sort')->clear($pattern);
    }
}

7.2 缓存更新策略

┌─────────────────────────────────────────────────────────────────┐
│                      缓存更新策略                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   写入时:                                                      │
│   1. 更新数据库                                                 │
│   2. 删除缓存(Cache-Aside模式)                                │
│   3. 下次查询时自动回填                                          │
│                                                                 │
│   读取时:                                                      │
│   1. 查询缓存 → 命中则返回                                       │
│   2. 未命中 → 查询数据库 → 写入缓存 → 返回                       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

八、测试策略

8.1 单元测试用例

/**
 * 规格排序服务单元测试
 */
class GoodsSpecSortServiceTest extends TestCase
{
    /**
     * 测试:保存规格组排序
     */
    public function testSaveSpecGroupSort()
    {
        $service = new GoodsSpecSortService();
        $result = $service->saveSpecGroupSort(10001, [10023, 10024, 10025], 10001);

        $this->assertTrue($result);

        // 验证数据库
        $specSort = (new GoodsSpecSort())
            ->where('goods_id', 10001)
            ->where('wxapp_id', 10001)
            ->column('sort', 'spec_id');

        $this->assertEquals(10, $specSort[10023]);
        $this->assertEquals(20, $specSort[10024]);
        $this->assertEquals(30, $specSort[10025]);
    }

    /**
     * 测试:中间插入规格后重排
     */
    public function testInsertBetweenTriggersRebalance()
    {
        $service = new GoodsSpecSortService();

        // 初始:A(10), B(20), C(30)
        $service->saveSpecGroupSort(10001, [10023, 10024, 10025], 10001);

        // 插入D到B和C之间
        $service->saveSpecGroupSort(10001, [10023, 10026, 10024, 10025], 10001);

        // 验证:D应该在B和C之间
        $specSort = (new GoodsSpecSort())
            ->where('goods_id', 10001)
            ->order('sort')
            ->column('spec_id', 'sort');

        $this->assertEquals([10 => 10023, 20 => 10026, 30 => 10024, 40 => 10025], $specSort);
    }

    /**
     * 测试:查询带排序的规格数据
     */
    public function testGetGoodsSpecDataWithSort()
    {
        $service = new GoodsSpecSortService();
        $data = $service->getGoodsSpecData(10001, 10001);

        // 验证排序正确
        $this->assertEquals(10023, $data[0]['group_id']);
        $this->assertEquals(10024, $data[1]['group_id']);
    }
}

8.2 性能测试标准

指标 标准 测试方法
单商品规格查询 < 10ms ab -n 1000
批量排序更新(10组) < 50ms 接口压测
100商品并发查询 QPS > 500 wrk压测
缓存命中率 > 95% Redis MONITOR

九、风险评估与回滚方案

9.1 风险矩阵

风险 概率 影响 应对措施
排序数据丢失 低 高 事务保护 + 备份表
缓存雪崩 中 中 缓存过期时间随机化
主从延迟 低 低 读写分离 + 强制从主库写
跨版本兼容 低 高 接口版本控制

9.2 回滚方案

-- 回滚脚本:删除排序表
BEGIN;
-- 备份数据
CREATE TABLE ltshop_goods_spec_sort_backup AS SELECT * FROM ltshop_goods_spec_sort;
CREATE TABLE ltshop_goods_spec_value_sort_backup AS SELECT * FROM ltshop_goods_spec_value_sort;

-- 删除排序表
DROP TABLE IF EXISTS ltshop_goods_spec_sort;
DROP TABLE IF EXISTS ltshop_goods_spec_value_sort;

-- 验证回滚(检查商品详情是否正常)
SELECT goods_id, goods_name FROM ltshop_goods WHERE goods_id = 10001;
COMMIT;

十、里程碑计划

阶段 内容 交付物
Phase 1 数据库设计与创建 建表SQL
Phase 2 后端Service层开发 排序服务类
Phase 3 API接口开发 RESTful接口
Phase 4 前端组件开发 Vue拖拽组件
Phase 5 缓存集成 Redis缓存方案
Phase 6 单元测试 测试报告
Phase 7 集成测试 测试报告
Phase 8 上线部署 部署文档

十一、总结

本方案通过以下设计实现了一个高效、可扩展的商品规格排序系统:

  1. 独立排序表设计:规格组排序和规格值排序分离,互不影响
  2. 紧凑排序算法:间隔10的策略兼顾查询效率和插入灵活性
  3. Service层封装:业务逻辑与数据访问分离,利于维护
  4. 缓存优化:多级缓存策略提升查询性能
  5. 完整测试覆盖:单元测试 + 集成测试确保质量

方案具备以下优势:

  • 高性能:整数排序 + 索引优化,查询效率高
  • 可扩展:模块化设计,易于功能迭代
  • 一致性:前后端统一排序规则,避免SKU匹配失败
  • 可维护:代码结构清晰,文档完善
大纲

文章目录

    联系我们
    联系方式
    • 官方服务热线:17721141027
    • 邮箱:kf@ilaituan.com
    • QQ:20262336
    扫码添加客服
    微信
    联系我们