瀏覽代碼

fix: 并解决冲突

jcq 1 周之前
父節點
當前提交
0808cda6b2

+ 1 - 0
src/utils/validate.ts

@@ -243,6 +243,7 @@ export const getRegExp = function (validatorName) {
 		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+&@#/%=~_|]',
+		 domain: '^(?=.{1,253}$)(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}|(?:[0-9]{1,3}\\.){3}[0-9]{1,3})(?::[0-9]{1,5})?$',
 		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]?)(\/([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))?$',
 	};
 	return commonRegExp[validatorName];

+ 22 - 7
src/views/marketing/config/components/domainEdit.vue

@@ -2,9 +2,11 @@
 	<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">
 			<div class="custom-style">
-				<el-segmented v-model="state.ruleForm.sourceTypeText" :options="[t('marketingConfig.grouping'), t('marketingConfig.ip')]" size="default">
+				<el-segmented v-model="state.ruleForm.sourceTypeText" :options="[t('marketingConfig.grouping'), t('marketingConfig.domain')]" size="default">
 					<template #default="scope">
-						<div style="min-width: 50px; line-height: 32px">{{ scope.item }}</div>
+						<div style="min-width: 50px; line-height: 32px">
+							{{ scope.item }}
+						</div>
 					</template>
 				</el-segmented>
 			</div>
@@ -30,6 +32,7 @@
 import { useI18n } from 'vue-i18n';
 import { addDomains } from '/@/api/marketing/config';
 import { useMessage } from '/@/hooks/message';
+import { rule } from '/@/utils/validate';
 
 // 定义子组件向父组件传值/事件
 const emit = defineEmits(['update:open', 'onsuccess']);
@@ -64,7 +67,10 @@ const props = defineProps({
 //  表单校验规则
 const dataRules = reactive({
 	groupId: [{ required: true, message: '分组不能为空', trigger: 'blur' }],
-	domain: [{ required: true, message: '域名不能为空', trigger: 'blur' }],
+	domain: [
+		{ required: true, message: '域名不能为空', trigger: 'blur' },
+		{ validator: rule.domain, trigger: 'blur' },
+	],
 });
 const onCancel = () => {
 	emit('update:open', false);
@@ -72,11 +78,20 @@ const onCancel = () => {
 // 保存数据
 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('域名不能为空');
+	if (state.ruleForm.sourceType == 1 ) {
+		try {
+			await menuDialogFormRef.value.validateField('groupId');
+		} catch {
+			return;
+		}
+	} else if (state.ruleForm.sourceType == 2 ) {
+		try {
+			await menuDialogFormRef.value.validateField('domain');
+		} catch {
+			return;
+		}
 	}
+
 	try {
 		loading.value = true;
 		await addDomains(state.ruleForm);

+ 21 - 13
src/views/marketing/config/components/ipGroupingEdit.vue

@@ -1,6 +1,6 @@
 <template>
 	<el-dialog
-		:title="type == 'ip'? '添加IP分组':'添加域名分组'"
+		:title="type == 'ip' ? '添加IP分组' : '添加域名分组'"
 		width="600"
 		v-model="props.open"
 		:close-on-click-modal="false"
@@ -9,7 +9,7 @@
 		draggable
 	>
 		<el-form ref="menuDialogFormRef" :rules="dataRules" :model="state.ruleForm" v-loading="loading">
-			<el-form-item :label="t('marketingConfig.groupingName')" prop="groupName" >
+			<el-form-item :label="t('marketingConfig.groupingName')" prop="groupName">
 				<el-input v-model="state.ruleForm.groupName" type="text" :placeholder="t('marketingConfig.groupingNameTip')"></el-input>
 			</el-form-item>
 		</el-form>
@@ -38,7 +38,7 @@ const menuDialogFormRef = ref();
 // 定义需要的数据
 const state = reactive({
 	ruleForm: {
-		groupName:''
+		groupName: '',
 	},
 });
 
@@ -61,6 +61,11 @@ const onCancel = () => {
 };
 // 保存数据
 const onSubmit = async () => {
+	try {
+		await menuDialogFormRef.value.validateField('groupName');
+	} catch {
+		return;
+	}
 	try {
 		loading.value = true;
 		await addGroup({
@@ -76,16 +81,19 @@ const onSubmit = async () => {
 		loading.value = false;
 	}
 };
-watch(() => props.open, (val) => {
-	if(val){
-		state.ruleForm = {
-			groupName: '',
-			groupType: '',
-			groupDesc: '',
-			groupStatus: '',
-		};
-	} 
-})
+watch(
+	() => props.open,
+	(val) => {
+		if (val) {
+			state.ruleForm = {
+				groupName: '',
+				groupType: '',
+				groupDesc: '',
+				groupStatus: '',
+			};
+		}
+	}
+);
 </script>
 <style>
 .apps-loadmore.el-select-dropdown .el-scrollbar__wrap {

+ 21 - 11
src/views/marketing/config/components/ipListEdit.vue

@@ -7,11 +7,16 @@
 		:destroy-on-close="true"
 		draggable
 	>
-		<el-form ref="menuDialogFormRef" :model="state.ruleForm" :rules="dataRules" label-width="90px" v-loading="loading">
+		<el-form ref="menuDialogFormRef" :model="state.ruleForm" :rules="dataRules" label-width="90px" :hide-required-asterisk="true" v-loading="loading">
 			<el-form-item label="名称" prop="groupName">
 				<el-input class="!w-[300px]" v-model="state.ruleForm.groupName" placeholder="请输入名称"></el-input>
 			</el-form-item>
-			<el-form-item v-for="(item, index) in state.ruleForm.list" :key="item.id || index" :prop="'list.' + index + '.val'" :rules="dataRules.configs">
+			<el-form-item
+				v-for="(item, index) in state.ruleForm.list"
+				:key="item.id || index"
+				:prop="'list.' + index + '.val'"
+				:rules="sign === 'domain' ? dataRules.domain : dataRules.ip"
+			>
 				<template #label>
 					<div v-if="index === 0" class="flex items-center">
 						<el-tooltip v-if="sign === 'ip'" effect="light" content="输入127.0.0.1/24格式代表网段" placement="top">
@@ -73,7 +78,7 @@
 
 <script setup name="systemMenuDialog">
 import { useI18n } from 'vue-i18n';
-import { saveDomains ,saveIps } from '/@/api/marketing/config';
+import { saveDomains, saveIps } from '/@/api/marketing/config';
 import { useMessage } from '/@/hooks/message';
 import { rule } from '/@/utils/validate';
 import { parseIpRange } from '/@/utils/ipUpdate';
@@ -82,7 +87,13 @@ import { parseIpRange } from '/@/utils/ipUpdate';
 const emit = defineEmits(['onsuccess']);
 const { t } = useI18n();
 
-const inputTip = computed(() => t('marketingConfig.inputIPTip'));
+const inputTip = computed(() => {
+  if (sign.value === 'domain') {
+    return '请输入域名';
+  } else {
+    return t('marketingConfig.inputIPTip');
+  }
+});
 // 定义变量内容
 const visible = ref(false);
 const loading = ref(false);
@@ -109,11 +120,14 @@ const onAddItem = () => {
 
 // // 表单校验规则
 const dataRules = computed(() => ({
-	groupId: [{ required: true, message: '分组不能为空', trigger: 'blur' }],
 	ip: [
 		{ required: rule.ip, message: 'IP不能为空', trigger: 'blur' },
 		{ validator: rule.ip, trigger: 'blur' },
 	],
+	domain: [
+		{ required: true, message: '域名不能为空', trigger: 'blur' },
+		{ validator: rule.domain, trigger: 'blur' },
+	],
 }));
 
 // 打开弹窗
@@ -141,10 +155,10 @@ const onSubmit = async () => {
 	if (sign.value === 'ip') {
 		state.ruleForm.ips = state.ruleForm.list.map((item) => {
 			const { start, end } = parseIpRange(item.val);
-			
+
 			return {
 				...item,
-				ipMode:start === end ? 1 : 2,
+				ipMode: end === '' ? 1 : 2,
 				startIp: start,
 				endIp: end,
 			};
@@ -155,10 +169,6 @@ const onSubmit = async () => {
 			domain: item.val,
 		}));
 	}
-	console.log(state.ruleForm);
-
-	// delete state.ruleForm.list;
-	// return;
 	try {
 		loading.value = true;
 		if (sign.value === 'ip') {

+ 50 - 10
src/views/marketing/config/components/listEdit.vue

@@ -18,7 +18,39 @@
 			<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>
+						<div style="min-width: 50px; line-height: 32px">
+							{{ scope.item }}
+							<el-icon v-if="scope.item === t('marketingConfig.ip')" size="12" style="vertical-align: middle">
+								<el-tooltip effect="light" content="输入127.0.0.1/24格式代表网段" placement="top">
+									<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
+										<path
+											d="M7 14C8.93298 14 10.683 13.2165 11.9497 11.9497C13.2165 10.683 14 8.93298 14 7C14 5.06702 13.2165 3.31702 11.9497 2.05025C10.683 0.783503 8.93298 0 7 0C5.06702 0 3.31702 0.783503 2.05025 2.05025C0.783503 3.31702 0 5.06702 0 7C0 8.93298 0.783503 10.683 2.05025 11.9497C3.31702 13.2165 5.06702 14 7 14Z"
+											fill="#1B4D88"
+											fill-opacity="0.4"
+										/>
+										<path
+											fill-rule="evenodd"
+											clip-rule="evenodd"
+											d="M6.99957 1.94434C7.5365 1.94434 7.97179 2.37962 7.97179 2.91656C7.97179 3.4535 7.5365 3.88878 6.99957 3.88878C6.46263 3.88878 6.02734 3.4535 6.02734 2.91656C6.02734 2.37962 6.46263 1.94434 6.99957 1.94434Z"
+											fill="white"
+										/>
+										<path
+											d="M6.99957 1.94434C7.5365 1.94434 7.97179 2.37962 7.97179 2.91656C7.97179 3.4535 7.5365 3.88878 6.99957 3.88878C6.46263 3.88878 6.02734 3.4535 6.02734 2.91656C6.02734 2.37962 6.46263 1.94434 6.99957 1.94434ZM6.99957 2.33322C6.6774 2.33322 6.41623 2.5944 6.41623 2.91656C6.41623 3.23872 6.6774 3.49989 6.99957 3.49989C7.32173 3.49989 7.5829 3.23872 7.5829 2.91656C7.5829 2.5944 7.32173 2.33322 6.99957 2.33322Z"
+											fill="white"
+										/>
+										<path d="M7.19477 10.8888V5.44434H6.80588H6.41699" fill="white" />
+										<path
+											d="M6.41645 10.8887V6.22206C5.98689 6.22206 5.63867 5.87384 5.63867 5.44428C5.63867 5.01473 5.98689 4.6665 6.41645 4.6665H7.19423L7.27398 4.6703C7.66608 4.71023 7.97201 5.04164 7.97201 5.44428V10.8887C7.97201 11.3183 7.70354 11.3447 7.27398 11.3447C6.84443 11.3447 6.41645 11.3183 6.41645 10.8887Z"
+											fill="white"
+										/>
+										<path
+											d="M8.55566 10C8.98522 10 9.33344 10.3482 9.33344 10.7778C9.33344 11.2073 8.98522 11.5556 8.55566 11.5556H5.83344C5.40389 11.5556 5.05566 11.2073 5.05566 10.7778C5.05566 10.3482 5.40389 10 5.83344 10H8.55566Z"
+											fill="white"
+										/>
+									</svg>
+								</el-tooltip>
+							</el-icon>
+						</div>
 					</template>
 				</el-segmented>
 			</div>
@@ -65,7 +97,7 @@ const state = reactive({
 		sourceTypeText: t('marketingConfig.grouping'),
 		groupId: '',
 		ipMode: 1,
-		groupName:'',
+		groupName: '',
 		startIp: '',
 		endIp: '',
 		ip: '',
@@ -77,10 +109,10 @@ const props = defineProps({
 		type: Boolean,
 		default: false,
 	},
-	selectData:{
+	selectData: {
 		type: Array,
 		default: () => [],
-	}
+	},
 });
 // // 表单校验规则
 const dataRules = reactive({
@@ -101,13 +133,22 @@ const onSubmit = async () => {
 	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不能为空');
+	if (state.ruleForm.sourceType == 1) {
+		try {
+			await menuDialogFormRef.value.validateField('groupId');
+		} catch {
+			return;
+		}
+	} else if (state.ruleForm.sourceType == 2) {
+		try {
+			await menuDialogFormRef.value.validateField('ip');
+		} catch {
+			return;
+		}
 	}
+
 	try {
 		loading.value = true;
 		await saveIpList(state.ruleForm);
@@ -163,5 +204,4 @@ watch(
 		--el-segmented-padding: 0;
 	}
 }
-
 </style>

+ 35 - 11
src/views/marketing/config/index.vue

@@ -254,7 +254,6 @@ import { useI18n } from 'vue-i18n';
 import { useMessage } from '/@/hooks/message';
 import { rule } from '/@/utils/validate';
 import { ipSplicing } from '/@/utils/ipUpdate';
-import type { FormInstance } from 'element-plus';
 
 // 引入组件
 const JCollapse = defineAsyncComponent(() => import('/@/components/JCollapse/index.vue'));
@@ -322,7 +321,10 @@ const onLoadDetail = async (item: any) => {
 const dataRules = reactive({
 	url: [
 		{ required: true, message: '跳转连接不能为空', trigger: 'blur' },
-		{ validator: rule.url, trigger: 'blur' },
+		{ validator: rule.domain, trigger: 'blur' },
+	],
+	promptMsg: [
+		{ required: true, message: '提示信息不能为空', trigger: 'blur' },
 	],
 	triggerNum: [
 		{ required: true, message: '触发频率不能为空', trigger: 'blur' },
@@ -335,7 +337,13 @@ const dataRules = reactive({
 });
 
 const onSubmit = async () => {
-	let isValid = true;
+	try {
+		await ruleFormRef.value.validateField('triggerNum');
+	} catch (error) {
+		// 验证失败,阻止后续逻辑执行
+		return;
+	}
+
 	if (formData.value.triggerMode === '1' || formData.value.triggerMode === '3') {
 		try {
 			await ruleFormRef.value.validateField('url');
@@ -344,17 +352,30 @@ const onSubmit = async () => {
 			return;
 		}
 	}
-	// 如果验证失败,直接返回,不执行后续逻辑
-	if (!isValid) {
-		return;
-	}
+
 	try {
 		loading.value = true;
-		await saveConfigDetail(formData.value);
+
+		// 处理 triggerNum 参数
+		let triggerNum = formData.value.triggerNum;
+		if (typeof triggerNum === 'string' && triggerNum.includes('%')) {
+			// 如果包含百分比符号,去除百分比符号并除以100
+			const num = parseFloat(triggerNum.replace('%', ''));
+			if (!isNaN(num)) {
+				triggerNum = num / 100;
+			}
+		}
+
+		await saveConfigDetail({
+			...formData.value,
+			triggerNum: triggerNum.toString(),
+		});
+
 		useMessage().success(t('common.editSuccessText'));
 	} catch (err) {
 		useMessage().error(err.msg);
 	} finally {
+		loading.value = false;
 		getConfig();
 	}
 };
@@ -425,7 +446,6 @@ const onOpenEditMenu = (type: string, row: any) => {
 const getConfig = () => {
 	configIp();
 	configDomain();
-	getConfigDetail();
 };
 const configDomain = async () => {
 	await getConfigDomainList().then((val) => {
@@ -499,8 +519,12 @@ const getIpData = async () => {
 			url: '',
 			triggerNum: '',
 		};
-		formData.value = { ...val.data, triggerMode: val.data?.triggerMode.toString(), triggerRule: val.data?.triggerRule.toString() };
-		console.log(val);
+		formData.value = {
+			...val.data,
+			triggerMode: val.data?.triggerMode.toString(),
+			triggerRule: val.data?.triggerRule.toString(),
+			triggerNum: parseFloat(val.data?.triggerNum) < 1 ? parseFloat(val.data?.triggerNum) * 100 + '%' : val.data?.triggerNum,
+		};
 	});
 };