tt-help-cli-ycl 1.4.149 → 1.4.151
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/add-claim-index.mjs +28 -0
- package/scripts/checkpoint-wal.mjs +20 -0
- package/scripts/test-photo-post.mjs +156 -0
- package/scripts/test-precheck-perf.mjs +270 -0
- package/scripts/test-product-fill-cdp.mjs +44 -0
- package/scripts/test-product-fill-db.mjs +43 -0
- package/scripts/test-seller-any-country.mjs +167 -0
- package/src/cli/product-fill.js +13 -1
- package/src/lib/api-interceptor.js +10 -1
- package/src/lib/app-config.js +15 -1
- package/src/lib/browser/cdp.js +2 -0
- package/src/lib/browser/page.js +14 -0
- package/src/lib/shop-scraper.mjs +79 -0
- package/src/lib/target-locations.js +8 -5
- package/src/scraper/explore-core.js +8 -2
- package/src/watch/data-store.js +136 -130
- package/src/watch/db-columns.js +1 -0
- package/src/watch/db-schema.js +17 -5
- package/src/watch/db-tags.js +15 -5
- package/src/watch/public/app.js +285 -50
- package/src/watch/public/index.html +66 -46
- package/src/watch/public/style.css +267 -0
- package/src/watch/server.js +16 -2
|
@@ -1703,6 +1703,194 @@ td.user-id:hover {
|
|
|
1703
1703
|
display: block;
|
|
1704
1704
|
}
|
|
1705
1705
|
|
|
1706
|
+
.settings-layout {
|
|
1707
|
+
display: flex;
|
|
1708
|
+
gap: 20px;
|
|
1709
|
+
max-width: 860px;
|
|
1710
|
+
margin: 0 auto;
|
|
1711
|
+
align-items: flex-start;
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
.settings-nav {
|
|
1715
|
+
width: 170px;
|
|
1716
|
+
flex-shrink: 0;
|
|
1717
|
+
display: flex;
|
|
1718
|
+
flex-direction: column;
|
|
1719
|
+
gap: 6px;
|
|
1720
|
+
position: sticky;
|
|
1721
|
+
top: 16px;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
.settings-nav-item {
|
|
1725
|
+
text-align: left;
|
|
1726
|
+
padding: 10px 14px;
|
|
1727
|
+
background: #1a1a24;
|
|
1728
|
+
border: 1px solid transparent;
|
|
1729
|
+
border-radius: 10px;
|
|
1730
|
+
color: #999;
|
|
1731
|
+
cursor: pointer;
|
|
1732
|
+
font-size: 13px;
|
|
1733
|
+
transition: color 0.15s, background 0.15s, border-color 0.15s;
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
.settings-nav-item:hover {
|
|
1737
|
+
color: #ccc;
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
.settings-nav-item.active {
|
|
1741
|
+
color: #60a5fa;
|
|
1742
|
+
border-color: rgba(96, 165, 250, 0.4);
|
|
1743
|
+
background: rgba(96, 165, 250, 0.08);
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
.settings-panels {
|
|
1747
|
+
flex: 1;
|
|
1748
|
+
min-width: 0;
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
.settings-panel {
|
|
1752
|
+
display: none;
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
.settings-panel.active {
|
|
1756
|
+
display: block;
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
.settings-panel .settings-card {
|
|
1760
|
+
margin: 0;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
@media (max-width: 720px) {
|
|
1764
|
+
.settings-layout {
|
|
1765
|
+
flex-direction: column;
|
|
1766
|
+
}
|
|
1767
|
+
.settings-nav {
|
|
1768
|
+
width: 100%;
|
|
1769
|
+
flex-direction: row;
|
|
1770
|
+
flex-wrap: wrap;
|
|
1771
|
+
position: static;
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
/* ---- 目标国家宫格(拖拽排序) ---- */
|
|
1776
|
+
.loc-chips {
|
|
1777
|
+
display: flex;
|
|
1778
|
+
flex-wrap: wrap;
|
|
1779
|
+
gap: 10px;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
.loc-chip {
|
|
1783
|
+
display: flex;
|
|
1784
|
+
align-items: center;
|
|
1785
|
+
gap: 6px;
|
|
1786
|
+
padding: 8px 10px;
|
|
1787
|
+
background: #1a1a24;
|
|
1788
|
+
border: 1px solid #333;
|
|
1789
|
+
border-radius: 10px;
|
|
1790
|
+
cursor: grab;
|
|
1791
|
+
user-select: none;
|
|
1792
|
+
font-size: 13px;
|
|
1793
|
+
color: #e0e0e0;
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
.loc-chip:active {
|
|
1797
|
+
cursor: grabbing;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
.loc-chip.dragging {
|
|
1801
|
+
opacity: 0.4;
|
|
1802
|
+
cursor: grabbing;
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
.loc-chip.drop-before {
|
|
1806
|
+
box-shadow: -3px 0 0 0 #60a5fa;
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
.loc-chip.drop-after {
|
|
1810
|
+
box-shadow: 3px 0 0 0 #60a5fa;
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
.loc-chip-idx {
|
|
1814
|
+
min-width: 18px;
|
|
1815
|
+
height: 18px;
|
|
1816
|
+
display: inline-flex;
|
|
1817
|
+
align-items: center;
|
|
1818
|
+
justify-content: center;
|
|
1819
|
+
background: rgba(96, 165, 250, 0.15);
|
|
1820
|
+
color: #60a5fa;
|
|
1821
|
+
border-radius: 5px;
|
|
1822
|
+
font-size: 11px;
|
|
1823
|
+
font-weight: 600;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
.loc-chip-flag {
|
|
1827
|
+
font-size: 15px;
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
.loc-chip-code {
|
|
1831
|
+
font-weight: 600;
|
|
1832
|
+
letter-spacing: 0.5px;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
.loc-chip-del {
|
|
1836
|
+
background: none;
|
|
1837
|
+
border: none;
|
|
1838
|
+
color: #666;
|
|
1839
|
+
font-size: 14px;
|
|
1840
|
+
cursor: pointer;
|
|
1841
|
+
padding: 0 2px;
|
|
1842
|
+
line-height: 1;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
.loc-chip-del:hover {
|
|
1846
|
+
color: #f87171;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
.loc-chip-add {
|
|
1850
|
+
border: 1px dashed #555;
|
|
1851
|
+
color: #888;
|
|
1852
|
+
background: transparent;
|
|
1853
|
+
font-size: 16px;
|
|
1854
|
+
cursor: pointer;
|
|
1855
|
+
padding: 8px 14px;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
.loc-chip-add:hover {
|
|
1859
|
+
border-color: #60a5fa;
|
|
1860
|
+
color: #60a5fa;
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
.country-picker {
|
|
1864
|
+
margin-top: 12px;
|
|
1865
|
+
padding: 14px;
|
|
1866
|
+
background: #14141c;
|
|
1867
|
+
border: 1px solid #2a2a38;
|
|
1868
|
+
border-radius: 10px;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
.country-picker-title {
|
|
1872
|
+
font-size: 12px;
|
|
1873
|
+
color: #888;
|
|
1874
|
+
margin-bottom: 10px;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
.country-picker .custom-loc-row {
|
|
1878
|
+
display: flex;
|
|
1879
|
+
gap: 8px;
|
|
1880
|
+
margin-top: 12px;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
.country-picker .custom-loc-input {
|
|
1884
|
+
flex: 1;
|
|
1885
|
+
padding: 8px 10px;
|
|
1886
|
+
background: #111;
|
|
1887
|
+
border: 1px solid #333;
|
|
1888
|
+
color: #e0e0e0;
|
|
1889
|
+
border-radius: 6px;
|
|
1890
|
+
font-size: 12px;
|
|
1891
|
+
text-transform: uppercase;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1706
1894
|
.settings-card {
|
|
1707
1895
|
background: #1a1a24;
|
|
1708
1896
|
border-radius: 12px;
|
|
@@ -1908,6 +2096,85 @@ td.user-id:hover {
|
|
|
1908
2096
|
}
|
|
1909
2097
|
|
|
1910
2098
|
/* ===== 精准商家:视频卡片视图 ===== */
|
|
2099
|
+
/* ── 精准商家页 SKU 列与弹窗 ── */
|
|
2100
|
+
.sku-cell {
|
|
2101
|
+
cursor: pointer;
|
|
2102
|
+
color: #60a5fa;
|
|
2103
|
+
white-space: nowrap;
|
|
2104
|
+
}
|
|
2105
|
+
.sku-cell:hover {
|
|
2106
|
+
text-decoration: underline;
|
|
2107
|
+
}
|
|
2108
|
+
.sku-modal {
|
|
2109
|
+
width: 640px;
|
|
2110
|
+
display: flex;
|
|
2111
|
+
flex-direction: column;
|
|
2112
|
+
max-height: 80vh;
|
|
2113
|
+
}
|
|
2114
|
+
.sku-modal-meta {
|
|
2115
|
+
font-size: 12px;
|
|
2116
|
+
color: #9ca3af;
|
|
2117
|
+
margin: 6px 0 12px;
|
|
2118
|
+
display: flex;
|
|
2119
|
+
flex-direction: column;
|
|
2120
|
+
gap: 4px;
|
|
2121
|
+
}
|
|
2122
|
+
.sku-modal-name {
|
|
2123
|
+
color: #e0e0e0;
|
|
2124
|
+
font-size: 13px;
|
|
2125
|
+
}
|
|
2126
|
+
.sku-modal-link {
|
|
2127
|
+
color: #60a5fa;
|
|
2128
|
+
text-decoration: none;
|
|
2129
|
+
font-size: 12px;
|
|
2130
|
+
}
|
|
2131
|
+
.sku-modal-link:hover {
|
|
2132
|
+
text-decoration: underline;
|
|
2133
|
+
}
|
|
2134
|
+
.sku-table-wrap {
|
|
2135
|
+
overflow: auto;
|
|
2136
|
+
border: 1px solid #2a2a3a;
|
|
2137
|
+
border-radius: 8px;
|
|
2138
|
+
}
|
|
2139
|
+
.sku-table {
|
|
2140
|
+
width: 100%;
|
|
2141
|
+
border-collapse: collapse;
|
|
2142
|
+
font-size: 12px;
|
|
2143
|
+
}
|
|
2144
|
+
.sku-table th {
|
|
2145
|
+
position: sticky;
|
|
2146
|
+
top: 0;
|
|
2147
|
+
background: #14141d;
|
|
2148
|
+
color: #9ca3af;
|
|
2149
|
+
text-align: left;
|
|
2150
|
+
padding: 8px 10px;
|
|
2151
|
+
border-bottom: 1px solid #2a2a3a;
|
|
2152
|
+
}
|
|
2153
|
+
.sku-table td {
|
|
2154
|
+
padding: 6px 10px;
|
|
2155
|
+
border-bottom: 1px solid #22222e;
|
|
2156
|
+
color: #d1d5db;
|
|
2157
|
+
}
|
|
2158
|
+
.sku-spec {
|
|
2159
|
+
max-width: 320px;
|
|
2160
|
+
overflow: hidden;
|
|
2161
|
+
text-overflow: ellipsis;
|
|
2162
|
+
white-space: nowrap;
|
|
2163
|
+
}
|
|
2164
|
+
.sku-id {
|
|
2165
|
+
color: #6b7280;
|
|
2166
|
+
font-family: monospace;
|
|
2167
|
+
}
|
|
2168
|
+
.sku-ok {
|
|
2169
|
+
color: #4ade80;
|
|
2170
|
+
}
|
|
2171
|
+
.sku-low {
|
|
2172
|
+
color: #fbbf24;
|
|
2173
|
+
}
|
|
2174
|
+
.sku-oos {
|
|
2175
|
+
color: #f87171;
|
|
2176
|
+
}
|
|
2177
|
+
|
|
1911
2178
|
.precise-list-header {
|
|
1912
2179
|
display: flex;
|
|
1913
2180
|
align-items: center;
|
package/src/watch/server.js
CHANGED
|
@@ -592,6 +592,9 @@ export function startWatchServer(
|
|
|
592
592
|
"CREATE INDEX IF NOT EXISTS idx_videos_user_update ON videos(user_update_count)",
|
|
593
593
|
// product-fill 领任务查询的部分索引:只索引候选行,避免全表扫描 164 万行
|
|
594
594
|
"CREATE INDEX IF NOT EXISTS idx_jobs_product_fill ON jobs(claimed_at, updated_at) WHERE top_video_seo_url IS NOT NULL AND top_video_seo_url != '' AND (product_name IS NULL OR product_name = '') AND product_rating IS NULL AND product_sold_count IS NULL",
|
|
595
|
+
// precheck 候选查询部分索引:预缩候选集且天然按 refresh_time 有序,
|
|
596
|
+
// 消除 TEMP B-TREE 排序(76 万行实测 ~1s → 毫秒级)
|
|
597
|
+
"CREATE INDEX IF NOT EXISTS idx_jobs_precheck ON jobs(refresh_time) WHERE tt_seller = 1 AND verified = 0 AND (pending_refresh IS NULL OR pending_refresh = 0)",
|
|
595
598
|
];
|
|
596
599
|
for (const sql of ensureIdx) {
|
|
597
600
|
try {
|
|
@@ -1607,6 +1610,17 @@ export function startWatchServer(
|
|
|
1607
1610
|
productReviewCount: u.productReviewCount ?? null,
|
|
1608
1611
|
productSoldCount: u.productSoldCount ?? null,
|
|
1609
1612
|
productName: u.productName || null,
|
|
1613
|
+
skuCount: u.skuCount || 0,
|
|
1614
|
+
skuTotalStock: u.skuTotalStock || 0,
|
|
1615
|
+
productSkus: (() => {
|
|
1616
|
+
try {
|
|
1617
|
+
return Array.isArray(u.productSkus)
|
|
1618
|
+
? u.productSkus
|
|
1619
|
+
: JSON.parse(u.productSkus || "[]");
|
|
1620
|
+
} catch {
|
|
1621
|
+
return [];
|
|
1622
|
+
}
|
|
1623
|
+
})(),
|
|
1610
1624
|
ecOver1k: u.ecOver1k || 0,
|
|
1611
1625
|
maxEcPlay: u.maxEcPlay || null,
|
|
1612
1626
|
recentEcVideos: (() => {
|
|
@@ -2169,7 +2183,7 @@ export function startWatchServer(
|
|
|
2169
2183
|
}
|
|
2170
2184
|
const targetCountries = Array.isArray(body.countries)
|
|
2171
2185
|
? body.countries
|
|
2172
|
-
:
|
|
2186
|
+
: getTargetLocations();
|
|
2173
2187
|
const serverUrl = body.serverUrl || null;
|
|
2174
2188
|
|
|
2175
2189
|
const { scoreTag } = await import("./tag-service.js");
|
|
@@ -2192,7 +2206,7 @@ export function startWatchServer(
|
|
|
2192
2206
|
const limit = Math.min(parseInt(body.limit) || 10, 50);
|
|
2193
2207
|
const targetCountries = Array.isArray(body.countries)
|
|
2194
2208
|
? body.countries
|
|
2195
|
-
:
|
|
2209
|
+
: getTargetLocations();
|
|
2196
2210
|
const serverUrl = body.serverUrl || null;
|
|
2197
2211
|
|
|
2198
2212
|
const pendingTags = store.getTagsByStatus("new", limit);
|