123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- <script setup lang="ts">
- /**
- * @Name: index.vue
- * @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 {
- Download,
- Goods,
- Key,
- Medal,
- Memo,
- Pointer,
- Rank,
- Reading,
- RefreshRight,
- Search,
- Switch,
- TopRight,
- } 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 handleSelectChange() {
- await fetchTableData();
- }
- async function handleQueryChange() {
- if (!validateSearchTermInput(searchTermInp.value)) {
- if (searchTermInp.value.length == 0) {
- return;
- } else {
- ElMessage.warning({ message: '关键词只能输入数字和英文字母', plain: true });
- return;
- }
- }
- if (asinInp.value.length > 0 && !validateAsinInput(asinInp.value)) {
- ElMessage.warning({ message: '不符合匹配规范', plain: true });
- return;
- }
- await fetchTableData();
- }
- /**
- * 校验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);
- }
- function handleJump() {
- // console.log('All defined routes:', router.getRoutes());
- router.push({ path: '/keyword/rootWordManage' });
- }
- function getTagStyle(clickShareRank: number): Record<string, string> {
- switch (clickShareRank) {
- case 1:
- return { backgroundColor: '#fbbf24', color: '#fff', border: '1px solid #fbbf24' }; // 金色
- case 2:
- return { backgroundColor: '#C0C0C0', color: '#fff', border: '1px solid #C0C0C0' }; // 银色
- case 3:
- return { backgroundColor: '#CD7F32', color: '#fff', border: '1px solid #CD7F32' }; // 铜色
- default:
- return { backgroundColor: '#e0e0e0', color: '#000', border: '1px solid #e0e0e0' };
- }
- }
- </script>
- <template>
- <!--<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" :icon="TopRight">关键词管理</el-button>-->
- <!-- <el-button type="success" plain round :icon="Download">下载表格</el-button>-->
- <!-- </div>-->
- <!-- </div>-->
- <!--</div>-->
- <div class="mx-3" style="margin-top: -8px">
- <el-divider>
- <!--<el-icon>-->
- <!-- <star-filled />-->
- <!--</el-icon>-->
- <div class="font-bold text-lg">
- <el-icon style="top: 3px">
- <Memo />
- </el-icon>
- Top Search Term - Table
- </div>
- </el-divider>
- </div>
- <el-card class="mx-3" v-loading="tableLoading" style="border: none">
- <!-- table筛选栏 -->
- <div class="flex justify-between">
- <div class="flex gap-5 flex-wrap">
- <div>
- <span class="font-medium mr-0.5">市场 </span>
- <el-select v-model="marketplaceSelect" @change="handleSelectChange" 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="handleSelectChange" 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"
- :disabled-date="(time: Date) => time > new Date()"
- range-separator="至"
- start-placeholder="开始日期"
- end-placeholder="结束日期" />
- </div>
- </div>
- <div>
- <el-button type="primary" plain @click="handleJump" :icon="TopRight">关键词管理</el-button>
- <el-button type="success" plain round :icon="Download">下载表格</el-button>
- <el-button @click="refreshTable" :icon="RefreshRight" circle></el-button>
- </div>
- </div>
- <!-- table -->
- <el-card shadow="never" class="mt-5">
- <div style="height: 795px; overflow: auto">
- <el-table :data="tableData" stripe 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 }">
- <el-link :underline="false" href="https://www.bilibili.com/" target="_blank" style="color: #0b3289">{{
- row.searchTerm
- }}</el-link>
- </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>-->
- <el-tag :style="getTagStyle(row.clickShareRank)">
- {{ row.clickShareRank }}
- </el-tag>
- </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, 100, 200]"
- 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>
|