index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <template>
  2. <div class="layout-padding">
  3. <div class="layout-padding-auto layout-padding-view">
  4. <el-row shadow="hover" v-show="showSearch" class="ml10">
  5. <el-form :inline="true" :model="state.queryForm" @keyup.enter="getDataList" ref="queryRef">
  6. <el-form-item :label="$t('marketingApps.name')" prop="domain">
  7. <el-input :placeholder="$t('marketingApps.inputNameTip')" clearable
  8. v-model="state.queryForm.domain" />
  9. </el-form-item>
  10. <el-form-item :label="'应用ID'" prop="appId">
  11. <el-input :placeholder="'请输入应用ID'" clearable v-model="state.queryForm.appId" />
  12. </el-form-item>
  13. <el-form-item :label="'应用类型'" prop="appType">
  14. <el-select placeholder="请选择应用类型" v-model="state.queryForm.appType">
  15. <el-option :key="''" :label="'全部'" :value="''" />
  16. <el-option v-for="item in appTypes" :key="item.value" :label="item.description" :value="item.value" />
  17. </el-select>
  18. </el-form-item>
  19. <el-form-item :label="'备注'" prop="remark">
  20. <el-input :placeholder="'请输入备注'" clearable v-model="state.queryForm.domain" />
  21. </el-form-item>
  22. <el-form-item>
  23. <el-button @click="query" class="ml10" icon="search" type="primary">
  24. {{ $t('common.queryBtn') }}
  25. </el-button>
  26. <el-button @click="resetQuery" icon="Refresh">{{ $t('common.resetBtn') }}</el-button>
  27. <el-button @click="handleEdit" icon="EditPen">{{ $t('common.editBtn') }}</el-button>
  28. </el-form-item>
  29. </el-form>
  30. </el-row>
  31. <!-- <el-row>
  32. <div class="mb8" style="width: 100%">
  33. <right-toolbar v-model:showSearch="showSearch" class="ml10" style="float: right; margin-right: 20px"
  34. @queryTable="getDataList"></right-toolbar>
  35. </div>
  36. </el-row> -->
  37. <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
  38. <el-tab-pane label="使用中" name="tab1"></el-tab-pane>
  39. <el-tab-pane label="回收站" name="tab2"></el-tab-pane>
  40. </el-tabs>
  41. <el-table @selection-change="handleSelectionChange" ref="tableRef" :data="state.dataList" row-key="path"
  42. style="width: 100%" v-loading="state.loading" border :cell-style="tableStyle.cellStyle"
  43. :header-cell-style="tableStyle?.headerCellStyle">
  44. <el-table-column type="selection" fixed="left" width="55" />
  45. <el-table-column fixed="left" :label="$t('marketingApps.id')" prop="id" width="80" show-overflow-tooltip>
  46. <template #default="{ row }">{{ row.id }}</template>
  47. </el-table-column>
  48. <el-table-column :label="$t('marketingApps.appId')" prop="appId" width="120" show-overflow-tooltip>
  49. <template #default="{ row }">{{ row.appId }}</template>
  50. </el-table-column>
  51. <el-table-column :label="$t('marketingApps.appImg')" prop="appImg" width="150" show-overflow-tooltip>
  52. <template #default="{ row }" style="display: flex; align-self: center;">
  53. <el-image style="width: 100px; height: 100px" :src="row.appImg" :fit="fit" />
  54. </template>
  55. </el-table-column>
  56. <el-table-column :label="$t('marketingApps.name')" prop="appName" width="150" show-overflow-tooltip>
  57. <template #default="{ row }">
  58. <el-link :href="row.url">{{ row.appName }}</el-link>
  59. </template>
  60. </el-table-column>
  61. <el-table-column :label="$t('marketingApps.appType')" prop="appType" width="110" show-overflow-tooltip>
  62. <template #default="{ row }">
  63. <el-select v-model="row.appType" placeholder="" style="width: 80px">
  64. <el-option v-for="item in appTypes" :key="item.value" :label="item.description" :value="item.value" />
  65. </el-select>
  66. </template>
  67. </el-table-column>
  68. <el-table-column label="营销投放" prop="isMarketing" width="120">
  69. <template #default="{ row }">
  70. <el-switch v-model="row.isMarketing" inline-prompt :active-value="1"
  71. :inactive-value="0" @change="handleChange(row)" />
  72. <!-- active-text="开启" inactive-text="关闭" -->
  73. </template>
  74. </el-table-column>
  75. <el-table-column label="域名限制" prop="isHttp" width="120">
  76. <template #default="{ row }">
  77. <el-switch v-model="row.isHttp" inline-prompt :active-value="1"
  78. :inactive-value="0" @change="handleChange(row)" />
  79. <!-- active-text="开启" inactive-text="关闭" -->
  80. </template>
  81. </el-table-column>
  82. <el-table-column prop="domains" width="240" show-overflow-tooltip>
  83. <template #header>
  84. <span style="display: inline-block; align-items: center;">
  85. 域名集合
  86. <el-tooltip effect="light" content="鼠标悬浮查看域名分组详情" placement="top">
  87. <el-icon><Warning /></el-icon>
  88. </el-tooltip>
  89. </span>
  90. </template>
  91. <template #default="{ row }">
  92. <div style="
  93. padding: 0 20px;
  94. text-wrap: auto;
  95. text-align: left;
  96. ">
  97. <el-tooltip effect="light">
  98. <template #content>
  99. <div v-for="(item, index) in row.domains" :key="index">{{ item.domain }};</div>
  100. </template>
  101. <el-text line-clamp="6">
  102. <template v-for="(item, index) in row.domains" :key="index">
  103. <div>{{ item.domain }};</div>
  104. </template>
  105. </el-text>
  106. </el-tooltip>
  107. </div>
  108. </template>
  109. </el-table-column>
  110. <el-table-column prop="ips" width="300">
  111. <template #header>
  112. <span style="display: inline-block; align-items: center;">
  113. IP集合
  114. <el-tooltip effect="light" content="鼠标悬浮查看ip分组详情" placement="top">
  115. <el-icon><Warning /></el-icon>
  116. </el-tooltip>
  117. </span>
  118. </template>
  119. <template #default="{ row }">
  120. <div style="
  121. padding: 0 20px;
  122. text-wrap: auto;
  123. text-align: left;
  124. ">
  125. <div style="text-align: left;">白名单:</div>
  126. <el-tooltip effect="light">
  127. <template #content>
  128. <div v-for="(item, index) in row.ips" :key="index">
  129. {{ item.ipType == 1 ? item.startIp + ';' : '' }}
  130. </div>
  131. </template>
  132. <el-text line-clamp="4">
  133. <template v-for="(item, index) in row.ips" :key="index">
  134. <div>{{ item.ipType == 1 ? item.startIp + ';' : '' }}</div>
  135. </template>
  136. </el-text>
  137. </el-tooltip>
  138. <div style="text-align: left;">黑名单:</div>
  139. <el-tooltip effect="light">
  140. <template #content>
  141. <div v-for="(item, index) in row.ips" :key="index">
  142. {{ item.ipType == 2 ? item.startIp + ';' : '' }}
  143. </div>
  144. </template>
  145. <el-text line-clamp="4">
  146. <template v-for="(item, index) in row.ips" :key="index">
  147. <div>{{ item.ipType == 2 ? item.startIp + ';' : '' }}</div>
  148. </template>
  149. </el-text>
  150. </el-tooltip>
  151. </div>
  152. </template>
  153. </el-table-column>
  154. <el-table-column :label="'触发频率'" prop="triggerRule" width="150" show-overflow-tooltip>
  155. <template #default="{ row }">
  156. <!-- <el-input-number v-model="row.triggerNum" :max=20 /> -->
  157. {{ row.triggerNum }}
  158. </template>
  159. </el-table-column>
  160. <el-table-column :label="$t('marketingApps.triggerRule')" width="200" prop="triggerRule" show-overflow-tooltip>
  161. <template #default="{ row }">
  162. <el-select v-model="row.triggerRule" placeholder="" style="width: 160px">
  163. <el-option v-for="item in triggerRules" :key="item.value" :label="item.label" :value="item.value" />
  164. </el-select>
  165. </template>
  166. </el-table-column>
  167. <el-table-column fixed="right" :label="$t('common.action')" width="80">
  168. <template #default="scope">
  169. <div class="action" style="text-align: left;">
  170. <el-button style="margin-left: 0;" icon="edit-pen" @click="onOpenEditMenu('edit', scope.row)" text type="primary"
  171. v-auth="'sys_menu_edit'">修改
  172. </el-button>
  173. <el-button style="margin-left: 0;" icon="TrendCharts" @click="onOpenStatistical(scope.row)" text type="primary"
  174. v-auth="'sys_menu_edit'">统计
  175. </el-button>
  176. <el-button
  177. :type="activeName == 'tab1' ? 'danger' : 'success'"
  178. style="margin-left: 0;"
  179. :icon="activeName == 'tab1' ? 'delete' : 'refresh'"
  180. @click="handleDelete(scope.row)" text
  181. v-auth="'sys_menu_edit'">
  182. {{ activeName == 'tab1' ? '拉黑' : '还原' }}
  183. </el-button>
  184. </div>
  185. </template>
  186. </el-table-column>
  187. </el-table>
  188. <pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
  189. </div>
  190. <MenuDialog @refresh="getDataList()" ref="menuDialogRef" />
  191. <StatisticalDialog @refresh="getDataList()" ref="statisticalDialogRef" />
  192. </div>
  193. </template>
  194. <script lang="ts" name="marketingApps" setup>
  195. import { pageList } from '/@/api/marketing/apps';
  196. import { BasicTableProps, useTable } from '/@/hooks/table';
  197. import { useMessage, useMessageBox } from '/@/hooks/message';
  198. import { useI18n } from 'vue-i18n';
  199. import { fetchItemList } from '/@/api/admin/dict';
  200. import { ref } from 'vue'
  201. const MenuDialog = defineAsyncComponent(() => import('./components/form.vue'));
  202. const StatisticalDialog = defineAsyncComponent(() => import('./components/statistical.vue'));
  203. import { ElMessage, ElNotification, messageConfig, type TabsPaneContext } from 'element-plus'
  204. const activeName = ref('tab1')
  205. const handleClick = (tab: TabsPaneContext, event: Event) => {
  206. console.log(tab, event);
  207. query();
  208. }
  209. const { t } = useI18n();
  210. // 定义变量内容
  211. const tableRef = ref();
  212. const menuDialogRef = ref();
  213. const statisticalDialogRef = ref();
  214. const queryRef = ref();
  215. const showSearch = ref(true);
  216. // 多选rows
  217. const selectObjs = ref([]) as any;
  218. // 是否可以多选
  219. const multiple = ref(true);
  220. const state: BasicTableProps = reactive<BasicTableProps>({
  221. pageList: pageList, // H
  222. queryForm: {
  223. domain: '',
  224. appType: '',
  225. appId: '',
  226. remark: '',
  227. }
  228. });
  229. const appTypes = ref([]) as any;
  230. const getAppTypes = async () => {
  231. const { data } = await fetchItemList({
  232. dictType: 'DomianType'
  233. });
  234. appTypes.value = data?.records || [];
  235. }
  236. getAppTypes();
  237. const triggerRules = [
  238. {
  239. label: '仅一次',
  240. value: 1,
  241. },
  242. {
  243. label: '多次',
  244. value: 2,
  245. },
  246. ]
  247. const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state);
  248. // 搜索事件
  249. const query = () => {
  250. state.dataList = [];
  251. getDataList();
  252. };
  253. // 修改单条配置信息
  254. const handleChange = (row: any) => {
  255. // update(row).then(() => {
  256. // useMessage().success(t('common.updateSuccessText'));
  257. // getDataList();
  258. // }).catch((err: any) => {
  259. // useMessage().error(err.msg);
  260. // });
  261. };
  262. // 清空搜索条件
  263. const resetQuery = () => {
  264. queryRef.value.resetFields();
  265. state.dataList = [];
  266. getDataList();
  267. };
  268. // 批量修改配置
  269. const handleEdit = () => {
  270. if (selectObjs.value.length === 0) {
  271. useMessage().warning('请选择要修改的项');
  272. return;
  273. }
  274. menuDialogRef.value.openDialog('', {});
  275. // menuDialogRef.value.openDialog('edit', selectObjs.value);
  276. };
  277. // 多选
  278. const handleSelectionChange = (selection: any) => {
  279. selectObjs.value = selection;
  280. };
  281. // 打开编辑菜单弹窗
  282. const onOpenEditMenu = (type: string, row: any) => {
  283. menuDialogRef.value.openDialog(type, row);
  284. };
  285. // 打开统计弹窗
  286. const onOpenStatistical = (row: any) => {
  287. statisticalDialogRef.value.openDialog(row);
  288. };
  289. // 删除操作
  290. const handleDelete = async (row: any) => {
  291. try {
  292. if(activeName.value == 'tab1'){
  293. await useMessageBox().confirm('是否确认拉黑该应用');
  294. }else{
  295. ElMessage.success('还原成功!');
  296. }
  297. } catch {
  298. return;
  299. }
  300. // try {
  301. // await delObj(ids);
  302. // getDataList();
  303. // useMessage().success(t('common.delSuccessText'));
  304. // } catch (err: any) {
  305. // useMessage().error(err.msg);
  306. // }
  307. query();
  308. };
  309. </script>
  310. <style scoped lang="scss">
  311. :deep(.el-link__inner) {
  312. display: inline-block;
  313. width: 100%;
  314. justify-content: start;
  315. }
  316. :deep(.el-link.is-underline:hover:after) {
  317. display: none;
  318. }
  319. </style>