|
@@ -4,19 +4,282 @@
|
|
|
* @Description: 关键词-TopSearchTerm Table
|
|
|
* @Author: Cheney
|
|
|
*/
|
|
|
+
|
|
|
+import { onMounted, ref, watch } from 'vue';
|
|
|
+import { usePagination } from '/@/utils/usePagination';
|
|
|
+import { getTopSearchTermTable } from './api';
|
|
|
+import { marketplaceIdEnum } from '/@/utils/marketplaceIdEnum';
|
|
|
+import { RefreshRight, Search } from '@element-plus/icons-vue';
|
|
|
+import { useRouter } from 'vue-router';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import dayjs from 'dayjs';
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+
|
|
|
+const { tableData, total, currentPage, pageSize, handlePageChange } = usePagination(fetchTableData);
|
|
|
+
|
|
|
+const date = ref([dayjs().subtract(7, 'day').format('YYYY-MM-DD'), dayjs().subtract(1, 'day').format('YYYY-MM-DD')]);
|
|
|
+const searchTermInp = ref('');
|
|
|
+const asinInp = ref('');
|
|
|
+const marketplaceSelect = ref(marketplaceIdEnum[0].value); // 当前只有美国区 默认第一个为美国
|
|
|
+const marketplaceOptions = marketplaceIdEnum;
|
|
|
+const reportTypeSelect = ref('weekly');
|
|
|
+
|
|
|
+const tableLoading = ref(false);
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ fetchTableData();
|
|
|
+});
|
|
|
+
|
|
|
+watch(date, () => {
|
|
|
+ fetchTableData();
|
|
|
+});
|
|
|
+
|
|
|
+async function refreshTable() {
|
|
|
+ currentPage.value = 1;
|
|
|
+ pageSize.value = 10;
|
|
|
+ asinInp.value = '';
|
|
|
+ searchTermInp.value = '';
|
|
|
+ reportTypeSelect.value = 'weekly';
|
|
|
+ marketplaceSelect.value = marketplaceIdEnum[0].value;
|
|
|
+ await fetchTableData();
|
|
|
+}
|
|
|
+
|
|
|
+async function fetchTableData() {
|
|
|
+ tableLoading.value = true;
|
|
|
+ const query = {
|
|
|
+ page: currentPage.value,
|
|
|
+ limit: pageSize.value,
|
|
|
+ asin: asinInp.value,
|
|
|
+ search_term: searchTermInp.value,
|
|
|
+ report_type: reportTypeSelect.value,
|
|
|
+ marketplace_Ids: marketplaceSelect.value,
|
|
|
+ date_start: date.value[0],
|
|
|
+ date_end: date.value[1],
|
|
|
+ };
|
|
|
+ const response = await getTopSearchTermTable(query);
|
|
|
+ total.value = response.total;
|
|
|
+ tableData.value = response.data;
|
|
|
+ tableLoading.value = false;
|
|
|
+}
|
|
|
+
|
|
|
+async function handleQueryChange() {
|
|
|
+ if (!validateSearchTermInput(searchTermInp.value)) {
|
|
|
+ ElMessage.warning({ message: '关键词只能输入数字和英文字母', plain: true });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!validateAsinInput(asinInp.value)) {
|
|
|
+ if (asinInp.value.length == 0) return;
|
|
|
+ else {
|
|
|
+ ElMessage.warning({ message: '不符合匹配规范', plain: true });
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ await fetchTableData();
|
|
|
+}
|
|
|
+
|
|
|
+function handleJump() {
|
|
|
+ // console.log('All defined routes:', router.getRoutes());
|
|
|
+ router.push({ path: '/keyword/rootWordManage' });
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 校验SearchTerm输入是否合法
|
|
|
+ * @param input 输入的字符串
|
|
|
+ */
|
|
|
+function validateSearchTermInput(input: string) {
|
|
|
+ const regex = /^[a-zA-Z0-9\s]*$/;
|
|
|
+ return regex.test(input);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 校验Asin输入是否合法
|
|
|
+ * @param input 输入的字符串
|
|
|
+ */
|
|
|
+function validateAsinInput(input: string) {
|
|
|
+ const regex = /^[Bb]0[A-Za-z0-9\s]+$/i;
|
|
|
+ return regex.test(input);
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
-<div style="background-color: #f7f7f7;">
|
|
|
- <div class="flex justify-between mt-1.5 mx-2">
|
|
|
- <span class="font-bold text-lg">
|
|
|
- Top Search Term - Table
|
|
|
- </span>
|
|
|
- <el-button type="info">关键词管理</el-button>
|
|
|
+ <div class="mt-3 mx-1.5" style="background-color: #f7f7f7">
|
|
|
+ <div class="flex justify-between mt-1.5 mx-2">
|
|
|
+ <div class="font-bold text-lg">
|
|
|
+ <el-icon style="top: 3px">
|
|
|
+ <Memo />
|
|
|
+ </el-icon>
|
|
|
+ Top Search Term - Table
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <el-button type="primary" plain @click="handleJump">关键词管理</el-button>
|
|
|
+ <el-button type="success" plain round>下载表格</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="mx-3" style="margin-top: -8px">
|
|
|
+ <el-divider>
|
|
|
+ <el-icon>
|
|
|
+ <star-filled />
|
|
|
+ </el-icon>
|
|
|
+ </el-divider>
|
|
|
</div>
|
|
|
-</div>
|
|
|
+
|
|
|
+ <el-card class="mx-3" v-loading="tableLoading" style="border: none">
|
|
|
+ <!-- table筛选栏 -->
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <div class="flex gap-6 flex-wrap">
|
|
|
+ <div>
|
|
|
+ <span class="font-medium mr-0.5">市场 </span>
|
|
|
+ <el-select v-model="marketplaceSelect" @change="handleQueryChange" style="width: 130px">
|
|
|
+ <el-option
|
|
|
+ v-for="item in marketplaceOptions"
|
|
|
+ :disabled="item.disabled"
|
|
|
+ :key="item.value"
|
|
|
+ :value="item.value"
|
|
|
+ :label="item.label" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="font-medium mr-0.5">报告类型 </span>
|
|
|
+ <el-select v-model="reportTypeSelect" @change="handleQueryChange" style="width: 100px">
|
|
|
+ <el-option label="周度" value="weekly" />
|
|
|
+ <el-option label="月度" value="monthly" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="font-medium mr-0.5">关键词 </span>
|
|
|
+ <el-input
|
|
|
+ v-model="searchTermInp"
|
|
|
+ @keyup.enter="handleQueryChange"
|
|
|
+ :prefix-icon="Search"
|
|
|
+ placeholder="输入后回车查询"
|
|
|
+ clearable
|
|
|
+ style="width: 300px"></el-input>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="font-medium mr-0.5">ASIN </span>
|
|
|
+ <el-input
|
|
|
+ v-model="asinInp"
|
|
|
+ @keyup.enter="handleQueryChange"
|
|
|
+ :prefix-icon="Search"
|
|
|
+ placeholder="输入后回车查询"
|
|
|
+ clearable
|
|
|
+ style="width: 180px"></el-input>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="font-medium mr-0.5">报告日期 </span>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="date"
|
|
|
+ type="daterange"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ :popper-options="{ placement: 'bottom-end' }"
|
|
|
+ :clearable="false"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-button @click="refreshTable" :icon="RefreshRight" circle></el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- table -->
|
|
|
+ <el-card shadow="never" class="mt-5">
|
|
|
+ <div style="height: 765px">
|
|
|
+ <el-table :data="tableData" stripe height="765px" style="width: 100%">
|
|
|
+ <el-table-column fixed prop="searchTerm" label="关键词" width="260">
|
|
|
+ <template #header>
|
|
|
+ <el-icon style="top: 2px; margin-right: 3px">
|
|
|
+ <Key />
|
|
|
+ </el-icon>
|
|
|
+ <span>关键词</span>
|
|
|
+ </template>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span class="font-medium text-lg" style="color: #0b3289">{{ row.searchTerm }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="searchFrequencyRank" label="关键词搜索排名" align="center" width="150">
|
|
|
+ <template #header>
|
|
|
+ <el-icon style="top: 2px; margin-right: 4px">
|
|
|
+ <Rank />
|
|
|
+ </el-icon>
|
|
|
+ <span>关键词搜索排名</span>
|
|
|
+ </template>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span class="font-medium">{{ row.searchFrequencyRank }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="clickedAsin" align="center" label="Asin">
|
|
|
+ <template #header>
|
|
|
+ <el-icon style="top: 2px; margin-right: 5px">
|
|
|
+ <Goods />
|
|
|
+ </el-icon>
|
|
|
+ <span>Asin</span>
|
|
|
+ </template>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span class="font-medium">{{ row.clickedAsin }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="clickedItemName" label="标题">
|
|
|
+ <template #header>
|
|
|
+ <el-icon style="top: 2px; margin-right: 5px">
|
|
|
+ <Reading />
|
|
|
+ </el-icon>
|
|
|
+ <span>标题</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="clickShareRank" label="点击分享率排名" align="center" width="150">
|
|
|
+ <template #header>
|
|
|
+ <el-icon style="top: 2px; margin-right: 4px">
|
|
|
+ <Medal />
|
|
|
+ </el-icon>
|
|
|
+ <span>点击分享率排名</span>
|
|
|
+ </template>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span class="font-semibold">{{ row.clickShareRank }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="clickShare" align="center" label="点击分享率">
|
|
|
+ <template #header>
|
|
|
+ <el-icon style="top: 2px; margin-right: 4px">
|
|
|
+ <Pointer />
|
|
|
+ </el-icon>
|
|
|
+ <span>点击分享率</span>
|
|
|
+ </template>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span class="font-semibold">{{ row.clickShare }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="conversionShare" align="center" label="转化分享率">
|
|
|
+ <template #header>
|
|
|
+ <el-icon style="top: 2px; margin-right: 5px">
|
|
|
+ <Switch />
|
|
|
+ </el-icon>
|
|
|
+ <span>转化分享率</span>
|
|
|
+ </template>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span class="font-semibold">{{ row.conversionShare }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ <div class="mt-3.5 flex justify-end">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="currentPage"
|
|
|
+ v-model:page-size="pageSize"
|
|
|
+ :page-sizes="[10, 20, 30, 50]"
|
|
|
+ layout="sizes, prev, pager, next"
|
|
|
+ :total="total"
|
|
|
+ @change="handlePageChange" />
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </el-card>
|
|
|
</template>
|
|
|
|
|
|
<style scoped>
|
|
|
-
|
|
|
+:deep(.el-divider__text.is-center.el-divider__text) {
|
|
|
+ background-color: #f8f8f8;
|
|
|
+}
|
|
|
</style>
|