index.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <template>
  2. <div class="layout-padding">
  3. <div class="layout-padding-auto layout-padding-view">
  4. <el-row shadow="hover" class="ml10">
  5. <el-form :inline="true" :model="state.queryForm" @keyup.enter="query" ref="queryRef">
  6. <!-- <el-form-item :label="'规则名称'" prop="ruleName">
  7. <el-input :placeholder="'请输入规则名称'" v-model="state.queryForm.ruleName" />
  8. </el-form-item>
  9. <el-form-item :label="'触发信息'" prop="triggerCondition">
  10. <el-input :placeholder="'请输入触发信息'" v-model="state.queryForm.triggerCondition" />
  11. </el-form-item> -->
  12. <el-form-item :label="'推送时间'" prop="createTime">
  13. <el-date-picker :disabled-date="disabledDate" :end-placeholder="'结束日期'" :start-placeholder="'开始日期'"
  14. format="YYYY-MM-DD" range-separator="至" type="daterange" v-model="state.queryForm.createTime" />
  15. </el-form-item>
  16. <el-form-item>
  17. <el-button @click="query" class="ml10" icon="search" type="primary">
  18. {{ t('common.queryBtn') }}
  19. </el-button>
  20. <el-button @click="resetQuery" icon="Refresh">{{ t('common.resetBtn') }}</el-button>
  21. </el-form-item>
  22. </el-form>
  23. </el-row>
  24. <el-table ref="tableRef" :data="state.dataList" row-key="id" style="width: 100%" v-loading="state.loading" border
  25. :cell-style="tableStyle.cellStyle" :header-cell-style="tableStyle?.headerCellStyle">
  26. <!-- <el-table-column :formatter="statusFormatter" :label="'推送IP'" prop="pushIP" min-width="200"
  27. show-overflow-tooltip></el-table-column>
  28. <el-table-column :formatter="statusFormatter" :label="'推送域名'" prop="pushDomain" min-width="200"
  29. show-overflow-tooltip></el-table-column> -->
  30. <el-table-column :label="'客户端ID'" prop="clientId" min-width="200"
  31. show-overflow-tooltip>
  32. </el-table-column>
  33. <el-table-column :formatter="statusFormatter" :label="'推送内容'" prop="pushContent" min-width="200"
  34. show-overflow-tooltip>
  35. <template #default="{ row }">
  36. <el-image v-if="row.pushType" :src="row.pushContent" style="width: 100px; height: 100px;" />
  37. <div v-else>{{ row.pushContent }}</div>
  38. </template>
  39. </el-table-column>
  40. <el-table-column :formatter="statusFormatter" :label="'推送方式'" prop="pushType" min-width="200"
  41. show-overflow-tooltip>
  42. <template #default="{ row }">
  43. {{pushMode.filter(item => item.value == row.pushAction)[0]?.label}}
  44. </template>
  45. </el-table-column>
  46. <el-table-column :formatter="statusFormatter" :label="'推送频率'" prop="pushFrequency" min-width="120"
  47. show-overflow-tooltip>
  48. <template #default="{ row }">
  49. {{ formatNum(row.pushFrequency) }}
  50. </template>
  51. </el-table-column>
  52. <el-table-column :formatter="statusFormatter" :label="'延时推送'" prop="delayPush" min-width="100"
  53. show-overflow-tooltip>
  54. <template #default="{ row }">
  55. {{ row.delayPush }}s
  56. </template>
  57. </el-table-column>
  58. <el-table-column :formatter="statusFormatter" :label="'推送时间'" prop="createTime" min-width="200"
  59. show-overflow-tooltip></el-table-column>
  60. <el-table-column :formatter="statusFormatter" :label="'推送状态'" prop="pushStatus" min-width="120"
  61. show-overflow-tooltip>
  62. <template #default="{ row }">
  63. {{ row.pushStatus ? '已推送' : '未推送' }}
  64. </template>
  65. </el-table-column>
  66. <el-table-column :formatter="statusFormatter" :label="'推送详情'" prop="pushDetail" min-width="250">
  67. <template #default="{ row }">
  68. <div class="trigger-info" @click="showTriggerInfo(row)">
  69. {{ row.pushDetail }}
  70. </div>
  71. </template>
  72. </el-table-column>
  73. </el-table>
  74. <pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle" v-bind="state.pagination" />
  75. </div>
  76. <dataInfoModal ref="richContentDialogRef"></dataInfoModal>
  77. </div>
  78. </template>
  79. <script lang="ts" name="marketingApps" setup>
  80. import { getHandPushPage } from '/@/api/marketing/apps';
  81. import { BasicTableProps, useTable } from '/@/hooks/table';
  82. import { useI18n } from 'vue-i18n';
  83. import { ref, reactive, onMounted, defineAsyncComponent } from 'vue'
  84. const dataInfoModal = defineAsyncComponent(() => import('/@/views/marketing/data/dataInfoModal.vue'));
  85. import { ElImage } from 'element-plus';
  86. import { fetchItemList } from '/@/api/admin/dict';
  87. import { formatDate } from '/@/utils/formatTime';
  88. const { t } = useI18n();
  89. const getDataListWithProcess = (params: any): Promise<any> => {
  90. return new Promise((resolve, reject) => {
  91. console.log(params, 'params');
  92. const data = {
  93. ...params,
  94. pageNum: params.current,
  95. pageSize: params.size,
  96. endTime: params.createTime ? formatDate(params.createTime[1], 'YYYY-mm-dd') : '',
  97. createTime: params.createTime ? formatDate(params.createTime[0], 'YYYY-mm-dd') : '',
  98. }
  99. delete data.current;
  100. delete data.size;
  101. delete data.ascs;
  102. delete data.descs;
  103. getHandPushPage(data).then((res: any) => {
  104. console.log(res, 'res');
  105. try {
  106. if (res.data && res.data.records && res.data.records.length > 0) {
  107. res.data.records = res.data.records.map((item: any) => {
  108. let parsedData: any = null;
  109. try {
  110. if (item.triggerCondition) {
  111. parsedData = JSON.parse(item.triggerCondition);
  112. }
  113. } catch (error) {
  114. console.warn('解析触发器条件失败:', item.triggerCondition, error);
  115. }
  116. return {
  117. ...item,
  118. _keywords: parsedData?.keywords || [],
  119. _ip: parsedData?.ip || '',
  120. _domain: parsedData?.domain || ''
  121. };
  122. });
  123. }
  124. resolve(res);
  125. } catch (error: any) {
  126. console.error('数据处理失败:', error);
  127. reject(error);
  128. }
  129. }).catch((error: any) => {
  130. reject(error);
  131. });
  132. });
  133. };
  134. // 定义变量内容
  135. const tableRef = ref();
  136. const queryRef = ref();
  137. const state: BasicTableProps = reactive<BasicTableProps>({
  138. pageList: getDataListWithProcess,
  139. createdIsNeed: false,
  140. queryForm: {
  141. ruleName: '',
  142. triggerCondition: '',
  143. },
  144. pagination: {
  145. current: 1,
  146. size: 10,
  147. total: 0,
  148. pageSizes: [5, 10, 20, 50, 100]
  149. },
  150. });
  151. const pushMode = ref<any>([]);
  152. const disabledDate = (time: Date) => {
  153. return time.getTime() > Date.now();
  154. }
  155. interface SourceData {
  156. ruleName: string;
  157. triggerCondition: string;
  158. triggerTime: string;
  159. pushStatus: string;
  160. pushContent: string;
  161. pushFrequency: string;
  162. pushTime: string;
  163. }
  164. const richContentDialogRef = ref();
  165. const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state);
  166. // 搜索事件
  167. const query = (refresh: boolean = false) => {
  168. state.dataList = [];
  169. getDataList(refresh);
  170. };
  171. // 清空搜索条件
  172. const resetQuery = () => {
  173. queryRef.value.resetFields();
  174. state.dataList = [];
  175. getDataList();
  176. };
  177. const statusFormatter = (row: any, column: any, cellValue: any, index: any) => {
  178. return cellValue || '--';
  179. }
  180. const showTriggerInfo = (row: any) => {
  181. // 信息详情弹窗
  182. richContentDialogRef.value.openDialog(
  183. row.pushDetail,
  184. {
  185. createTime: row.createTime,
  186. triggerKeyword: row._keywords
  187. }
  188. )
  189. }
  190. const getFetchItemList = async () => {
  191. const res = await fetchItemList({
  192. dictType: 'pushMode',
  193. });
  194. pushMode.value = res.data.records.map((item: any) => ({
  195. label: item.description,
  196. value: item.value
  197. }));
  198. console.log(pushMode, 'pushMode');
  199. }
  200. // 格式化数据展示
  201. const formatNum = (value: string | number = 0) => {
  202. let num = Number(value);
  203. if (num > 0 && num < 1) {
  204. return (num * 100).toFixed(0) + '%';
  205. } else if (num >= 1 && num < 10000) {
  206. return '每'+num+'次推送';
  207. }
  208. return '--';
  209. };
  210. onMounted(() => {
  211. getFetchItemList();
  212. query();
  213. });
  214. </script>
  215. <style scoped lang="scss">
  216. :deep(.el-link__inner) {
  217. display: inline-block;
  218. width: 100%;
  219. justify-content: start;
  220. }
  221. :deep(.el-link.is-underline:hover:after) {
  222. display: none;
  223. }
  224. .table-tabs {
  225. margin-bottom: 10px;
  226. }
  227. .trigger-info {
  228. overflow: hidden;
  229. text-align: center;
  230. width: 100%;
  231. text-overflow: ellipsis;
  232. overflow: hidden;
  233. white-space: nowrap;
  234. color: #409eff;
  235. cursor: pointer;
  236. }
  237. .header-wrapper {
  238. display: inline-flex;
  239. align-items: center;
  240. }
  241. .header-icon {
  242. margin-left: 5px;
  243. color: #999;
  244. font-size: 14px;
  245. cursor: help;
  246. &:hover {
  247. color: #409eff;
  248. }
  249. }
  250. </style>