浏览代码

fix: 域名弹窗

jcq 2 周之前
父节点
当前提交
812466aa5c

+ 1 - 1
src/components/Title/index.vue

@@ -1,5 +1,5 @@
 <template>
-	<div class="text-lg font-medium mb-4">
+	<div class="text-lg font-medium ">
 		{{ props.title }}
 		<slot></slot>
 	</div>

+ 7 - 1
src/utils/validate.ts

@@ -154,6 +154,11 @@ export const rule = {
 	url(rule, value, callback) {
 		validateFn('url', rule, value, callback, 'URL格式有误');
 	},
+	/* IP地址 */
+	ip(rule, value, callback) {
+		validateFn('ip', rule, value, callback, 'IP格式有误');
+	},
+
 
 	regExp(rule, value, callback) {
 		if (validateNull(value) || value.length <= 0) {
@@ -191,7 +196,8 @@ export const getRegExp = function (validatorName) {
 		noChinese: '^[^\u4e00-\u9fa5]+$',
 		chinese: '^[\u4e00-\u9fa5]+$',
 		email: '^([-_A-Za-z0-9.]+)@([_A-Za-z0-9]+\\.)+[A-Za-z0-9]{2,3}$',
-		url: '(https?|ftp|file|http)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]'
+		url: '(https?|ftp|file|http)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]',
+		ip:'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$',
 	};
 	return commonRegExp[validatorName];
 };

+ 113 - 0
src/views/marketing/config/components/domainEdit.vue

@@ -0,0 +1,113 @@
+<template>
+	<el-dialog
+		:title="type === 'Edit' ? '修改域名' : '添加域名'"
+		width="600"
+		v-model="props.open"
+		:close-on-click-modal="false"
+		:destroy-on-close="true"
+        @close="onCancel"
+		draggable
+	>
+		<el-form ref="menuDialogFormRef" :rules="dataRules" :model="state.ruleForm" v-loading="loading">
+			<el-segmented v-model="activeName" :options="[t('marketingConfig.grouping'), t('marketingConfig.domain')]" size="large" />
+			<el-form-item label="" prop="grouping" v-if="activeName === t('marketingConfig.grouping')">
+				<el-select v-model="state.ruleForm.groupingTip" :placeholder="t('marketingConfig.groupingTip')" clearable>
+					<el-option v-for="item in listSelect" :key="item.value" :label="item.label" :value="item.value" />
+				</el-select>
+			</el-form-item>
+			<el-form-item label="" prop="domain" v-else>
+				<el-input v-model="state.ruleForm.domain" type="text" :placeholder="t('marketingConfig.domainTip')"></el-input>
+			</el-form-item>
+		</el-form>
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="onCancel">{{ t('common.cancelButtonText') }}</el-button>
+				<el-button type="primary" @click="onSubmit" :disabled="loading">{{ t('common.confirmButtonText') }}</el-button>
+			</span>
+		</template>
+	</el-dialog>
+</template>
+
+<script setup name="systemMenuDialog">
+import { useI18n } from 'vue-i18n';
+import { info, getAppList, save } from '/@/api/marketing/config';
+import { useMessage } from '/@/hooks/message';
+import { rule } from '/@/utils/validate';
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['update:open','onsuccess']);
+const { t } = useI18n();
+
+// 定义变量内容
+const loading = ref(false);
+const type = ref('add'); // 'add' or 'edit'
+const activeName = ref(t('marketingConfig.grouping'));
+const menuDialogFormRef = ref();
+const listSelect = ref([
+	{
+		value: 'group1',
+		label: '分组1',
+	},
+	{
+		value: 'group2',
+		label: '分组2',
+	},
+	{
+		value: 'group3',
+		label: '分组3',
+	},
+]);
+// 定义需要的数据
+const state = reactive({
+	ruleForm: {
+		list: [''],
+		https: [''], // 域名集合
+		ips: [''], // ip集合
+		// {
+		//   id: '1',
+		//   ip: '美国',
+		//   appId: '1',
+		//   appUrl: 'www.baidu.com',
+		//   appName: 'adsa'
+		// },
+	},
+	appList: [], // 应用下拉框列表
+});
+
+const props = defineProps({
+	open: {
+		type: Boolean,
+		default: false,
+	},
+});
+// // 表单校验规则
+const dataRules = reactive({
+	domain: [
+		{ required: true, message: '域名不能为空', trigger: 'blur' }
+	],
+});
+const onCancel = () => {
+	emit('update:open', false);
+};
+// 保存数据
+const onSubmit = async () => {
+
+  
+	try {
+		loading.value = true;
+		// await save(state.ruleForm);
+		useMessage().success(t(state.ruleForm.id ? 'common.editSuccessText' : 'common.addSuccessText'));
+		emit('onsuccess');
+        onCancel();
+	} catch (err) {
+		useMessage().error(err.msg);
+	} finally {
+		loading.value = false;
+	}
+};
+</script>
+<style>
+.apps-loadmore.el-select-dropdown .el-scrollbar__wrap {
+	height: 330px !important;
+}
+</style>

+ 152 - 0
src/views/marketing/config/components/ipEdit.vue

@@ -0,0 +1,152 @@
+<template>
+  <el-dialog :title="sign === 'domain' ? '修改域名集合' : '修改ip集合'" width="600" v-model="visible"
+             :close-on-click-modal="false" :destroy-on-close="true" draggable>
+    <el-form ref="menuDialogFormRef" :model="state.ruleForm" 
+      label-width="90px" v-loading="loading">
+      <el-form-item :label="sign === 'domain' ? '域名集合' : 'ip集合'" prop="configs">
+        <div v-for="(item, index) in state.ruleForm.list" :key="item.index" class="flex items-center mb-2 text-sm font-normal justify-start w-full">
+          <el-input style="width: 300px; margin-right: 20px;" v-model="item.val" clearable :placeholder="t('marketingConfig.inputIPTip')"></el-input>
+          <div class="config-actions w-[50px] flex items-center justify-between ">
+            <svg 
+              v-if="index === state.ruleForm.list.length - 1" 
+              @click="state.ruleForm.list.push({val: ''})"
+              style="cursor: pointer;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+              <path d="M19.5 3H4.5C3.67157 3 3 3.67157 3 4.5V19.5C3 20.3284 3.67157 21 4.5 21H19.5C20.3284 21 21 20.3284 21 19.5V4.5C21 3.67157 20.3284 3 19.5 3Z" stroke="#646464" stroke-linejoin="round"/>
+              <path d="M12 8V16" stroke="#646464" stroke-linecap="round" stroke-linejoin="round"/>
+              <path d="M8 12H16" stroke="#646464" stroke-linecap="round" stroke-linejoin="round"/>
+            </svg>
+            <svg 
+              v-if="state.ruleForm.list.length > 1" style="cursor: pointer;"
+              @click="state.ruleForm.list.splice(index, 1)"
+              width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+              <path d="M19.5 3H4.5C3.67157 3 3 3.67157 3 4.5V19.5C3 20.3284 3.67157 21 4.5 21H19.5C20.3284 21 21 20.3284 21 19.5V4.5C21 3.67157 20.3284 3 19.5 3Z" stroke="#646464" stroke-linejoin="round"/>
+              <path d="M8 12H16" stroke="#646464" stroke-linecap="round" stroke-linejoin="round"/>
+            </svg>
+          </div>
+        </div>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+			<span class="dialog-footer">
+				<el-button @click="visible = false">{{ t('common.cancelButtonText') }}</el-button>
+				<el-button type="primary" @click="onSubmit" :disabled="loading">{{ t('common.confirmButtonText') }}</el-button>
+			</span>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup name="systemMenuDialog">
+import {useI18n} from 'vue-i18n';
+import {info, getAppList, save} from '/@/api/marketing/config';
+import {useMessage} from '/@/hooks/message';
+import {rule} from '/@/utils/validate';
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['refresh']);
+const { t } = useI18n();
+
+// 定义变量内容
+const visible = ref(false);
+const loading = ref(false);
+const sign = ref('domain')
+const menuDialogFormRef = ref();
+// 定义需要的数据
+const state = reactive({
+  ruleForm: {
+    list: [''], 
+    https: [''], // 域名集合
+    ips: [''], // ip集合
+      // {
+      //   id: '1',
+      //   ip: '美国',
+      //   appId: '1',
+      //   appUrl: 'www.baidu.com',
+      //   appName: 'adsa'
+      // },
+  },
+  appList: [], // 应用下拉框列表
+});
+
+// // 表单校验规则
+// const dataRules = reactive({
+//   domain: [
+//     {required: true, message: '域名不能为空', trigger: 'blur'},
+//     // { validator: rule.url, trigger: 'blur' }
+//   ],
+// });
+
+// 分页参数
+const pagination = reactive({
+  current: 1,
+  size: 10,
+  total: 0
+})
+
+// 打开弹窗
+const openDialog = async (type, row, str = 'domain') => {
+  visible.value = true;
+  sign.value = str;
+  nextTick(() => {
+    menuDialogFormRef.value?.resetFields();
+  });
+  state.ruleForm = JSON.parse(JSON.stringify(row));
+  str === 'domain' ? state.ruleForm.list = row.https.map(e => ({val: e})) : state.ruleForm.list = row.ips.map(e => ({val: e}));
+  // if (row?.id && type === 'edit') {
+  //   await getConfigDetail(row.id);
+  // } else {
+  //   state.ruleForm = {
+  //     id: null,
+  //     domain: '',
+  //     configs: [
+  //       {
+  //         id: '',
+  //         ip: '',
+  //         appId: '',
+  //         appUrl: '',
+  //         appName: ''
+  //       }
+  //     ],
+  //   };
+  // }
+  // pagination.current = 1;
+  // // 获取应用列表
+  // getAllAppData();
+};
+
+// 获取当条配置信息
+const getConfigDetail = (id) => {
+  info(id).then((res) => {
+    Object.assign(state.ruleForm, res.data);
+  });
+};
+
+// 保存数据
+const onSubmit = async () => {
+  // const valid = await menuDialogFormRef.value.validate().catch(() => {
+  // });
+  // if (!valid) return false;
+  sign.value === 'domain' ? state.ruleForm.https = state.ruleForm.list.map(e => e.val) : state.ruleForm.ips = state.ruleForm.list.map(e => e.val);
+  delete state.ruleForm.list;
+  try {
+    loading.value = true;
+    await save(state.ruleForm);
+    useMessage().success(t(state.ruleForm.id ? 'common.editSuccessText' : 'common.addSuccessText'));
+    visible.value = false;
+    emit('refresh');
+  } catch (err) {
+    useMessage().error(err.msg);
+  } finally {
+    loading.value = false;
+  }
+};
+
+// 暴露变量 只有暴漏出来的变量 父组件才能使用
+defineExpose({
+  openDialog,
+});
+</script>
+<style>
+.apps-loadmore.el-select-dropdown .el-scrollbar__wrap {
+  height: 330px !important;
+}
+</style>

+ 152 - 0
src/views/marketing/config/components/ipListEdit.vue

@@ -0,0 +1,152 @@
+<template>
+  <el-dialog :title="sign === 'domain' ? '修改域名集合' : '修改ip集合'" width="600" v-model="visible"
+             :close-on-click-modal="false" :destroy-on-close="true" draggable>
+    <el-form ref="menuDialogFormRef" :model="state.ruleForm" 
+      label-width="90px" v-loading="loading">
+      <el-form-item :label="sign === 'domain' ? '域名集合' : 'ip集合'" prop="configs">
+        <div v-for="(item, index) in state.ruleForm.list" :key="item.index" class="flex items-center mb-2 text-sm font-normal justify-start w-full">
+          <el-input style="width: 300px; margin-right: 20px;" v-model="item.val" clearable :placeholder="t('marketingConfig.inputIPTip')"></el-input>
+          <div class="config-actions w-[50px] flex items-center justify-between ">
+            <svg 
+              v-if="index === state.ruleForm.list.length - 1" 
+              @click="state.ruleForm.list.push({val: ''})"
+              style="cursor: pointer;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+              <path d="M19.5 3H4.5C3.67157 3 3 3.67157 3 4.5V19.5C3 20.3284 3.67157 21 4.5 21H19.5C20.3284 21 21 20.3284 21 19.5V4.5C21 3.67157 20.3284 3 19.5 3Z" stroke="#646464" stroke-linejoin="round"/>
+              <path d="M12 8V16" stroke="#646464" stroke-linecap="round" stroke-linejoin="round"/>
+              <path d="M8 12H16" stroke="#646464" stroke-linecap="round" stroke-linejoin="round"/>
+            </svg>
+            <svg 
+              v-if="state.ruleForm.list.length > 1" style="cursor: pointer;"
+              @click="state.ruleForm.list.splice(index, 1)"
+              width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+              <path d="M19.5 3H4.5C3.67157 3 3 3.67157 3 4.5V19.5C3 20.3284 3.67157 21 4.5 21H19.5C20.3284 21 21 20.3284 21 19.5V4.5C21 3.67157 20.3284 3 19.5 3Z" stroke="#646464" stroke-linejoin="round"/>
+              <path d="M8 12H16" stroke="#646464" stroke-linecap="round" stroke-linejoin="round"/>
+            </svg>
+          </div>
+        </div>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+			<span class="dialog-footer">
+				<el-button @click="visible = false">{{ t('common.cancelButtonText') }}</el-button>
+				<el-button type="primary" @click="onSubmit" :disabled="loading">{{ t('common.confirmButtonText') }}</el-button>
+			</span>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup name="systemMenuDialog">
+import {useI18n} from 'vue-i18n';
+import {info, getAppList, save} from '/@/api/marketing/config';
+import {useMessage} from '/@/hooks/message';
+import {rule} from '/@/utils/validate';
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['refresh']);
+const { t } = useI18n();
+
+// 定义变量内容
+const visible = ref(false);
+const loading = ref(false);
+const sign = ref('domain')
+const menuDialogFormRef = ref();
+// 定义需要的数据
+const state = reactive({
+  ruleForm: {
+    list: [''], 
+    https: [''], // 域名集合
+    ips: [''], // ip集合
+      // {
+      //   id: '1',
+      //   ip: '美国',
+      //   appId: '1',
+      //   appUrl: 'www.baidu.com',
+      //   appName: 'adsa'
+      // },
+  },
+  appList: [], // 应用下拉框列表
+});
+
+// // 表单校验规则
+// const dataRules = reactive({
+//   domain: [
+//     {required: true, message: '域名不能为空', trigger: 'blur'},
+//     // { validator: rule.url, trigger: 'blur' }
+//   ],
+// });
+
+// 分页参数
+const pagination = reactive({
+  current: 1,
+  size: 10,
+  total: 0
+})
+
+// 打开弹窗
+const openDialog = async (type, row, str = 'domain') => {
+  visible.value = true;
+  sign.value = str;
+  nextTick(() => {
+    menuDialogFormRef.value?.resetFields();
+  });
+  state.ruleForm = JSON.parse(JSON.stringify(row));
+  str === 'domain' ? state.ruleForm.list = row.https.map(e => ({val: e})) : state.ruleForm.list = row.ips.map(e => ({val: e}));
+  // if (row?.id && type === 'edit') {
+  //   await getConfigDetail(row.id); 
+  // } else {
+  //   state.ruleForm = {
+  //     id: null,
+  //     domain: '',
+  //     configs: [
+  //       {
+  //         id: '',
+  //         ip: '',
+  //         appId: '',
+  //         appUrl: '',
+  //         appName: ''
+  //       }
+  //     ],
+  //   };
+  // }
+  // pagination.current = 1;
+  // // 获取应用列表
+  // getAllAppData();
+};
+
+// 获取当条配置信息
+const getConfigDetail = (id) => {
+  info(id).then((res) => {
+    Object.assign(state.ruleForm, res.data);
+  });
+};
+
+// 保存数据
+const onSubmit = async () => {
+  // const valid = await menuDialogFormRef.value.validate().catch(() => {
+  // });
+  // if (!valid) return false;
+  sign.value === 'domain' ? state.ruleForm.https = state.ruleForm.list.map(e => e.val) : state.ruleForm.ips = state.ruleForm.list.map(e => e.val);
+  delete state.ruleForm.list;
+  try {
+    loading.value = true;
+    await save(state.ruleForm);
+    useMessage().success(t(state.ruleForm.id ? 'common.editSuccessText' : 'common.addSuccessText'));
+    visible.value = false;
+    emit('refresh');
+  } catch (err) {
+    useMessage().error(err.msg);
+  } finally {
+    loading.value = false;
+  }
+};
+
+// 暴露变量 只有暴漏出来的变量 父组件才能使用
+defineExpose({
+  openDialog,
+});
+</script>
+<style>
+.apps-loadmore.el-select-dropdown .el-scrollbar__wrap {
+  height: 330px !important;
+}
+</style>

+ 152 - 0
src/views/marketing/config/components/listEdit.vue

@@ -0,0 +1,152 @@
+<template>
+  <el-dialog :title="sign === 'domain' ? '修改域名集合' : '修改ip集合'" width="600" v-model="visible"
+             :close-on-click-modal="false" :destroy-on-close="true" draggable>
+    <el-form ref="menuDialogFormRef" :model="state.ruleForm" 
+      label-width="90px" v-loading="loading">
+      <el-form-item :label="sign === 'domain' ? '域名集合' : 'ip集合'" prop="configs">
+        <div v-for="(item, index) in state.ruleForm.list" :key="item.index" class="flex items-center mb-2 text-sm font-normal justify-start w-full">
+          <el-input style="width: 300px; margin-right: 20px;" v-model="item.val" clearable :placeholder="t('marketingConfig.inputIPTip')"></el-input>
+          <div class="config-actions w-[50px] flex items-center justify-between ">
+            <svg 
+              v-if="index === state.ruleForm.list.length - 1" 
+              @click="state.ruleForm.list.push({val: ''})"
+              style="cursor: pointer;" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+              <path d="M19.5 3H4.5C3.67157 3 3 3.67157 3 4.5V19.5C3 20.3284 3.67157 21 4.5 21H19.5C20.3284 21 21 20.3284 21 19.5V4.5C21 3.67157 20.3284 3 19.5 3Z" stroke="#646464" stroke-linejoin="round"/>
+              <path d="M12 8V16" stroke="#646464" stroke-linecap="round" stroke-linejoin="round"/>
+              <path d="M8 12H16" stroke="#646464" stroke-linecap="round" stroke-linejoin="round"/>
+            </svg>
+            <svg 
+              v-if="state.ruleForm.list.length > 1" style="cursor: pointer;"
+              @click="state.ruleForm.list.splice(index, 1)"
+              width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+              <path d="M19.5 3H4.5C3.67157 3 3 3.67157 3 4.5V19.5C3 20.3284 3.67157 21 4.5 21H19.5C20.3284 21 21 20.3284 21 19.5V4.5C21 3.67157 20.3284 3 19.5 3Z" stroke="#646464" stroke-linejoin="round"/>
+              <path d="M8 12H16" stroke="#646464" stroke-linecap="round" stroke-linejoin="round"/>
+            </svg>
+          </div>
+        </div>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+			<span class="dialog-footer">
+				<el-button @click="visible = false">{{ t('common.cancelButtonText') }}</el-button>
+				<el-button type="primary" @click="onSubmit" :disabled="loading">{{ t('common.confirmButtonText') }}</el-button>
+			</span>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup name="systemMenuDialog">
+import {useI18n} from 'vue-i18n';
+import {info, getAppList, save} from '/@/api/marketing/config';
+import {useMessage} from '/@/hooks/message';
+import {rule} from '/@/utils/validate';
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['refresh']);
+const { t } = useI18n();
+
+// 定义变量内容
+const visible = ref(false);
+const loading = ref(false);
+const sign = ref('domain')
+const menuDialogFormRef = ref();
+// 定义需要的数据
+const state = reactive({
+  ruleForm: {
+    list: [''], 
+    https: [''], // 域名集合
+    ips: [''], // ip集合
+      // {
+      //   id: '1',
+      //   ip: '美国',
+      //   appId: '1',
+      //   appUrl: 'www.baidu.com',
+      //   appName: 'adsa'
+      // },
+  },
+  appList: [], // 应用下拉框列表
+});
+
+// // 表单校验规则
+// const dataRules = reactive({
+//   domain: [
+//     {required: true, message: '域名不能为空', trigger: 'blur'},
+//     // { validator: rule.url, trigger: 'blur' }
+//   ],
+// });
+
+// 分页参数
+const pagination = reactive({
+  current: 1,
+  size: 10,
+  total: 0
+})
+
+// 打开弹窗
+const openDialog = async (type, row, str = 'domain') => {
+  visible.value = true;
+  sign.value = str;
+  nextTick(() => {
+    menuDialogFormRef.value?.resetFields();
+  });
+  state.ruleForm = JSON.parse(JSON.stringify(row));
+  str === 'domain' ? state.ruleForm.list = row.https.map(e => ({val: e})) : state.ruleForm.list = row.ips.map(e => ({val: e}));
+  // if (row?.id && type === 'edit') {
+  //   await getConfigDetail(row.id);
+  // } else {
+  //   state.ruleForm = {
+  //     id: null,
+  //     domain: '',
+  //     configs: [
+  //       {
+  //         id: '',
+  //         ip: '',
+  //         appId: '',
+  //         appUrl: '',
+  //         appName: ''
+  //       }
+  //     ],
+  //   };
+  // }
+  // pagination.current = 1;
+  // // 获取应用列表
+  // getAllAppData();
+};
+
+// 获取当条配置信息
+const getConfigDetail = (id) => {
+  info(id).then((res) => {
+    Object.assign(state.ruleForm, res.data);
+  });
+};
+
+// 保存数据
+const onSubmit = async () => {
+  // const valid = await menuDialogFormRef.value.validate().catch(() => {
+  // });
+  // if (!valid) return false;
+  sign.value === 'domain' ? state.ruleForm.https = state.ruleForm.list.map(e => e.val) : state.ruleForm.ips = state.ruleForm.list.map(e => e.val);
+  delete state.ruleForm.list;
+  try {
+    loading.value = true;
+    await save(state.ruleForm);
+    useMessage().success(t(state.ruleForm.id ? 'common.editSuccessText' : 'common.addSuccessText'));
+    visible.value = false;
+    emit('refresh');
+  } catch (err) {
+    useMessage().error(err.msg);
+  } finally {
+    loading.value = false;
+  }
+};
+
+// 暴露变量 只有暴漏出来的变量 父组件才能使用
+defineExpose({
+  openDialog,
+});
+</script>
+<style>
+.apps-loadmore.el-select-dropdown .el-scrollbar__wrap {
+  height: 330px !important;
+}
+</style>

+ 5 - 1
src/views/marketing/config/i18n/zh-cn.ts

@@ -18,6 +18,10 @@ export default {
 		cancel: '取消',
 		addDomain: '添加域名',
 		deleteDomain: '删除域名',
-
+		deleteIp: '删除IP',
+		grouping: '分组',
+		domain: '单域名',
+		domainTip: '请输入域名',
+		groupingTip: '请选择分组名称',
 	},
 };

+ 12 - 14
src/views/marketing/config/index.vue

@@ -31,14 +31,9 @@
 				<Title class="" :title="t('marketingConfig.disposition')" />
 				<div class="p-4 rounded">
 					<JCollapse
-						:data="[
-							{
-								title: 'IP集合',
-								id: '1',
-							},
-						]"
+						:data="[{title: 'IP集合',id: '1',}]"
 						@update="(item) => console.log(item)"
-						@delete="(item) => console.log(item)"
+						@delete="(item) => closeIpTags = !closeIpTags"
 						:deleteText="t('marketingConfig.deleteText')"
 						:updateText="t('marketingConfig.updateText')"
 					>
@@ -52,7 +47,7 @@
 										</span>
 									</div>
 									<template #reference>
-										<el-tag effect="light" color="#f4f4f4" round class="ml-1 cursor-pointer">
+										<el-tag effect="light" color="#f4f4f4" :closable="closeIpTags" round class="ml-1 cursor-pointer">
 											{{ item.title }}
 										</el-tag>
 									</template>
@@ -67,7 +62,7 @@
 										</span>
 									</div>
 									<template #reference>
-										<el-tag effect="light" color="#f4f4f4" round class="ml-1 cursor-pointer">
+										<el-tag effect="light" color="#f4f4f4" :closable="closeIpTags" round class="ml-1 cursor-pointer">
 											{{ item.title }}
 										</el-tag>
 									</template>
@@ -84,14 +79,14 @@
 								id: '1',
 							},
 						]"
-						@update="(item) => console.log(item)"
-						@delete="(item) => closeTags = !closeTags"
+						@update="(item) => domainEditOpen = true"
+						@delete="(item) => closeDomainTags = !closeDomainTags"
 						:deleteText="closeTags ? t('marketingConfig.cancel') : t('marketingConfig.deleteDomain')"
 						:updateText="t('marketingConfig.addDomain')"
 					>
 						<template #default>
 							<div class="border-b p-2 items-center flex flex-wrap">
-								<el-tag v-for="item in whiteList" :key="item" effect="light" :closable="closeTags" color="#f4f4f4" round class="ml-1 cursor-pointer">
+								<el-tag v-for="item in whiteList" :key="item" effect="light" :closable="closeDomainTags" color="#f4f4f4" round class="ml-1 cursor-pointer">
 									{{ item.label }}
 								</el-tag>
 							</div>
@@ -100,6 +95,7 @@
 				</div>
 			</el-tab-pane>
 		</el-tabs>
+		<DomainEdit v-model:open="domainEditOpen" />
 	</div>
 </template>
 
@@ -111,10 +107,13 @@ import { useI18n } from 'vue-i18n';
 // 引入组件
 const JCollapse = defineAsyncComponent(() => import('/@/components/JCollapse/index.vue'));
 const Title = defineAsyncComponent(() => import('/@/components/Title/index.vue'));
+const DomainEdit = defineAsyncComponent(() => import('./components/domainEdit.vue'));
 const { t } = useI18n();
 // 定义变量内容
 const activeName = ref('first');
-const closeTags = ref(false);
+const closeDomainTags = ref(false);
+const closeIpTags = ref(false);
+const domainEditOpen = ref(false);
 const data = ref([
 	{
 		title: '分组1',
@@ -133,7 +132,6 @@ const data = ref([
 	},
 ]);
 const whiteList = ref([{ label: '站大' }, { label: '站而' }, { label: '站撒' }, { label: '站爱' }]);
-const blackList = ref([{ label: '站1' }, { label: '站2' }, { label: '站3' }, { label: '站4' }]);
 
 const menuDialogRef = ref();
 const state: BasicTableProps = reactive<BasicTableProps>({