domainCollapse.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <template>
  2. <JCollapse :data="[
  3. { title: '域名集合', id: '1' },
  4. ]" @update="(item) => domainEditOpen = true" @delete="(item) => domainDeletable = !domainDeletable"
  5. :deleteText="domainDeletable ? t('common.cancelButtonText') : t('marketingApps.delete')" :updateText="t('marketingApps.add')" :activeNames="['1']">
  6. <template #default>
  7. <div class="p-2 items-center flex flex-wrap">
  8. <template v-for="item in domains" >
  9. <!-- 具体域名 -->
  10. <el-tag v-if="item.sourceType == SourceType.DOMAIN" effect="light" :closable="domainDeletable"
  11. @close="handleDeleteDomain(item, SourceType.DOMAIN)" color="#f4f4f4" round class="mr-1 mb-1 cursor-pointer">
  12. <span class="ellipsis">{{ item.domain }}</span>
  13. </el-tag>
  14. <!-- 分组域名 -->
  15. <el-popover v-else width="200" trigger="hover" placement="top" @show="onLoadDetail(item)">
  16. <div class="flex flex-wrap break-all">
  17. {{ item.domains && item.domains.length ? item.domains.map(i=>i.domain).join(',') : t('marketingApps.noData') }}
  18. </div>
  19. <template #reference>
  20. <el-tag effect="light" :closable="domainDeletable"
  21. @close="handleDeleteDomain(item, SourceType.GROUP)" color="#f4f4f4" round class="mr-1 mb-1 cursor-pointer">
  22. <span class="ellipsis">{{ item.groupName }}</span>
  23. </el-tag>
  24. </template>
  25. </el-popover>
  26. </template>
  27. <div class="text-gray-400" v-if="domains.length <= 0">
  28. --
  29. </div>
  30. </div>
  31. </template>
  32. </JCollapse>
  33. <DomainEdit v-model:open="domainEditOpen" @onsuccess="addDomain" />
  34. </template>
  35. <script setup lang="ts" name="domainCollapse">
  36. const JCollapse = defineAsyncComponent(() => import('/@/components/JCollapse/index.vue'));
  37. const DomainEdit = defineAsyncComponent(() => import('./domainEdit.vue'));
  38. import { useI18n } from 'vue-i18n';
  39. import { useMessage } from '/@/hooks/message';
  40. import { getGroupDetail } from '/@/api/marketing/config';
  41. import { SourceType, DomainItem } from '../types'
  42. const props = defineProps(['data']);
  43. // 定义子组件向父组件传值/事件
  44. const emit = defineEmits(['refresh','domains', 'delDomains']);
  45. const { t } = useI18n();
  46. // 定义变量内容
  47. const domainDeletable = ref(false);// 控制域名列表项是否可删除
  48. const domainEditOpen = ref(false);
  49. const delDomains = ref<string[]>([]);
  50. const domains = ref<DomainItem[]>([]);
  51. watch(() => props.data, (newVal = []) => {
  52. domains.value = [];
  53. newVal.forEach((item: DomainItem) => {
  54. item.modify = false;
  55. domains.value = [...domains.value, item];
  56. })
  57. }, { immediate: true });
  58. // 监听domains变化,emit给父组件
  59. watch(domains, (newVal) => {
  60. emit('domains', newVal);
  61. }, { deep: true, immediate: true });
  62. watch(delDomains, (newVal) => {
  63. emit('delDomains', newVal);
  64. }, { deep: true, immediate: true });
  65. // 删除域名
  66. const handleDeleteDomain = (deleteItem: DomainItem, sourceType: SourceType) => {
  67. domains.value = domains.value.filter(i=>{
  68. if(!i.modify && i.id == deleteItem.id && !delDomains.value.includes(i.id as string)) {
  69. delDomains.value = [...delDomains.value, i.id as string];
  70. }
  71. if(sourceType == SourceType.GROUP) {
  72. return i.groupId != deleteItem.groupId
  73. }else{
  74. return i.domain != deleteItem.domain
  75. }
  76. });
  77. }
  78. // 分组去重
  79. function addGroupsUnique(newGroups: DomainItem[]) {
  80. const existIds = new Set([
  81. ...domains.value.map(item => item.groupId),
  82. ]);
  83. const filtered:DomainItem[] = newGroups.filter(item => !existIds.has(item.id as string))
  84. .map(item=>{
  85. return {
  86. "sourceType": SourceType.GROUP,
  87. "modify": true,
  88. "groupId": item.id?.toString() || '',
  89. "groupName": item.groupName,
  90. "domains": item.domains,
  91. "domain": "",
  92. }
  93. });
  94. if(filtered.length) {
  95. domains.value = [...domains.value, ...filtered];
  96. console.log(filtered);
  97. useMessage().success(t('common.addSuccessText'));
  98. }else{
  99. useMessage().warning(t('marketingApps.addDomainTip'));
  100. }
  101. }
  102. // 域名去重
  103. function addSinglesUnique(newSingles: DomainItem[]) {
  104. const existDomains = new Set([
  105. ...domains.value.map(item => item.domain),
  106. ]);
  107. const filtered = newSingles.filter(item => !existDomains.has(item.domain));
  108. if(filtered.length) {
  109. filtered.forEach(item => {
  110. Object.assign(item, {
  111. "groupId": "",
  112. "groupName": "",
  113. "domains": [],
  114. "domain": item.domain,
  115. "sourceType": SourceType.DOMAIN,
  116. "modify": true,
  117. })
  118. })
  119. domains.value = [...domains.value, ...filtered];
  120. console.log('去重后的域名:', filtered);
  121. useMessage().success(t('common.addSuccessText'));
  122. }else{
  123. useMessage().warning(t('marketingApps.addDomainTip2'));
  124. }
  125. }
  126. const addDomain = (data: DomainItem[], type: 'group' | 'domain') => {
  127. if (type === 'domain') {
  128. data.length && addSinglesUnique(data);
  129. } else {
  130. data.length && addGroupsUnique(data);
  131. }
  132. }
  133. const onLoadDetail = async (item: any) => {
  134. item.loading = true;
  135. if (item?.domains && item?.domains?.length !== 0) return;
  136. await getGroupDetail({ id: item.groupId }).then((val) => {
  137. item.domains = val.data.domains
  138. });
  139. item.loading = false;
  140. };
  141. </script>
  142. <style lang="scss">
  143. @import '/@/theme/mixins/index.scss';
  144. .el-collapse-item__content {
  145. padding: 0;
  146. }
  147. .ellipsis {
  148. @include text-ellipsis(1);
  149. }
  150. </style>