mirror of
https://github.com/primedigitaltech/azon_seeker.git
synced 2026-01-29 10:43:19 +08:00
181 lines
4.8 KiB
Vue
181 lines
4.8 KiB
Vue
<script setup lang="ts">
|
||
import type { Timeline } from '~/components/ProgressReport.vue';
|
||
import { usePageWorker } from '~/page-worker';
|
||
import { detailAsinInput, detailItems, detailWorkerSettings } from '~/logic/storages/amazon';
|
||
|
||
const message = useMessage();
|
||
|
||
const timelines = ref<Timeline[]>([]);
|
||
|
||
const asinInputRef = useTemplateRef('asin-input');
|
||
|
||
//#region Page Worker 初始化Code
|
||
const worker = usePageWorker('amazon', { detailItems });
|
||
worker.on('error', ({ message: msg }) => {
|
||
timelines.value.push({
|
||
type: 'error',
|
||
title: '错误发生',
|
||
time: new Date().toLocaleString(),
|
||
content: msg,
|
||
});
|
||
message.error(msg);
|
||
});
|
||
worker.on('item-base-info-collected', (ev) => {
|
||
timelines.value.push({
|
||
type: 'success',
|
||
title: `商品${ev.asin}基本信息`,
|
||
time: new Date().toLocaleString(),
|
||
content: `标题: ${ev.title};价格:${ev.price}; 评分: ${ev.rating}; 评论数: ${ev.ratingCount}`,
|
||
});
|
||
});
|
||
worker.on('item-category-rank-collected', (ev) => {
|
||
timelines.value.push({
|
||
type: 'success',
|
||
title: `商品${ev.asin}分类排名`,
|
||
time: new Date().toLocaleString(),
|
||
content: [
|
||
ev.category1 ? `#${ev.category1.rank} in ${ev.category1.name}` : '',
|
||
ev.category2 ? `#${ev.category2.rank} in ${ev.category2.name}` : '',
|
||
].join('\n'),
|
||
});
|
||
});
|
||
worker.on('item-images-collected', (ev) => {
|
||
timelines.value.push({
|
||
type: 'success',
|
||
title: `商品${ev.asin}图像`,
|
||
time: new Date().toLocaleString(),
|
||
content: `图片数: ${ev.imageUrls!.length}`,
|
||
});
|
||
});
|
||
worker.on('item-top-reviews-collected', (ev) => {
|
||
timelines.value.push({
|
||
type: 'success',
|
||
title: `商品${ev.asin}精选评论`,
|
||
time: new Date().toLocaleString(),
|
||
content: `精选评论数: ${ev.topReviews!.length}`,
|
||
});
|
||
});
|
||
worker.on('item-aplus-screenshot-collect', (ev) => {
|
||
timelines.value.push({
|
||
type: 'success',
|
||
title: `商品${ev.asin} A+信息`,
|
||
time: new Date().toLocaleString(),
|
||
content: `获取到A+信息`,
|
||
});
|
||
});
|
||
//#endregion
|
||
|
||
const launch = async () => {
|
||
const asinList = detailAsinInput.value.split(/\n|\s|,|;/).filter((item) => item.length > 0);
|
||
timelines.value = [
|
||
{
|
||
type: 'info',
|
||
title: '开始',
|
||
time: new Date().toLocaleString(),
|
||
content: '开始数据采集',
|
||
},
|
||
];
|
||
await worker.runDetailPageTask(asinList, {
|
||
progress: (remains) => {
|
||
detailAsinInput.value = remains.join('\n');
|
||
},
|
||
aplus: detailWorkerSettings.value.aplus,
|
||
});
|
||
timelines.value.push({
|
||
type: 'info',
|
||
title: '结束',
|
||
time: new Date().toLocaleString(),
|
||
content: '数据采集完成',
|
||
});
|
||
};
|
||
|
||
const handleStart = () => {
|
||
asinInputRef.value?.validate().then(async (success) => success && launch());
|
||
};
|
||
|
||
const handleInterrupt = () => {
|
||
if (!worker.isRunning.value) return;
|
||
worker.stop();
|
||
message.info('已触发中断,正在等待当前任务完成。', { duration: 2000 });
|
||
};
|
||
</script>
|
||
|
||
<template>
|
||
<div class="detail-page-entry">
|
||
<header-title>Amazon Detail</header-title>
|
||
<div class="interative-section">
|
||
<ids-input v-model="detailAsinInput" :disabled="worker.isRunning.value" ref="asin-input">
|
||
<template #extra-settings>
|
||
<div class="setting-panel">
|
||
<n-form label-placement="left">
|
||
<n-form-item label="Aplus: " :feedback-style="{ display: 'none' }">
|
||
<n-switch v-model:value="detailWorkerSettings.aplus" />
|
||
</n-form-item>
|
||
</n-form>
|
||
</div>
|
||
</template>
|
||
</ids-input>
|
||
<n-button
|
||
v-if="!worker.isRunning.value"
|
||
round
|
||
size="large"
|
||
type="primary"
|
||
@click="handleStart"
|
||
>
|
||
<template #icon>
|
||
<ant-design-thunderbolt-outlined />
|
||
</template>
|
||
开始
|
||
</n-button>
|
||
<n-button v-else round size="large" type="primary" @click="handleInterrupt">
|
||
<template #icon>
|
||
<ant-design-thunderbolt-outlined />
|
||
</template>
|
||
停止
|
||
</n-button>
|
||
</div>
|
||
<div v-if="worker.isRunning.value" class="running-tip-section">
|
||
<n-alert title="Warning" type="warning"> 警告,在插件运行期间请勿与浏览器交互。 </n-alert>
|
||
</div>
|
||
<progress-report class="progress-report" :timelines="timelines" />
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped lang="scss">
|
||
.detail-page-entry {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
|
||
.interative-section {
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 15px;
|
||
align-items: stretch;
|
||
justify-content: center;
|
||
width: 85%;
|
||
border-radius: 10px;
|
||
border: 1px #00000020 dashed;
|
||
margin: 0 0 10px 0;
|
||
}
|
||
|
||
.running-tip-section {
|
||
margin: 10px 0 0 0;
|
||
height: 100px;
|
||
border-radius: 10px;
|
||
cursor: wait;
|
||
}
|
||
|
||
.progress-report {
|
||
margin-top: 10px;
|
||
width: 95%;
|
||
}
|
||
|
||
.setting-panel {
|
||
padding: 7px 10px;
|
||
}
|
||
</style>
|