diff --git a/apps/backend/src/db/migrations/031_work_order_search.sql b/apps/backend/src/db/migrations/031_work_order_search.sql new file mode 100644 index 00000000..2adcd3c8 --- /dev/null +++ b/apps/backend/src/db/migrations/031_work_order_search.sql @@ -0,0 +1,22 @@ +-- 031_work_order_search.sql —— 扩展接单工单搜索字段并建立模糊检索索引。 + +CREATE EXTENSION IF NOT EXISTS pg_trgm; + +CREATE INDEX IF NOT EXISTS idx_work_orders_search_text_trgm + ON work_orders USING gin ( + LOWER( + COALESCE(work_order_no, '') || ' ' || + COALESCE(platform_order_id, '') || ' ' || + COALESCE(product_name, '') || ' ' || + COALESCE(material_json->'collect'->'fields'->>'gameId', '') || ' ' || + COALESCE(material_json->'collect'->'fields'->>'gameNickname', '') || ' ' || + COALESCE(material_json->'collect'->'fields'->>'gameAccount', '') || ' ' || + COALESCE(material_json->'collect'->'fields'->>'roleName', '') || ' ' || + COALESCE(material_json->'fields'->>'gameId', '') || ' ' || + COALESCE(material_json->'fields'->>'gameNickname', '') || ' ' || + COALESCE(material_json->>'gameId', '') || ' ' || + COALESCE(material_json->>'gameNickname', '') + ) gin_trgm_ops + ); + +COMMENT ON INDEX idx_work_orders_search_text_trgm IS '接单工单模糊搜索:订单号、商品名、游戏 ID/昵称及历史字段'; diff --git a/apps/backend/src/repositories/worker-platform/work-order-repo.ts b/apps/backend/src/repositories/worker-platform/work-order-repo.ts index 30e44516..3345c035 100644 --- a/apps/backend/src/repositories/worker-platform/work-order-repo.ts +++ b/apps/backend/src/repositories/worker-platform/work-order-repo.ts @@ -65,6 +65,23 @@ type WorkOrderStatisticsRow = { refund_amount: number | string } +/** 工单统一搜索字段,兼容当前资料结构和历史资料字段。 */ +function workOrderSearchExpression(alias = 'wo') { + return `LOWER( + COALESCE(${alias}.work_order_no, '') || ' ' || + COALESCE(${alias}.platform_order_id, '') || ' ' || + COALESCE(${alias}.product_name, '') || ' ' || + COALESCE(${alias}.material_json->'collect'->'fields'->>'gameId', '') || ' ' || + COALESCE(${alias}.material_json->'collect'->'fields'->>'gameNickname', '') || ' ' || + COALESCE(${alias}.material_json->'collect'->'fields'->>'gameAccount', '') || ' ' || + COALESCE(${alias}.material_json->'collect'->'fields'->>'roleName', '') || ' ' || + COALESCE(${alias}.material_json->'fields'->>'gameId', '') || ' ' || + COALESCE(${alias}.material_json->'fields'->>'gameNickname', '') || ' ' || + COALESCE(${alias}.material_json->>'gameId', '') || ' ' || + COALESCE(${alias}.material_json->>'gameNickname', '') + )` +} + export async function listWorkOrderShares( workOrderId: number | string, ): Promise { @@ -2821,9 +2838,7 @@ function buildWorkOrderWhere({ } if (keyword) { params.push(`%${keyword}%`) - filters.push( - `(wo.work_order_no ILIKE $${params.length} OR wo.platform_order_id ILIKE $${params.length} OR wo.product_name ILIKE $${params.length})`, - ) + filters.push(`${workOrderSearchExpression()} LIKE LOWER($${params.length})`) } if (workerId) { params.push(workerId) diff --git a/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx b/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx index 3945d294..d2f5c1c5 100644 --- a/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx +++ b/apps/frontend/src/pages/admin/panels/WorkOrdersPanel.tsx @@ -912,7 +912,7 @@ export default function WorkOrdersPanel() { setKeywordInput(event.target.value)} onPressEnter={searchOrders} diff --git a/apps/frontend/src/pages/worker/WorkerHallPage.tsx b/apps/frontend/src/pages/worker/WorkerHallPage.tsx index 308741ea..55fb8f46 100644 --- a/apps/frontend/src/pages/worker/WorkerHallPage.tsx +++ b/apps/frontend/src/pages/worker/WorkerHallPage.tsx @@ -327,7 +327,7 @@ export default function WorkerHallPage() { } className="worker-hall-mobile-search-input" onChange={(event) => { @@ -524,7 +524,7 @@ export default function WorkerHallPage() { } onChange={(event) => { const nextKeyword = event.target.value diff --git a/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx b/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx index c9586904..594708ae 100644 --- a/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx +++ b/apps/frontend/src/pages/worker/WorkerOrdersPage.tsx @@ -659,7 +659,7 @@ export default function WorkerOrdersPage() { } className="worker-orders-mobile-search-input" onChange={(event) => { @@ -986,7 +986,7 @@ export default function WorkerOrdersPage() { } onChange={(event) => { const nextValue = event.target.value