Bladeren bron

feat: 接口联调;

jcq 1 week geleden
bovenliggende
commit
5d1f8ed6e7

+ 48 - 0
src/api/marketing/config.ts

@@ -25,6 +25,54 @@ export const getConfigIpList = (params?: Object) => {
 		params,
 	});
 };
+//获取配置域名集合
+export const getConfigDomainList = (params?: Object) => {
+	return request({
+		url: '/marketing/config/domainList',
+		// url: 'https://m1.apifoxmock.com/m1/6687089-6396408-default/marketing/config/page',
+		method: 'get',
+		params,
+	});
+};
+//获取分组详细信息
+export const getGroupDetail = (params?: Object) => {
+	return request({
+		url: '/marketing/config/group/detail',
+		// url: 'https://m1.apifoxmock.com/m1/6687089-6396408-default/marketing/config/page',
+		method: 'get',
+		params,
+	});
+};
+//添加配置ip集合
+export const saveIpList = (data: Object) => {
+	return request({
+		url: '/marketing/config/addIp',
+		method: 'post',
+		data: data,
+	});
+};
+//删除配置ip集合
+export const delIpList = (id?: string) => {
+	return request({
+		url: '/marketing/config/delIp/'+id,
+		method: 'get',
+	});
+};
+//删除配置域名集合
+export const delDomainList = (id?: string) => {
+	return request({
+		url: '/marketing/config/delDomain/'+id,
+		method: 'get',
+	});
+};
+//添加配置域名集合
+export const addDomains = (data: Object) => {
+	return request({
+		url: '/marketing/config/addDomain',
+		method: 'post',
+		data: data,
+	});
+};
 //修改域名分组
 export const saveDomains = (data: Object) => {
 	return request({

+ 10 - 3
src/components/JCollapse/index.vue

@@ -13,10 +13,17 @@
 			</template>
 			<div v-if="item.list" class="">
 				<div v-if="item.list.length && typeof item.list[0] === 'object'">
-					<div v-for="ip in item.list" :key="ip.id" class="m-2 float-left" style="color: #646464; font-size: 14px">{{ ip.value }}</div>
+					<div v-if="item.list.length > 0">
+						<div v-for="ip in item.list" :key="ip.id" class="m-2 float-left" style="color: #646464; font-size: 14px">{{ ip.value }}</div>
+					</div>
+					<div class="text-gray-400 ml-2" v-else>--</div>
 				</div>
 				<div v-else>
-					<div v-for="ip in item.list" :key="ip" class="m-2 float-left" style="color: #646464; font-size: 14px">{{ ip }}</div>
+					<div v-if="item.list.length > 0">
+						<div v-for="ip in item.list" :key="ip" class="m-2 float-left" style="color: #646464; font-size: 14px">{{ ip }}</div>
+					</div>
+					<div class="text-gray-400 ml-2" v-else>--</div>
+
 				</div>
 			</div>
 			<slot v-else></slot>
@@ -76,7 +83,7 @@ const innerActiveNames = computed({
 		padding: 0 10px;
 		height: 50px;
 	}
-	.el-button+.el-button {
+	.el-button + .el-button {
 		margin-left: 0;
 	}
 	.coll-left-title,

+ 1 - 1
src/utils/ipUpdate.ts

@@ -10,7 +10,7 @@
  const parseIpRange = (ipWithRange: string): { start: string; end: string } => {
   if (!ipWithRange.includes('/')) {
     // 如果没有 /,说明是普通 IP
-    return { start: ipWithRange, end: ipWithRange };
+    return { start: ipWithRange, end: '' };
   }
 
   const [startIp, numberStr] = ipWithRange.split('/');

+ 73 - 50
src/views/marketing/config/components/domainEdit.vue

@@ -1,21 +1,19 @@
 <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-dialog :title="'添加域名'" 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="default" />
-			<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" />
+			<div class="custom-style">
+				<el-segmented v-model="state.ruleForm.sourceTypeText" :options="[t('marketingConfig.grouping'), t('marketingConfig.ip')]" size="default">
+					<template #default="scope">
+						<div style="min-width: 50px; line-height: 32px">{{ scope.item }}</div>
+					</template>
+				</el-segmented>
+			</div>
+			<el-form-item label="" prop="groupId" v-if="state.ruleForm.sourceTypeText === t('marketingConfig.grouping')">
+				<el-select v-model="state.ruleForm.groupId" @change="state.ruleForm.groupName" :placeholder="t('marketingConfig.groupingTip')">
+					<el-option v-for="item in selectData" :key="item.id" :label="item.groupName" :value="item.id" />
 				</el-select>
 			</el-form-item>
-			<el-form-item label="" prop="domain" v-else> 
+			<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>
@@ -30,47 +28,27 @@
 
 <script setup name="systemMenuDialog">
 import { useI18n } from 'vue-i18n';
-// import { info, getAppList } from '/@/api/marketing/config';
+import { addDomains } from '/@/api/marketing/config';
 import { useMessage } from '/@/hooks/message';
 
 // 定义子组件向父组件传值/事件
-const emit = defineEmits(['update:open','onsuccess']);
+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'
-		// },
+		ipType: 1, // 1: 白名单, 2: 黑名单
+		sourceType: 1,
+		sourceTypeText: t('marketingConfig.grouping'),
+		groupId: '',
+		groupName: '',
+		domain: '',
 	},
-	appList: [], // 应用下拉框列表
 });
 
 const props = defineProps({
@@ -78,33 +56,78 @@ const props = defineProps({
 		type: Boolean,
 		default: false,
 	},
+	selectData: {
+		type: Array,
+		default: () => [],
+	},
 });
-// // 表单校验规则
+//  表单校验规则
 const dataRules = reactive({
-	domain: [
-		{ required: true, message: '域名不能为空', trigger: 'blur' }
-	],
+	groupId: [{ required: true, message: '分组不能为空', trigger: 'blur' }],
+	domain: [{ required: true, message: '域名不能为空', trigger: 'blur' }],
 });
 const onCancel = () => {
 	emit('update:open', false);
 };
 // 保存数据
 const onSubmit = async () => {
+	state.ruleForm.sourceType = state.ruleForm.sourceTypeText === t('marketingConfig.grouping') ? 1 : 2;
+	if (state.ruleForm.sourceType == 1 && state.ruleForm.groupId == '') {
+		return useMessage().error('请选择分组');
+	} else if (state.ruleForm.sourceType == 2 && state.ruleForm.domain == '') {
+		return useMessage().error('域名不能为空');
+	}
 	try {
 		loading.value = true;
-		// await save(state.ruleForm);
+		await addDomains(state.ruleForm);
 		useMessage().success(t(state.ruleForm.id ? 'common.editSuccessText' : 'common.addSuccessText'));
 		emit('onsuccess');
-        onCancel();
+		onCancel();
 	} catch (err) {
 		useMessage().error(err.msg);
 	} finally {
 		loading.value = false;
 	}
 };
+watch(
+	() => props.open,
+	(val) => {
+		if (val) {
+			state.ruleForm = {
+				sourceType: 1,
+				sourceTypeText: t('marketingConfig.grouping'),
+				groupId: '',
+				groupName: '',
+				domain: '',
+			};
+		}
+	}
+);
 </script>
-<style>
+<style lang="scss">
 .apps-loadmore.el-select-dropdown .el-scrollbar__wrap {
 	height: 330px !important;
 }
+
+.custom-style {
+	margin-top: 14px;
+
+	.el-segmented__item {
+		border-right: 1px solid rgba(230, 230, 230, 1);
+		min-width: 72px;
+		flex: unset;
+	}
+
+	.el-segmented {
+		border: 1px solid rgba(230, 230, 230, 1);
+		border-bottom: unset;
+		--el-segmented-bg-color: #ffffff;
+		--el-segmented-item-hover-bg-color: rgba(22, 122, 240, 0.1);
+		--el-segmented-item-selected-color: rgba(22, 122, 240, 1);
+		--el-segmented-item-hover-color: rgba(22, 122, 240, 1);
+		--el-segmented-item-selected-bg-color: rgba(22, 122, 240, 0.1);
+		--el-border-radius-base: 4px 4px 0 0;
+		--el-segmented-padding: 0;
+	}
+}
 </style>

+ 4 - 3
src/views/marketing/config/components/ipListEdit.vue

@@ -109,9 +109,10 @@ const onAddItem = () => {
 
 // // 表单校验规则
 const dataRules = computed(() => ({
-	configs: [
-		{ required: false, message: `${sign.value === 'domain' ? '域名' : 'IP'}不能为空`, trigger: 'blur' },
-		{ validator: sign.value === 'domain' ? rule.url : rule.ipRange, trigger: 'blur' },
+	groupId: [{ required: true, message: '分组不能为空', trigger: 'blur' }],
+	ip: [
+		{ required: rule.ip, message: 'IP不能为空', trigger: 'blur' },
+		{ validator: rule.ip, trigger: 'blur' },
 	],
 }));
 

+ 91 - 39
src/views/marketing/config/components/listEdit.vue

@@ -9,16 +9,23 @@
 		draggable
 	>
 		<el-form ref="menuDialogFormRef" :rules="dataRules" :model="state.ruleForm" v-loading="loading">
-			<el-form-item label="" prop="listType" >
-				<el-radio-group v-model="state.ruleForm.listType">
-					<el-radio value="1">白名单</el-radio>
-					<el-radio value="2">黑名单</el-radio>
+			<el-form-item label="" prop="ipType">
+				<el-radio-group v-model="state.ruleForm.ipType">
+					<el-radio :value="1">白名单</el-radio>
+					<el-radio :value="2">黑名单</el-radio>
 				</el-radio-group>
 			</el-form-item>
-			<el-segmented v-model="activeName" :options="[t('marketingConfig.grouping'), t('marketingConfig.ip')]" size="default" />
-			<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" />
+			<div class="custom-style">
+				<el-segmented v-model="state.ruleForm.sourceTypeText" :options="[t('marketingConfig.grouping'), t('marketingConfig.ip')]" size="default">
+					<template #default="scope">
+						<div style="min-width: 50px; line-height: 32px">{{ scope.item }}</div>
+					</template>
+				</el-segmented>
+			</div>
+
+			<el-form-item label="" prop="groupId" v-if="state.ruleForm.sourceTypeText === t('marketingConfig.grouping')">
+				<el-select v-model="state.ruleForm.groupId" @change="state.ruleForm.groupName" :placeholder="t('marketingConfig.groupingTip')">
+					<el-option v-for="item in selectData" :key="item.id" :label="item.groupName" :value="item.id" />
 				</el-select>
 			</el-form-item>
 			<el-form-item label="" prop="ip" v-else>
@@ -36,8 +43,10 @@
 
 <script setup name="systemMenuDialog">
 import { useI18n } from 'vue-i18n';
-// import { info, getAppList } from '/@/api/marketing/config';
+import { saveIpList } from '/@/api/marketing/config';
 import { useMessage } from '/@/hooks/message';
+import { parseIpRange } from '/@/utils/ipUpdate';
+import { rule } from '/@/utils/validate';
 
 // 定义子组件向父组件传值/事件
 const emit = defineEmits(['update:open', 'onsuccess']);
@@ -46,38 +55,21 @@ 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: {
-		listType: '1', // 1: 白名单, 2: 黑名单
-		list: [''],
-		https: [''], // 域名集合
-		ips: [''], // ip集合
-		// {
-		//   id: '1',
-		//   ip: '美国',
-		//   appId: '1',
-		//   appUrl: 'www.baidu.com',
-		//   appName: 'adsa'
-		// },
+		ipType: 1, // 1: 白名单, 2: 黑名单
+		sourceType: 1,
+		sourceTypeText: t('marketingConfig.grouping'),
+		groupId: '',
+		ipMode: 1,
+		groupName:'',
+		startIp: '',
+		endIp: '',
+		ip: '',
 	},
-	appList: [], // 应用下拉框列表
 });
 
 const props = defineProps({
@@ -85,19 +77,40 @@ const props = defineProps({
 		type: Boolean,
 		default: false,
 	},
+	selectData:{
+		type: Array,
+		default: () => [],
+	}
 });
 // // 表单校验规则
 const dataRules = reactive({
-	domain: [{ required: true, message: '域名不能为空', trigger: 'blur' }],
+	groupId: [{ required: true, message: '分组不能为空', trigger: 'blur' }],
+	ip: [
+		{ required: rule.ip, message: 'IP不能为空', trigger: 'blur' },
+		{ validator: rule.ip, trigger: 'blur' },
+	],
 });
 const onCancel = () => {
 	emit('update:open', false);
 };
 // 保存数据
 const onSubmit = async () => {
+	const lis = parseIpRange(state.ruleForm.ip);
+	state.ruleForm.startIp = lis.start;
+	state.ruleForm.endIp = lis.end;
+	if (lis.end !== '') {
+		state.ruleForm.ipMode = 2;
+	}
+	
+	state.ruleForm.sourceType = state.ruleForm.sourceTypeText === t('marketingConfig.grouping') ? 1 : 2;
+	if (state.ruleForm.sourceType == 1 && state.ruleForm.groupId == '') {
+		return useMessage().error('请选择分组');
+	} else if (state.ruleForm.sourceType == 2 && state.ruleForm.ip == '') {
+		return useMessage().error('ip不能为空');
+	}
 	try {
 		loading.value = true;
-		// await save(state.ruleForm);
+		await saveIpList(state.ruleForm);
 		useMessage().success(t(state.ruleForm.id ? 'common.editSuccessText' : 'common.addSuccessText'));
 		emit('onsuccess');
 		onCancel();
@@ -107,9 +120,48 @@ const onSubmit = async () => {
 		loading.value = false;
 	}
 };
+watch(
+	() => props.open,
+	(val) => {
+		if (val) {
+			state.ruleForm = {
+				ipType: 1, // 1: 白名单, 2: 黑名单
+				sourceType: 1,
+				sourceTypeText: t('marketingConfig.grouping'),
+				groupId: '',
+				ipMode: 1,
+				startIp: '',
+				endIp: '',
+				ip: '',
+			};
+		}
+	}
+);
 </script>
-<style>
+<style lang="scss">
 .apps-loadmore.el-select-dropdown .el-scrollbar__wrap {
 	height: 330px !important;
 }
+.custom-style {
+	margin-top: 14px;
+
+	.el-segmented__item {
+		border-right: 1px solid rgba(230, 230, 230, 1);
+		min-width: 72px;
+		flex: unset;
+	}
+
+	.el-segmented {
+		border: 1px solid rgba(230, 230, 230, 1);
+		border-bottom: unset;
+		--el-segmented-bg-color: #ffffff;
+		--el-segmented-item-hover-bg-color: rgba(22, 122, 240, 0.1);
+		--el-segmented-item-selected-color: rgba(22, 122, 240, 1);
+		--el-segmented-item-hover-color: rgba(22, 122, 240, 1);
+		--el-segmented-item-selected-bg-color: rgba(22, 122, 240, 0.1);
+		--el-border-radius-base: 4px 4px 0 0;
+		--el-segmented-padding: 0;
+	}
+}
+
 </style>

+ 207 - 89
src/views/marketing/config/index.vue

@@ -19,14 +19,17 @@
 				<Title class="ml-4" :title="t('marketingConfig.domainList')" />
 				<div class="p-4 rounded">
 					<el-button type="primary" @click="onClickAdd('domain')">{{ t('marketingConfig.addDomainList') }}</el-button>
-					<JCollapse
-						@update="(item) => onClickEdit(item, 'domain')"
-						:data="domainData"
-						@delete="(item) => onOpenDelete(item, 'domain')"
-						:activeNames="domainActiveId"
-						:deleteText="t('marketingConfig.deleteListText')"
-						:updateText="t('marketingConfig.updateText')"
-					/>
+					<div v-if="domainData.length > 0">
+						<JCollapse
+							@update="(item) => onClickEdit(item, 'domain')"
+							:data="domainData"
+							@delete="(item) => onOpenDelete(item, 'domain')"
+							:activeNames="domainActiveId"
+							:deleteText="t('marketingConfig.deleteListText')"
+							:updateText="t('marketingConfig.updateText')"
+						/>
+					</div>
+					<div v-else class="ml-2">暂无数据</div>
 				</div>
 			</el-tab-pane>
 			<el-tab-pane :label="t('marketingConfig.disposition')" name="全局配置" class="layout-padding-auto layout-padding-view">
@@ -43,33 +46,76 @@
 						<template #default>
 							<div class="border-b p-2 items-center flex flex-wrap">
 								<span class="mr-2">白名单</span>
-								<el-popover v-for="item in data" :key="item.id" width="200" trigger="hover" placement="top">
-									<div class="flex flex-wrap">
-										<span v-for="ip in item.list" :key="ip" class="ml-2">
-											{{ ip }}
-										</span>
-									</div>
-									<template #reference>
-										<el-tag effect="light" color="#f4f4f4" :closable="closeIpTags" round class="ml-1 cursor-pointer">
-											{{ item.title }}
-										</el-tag>
-									</template>
-								</el-popover>
+								<span v-for="item in ipWhiteList" :key="item.id">
+									<el-popover v-if="item?.sourceType === 1" width="280" @show="onLoadDetail(item)" trigger="hover" placement="top">
+										<div v-if="item.list.length > 0" class="flex flex-wrap">
+											<span v-for="ip in item.list" :key="ip" class="ml-2">
+												{{ ip }}
+											</span>
+										</div>
+										<div v-else>暂无数据</div>
+										<template #reference>
+											<el-tag
+												effect="light"
+												color="#f4f4f4"
+												:closable="closeIpTags"
+												@close="handleDelete(item, 'ip')"
+												round
+												class="ml-1 cursor-pointer"
+											>
+												{{ item.groupName }}
+											</el-tag>
+										</template>
+									</el-popover>
+									<el-tag
+										v-else
+										effect="light"
+										color="#f4f4f4"
+										:closable="closeIpTags"
+										@close="handleDelete(item, 'ip')"
+										round
+										class="ml-1 cursor-pointer"
+									>
+										{{ ipSplicing(item.startIp, item.endIp) }}
+									</el-tag>
+								</span>
 							</div>
 							<div class="p-2 items-center flex flex-wrap">
 								<span class="mr-2">黑名单</span>
-								<el-popover v-for="item in data" :key="item.id" width="200" trigger="hover" placement="top">
-									<div class="flex flex-wrap">
-										<span v-for="ip in item.list" :key="ip" class="ml-2">
-											{{ ip }}
-										</span>
-									</div>
-									<template #reference>
-										<el-tag effect="light" color="#f4f4f4" :closable="closeIpTags" round class="ml-1 cursor-pointer">
-											{{ item.title }}
-										</el-tag>
-									</template>
-								</el-popover>
+								
+								<span v-for="item in ipBlackList" :key="item.id">
+									<el-popover v-if="item?.sourceType === 1" width="280" @show="onLoadDetail(item, ipList)" trigger="hover" placement="top">
+										<div v-if="item.list.length > 0" class="flex flex-wrap">
+											<span v-for="ip in item.list" :key="ip" class="ml-2">
+												{{ ip }}
+											</span>
+										</div>
+										<div v-else>暂无数据</div>
+										<template #reference>
+											<el-tag
+												effect="light"
+												color="#f4f4f4"
+												:closable="closeIpTags"
+												@close="handleDelete(item, 'ip')"
+												round
+												class="ml-1 cursor-pointer"
+											>
+												{{ item.groupName }}
+											</el-tag>
+										</template>
+									</el-popover>
+									<el-tag
+										v-else
+										effect="light"
+										color="#f4f4f4"
+										:closable="closeIpTags"
+										@close="handleDelete(item, 'ip')"
+										round
+										class="ml-1 cursor-pointer"
+									>
+										{{ ipSplicing(item.startIp, item.endIp) }}
+									</el-tag>
+								</span>
 							</div>
 						</template>
 					</JCollapse>
@@ -85,42 +131,60 @@
 					>
 						<template #default>
 							<div class="p-2 items-center flex flex-wrap">
-								<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>
+								<span v-if="domainList.length > 0">
+									<span v-for="item in domainList" :key="item.id">
+										<el-popover v-if="item?.sourceType === 1" width="280" @show="onLoadDetail(item)" trigger="hover" placement="top">
+											<div v-if="item.list.length > 0" class="flex flex-wrap">
+												<span v-for="domain in item.list" :key="domain.id" class="ml-2">
+													{{ domain.domain }}
+												</span>
+											</div>
+											<div v-else>暂无数据</div>
+											<template #reference>
+												<el-tag
+													effect="light"
+													color="#f4f4f4"
+													:closable="closeDomainTags"
+													@close="handleDelete(item, 'domain')"
+													round
+													class="ml-1 cursor-pointer"
+												>
+													{{ item.groupName }}
+												</el-tag>
+											</template>
+										</el-popover>
+										<el-tag
+											v-else
+											effect="light"
+											color="#f4f4f4"
+											:closable="closeDomainTags"
+											@close="handleDelete(item, 'domain')"
+											round
+											class="ml-1 cursor-pointer"
+										>
+											{{ item.domain }}
+										</el-tag>
+									</span>
+								</span>
+								<div class="text-gray-400 ml-2" v-else>--</div>
 							</div>
 						</template>
 					</JCollapse>
 				</div>
 				<div class="w-[66%] ml-[-8px] mt-5">
-					<el-form ref="menuDialogFormRef" :model="formData" :rule="dataRules" label-width="90px" class="flex flex-wrap">
+					<el-form ref="menuDialogFormRef" :model="formData" :rules="dataRules" label-width="90px" class="flex flex-wrap">
 						<el-form-item :label="t('marketingConfig.jumpMode')" prop="jumpMode" class="w-1/3">
-							<el-select v-model="formData.jumpMode" :placeholder="t('marketingConfig.jumpModeTip')" clearable>
+							<el-select v-model="formData.jumpMode" :placeholder="t('marketingConfig.jumpModeTip')">
 								<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="t('marketingConfig.triggerType')" prop="triggerType" class="w-1/3">
-							<el-select v-model="formData.triggerType" :placeholder="t('marketingConfig.triggerTypeTip')" clearable>
+							<el-select v-model="formData.triggerType" :placeholder="t('marketingConfig.triggerTypeTip')">
 								<el-option v-for="item in triggerSelect" :key="item.value" :label="item.label" :value="item.value" />
 							</el-select>
 						</el-form-item>
 						<el-form-item :label="t('marketingConfig.triggerFrequency')" prop="triggerFrequency" class="w-1/3">
-							<el-input-number
-								v-model="formData.triggerFrequency"
-								class="!w-40"
-								:min="1"
-								:max="20"
-								controls-position="right"
-								:placeholder="t('marketingConfig.triggerFrequencyTip')"
-							/>
+							<el-input v-model="formData.triggerFrequency" type="text" :placeholder="t('marketingConfig.triggerFrequencyTip')" />
 						</el-form-item>
 
 						<div class="w-full mb-[18px]">
@@ -148,12 +212,12 @@
 				</div>
 			</el-tab-pane>
 		</el-tabs>
-		<DomainEdit v-model:open="domainEditOpen" />
-		<ListEdit v-model:open="listEditOpen" />
+		<DomainEdit :select-data="domainData" v-model:open="domainEditOpen" @onsuccess="getConfig" />
+		<ListEdit :select-data="ipData" v-model:open="listEditOpen" @onsuccess="getConfig" />
 		<GroupingEdit v-model:open="groupingEditOpen" :type="openType" @onsuccess="getData" />
 		<IpListEdit :type="openType" ref="menuDialogRef" @onsuccess="getData" />
 		<el-dialog v-model="delOpen" title="提示" width="500" @close="delOpen = false">
-			<span>确认删除{{ delObj?.title }}分组吗?</span>
+			<span>确认删除{{ delObj?.title }}吗?</span>
 			<template #footer>
 				<div class="dialog-footer">
 					<el-button @click="delOpen = false">取消</el-button>
@@ -165,7 +229,16 @@
 </template>
 
 <script lang="ts" name="marketingConfig" setup>
-import { delGroup, pageListDomain, pageListIp ,getConfigIpList } from '/@/api/marketing/config';
+import {
+	delGroup,
+	pageListDomain,
+	pageListIp,
+	getConfigIpList,
+	getConfigDomainList,
+	delIpList,
+	delDomainList,
+	getGroupDetail,
+} from '/@/api/marketing/config';
 import { useI18n } from 'vue-i18n';
 import { useMessage } from '/@/hooks/message';
 import { rule } from '/@/utils/validate';
@@ -180,7 +253,7 @@ const GroupingEdit = defineAsyncComponent(() => import('./components/ipGroupingE
 const IpListEdit = defineAsyncComponent(() => import('./components/ipListEdit.vue'));
 const { t } = useI18n();
 // 定义变量内容
-const activeName = ref('IP分组');
+const activeName = ref('全局配置');
 //关闭或打开tabs的关闭按钮
 const closeDomainTags = ref(false);
 const closeIpTags = ref(false);
@@ -201,6 +274,9 @@ const domainData = ref([]);
 const ipData = ref([]);
 const delObj = ref({});
 const openType = ref('ip'); // 'ip' or 'domain'
+const ipWhiteList = ref([]); // ip白名单
+const ipBlackList = ref([]); // ip黑名单
+const domainList = ref([]);
 
 const listSelect = ref([
 	{
@@ -227,7 +303,6 @@ const triggerSelect = ref([
 	},
 ]);
 
-const menuDialogFormRef = ref();
 const formData = ref({
 	jumpMode: '1',
 	triggerType: '',
@@ -245,33 +320,32 @@ const onOpenDelete = (item: any, type: any) => {
 };
 const getData = () => {
 	openType.value === 'ip' ? getIpData() : getDomainData();
-	
+};
+const onLoadDetail = async (item: any) => {
+	if(item.list.length !== 0) return;
+	await getGroupDetail({ id: item.groupId }).then((val) => {
+		item.list = val.data.ips.map((item)=>{
+			return ipSplicing(item.startIp, item.endIp)
+		});
+	});	
 };
 
 // // 表单校验规则
 const dataRules = reactive({
-	jumpLink: [{ validator: rule.url, trigger: 'blur' }],
+	jumpLink: [
+		{ required: true, message: '跳转连接不能为空', trigger: 'blur' },
+		{ validator: rule.url, trigger: 'blur' },
+	],
+	triggerFrequency: [
+		{ required: true, message: '域名不能为空', trigger: 'blur' },
+		{
+			pattern: /^(10000|[1-9]\d{0,3}|0)$|^(100%|[1-9]?\d%|0%)$/,
+			message: '请输入 0-10000 的正整数或 0%-100% 的百分比',
+			trigger: 'blur',
+		},
+	],
 });
 
-const data = ref([
-	{
-		title: '分组1',
-		id: '1',
-		list: ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4'],
-	},
-	{
-		title: '分组2',
-		id: '2',
-		list: ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4'],
-	},
-	{
-		title: '分组3',
-		id: '3',
-		list: ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4'],
-	},
-]);
-const whiteList = ref([{ label: '站大' }, { label: '站而' }, { label: '站撒' }, { label: '站爱' }]);
-
 const onSubmit = () => {
 	useMessage().success(t(formData.value ? 'common.editSuccessText' : 'common.addSuccessText'));
 };
@@ -281,15 +355,39 @@ const handleClick = (data: any) => {
 	} else if (data.props.label === '域名分组') {
 		getDomainData();
 	} else {
-		getConfig()
+		getConfig();
 	}
 };
+const handleDelete = async (item: any, type: string) => {
+	console.log(item, type);
+	delObj.value = { ...item, delListType: type };
+	delOpen.value = true;
+};
 const onDel = async (data: any) => {
+	if (data?.delListType) {
+		try {
+			if (data?.delListType === 'ip') {
+				await delIpList(data.id);
+				useMessage().success(t('common.delSuccessText'));
+			} else if (data?.delListType === 'domain') {
+				await delDomainList(data.id);
+				useMessage().success(t('common.delSuccessText'));
+			}
+		} catch (err: any) {
+			useMessage().error(err.msg);
+		} finally {
+			loading.value = false;
+			delOpen.value = false;
+			getConfig();
+		}
+
+		return;
+	}
 	try {
 		loading.value = true;
 		await delGroup({
-			ids: [data.id],
 			groupType: data.type === 'ip' ? 1 : 2,
+			ids: [data.id],
 		});
 		useMessage().success(t('common.delSuccessText'));
 	} catch (err: any) {
@@ -315,15 +413,34 @@ const onClickEdit = (item: any, type: string) => {
 const onOpenEditMenu = (type: string, row: any) => {
 	menuDialogRef.value.openDialog(type, row);
 };
-const getConfig = () => { 
-      configIp()
+const getConfig = () => {
+	configIp();
+	configDomain();
 };
-const configIp = async()=>{
-	await getConfigIpList().then((val) => { 
-		console.log(val.data);
+const configDomain = async () => {
+	await getConfigDomainList().then((val) => {
+		domainList.value = val.data.map((item) => {
+			return {
+				...item,
+				list: [],
+			};
+		});
+	});
+};
+const configIp = async () => {
+	await getConfigIpList().then((val) => {
+		ipWhiteList.value = val.data
+			.filter((item) => item.ipType === 1)
+			.map((item) => {
+				return { ...item, list: [] };
+			});
+		ipBlackList.value = val.data.filter((item) => item.ipType === 2).map((item) => {
+				return { ...item, list: [] };
+			});;
+		console.log(ipBlackList.value);
 		
 	});
-}
+};
 const getDomainData = async () => {
 	await pageListDomain().then((val) => {
 		domainActiveId.value = [];
@@ -368,6 +485,7 @@ const getIpData = async () => {
 onMounted(() => {
 	//获取IP列表
 	getIpData();
+	getConfig();
 });
 </script>
 <style  lang="scss">