|
@@ -0,0 +1,281 @@
|
|
|
|
+<script lang="ts" setup>/**
|
|
|
|
+ * @Name: createKeyword.vue
|
|
|
|
+ * @Description: 谷歌关键词添加
|
|
|
|
+ * @Author: xinyan
|
|
|
|
+ */
|
|
|
|
+import { deleteKeyword, getKeyword, postCreateKeyword, UpdateKeyword } from '/@/views/googleTrends/api';
|
|
|
|
+import { Delete, Plus } from '@element-plus/icons-vue';
|
|
|
|
+import { ref } from 'vue';
|
|
|
|
+import { VxeGridInstance } from 'vxe-table';
|
|
|
|
+
|
|
|
|
+const emit = defineEmits([ 'updateKeyword' ]);
|
|
|
|
+
|
|
|
|
+const keywordInput = ref('');
|
|
|
|
+const btnLoading = ref(false);
|
|
|
|
+
|
|
|
|
+const isCancel = ref(false); // 是否取消编辑
|
|
|
|
+const isEditing = ref(false); // 是否正在编辑
|
|
|
|
+const keywordList = ref([]); // 关键词列表
|
|
|
|
+const xGrid = ref<VxeGridInstance>();
|
|
|
|
+const gridOptions = reactive({
|
|
|
|
+ border: 'inner',
|
|
|
|
+ keepSource: true,
|
|
|
|
+ loading: false,
|
|
|
|
+ height: 555,
|
|
|
|
+ columnConfig: {
|
|
|
|
+ resizable: true
|
|
|
|
+ },
|
|
|
|
+ rowConfig: {
|
|
|
|
+ isHover: true,
|
|
|
|
+ height: 38,
|
|
|
|
+ },
|
|
|
|
+ editConfig: {
|
|
|
|
+ trigger: 'manual',
|
|
|
|
+ showIcon: false,
|
|
|
|
+ // autoFocus: true,
|
|
|
|
+ autoClear: false,
|
|
|
|
+ },
|
|
|
|
+ pagerConfig: {
|
|
|
|
+ enabled: true,
|
|
|
|
+ total: 20,
|
|
|
|
+ currentPage: 1,
|
|
|
|
+ pageSize: 20,
|
|
|
|
+ pageSizes: [10, 20, 30],
|
|
|
|
+ },
|
|
|
|
+ columns: [
|
|
|
|
+ { field: 'keyword', title: '关键词', editRender: { name: 'input' }, slots: { edit: 'keyword_edit' } },
|
|
|
|
+ { field: 'insert_time', title: '添加时间' },
|
|
|
|
+ { title: '操作', width: 120, slots: { default: 'operate' }, align: 'center' },
|
|
|
|
+ ],
|
|
|
|
+ data: []
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+const gridEvents = {
|
|
|
|
+ pageChange({ currentPage, pageSize }) {
|
|
|
|
+ if (gridOptions.pagerConfig) {
|
|
|
|
+ gridOptions.pagerConfig.currentPage = currentPage;
|
|
|
|
+ gridOptions.pagerConfig.pageSize = pageSize;
|
|
|
|
+ }
|
|
|
|
+ getList();
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const hasActiveEditRow = (row) => {
|
|
|
|
+ const $grid = xGrid.value;
|
|
|
|
+ if ($grid) {
|
|
|
|
+ return $grid.isEditByRow(row);
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+function editRowEvent(row) {
|
|
|
|
+ isCancel.value = false;
|
|
|
|
+ isEditing.value = true;
|
|
|
|
+ const $grid = xGrid.value;
|
|
|
|
+ if ($grid) {
|
|
|
|
+ $grid.setEditRow(row);
|
|
|
|
+ row.original_keyword = row.keyword;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function handelEditClosed({ row }) {
|
|
|
|
+ isEditing.value = false;
|
|
|
|
+ if (isCancel.value)return;
|
|
|
|
+ if (row.original_keyword !== row.keyword){
|
|
|
|
+ updateKeyword(row);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function getList() {
|
|
|
|
+ gridOptions.loading = true;
|
|
|
|
+ try {
|
|
|
|
+ const resp = await getKeyword({
|
|
|
|
+ page: gridOptions.pagerConfig.currentPage,
|
|
|
|
+ limit: gridOptions.pagerConfig.pageSize,
|
|
|
|
+ });
|
|
|
|
+ gridOptions.data = resp.data;
|
|
|
|
+ keywordList.value = resp.data.map(item => item.keyword);
|
|
|
|
+ emit('updateKeyword',keywordList.value);
|
|
|
|
+ gridOptions.pagerConfig.total = resp.total;
|
|
|
|
+ gridOptions.loading = false;
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.log(error);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function handleAdd() {
|
|
|
|
+ const keywordsInput = keywordInput.value.trim();
|
|
|
|
+ if (!keywordsInput) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // 按行拆分关键词,并过滤掉空行
|
|
|
|
+ const keywords = keywordsInput.split('\n').map(keyword => keyword.trim()).filter(keyword => keyword.length > 0);
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ btnLoading.value = true;
|
|
|
|
+ const resp = await postCreateKeyword({ keyword: keywords.join(',') });
|
|
|
|
+ if (resp.code === 2000) {
|
|
|
|
+ ElMessage.success('关键词添加成功');
|
|
|
|
+ keywordInput.value = ''; // 清空输入框
|
|
|
|
+ await getList();
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ ElMessage.error('添加关键词失败,请重试!'); // 提示失败消息
|
|
|
|
+ } finally {
|
|
|
|
+ btnLoading.value = false;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function updateKeyword(row) {
|
|
|
|
+ try {
|
|
|
|
+ gridOptions.loading = true;
|
|
|
|
+ const resp = await UpdateKeyword({
|
|
|
|
+ id: row.id,
|
|
|
|
+ new_keyword: row.keyword
|
|
|
|
+ });
|
|
|
|
+ if (resp.code === 2000) {
|
|
|
|
+ await getList();
|
|
|
|
+ ElMessage.success('关键词更新成功');
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ ElMessage.error('更新关键词失败,请重试!'); // 提示失败消息
|
|
|
|
+ } finally {
|
|
|
|
+ gridOptions.loading = false;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function cancel(row) {
|
|
|
|
+ isCancel.value = true;
|
|
|
|
+ const $grid = xGrid.value;
|
|
|
|
+ if ($grid) {
|
|
|
|
+ $grid.clearEdit().then(() => {
|
|
|
|
+ $grid.revertData(row)
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function handleDelete(row) {
|
|
|
|
+ try {
|
|
|
|
+ gridOptions.loading = true;
|
|
|
|
+ const resp = await deleteKeyword({ keyword: row.keyword });
|
|
|
|
+ if (resp.code === 2000) {
|
|
|
|
+ ElMessage.success('关键词删除成功');
|
|
|
|
+ await getList();
|
|
|
|
+ }
|
|
|
|
+ } catch (error) {
|
|
|
|
+ ElMessage.error('删除关键词失败,请重试!'); // 提示失败消息
|
|
|
|
+ } finally {
|
|
|
|
+ gridOptions.loading = false;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function handleClear() {
|
|
|
|
+ keywordInput.value = '';
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const cellStyle = () => {
|
|
|
|
+ return {
|
|
|
|
+ fontSize: '13px',
|
|
|
|
+ fontWeight: '500',
|
|
|
|
+ };
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const headerCellStyle = () => {
|
|
|
|
+ return {
|
|
|
|
+ fontSize: '13px',
|
|
|
|
+ backgroundColor: '#f0f1f3',
|
|
|
|
+ height: 10,
|
|
|
|
+ };
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+onMounted(() => {
|
|
|
|
+ getList();
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<template>
|
|
|
|
+ <el-card class="mx-2 my-5">
|
|
|
|
+ <div class="my-4 mx-1.5" style="font-size: 18px;font-weight: bold;color: #464646">谷歌关键词添加</div>
|
|
|
|
+ <div class="mx-2">
|
|
|
|
+ <el-row :gutter="20">
|
|
|
|
+ <el-col :span="8" class="input-section">
|
|
|
|
+ <div class="input-container">
|
|
|
|
+ <el-input
|
|
|
|
+ v-model="keywordInput"
|
|
|
|
+ :rows="26"
|
|
|
|
+ class="textarea"
|
|
|
|
+ placeholder="添加谷歌趋势关键词,一行一个关键词......(关键词添加上限200个)"
|
|
|
|
+ type="textarea"
|
|
|
|
+ />
|
|
|
|
+ <!-- 按钮组 -->
|
|
|
|
+ <div class="button-group">
|
|
|
|
+ <el-popconfirm
|
|
|
|
+ :icon="InfoFilled"
|
|
|
|
+ icon-color="#626AEF"
|
|
|
|
+ title="确认清空关键词?"
|
|
|
|
+ width="220"
|
|
|
|
+ @confirm="handleClear"
|
|
|
|
+ >
|
|
|
|
+ <template #reference>
|
|
|
|
+ <el-button :icon="Delete" bg size="small" text type="danger">清空</el-button>
|
|
|
|
+ </template>
|
|
|
|
+ </el-popconfirm>
|
|
|
|
+ <el-button :icon="Plus" :loading="btnLoading" bg size="small" text type="primary" @click="handleAdd">添加
|
|
|
|
+ </el-button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="16">
|
|
|
|
+ <el-card body-style="padding: 0" shadow="never">
|
|
|
|
+ <vxe-grid ref="xGrid" :cell-style="cellStyle" :header-cell-style="headerCellStyle" show-overflow
|
|
|
|
+ v-bind="gridOptions" v-on="gridEvents" @edit-closed="handelEditClosed">
|
|
|
|
+ <template #operate="{ row }">
|
|
|
|
+ <template v-if="hasActiveEditRow(row)">
|
|
|
|
+ <el-button link size="small" @click="cancel(row)">取消</el-button>
|
|
|
|
+ <el-button link size="small" type="warning" @click="updateKeyword(row)">保存</el-button>
|
|
|
|
+ </template>
|
|
|
|
+ <template v-else>
|
|
|
|
+ <el-button link size="small" type="primary" @click="editRowEvent(row)">编辑</el-button>
|
|
|
|
+ <el-popconfirm
|
|
|
|
+ :icon="InfoFilled"
|
|
|
|
+ icon-color="#626AEF"
|
|
|
|
+ title="确认删除关键词?"
|
|
|
|
+ width="220"
|
|
|
|
+ @confirm="handleDelete(row)"
|
|
|
|
+ >
|
|
|
|
+ <template #reference>
|
|
|
|
+ <el-button :disabled="isEditing" link size="small" type="danger">删除</el-button>
|
|
|
|
+ </template>
|
|
|
|
+ </el-popconfirm>
|
|
|
|
+ </template>
|
|
|
|
+ </template>
|
|
|
|
+ <template #keyword_edit="{ row }">
|
|
|
|
+ <el-input v-model="row.keyword"/>
|
|
|
|
+ </template>
|
|
|
|
+ </vxe-grid>
|
|
|
|
+ </el-card>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ </div>
|
|
|
|
+ </el-card>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<style scoped>
|
|
|
|
+.input-container {
|
|
|
|
+ position: relative;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.textarea {
|
|
|
|
+ width: 100%;
|
|
|
|
+ padding-bottom: 40px; /* 为按钮腾出空间 */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.button-group {
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 50px;
|
|
|
|
+ right: 10px;
|
|
|
|
+ /* display: flex; */
|
|
|
|
+ /* gap: 5px; */
|
|
|
|
+}
|
|
|
|
+</style>
|