feat(pokemon): sort by display_id instead of internal id
Update schema to replace sort_order index with display_id index Apply display_id ordering to global search, lists, and relations Update design documentation to reflect the new sorting behavior
This commit is contained in:
@@ -28,7 +28,7 @@
|
|||||||
- 全局搜索 API 只返回公开浏览所需的最小结果字段:结果类型、ID、展示标题、目标 URL、可选摘要和可选图片;用户搜索结果只使用公开 Profile 所需的 `id`、`displayName` 和目标 URL,不返回邮箱、角色、权限、Referral、编辑审计、审核原因、token/hash、内部字段或调试信息。
|
- 全局搜索 API 只返回公开浏览所需的最小结果字段:结果类型、ID、展示标题、目标 URL、可选摘要和可选图片;用户搜索结果只使用公开 Profile 所需的 `id`、`displayName` 和目标 URL,不返回邮箱、角色、权限、Referral、编辑审计、审核原因、token/hash、内部字段或调试信息。
|
||||||
- 用户界面只展示业务数据和设计内的文案,不展示提示词、计划、调试信息、字段内部名或修改说明。
|
- 用户界面只展示业务数据和设计内的文案,不展示提示词、计划、调试信息、字段内部名或修改说明。
|
||||||
- 可编辑 Wiki 内容必须记录创建者、最后编辑者、创建时间、最后编辑时间和编辑历史。
|
- 可编辑 Wiki 内容必须记录创建者、最后编辑者、创建时间、最后编辑时间和编辑历史。
|
||||||
- 除 Pokemon 外,列表顺序由 `sort_order` 控制,默认按创建时间旧到新初始化,排序值按 10 递增以便后续插入和拖拽排序;Pokemon 列表按内部 `id` 升序展示,不提供手动排序。
|
- 除 Pokemon 外,列表顺序由 `sort_order` 控制,默认按创建时间旧到新初始化,排序值按 10 递增以便后续插入和拖拽排序;Pokemon 列表按 Pokopia 展示 ID(`display_id`)升序展示,不提供手动排序。
|
||||||
|
|
||||||
## 国际化
|
## 国际化
|
||||||
|
|
||||||
@@ -582,7 +582,7 @@ Pokemon 列表功能:
|
|||||||
- 按喜欢的东西筛选:
|
- 按喜欢的东西筛选:
|
||||||
- 满足任意条件
|
- 满足任意条件
|
||||||
- 满足全部条件
|
- 满足全部条件
|
||||||
- 按 Pokemon 内部 `id` 升序展示
|
- 按 Pokopia 展示 ID(`display_id`)升序展示;内部 `id` 仅用于路由、外键和稳定排序兜底
|
||||||
- 列表首屏只读取一页数据;滚动到列表底部时继续读取下一页,不一次性加载全部 Pokemon。
|
- 列表首屏只读取一页数据;滚动到列表底部时继续读取下一页,不一次性加载全部 Pokemon。
|
||||||
- Pokemon 列表卡片只展示 Pokemon 图片和下方的 `#ID 名称`;不展示喜欢的环境、属性、特长、喜欢的东西或编辑元信息。
|
- Pokemon 列表卡片只展示 Pokemon 图片和下方的 `#ID 名称`;不展示喜欢的环境、属性、特长、喜欢的东西或编辑元信息。
|
||||||
- Pokemon 卡片在已配置图片时展示所选图片缩略图;未配置图片时保留默认 Poké Ball 标记。
|
- Pokemon 卡片在已配置图片时展示所选图片缩略图;未配置图片时保留默认 Poké Ball 标记。
|
||||||
@@ -1329,7 +1329,7 @@ API 暴露边界:
|
|||||||
- `GET /api/admin/ai-moderation`
|
- `GET /api/admin/ai-moderation`
|
||||||
- `PUT /api/admin/ai-moderation`
|
- `PUT /api/admin/ai-moderation`
|
||||||
- `PUT /api/admin/system-wordings/:key`
|
- `PUT /api/admin/system-wordings/:key`
|
||||||
- 物品、材料单、栖息地的列表排序需要对应实体的 `order` 权限;Pokemon 按内部 `id` 排序,不提供列表排序 API 或 Admin 手动排序入口。
|
- 物品、材料单、栖息地的列表排序需要对应实体的 `order` 权限;Pokemon 按 Pokopia 展示 ID(`display_id`)排序,不提供列表排序 API 或 Admin 手动排序入口。
|
||||||
|
|
||||||
## 开发与验证
|
## 开发与验证
|
||||||
|
|
||||||
|
|||||||
@@ -1335,7 +1335,8 @@ CREATE INDEX IF NOT EXISTS environments_sort_order_idx ON environments(sort_orde
|
|||||||
CREATE INDEX IF NOT EXISTS skills_sort_order_idx ON skills(sort_order, id);
|
CREATE INDEX IF NOT EXISTS skills_sort_order_idx ON skills(sort_order, id);
|
||||||
CREATE INDEX IF NOT EXISTS favorite_things_sort_order_idx ON favorite_things(sort_order, id);
|
CREATE INDEX IF NOT EXISTS favorite_things_sort_order_idx ON favorite_things(sort_order, id);
|
||||||
CREATE INDEX IF NOT EXISTS pokemon_types_sort_order_idx ON pokemon_types(sort_order, id);
|
CREATE INDEX IF NOT EXISTS pokemon_types_sort_order_idx ON pokemon_types(sort_order, id);
|
||||||
CREATE INDEX IF NOT EXISTS pokemon_sort_order_idx ON pokemon(sort_order, id);
|
DROP INDEX IF EXISTS pokemon_sort_order_idx;
|
||||||
|
CREATE INDEX IF NOT EXISTS pokemon_display_order_idx ON pokemon(is_event_item, display_id, id);
|
||||||
CREATE UNIQUE INDEX IF NOT EXISTS pokemon_display_event_item_key ON pokemon(display_id, is_event_item);
|
CREATE UNIQUE INDEX IF NOT EXISTS pokemon_display_event_item_key ON pokemon(display_id, is_event_item);
|
||||||
CREATE INDEX IF NOT EXISTS acquisition_methods_sort_order_idx ON acquisition_methods(sort_order, id);
|
CREATE INDEX IF NOT EXISTS acquisition_methods_sort_order_idx ON acquisition_methods(sort_order, id);
|
||||||
CREATE INDEX IF NOT EXISTS items_sort_order_idx ON items(sort_order, id);
|
CREATE INDEX IF NOT EXISTS items_sort_order_idx ON items(sort_order, id);
|
||||||
|
|||||||
@@ -2871,7 +2871,7 @@ export async function globalSearch(paramsQuery: QueryParams = {}, locale = defau
|
|||||||
${pokemonImageJson('p')} AS image
|
${pokemonImageJson('p')} AS image
|
||||||
FROM pokemon p
|
FROM pokemon p
|
||||||
WHERE ${pokemonName} ILIKE $1
|
WHERE ${pokemonName} ILIKE $1
|
||||||
ORDER BY p.id
|
ORDER BY p.display_id, p.id
|
||||||
LIMIT $2
|
LIMIT $2
|
||||||
`,
|
`,
|
||||||
[pattern, limit]
|
[pattern, limit]
|
||||||
@@ -5757,7 +5757,7 @@ export async function listPokemon(paramsQuery: QueryParams, locale = defaultLoca
|
|||||||
}
|
}
|
||||||
|
|
||||||
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
||||||
return queryMaybePaged(`${pokemonProjection(locale)} ${whereClause} ORDER BY p.id`, params, paramsQuery);
|
return queryMaybePaged(`${pokemonProjection(locale)} ${whereClause} ORDER BY p.display_id, p.id`, params, paramsQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPokemon(id: number, locale = defaultLocale) {
|
export async function getPokemon(id: number, locale = defaultLocale) {
|
||||||
@@ -5963,6 +5963,7 @@ export async function getPokemon(id: number, locale = defaultLocale) {
|
|||||||
scored_pokemon."favoriteThingMatchCount" DESC,
|
scored_pokemon."favoriteThingMatchCount" DESC,
|
||||||
scored_pokemon."environmentIsOpposite" DESC,
|
scored_pokemon."environmentIsOpposite" DESC,
|
||||||
scored_pokemon."favoriteThingOppositeCount" DESC,
|
scored_pokemon."favoriteThingOppositeCount" DESC,
|
||||||
|
related_pokemon.display_id,
|
||||||
related_pokemon.id
|
related_pokemon.id
|
||||||
`,
|
`,
|
||||||
[id]
|
[id]
|
||||||
@@ -6351,7 +6352,7 @@ export async function listHabitats(paramsQuery: QueryParams = {}, locale = defau
|
|||||||
'name', pokemon_rows.name,
|
'name', pokemon_rows.name,
|
||||||
'isEventItem', pokemon_rows.is_event_item
|
'isEventItem', pokemon_rows.is_event_item
|
||||||
)
|
)
|
||||||
ORDER BY pokemon_rows.id
|
ORDER BY pokemon_rows.display_id, pokemon_rows.id
|
||||||
)
|
)
|
||||||
FROM (
|
FROM (
|
||||||
SELECT DISTINCT p.id, p.display_id, ${pokemonName} AS name, p.is_event_item
|
SELECT DISTINCT p.id, p.display_id, ${pokemonName} AS name, p.is_event_item
|
||||||
@@ -6425,7 +6426,7 @@ export async function getHabitat(id: number, locale = defaultLocale) {
|
|||||||
JOIN pokemon p ON p.id = hp.pokemon_id
|
JOIN pokemon p ON p.id = hp.pokemon_id
|
||||||
JOIN maps m ON m.id = hp.map_id
|
JOIN maps m ON m.id = hp.map_id
|
||||||
WHERE hp.habitat_id = $1
|
WHERE hp.habitat_id = $1
|
||||||
ORDER BY hp.rarity, p.id, ${orderByEntity('m')}
|
ORDER BY hp.rarity, p.display_id, p.id, ${orderByEntity('m')}
|
||||||
`,
|
`,
|
||||||
[id]
|
[id]
|
||||||
),
|
),
|
||||||
@@ -6836,7 +6837,7 @@ export async function getItem(id: number, locale = defaultLocale) {
|
|||||||
JOIN skills s ON s.id = psid.skill_id
|
JOIN skills s ON s.id = psid.skill_id
|
||||||
WHERE psid.item_id = $1
|
WHERE psid.item_id = $1
|
||||||
AND s.has_item_drop = true
|
AND s.has_item_drop = true
|
||||||
ORDER BY p.id, ${orderByEntity('s')}
|
ORDER BY p.display_id, p.id, ${orderByEntity('s')}
|
||||||
`,
|
`,
|
||||||
[id]
|
[id]
|
||||||
),
|
),
|
||||||
@@ -6874,7 +6875,7 @@ export async function getItem(id: number, locale = defaultLocale) {
|
|||||||
WHERE ps.pokemon_id = p.id
|
WHERE ps.pokemon_id = p.id
|
||||||
AND trading_skill.has_trading = true
|
AND trading_skill.has_trading = true
|
||||||
)
|
)
|
||||||
ORDER BY pti.preference DESC, p.id
|
ORDER BY pti.preference DESC, p.display_id, p.id
|
||||||
`,
|
`,
|
||||||
[id]
|
[id]
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user