|
@@ -0,0 +1,272 @@
|
|
|
+<template>
|
|
|
+ <div class="layout-padding">
|
|
|
+ <div class="layout-padding-auto layout-padding-view">
|
|
|
+ <el-row shadow="hover" class="ml10">
|
|
|
+ <el-form :inline="true" :model="state.queryForm" @keyup.enter="query" ref="queryRef">
|
|
|
+ <!-- <el-form-item :label="'规则名称'" prop="ruleName">
|
|
|
+ <el-input :placeholder="'请输入规则名称'" v-model="state.queryForm.ruleName" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item :label="'触发信息'" prop="triggerCondition">
|
|
|
+ <el-input :placeholder="'请输入触发信息'" v-model="state.queryForm.triggerCondition" />
|
|
|
+ </el-form-item> -->
|
|
|
+ <el-form-item :label="'推送时间'" prop="createTime">
|
|
|
+ <el-date-picker :disabled-date="disabledDate" :end-placeholder="'结束日期'" :start-placeholder="'开始日期'"
|
|
|
+ format="YYYY-MM-DD" range-separator="至" type="daterange" v-model="state.queryForm.createTime" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button @click="query" class="ml10" icon="search" type="primary">
|
|
|
+ {{ t('common.queryBtn') }}
|
|
|
+ </el-button>
|
|
|
+ <el-button @click="resetQuery" icon="Refresh">{{ t('common.resetBtn') }}</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-table ref="tableRef" :data="state.dataList" row-key="id" style="width: 100%" v-loading="state.loading" border
|
|
|
+ :cell-style="tableStyle.cellStyle" :header-cell-style="tableStyle?.headerCellStyle">
|
|
|
+ <!-- <el-table-column :formatter="statusFormatter" :label="'推送IP'" prop="pushIP" min-width="200"
|
|
|
+ show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column :formatter="statusFormatter" :label="'推送域名'" prop="pushDomain" min-width="200"
|
|
|
+ show-overflow-tooltip></el-table-column> -->
|
|
|
+ <el-table-column :formatter="statusFormatter" :label="'推送内容'" prop="pushContent" min-width="200"
|
|
|
+ show-overflow-tooltip>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-image v-if="row.pushType" :src="row.pushContent" style="width: 100px; height: 100px;" />
|
|
|
+ <div v-else>{{ row.pushContent }}</div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column :formatter="statusFormatter" :label="'推送方式'" prop="pushType" min-width="200"
|
|
|
+ show-overflow-tooltip>
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{pushMode.filter(item => item.value == row.pushAction)[0]?.label}}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column :formatter="statusFormatter" :label="'推送频率'" prop="pushFrequency" min-width="120"
|
|
|
+ show-overflow-tooltip>
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ formatNum(row.pushFrequency) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column :formatter="statusFormatter" :label="'推送时间'" prop="createTime" min-width="200"
|
|
|
+ show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column :formatter="statusFormatter" :label="'延时推送'" prop="delayPush" min-width="100"
|
|
|
+ show-overflow-tooltip>
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ row.delayPush }}s
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column :formatter="statusFormatter" :label="'推送状态'" prop="pushStatus" min-width="120"
|
|
|
+ show-overflow-tooltip>
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ row.pushStatus ? '已推送' : '未推送' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column :formatter="statusFormatter" :label="'推送详情'" prop="pushDetail" min-width="250">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <div class="trigger-info" @click="showTriggerInfo(row)">
|
|
|
+ {{ row.pushDetail }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle" v-bind="state.pagination" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <dataInfoModal ref="richContentDialogRef"></dataInfoModal>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" name="marketingApps" setup>
|
|
|
+import { getHandPushPage } from '/@/api/marketing/apps';
|
|
|
+import { BasicTableProps, useTable } from '/@/hooks/table';
|
|
|
+import { useI18n } from 'vue-i18n';
|
|
|
+import { ref, reactive, onMounted, defineAsyncComponent } from 'vue'
|
|
|
+const dataInfoModal = defineAsyncComponent(() => import('/@/views/marketing/data/dataInfoModal.vue'));
|
|
|
+import { ElImage } from 'element-plus';
|
|
|
+import { fetchItemList } from '/@/api/admin/dict';
|
|
|
+import { formatDate } from '/@/utils/formatTime';
|
|
|
+
|
|
|
+const { t } = useI18n();
|
|
|
+
|
|
|
+const getDataListWithProcess = (params: any): Promise<any> => {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ console.log(params, 'params');
|
|
|
+ const data = {
|
|
|
+ ...params,
|
|
|
+ pageNum: params.current,
|
|
|
+ pageSize: params.size,
|
|
|
+ endTime: params.createTime ? formatDate(params.createTime[0], 'YYYY-mm-dd') : '',
|
|
|
+ createTime: params.createTime ? formatDate(params.createTime[1], 'YYYY-mm-dd') : '',
|
|
|
+ }
|
|
|
+ delete data.current;
|
|
|
+ delete data.size;
|
|
|
+ delete data.ascs;
|
|
|
+ delete data.descs;
|
|
|
+
|
|
|
+ getHandPushPage(data).then((res: any) => {
|
|
|
+ console.log(res, 'res');
|
|
|
+ try {
|
|
|
+ if (res.data && res.data.records && res.data.records.length > 0) {
|
|
|
+ res.data.records = res.data.records.map((item: any) => {
|
|
|
+ let parsedData: any = null;
|
|
|
+ try {
|
|
|
+ if (item.triggerCondition) {
|
|
|
+ parsedData = JSON.parse(item.triggerCondition);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.warn('解析触发器条件失败:', item.triggerCondition, error);
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ _keywords: parsedData?.keywords || [],
|
|
|
+ _ip: parsedData?.ip || '',
|
|
|
+ _domain: parsedData?.domain || ''
|
|
|
+ };
|
|
|
+ });
|
|
|
+ }
|
|
|
+ resolve(res);
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('数据处理失败:', error);
|
|
|
+ reject(error);
|
|
|
+ }
|
|
|
+ }).catch((error: any) => {
|
|
|
+ reject(error);
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 定义变量内容
|
|
|
+const tableRef = ref();
|
|
|
+const queryRef = ref();
|
|
|
+const state: BasicTableProps = reactive<BasicTableProps>({
|
|
|
+ pageList: getDataListWithProcess,
|
|
|
+ createdIsNeed: false,
|
|
|
+ queryForm: {
|
|
|
+ ruleName: '',
|
|
|
+ triggerCondition: '',
|
|
|
+ },
|
|
|
+ pagination: {
|
|
|
+ current: 1,
|
|
|
+ size: 10,
|
|
|
+ total: 0,
|
|
|
+ pageSizes: [5, 10, 20, 50, 100]
|
|
|
+ },
|
|
|
+});
|
|
|
+const pushMode = ref<any>([]);
|
|
|
+const disabledDate = (time: Date) => {
|
|
|
+ return time.getTime() > Date.now();
|
|
|
+}
|
|
|
+
|
|
|
+interface SourceData {
|
|
|
+ ruleName: string;
|
|
|
+ triggerCondition: string;
|
|
|
+ triggerTime: string;
|
|
|
+ pushStatus: string;
|
|
|
+ pushContent: string;
|
|
|
+ pushFrequency: string;
|
|
|
+ pushTime: string;
|
|
|
+}
|
|
|
+
|
|
|
+const richContentDialogRef = ref();
|
|
|
+const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state);
|
|
|
+
|
|
|
+// 搜索事件
|
|
|
+const query = (refresh: boolean = false) => {
|
|
|
+ state.dataList = [];
|
|
|
+ getDataList(refresh);
|
|
|
+};
|
|
|
+
|
|
|
+// 清空搜索条件
|
|
|
+const resetQuery = () => {
|
|
|
+ queryRef.value.resetFields();
|
|
|
+ state.dataList = [];
|
|
|
+ getDataList();
|
|
|
+};
|
|
|
+
|
|
|
+const statusFormatter = (row: any, column: any, cellValue: any, index: any) => {
|
|
|
+ return cellValue || '--';
|
|
|
+}
|
|
|
+
|
|
|
+const showTriggerInfo = (row: any) => {
|
|
|
+ // 信息详情弹窗
|
|
|
+ richContentDialogRef.value.openDialog(
|
|
|
+ row.pushDetail,
|
|
|
+ {
|
|
|
+ createTime: row.createTime,
|
|
|
+ triggerKeyword: row._keywords
|
|
|
+ }
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+const getFetchItemList = async () => {
|
|
|
+ const res = await fetchItemList({
|
|
|
+ dictType: 'pushMode',
|
|
|
+ });
|
|
|
+
|
|
|
+ pushMode.value = res.data.records.map((item: any) => ({
|
|
|
+ label: item.description,
|
|
|
+ value: item.value
|
|
|
+ }));
|
|
|
+ console.log(pushMode, 'pushMode');
|
|
|
+}
|
|
|
+
|
|
|
+// 格式化数据展示
|
|
|
+const formatNum = (value: string | number = 0) => {
|
|
|
+ let num = Number(value);
|
|
|
+ if (num > 0 && num < 1) {
|
|
|
+ return (num * 100).toFixed(0) + '%';
|
|
|
+ } else if (num >= 1 && num < 10000) {
|
|
|
+ return '每'+num+'次推送';
|
|
|
+ }
|
|
|
+ return '--';
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getFetchItemList();
|
|
|
+ query();
|
|
|
+});
|
|
|
+
|
|
|
+</script>
|
|
|
+<style scoped lang="scss">
|
|
|
+:deep(.el-link__inner) {
|
|
|
+ display: inline-block;
|
|
|
+ width: 100%;
|
|
|
+ justify-content: start;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-link.is-underline:hover:after) {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+
|
|
|
+.table-tabs {
|
|
|
+ margin-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.trigger-info {
|
|
|
+ overflow: hidden;
|
|
|
+ text-align: center;
|
|
|
+ width: 100%;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ overflow: hidden;
|
|
|
+ white-space: nowrap;
|
|
|
+ color: #409eff;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.header-wrapper {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.header-icon {
|
|
|
+ margin-left: 5px;
|
|
|
+ color: #999;
|
|
|
+ font-size: 14px;
|
|
|
+ cursor: help;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #409eff;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|