Files
mv2_simple_crx/server/services/amazon_persist.js
张成 7b42ee8ef5 1
2026-03-18 16:40:09 +08:00

111 lines
3.6 KiB
JavaScript

import {
amazon_product,
amazon_search_item,
amazon_review
} from '../models/index.js';
import { safe_json_stringify } from './json_utils.js';
function build_batch_key(prefix) {
return `${prefix}_${Date.now()}_${Math.random().toString().slice(2, 8)}`;
}
function pick_asin_from_url(url) {
if (!url) return null;
const m = String(url).match(/\/dp\/([A-Z0-9]{8,16})/i);
return m && m[1] ? m[1].toUpperCase() : null;
}
export async function persist_amazon_result({ result }) {
if (!result || !result.stage) {
return;
}
if (result.stage === 'detail') {
const asin = result.asin || pick_asin_from_url(result.url);
if (!asin) {
return;
}
await amazon_product.upsert({
asin,
url: result.url || '',
title: result.title || null,
price: result.price || null,
sku: result.sku || null,
sku_color: result.sku_color || null,
sku_size: result.sku_size || null,
brand_line: result.brand_line || null,
brand_store_url: result.brand_store_url || null,
ac_badge: result.ac_badge || null,
bestseller_hint: result.bestseller_hint || null,
delivery_hint: result.delivery_hint || null,
social_proof: result.social_proof || null,
sustainability_hint: result.sustainability_hint || null,
rating_stars: result.rating_stars || null,
review_count_text: result.review_count_text || null,
main_image: result.main_image || null,
images_json: safe_json_stringify(result.images || []),
bullets_json: safe_json_stringify(result.bullets || []),
product_info_json: safe_json_stringify(result.product_info || {}),
detail_extra_lines_json: safe_json_stringify(result.detail_extra_lines || [])
});
return;
}
if (result.stage === 'list') {
const batch_key = build_batch_key('list');
const items = Array.isArray(result.items) ? result.items : [];
for (const it of items) {
const asin = it.asin || pick_asin_from_url(it.url);
if (!asin || !it.url) continue;
await amazon_search_item.create({
asin,
url: it.url,
title: it.title || null,
price: it.price || null,
rating: typeof it.rating === 'number' ? it.rating : null,
rating_text: it.rating_text || null,
review_count: typeof it.review_count === 'number' ? it.review_count : null,
review_count_text: it.review_count_text || null,
rank_index: typeof it.index === 'number' ? it.index : null,
batch_key,
batch_total: typeof result.total === 'number' ? result.total : null,
batch_limit: typeof result.limit === 'number' ? result.limit : null
});
}
return;
}
if (result.stage === 'reviews') {
const batch_key = build_batch_key('reviews');
const asin = pick_asin_from_url(result.url);
const items = Array.isArray(result.items) ? result.items : [];
for (const it of items) {
const review_id = it.review_id;
if (!review_id) continue;
const asin_value = asin || pick_asin_from_url(it.url) || pick_asin_from_url(result.url);
await amazon_review.upsert({
asin: asin_value || null,
url: result.url || '',
review_id,
author: it.author || null,
title: it.title || null,
body: it.body || null,
rating_text: it.rating_text || null,
review_date: it.date || null,
review_index: typeof it.index === 'number' ? it.index : null,
batch_key,
batch_total: typeof result.total === 'number' ? result.total : null,
batch_limit: typeof result.limit === 'number' ? result.limit : null
});
}
}
}