diff --git a/package.json b/package.json
index 2410fe8..7267f85 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "azon-seeker",
"displayName": "Azon Seeker",
- "version": "0.3.0",
+ "version": "0.4.1",
"private": true,
"description": "Starter modify by honestfox101",
"scripts": {
diff --git a/src/components/ControlStrip.vue b/src/components/ControlStrip.vue
index ce4cdf5..d630cc6 100644
--- a/src/components/ControlStrip.vue
+++ b/src/components/ControlStrip.vue
@@ -76,6 +76,17 @@ const emit = defineEmits<{
+
+
+
+
+
+
+ 设置
+
+
+
+
diff --git a/src/components/IdsInput.vue b/src/components/IdsInput.vue
index 754d758..71754bd 100644
--- a/src/components/IdsInput.vue
+++ b/src/components/IdsInput.vue
@@ -27,7 +27,7 @@ const formItemRule: FormItemRule = {
trigger: ['submit'],
message: props.validateMessage,
validator: () => {
- return props.matchPattern.exec(modelValue.value) !== null;
+ return props.matchPattern && props.matchPattern.exec(modelValue.value) !== null;
},
};
diff --git a/src/env.ts b/src/env.ts
index ea86683..3be77b2 100644
--- a/src/env.ts
+++ b/src/env.ts
@@ -14,4 +14,5 @@ export function isForbiddenUrl(url: string): boolean {
export const isFirefox = navigator.userAgent.includes('Firefox');
-export const remoteHost = __DEV__ ? '127.0.0.1:8000' : '47.251.4.191:8000';
+// export const remoteHost = __DEV__ ? '127.0.0.1:8000' : '47.251.4.191:8000';
+export const remoteHost = '47.251.4.191:8000';
diff --git a/src/logic/execute-script.ts b/src/logic/execute-script.ts
index e195552..717b094 100644
--- a/src/logic/execute-script.ts
+++ b/src/logic/execute-script.ts
@@ -47,13 +47,11 @@ export async function exec>(
): Promise {
const { timeout = 30000 } = options;
return new Promise(async (resolve, reject) => {
- if (isFirefox) {
- while (true) {
- await new Promise((r) => setTimeout(r, 200));
- const tab = await browser.tabs.get(tabId);
- if (tab.status === 'complete') {
- break;
- }
+ while (true) {
+ await new Promise((r) => setTimeout(r, 200));
+ const tab = await browser.tabs.get(tabId);
+ if (tab.status === 'complete') {
+ break;
}
}
setTimeout(() => reject('脚本运行超时'), timeout);
diff --git a/src/logic/storages/amazon.ts b/src/logic/storages/amazon.ts
index 5f91928..68b0b8c 100644
--- a/src/logic/storages/amazon.ts
+++ b/src/logic/storages/amazon.ts
@@ -6,6 +6,10 @@ export const detailAsinInput = useWebExtensionStorage('detailAsinInputTe
export const reviewAsinInput = useWebExtensionStorage('reviewAsinInputText', '');
+export const itemColumnSettings = useWebExtensionStorage<
+ Set>
+>('itemColumnSettings', new Set(['keywords', 'page', 'rank', 'createTime']));
+
export const searchItems = useWebExtensionStorage('searchItems', []);
export const detailWorkerSettings = useWebExtensionStorage<{ aplus: boolean }>(
diff --git a/src/logic/upload.ts b/src/logic/upload.ts
index 07fd9f2..69c158b 100644
--- a/src/logic/upload.ts
+++ b/src/logic/upload.ts
@@ -23,12 +23,13 @@ export async function uploadImage(
formData.append('file', blob, filename);
const url = `http://${remoteHost}/upload/image/${encodeURIComponent(filename)}`;
- return fetch(url, {
+ const resp = (await fetch(url, {
method: 'POST',
body: formData,
- })
- .then((response) => response.json())
- .then((data) => {
- return data.file ? `http://${remoteHost}${data.file}` : undefined;
- });
+ }).catch((err) => undefined)) as Response | undefined;
+ if (!resp) {
+ return undefined;
+ }
+ const data = await resp.json();
+ return `http://${remoteHost}${data.file}`;
}
diff --git a/src/logic/web-injectors/base.ts b/src/logic/web-injectors/base.ts
index 02443e2..f61364e 100644
--- a/src/logic/web-injectors/base.ts
+++ b/src/logic/web-injectors/base.ts
@@ -26,14 +26,14 @@ export class BaseInjector {
}
}
- protected async screenshot(params: ProtocolMap['html-to-image']['data']) {
+ protected async screenshot(
+ params: ProtocolMap['html-to-image']['data'],
+ ): Promise {
const sender = await this.getMessageSender();
- return Promise.resolve(
- sender.sendMessage('html-to-image', params, {
- context: 'content-script',
- tabId: this._tab.id!,
- }),
- );
+ return sender!.sendMessage('html-to-image', params, {
+ context: 'content-script',
+ tabId: this._tab.id!,
+ });
}
protected run>(
diff --git a/src/options/views/AmazonResultTable.vue b/src/options/views/AmazonResultTable.vue
index 40fb958..90caad9 100644
--- a/src/options/views/AmazonResultTable.vue
+++ b/src/options/views/AmazonResultTable.vue
@@ -3,7 +3,7 @@ import { NButton, NSpace } from 'naive-ui';
import type { TableColumn } from '~/components/ResultTable.vue';
import { useCloudExporter } from '~/composables/useCloudExporter';
import { castRecordsByHeaders, createWorkbook, Header, importFromXLSX } from '~/logic/excel';
-import { allItems, reviewItems } from '~/logic/storages/amazon';
+import { allItems, itemColumnSettings, reviewItems } from '~/logic/storages/amazon';
const message = useMessage();
const modal = useModal();
@@ -21,96 +21,108 @@ const onFilterReset = () => {
filter.value = {};
};
-const columns: TableColumn[] = [
- {
- type: 'expand',
- expandable: (row) => row.hasDetail,
- renderExpand(row) {
- return ;
+const columns = computed(() => {
+ return [
+ {
+ type: 'expand',
+ expandable: (row) => row.hasDetail,
+ renderExpand(row) {
+ return ;
+ },
},
- },
- {
- title: '关键词',
- key: 'keywords',
- minWidth: 120,
- },
- {
- title: '页码',
- key: 'page',
- minWidth: 60,
- },
- {
- title: '排位',
- key: 'rank',
- minWidth: 60,
- },
- {
- title: 'ASIN',
- key: 'asin',
- minWidth: 130,
- },
- {
- title: '标题',
- key: 'title',
- },
- {
- title: '价格',
- key: 'price',
- minWidth: 100,
- },
- {
- title: '封面图',
- key: 'imageSrc',
- hidden: true,
- },
- {
- title: '获取日期',
- key: 'createTime',
- minWidth: 160,
- },
- {
- title: '查看',
- key: 'actions',
- minWidth: 100,
- render(row) {
- return (
-
- {[
- {
- text: '评论',
- disabled: !reviewItems.value.has(row.asin),
- onClick: () => {
- const asin = row.asin;
- modal.create({
- title: `${asin}评论`,
- preset: 'card',
- style: {
- width: '80vw',
- height: '85vh',
- },
- content: () => ,
- });
- },
- },
- {
- text: '链接',
- onClick: () => {
- browser.tabs.create({
- active: true,
- url: row.link,
- });
- },
- },
- ].map(({ text, onClick, disabled }) => (
-
- {text}
-
- ))}
-
- );
+ {
+ title: '关键词',
+ key: 'keywords',
+ minWidth: 120,
+ hidden: !itemColumnSettings.value.has('keywords'),
},
- },
-];
+ {
+ title: '页码',
+ key: 'page',
+ minWidth: 60,
+ hidden: !itemColumnSettings.value.has('page'),
+ },
+ {
+ title: '排位',
+ key: 'rank',
+ minWidth: 60,
+ hidden: !itemColumnSettings.value.has('rank'),
+ },
+ {
+ title: 'ASIN',
+ key: 'asin',
+ minWidth: 130,
+ },
+ {
+ title: '标题',
+ key: 'title',
+ },
+ {
+ title: '价格',
+ key: 'price',
+ minWidth: 100,
+ },
+ {
+ title: '封面图',
+ key: 'imageSrc',
+ hidden: true,
+ },
+ {
+ title: '获取日期',
+ key: 'createTime',
+ minWidth: 160,
+ hidden: !itemColumnSettings.value.has('createTime'),
+ },
+ {
+ title: '获取日期(详情页)',
+ key: 'timestamp',
+ minWidth: 160,
+ hidden: !itemColumnSettings.value.has('timestamp'),
+ },
+ {
+ title: '查看',
+ key: 'actions',
+ minWidth: 100,
+ render(row) {
+ return (
+
+ {[
+ {
+ text: '评论',
+ disabled: !reviewItems.value.has(row.asin),
+ onClick: () => {
+ const asin = row.asin;
+ modal.create({
+ title: `${asin}评论`,
+ preset: 'card',
+ style: {
+ width: '80vw',
+ height: '85vh',
+ },
+ content: () => ,
+ });
+ },
+ },
+ {
+ text: '链接',
+ onClick: () => {
+ browser.tabs.create({
+ active: true,
+ url: row.link,
+ });
+ },
+ },
+ ].map(({ text, onClick, disabled }) => (
+
+ {text}
+
+ ))}
+
+ );
+ },
+ },
+ ];
+});
const extraHeaders: Header[] = [
{ prop: 'link', label: '商品链接' },
@@ -155,7 +167,7 @@ const reviewHeaders: Header[] = [
];
const getItemHeaders = () => {
- return columns
+ return columns.value
.filter((col: Record) => col.key !== 'actions')
.reduce(
(p, v: Record) => {
@@ -240,7 +252,7 @@ const handleCloudExport = async () => {
const mappedData1 = await castRecordsByHeaders(items, itemHeaders);
const mappedData2 = await castRecordsByHeaders(reviews, reviewHeaders);
const fragments = [
- { data: mappedData1, imageColumn: ['商品图片链接', 'A+截图'], name: 'items' },
+ { data: mappedData1, imageColumn: ['A+截图', '商品图片链接'], name: 'items' },
{ data: mappedData2, imageColumn: '图片链接', name: 'reviews' },
];
const filename = await cloudExporter.doExport(fragments);
@@ -369,18 +381,32 @@ const handleClearData = async () => {
+
+ (itemColumnSettings = new Set(val) as any)"
+ >
+
+
+
+
+
+
+
+
+
@@ -445,7 +471,7 @@ const handleClearData = async () => {
}
.filter-section {
- max-width: 360px;
+ max-width: 500px;
.filter-title {
font-size: 18px;
diff --git a/src/page-worker/error-handler.ts b/src/page-worker/error-handler.ts
index 2b07691..d0453c2 100644
--- a/src/page-worker/error-handler.ts
+++ b/src/page-worker/error-handler.ts
@@ -1,5 +1,5 @@
export interface ErrorChannelContainer {
- emit: (event: 'error', error: { message: string }) => void;
+ emit: (event: 'error', error: { message: string }) => Promise;
}
/**
@@ -16,7 +16,7 @@ export function withErrorHandling(
try {
return await originalMethod.call(this, ...args); // 调用原有方法
} catch (error) {
- this.emit('error', { message: `发生未知错误:${error}` });
+ await this.emit('error', { message: `发生未知错误:${error}` });
throw error;
}
};
diff --git a/src/page-worker/index.ts b/src/page-worker/index.ts
index 670e4dd..9263ca6 100644
--- a/src/page-worker/index.ts
+++ b/src/page-worker/index.ts
@@ -47,10 +47,9 @@ class AmazonPageWorkerFactory {
worker.on('item-top-reviews-collected', (ev) => {
updateDetailCache(ev);
}),
- worker.on('item-aplus-screenshot-collect', (ev) => {
- uploadImage(ev.base64data, `${ev.asin}.png`).then((url) => {
- url && updateDetailCache({ asin: ev.asin, aplus: url });
- });
+ worker.on('item-aplus-screenshot-collect', async (ev) => {
+ const url = await uploadImage(ev.base64data, `${ev.asin}.png`);
+ url && updateDetailCache({ asin: ev.asin, aplus: url });
}),
worker.on('item-review-collected', (ev) => {
updateReviews(ev);
@@ -92,14 +91,12 @@ class AmazonPageWorkerFactory {
const { searchItems, detailItems, reviewItems } = this.amazonWorkerSettings;
if (typeof searchItems !== 'undefined') {
searchItems.value = searchItems.value.concat(searchCache);
- searchCache.splice(0, searchCache.length);
}
if (typeof detailItems !== 'undefined') {
for (const [k, v] of detailCache.entries()) {
detailItems.value.delete(k); // Trigger update
detailItems.value.set(k, v);
}
- detailCache.clear();
}
if (typeof reviewItems !== 'undefined') {
for (const [asin, reviews] of reviewCache.entries()) {
@@ -116,12 +113,11 @@ class AmazonPageWorkerFactory {
reviewItems.value.set(asin, reviews);
}
}
- reviewCache.clear();
}
};
const taskWrapper = any>(func: T) => {
- const { commitChangeIngerval = 1500 } = this.amazonWorkerSettings;
+ const { commitChangeIngerval = 10000 } = this.amazonWorkerSettings;
searchCache.splice(0, searchCache.length);
detailCache.clear();
reviewCache.clear();
@@ -215,7 +211,7 @@ class HomedepotWorkerFactory {
};
const taskWrapper = any>(func: T) => {
- const { commitChangeIngerval = 1500 } = this.homedepotWorkerSettings;
+ const { commitChangeIngerval = 10000 } = this.homedepotWorkerSettings;
return (...params: Parameters) =>
startTask(async () => {
const interval = setInterval(() => commitChange(), commitChangeIngerval);
@@ -249,7 +245,6 @@ class HomedepotWorkerFactory {
}
const amazonfacotry = new AmazonPageWorkerFactory();
-
const homedepotfactory = new HomedepotWorkerFactory();
export function usePageWorker(