|
@@ -1,13 +1,6 @@
|
|
<template>
|
|
<template>
|
|
- <el-dialog
|
|
|
|
- :title="props.rowData?.id ? '修改规则' : '新增规则'"
|
|
|
|
- width="1000"
|
|
|
|
- v-model="props.open"
|
|
|
|
- :close-on-click-modal="false"
|
|
|
|
- :destroy-on-close="true"
|
|
|
|
- @close="onCancel"
|
|
|
|
- draggable
|
|
|
|
- >
|
|
|
|
|
|
+ <el-dialog :title="props.rowData?.id ? '修改规则' : '新增规则'" width="1000" v-model="props.open"
|
|
|
|
+ :close-on-click-modal="false" :destroy-on-close="true" @close="onCancel" draggable>
|
|
<div class="w-full ml-[-8px]">
|
|
<div class="w-full ml-[-8px]">
|
|
<el-form ref="ruleFormRef" :model="formData" :rules="dataRules" label-width="90px" class="flex flex-wrap">
|
|
<el-form ref="ruleFormRef" :model="formData" :rules="dataRules" label-width="90px" class="flex flex-wrap">
|
|
<el-form-item label="规则名称" prop="ruleName" class="w-1/3">
|
|
<el-form-item label="规则名称" prop="ruleName" class="w-1/3">
|
|
@@ -18,17 +11,12 @@
|
|
<div class="flex items-start">
|
|
<div class="flex items-start">
|
|
<label class="w-[65px] leading-8 text-right"><span class="text-[#f56c6c] mr-1">*</span> 关键字</label>
|
|
<label class="w-[65px] leading-8 text-right"><span class="text-[#f56c6c] mr-1">*</span> 关键字</label>
|
|
<div class="flex gap-2 ml-2 flex-wrap w-57vw]">
|
|
<div class="flex gap-2 ml-2 flex-wrap w-57vw]">
|
|
- <el-tag v-for="tag in keywordData" :key="tag" size="large" closable :disable-transitions="false" @close="handleClose(tag, 'keyword')">
|
|
|
|
|
|
+ <el-tag v-for="tag in keywordData" :key="tag" size="large" closable :disable-transitions="false"
|
|
|
|
+ @close="handleClose(tag, 'keyword')">
|
|
{{ tag }}
|
|
{{ tag }}
|
|
</el-tag>
|
|
</el-tag>
|
|
- <el-input
|
|
|
|
- v-if="inputVisible"
|
|
|
|
- ref="InputRef"
|
|
|
|
- v-model="inputValue"
|
|
|
|
- class="!w-32"
|
|
|
|
- @keyup.enter="handleInputConfirm('keyword')"
|
|
|
|
- @blur="handleInputConfirm('keyword')"
|
|
|
|
- />
|
|
|
|
|
|
+ <el-input v-if="inputVisible" ref="InputRef" v-model="inputValue" class="!w-32"
|
|
|
|
+ @keyup.enter="handleInputConfirm('keyword')" @blur="handleInputConfirm('keyword')" />
|
|
<el-button v-else class="button-new-tag" @click="showInput"> 添加关键字</el-button>
|
|
<el-button v-else class="button-new-tag" @click="showInput"> 添加关键字</el-button>
|
|
<!-- 注册隐藏的表单项以启用校验 -->
|
|
<!-- 注册隐藏的表单项以启用校验 -->
|
|
<el-form-item prop="keyword" style="display: none"></el-form-item>
|
|
<el-form-item prop="keyword" style="display: none"></el-form-item>
|
|
@@ -39,19 +27,13 @@
|
|
<div class="flex items-start">
|
|
<div class="flex items-start">
|
|
<label class="w-[65px] leading-8 text-right">IP</label>
|
|
<label class="w-[65px] leading-8 text-right">IP</label>
|
|
<div class="flex gap-2 ml-2 flex-wrap w-57vw]">
|
|
<div class="flex gap-2 ml-2 flex-wrap w-57vw]">
|
|
- <el-tag v-for="tag in ipData" :key="tag" size="large" closable :disable-transitions="false" @close="handleClose(tag, 'ip')">
|
|
|
|
|
|
+ <el-tag v-for="tag in ipData" :key="tag" size="large" closable :disable-transitions="false"
|
|
|
|
+ @close="handleClose(tag, 'ip')">
|
|
{{ tag }}
|
|
{{ tag }}
|
|
</el-tag>
|
|
</el-tag>
|
|
- <el-input
|
|
|
|
- v-if="ipInputVisible"
|
|
|
|
- ref="ipInputRef"
|
|
|
|
- v-model="ipInputValue"
|
|
|
|
- class="!w-32"
|
|
|
|
- @keyup.enter="handleInputConfirm('ip')"
|
|
|
|
- @blur="handleInputConfirm('ip')"
|
|
|
|
- />
|
|
|
|
|
|
+ <el-input v-if="ipInputVisible" ref="ipInputRef" v-model="ipInputValue" class="!w-32"
|
|
|
|
+ @keyup.enter="handleInputConfirm('ip')" @blur="handleInputConfirm('ip')" />
|
|
<el-button v-else class="button-new-tag" @click="showIpInput"> 添加IP</el-button>
|
|
<el-button v-else class="button-new-tag" @click="showIpInput"> 添加IP</el-button>
|
|
- <!-- 注册隐藏的表单项以启用校验 -->
|
|
|
|
<el-form-item prop="ip" style="display: none"></el-form-item>
|
|
<el-form-item prop="ip" style="display: none"></el-form-item>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@@ -61,27 +43,42 @@
|
|
<div class="flex items-start">
|
|
<div class="flex items-start">
|
|
<label class="w-[66px] leading-8 text-right">添加域名</label>
|
|
<label class="w-[66px] leading-8 text-right">添加域名</label>
|
|
<div class="flex gap-2 ml-2 flex-wrap w-57vw]">
|
|
<div class="flex gap-2 ml-2 flex-wrap w-57vw]">
|
|
- <el-tag v-for="tag in domainData" :key="tag" size="large" closable :disable-transitions="false" @close="handleClose(tag, 'domain')">
|
|
|
|
|
|
+ <el-tag v-for="tag in domainData" :key="tag" size="large" closable :disable-transitions="false"
|
|
|
|
+ @close="handleClose(tag, 'domain')">
|
|
{{ tag }}
|
|
{{ tag }}
|
|
</el-tag>
|
|
</el-tag>
|
|
- <el-input
|
|
|
|
- v-if="domainInputVisible"
|
|
|
|
- ref="domainInputRef"
|
|
|
|
- v-model="domainInputValue"
|
|
|
|
- class="!w-32"
|
|
|
|
- @keyup.enter="handleInputConfirm('domain')"
|
|
|
|
- @blur="handleInputConfirm('domain')"
|
|
|
|
- placeholder="如: example.com"
|
|
|
|
- />
|
|
|
|
|
|
+ <el-input v-if="domainInputVisible" ref="domainInputRef" v-model="domainInputValue"
|
|
|
|
+ class="!w-32" @keyup.enter="handleInputConfirm('domain')"
|
|
|
|
+ @blur="handleInputConfirm('domain')" placeholder="如: example.com" />
|
|
<el-button v-else class="button-new-tag" @click="showDomainInput"> 添加域名</el-button>
|
|
<el-button v-else class="button-new-tag" @click="showDomainInput"> 添加域名</el-button>
|
|
- <!-- 注册隐藏的表单项以启用校验 -->
|
|
|
|
<el-form-item prop="domain" style="display: none"></el-form-item>
|
|
<el-form-item prop="domain" style="display: none"></el-form-item>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
- <el-form ref="ruleFormRef" :model="formData" :rules="dataRules" label-width="90px" class="flex flex-wrap mt-4">
|
|
|
|
|
|
+
|
|
|
|
+ <!-- 地区选择 -->
|
|
|
|
+ <div class="px-4 rounded overflow-y-auto mt-4" style="max-height: calc(100vh - 350px)">
|
|
|
|
+ <div class="flex items-start">
|
|
|
|
+ <label class="w-[65px] leading-8 text-right">地区</label>
|
|
|
|
+ <div class="flex gap-2 ml-2 flex-wrap w-57vw]">
|
|
|
|
+ <el-tag v-for="(tag, index) in regionData" :key="index" size="large" closable
|
|
|
|
+ :disable-transitions="false" @close="handleClose(tag, 'region')">
|
|
|
|
+ {{ tag == 'All' ? '全部国家' : tag }}
|
|
|
|
+ </el-tag>
|
|
|
|
+ <ChineseRegionSelector v-show="regionInputVisible" v-model="regionData" showAll
|
|
|
|
+ @update:modelValue="handleRegionDataUpdate" />
|
|
|
|
+ <el-button v-show="!regionInputVisible" class="button-new-tag" @click="showRegionInput">
|
|
|
|
+ 添加地区</el-button>
|
|
|
|
+ <!-- 注册隐藏的表单项以启用校验 -->
|
|
|
|
+ <el-form-item prop="region" style="display: none"></el-form-item>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <el-form ref="ruleFormRef" :model="formData" :rules="dataRules" label-width="90px"
|
|
|
|
+ class="flex flex-wrap mt-4">
|
|
<el-form-item label="推送方式" prop="action" class="w-1/2">
|
|
<el-form-item label="推送方式" prop="action" class="w-1/2">
|
|
- <JDictSelect v-model:value="formData.action" placeholder="请选择推送方式" dictType="pushMode" :styleClass="'w-full'" />
|
|
|
|
|
|
+ <JDictSelect v-model:value="formData.action" placeholder="请选择推送方式" dictType="pushMode"
|
|
|
|
+ :styleClass="'w-full'" />
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="推送频率" prop="pushFrequency" class="w-1/2">
|
|
<el-form-item label="推送频率" prop="pushFrequency" class="w-1/2">
|
|
@@ -92,10 +89,12 @@
|
|
<el-input v-model="formData.delayPush" type="text" placeholder="请输入推送延时" />
|
|
<el-input v-model="formData.delayPush" type="text" placeholder="请输入推送延时" />
|
|
</div>
|
|
</div>
|
|
</el-form-item>
|
|
</el-form-item>
|
|
- <el-form-item label="推送图片" prop="pushContent" class="w-full">
|
|
|
|
|
|
+ <el-form-item label="推送图片" class="w-full">
|
|
<div class="flex items-start">
|
|
<div class="flex items-start">
|
|
- <el-switch v-model="formData.pushType" class="mr-2" @change="(oldUrl = formData.pushContent), (formData.pushContent = '')" />
|
|
|
|
- <Image v-if="formData.pushType" @change="success" :imageUrl="formData.pushContent" @update="success" />
|
|
|
|
|
|
+ <el-switch v-model="formData.pushType" class="mr-2"
|
|
|
|
+ @change="(oldUrl = formData.pushContent), (formData.pushContent = '')" />
|
|
|
|
+ <Image v-if="formData.pushType" @change="success" :imageUrl="formData.pushContent"
|
|
|
|
+ @update="success" />
|
|
</div>
|
|
</div>
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
|
@@ -110,7 +109,8 @@
|
|
<template #footer>
|
|
<template #footer>
|
|
<span class="dialog-footer">
|
|
<span class="dialog-footer">
|
|
<el-button @click="onCancel">{{ t('common.cancelButtonText') }}</el-button>
|
|
<el-button @click="onCancel">{{ t('common.cancelButtonText') }}</el-button>
|
|
- <el-button type="primary" @click="onSubmit" :disabled="loading">{{ t('common.confirmButtonText') }}</el-button>
|
|
|
|
|
|
+ <el-button type="primary" @click="onSubmit"
|
|
|
|
+ :disabled="loading">{{ t('common.confirmButtonText') }}</el-button>
|
|
</span>
|
|
</span>
|
|
</template>
|
|
</template>
|
|
</el-dialog>
|
|
</el-dialog>
|
|
@@ -132,7 +132,7 @@ const props = defineProps({
|
|
},
|
|
},
|
|
rowData: {
|
|
rowData: {
|
|
type: Object,
|
|
type: Object,
|
|
- default: () => {},
|
|
|
|
|
|
+ default: () => { },
|
|
},
|
|
},
|
|
});
|
|
});
|
|
const onCancel = () => {
|
|
const onCancel = () => {
|
|
@@ -146,6 +146,13 @@ const success = (val: string) => {
|
|
// 引入组件
|
|
// 引入组件
|
|
const JDictSelect = defineAsyncComponent(() => import('/@/components/JDictSelect/index.vue'));
|
|
const JDictSelect = defineAsyncComponent(() => import('/@/components/JDictSelect/index.vue'));
|
|
const Image = defineAsyncComponent(() => import('/@/components/Upload/Image.vue'));
|
|
const Image = defineAsyncComponent(() => import('/@/components/Upload/Image.vue'));
|
|
|
|
+// 懒加载地区选择器(与 push 页面一致)
|
|
|
|
+const ChineseRegionSelector = defineAsyncComponent({
|
|
|
|
+ loader: () => import('/@/components/common/SimpleRegionSelector.vue'),
|
|
|
|
+ loadingComponent: () => h('div', { class: 'text-center p-4' }, '加载地区数据中...'),
|
|
|
|
+ delay: 200,
|
|
|
|
+ timeout: 10000
|
|
|
|
+});
|
|
const { t } = useI18n();
|
|
const { t } = useI18n();
|
|
// 定义变量内容
|
|
// 定义变量内容
|
|
|
|
|
|
@@ -163,13 +170,17 @@ const formData = ref<any>({
|
|
action: '1',
|
|
action: '1',
|
|
remark: '',
|
|
remark: '',
|
|
pushType: false,
|
|
pushType: false,
|
|
- delayPush:''
|
|
|
|
|
|
+ delayPush: '',
|
|
|
|
+ pushApp: [],
|
|
|
|
+ pushBundle: [],
|
|
|
|
+ pushAddr: [],
|
|
});
|
|
});
|
|
|
|
|
|
// // 表单校验规则
|
|
// // 表单校验规则
|
|
const dataRules = reactive({
|
|
const dataRules = reactive({
|
|
ruleName: [{ required: true, message: '规则名称不能为空', trigger: 'blur' }],
|
|
ruleName: [{ required: true, message: '规则名称不能为空', trigger: 'blur' }],
|
|
delayPush: [{ required: true, message: '推送延时不能为空', trigger: 'blur' }],
|
|
delayPush: [{ required: true, message: '推送延时不能为空', trigger: 'blur' }],
|
|
|
|
+
|
|
keyword: [
|
|
keyword: [
|
|
{
|
|
{
|
|
required: true,
|
|
required: true,
|
|
@@ -235,6 +246,10 @@ const domainInputRef = ref();
|
|
const keywordData = ref<string[]>([]);
|
|
const keywordData = ref<string[]>([]);
|
|
const ipData = ref<string[]>([]);
|
|
const ipData = ref<string[]>([]);
|
|
const domainData = ref<string[]>([]);
|
|
const domainData = ref<string[]>([]);
|
|
|
|
+// 地区相关
|
|
|
|
+const regionData = ref<any[]>([]);
|
|
|
|
+const regionInputVisible = ref(false);
|
|
|
|
+const regionInputRef = ref();
|
|
|
|
|
|
const showInput = () => {
|
|
const showInput = () => {
|
|
inputVisible.value = true;
|
|
inputVisible.value = true;
|
|
@@ -254,6 +269,12 @@ const showDomainInput = () => {
|
|
domainInputRef.value!.input!.focus();
|
|
domainInputRef.value!.input!.focus();
|
|
});
|
|
});
|
|
};
|
|
};
|
|
|
|
+const showRegionInput = () => {
|
|
|
|
+ regionInputVisible.value = true;
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ regionInputRef.value?.focus();
|
|
|
|
+ });
|
|
|
|
+};
|
|
const handleClose = (tag: string, type: string) => {
|
|
const handleClose = (tag: string, type: string) => {
|
|
if (type === 'keyword') {
|
|
if (type === 'keyword') {
|
|
keywordData.value = keywordData.value.filter((item: string) => item !== tag);
|
|
keywordData.value = keywordData.value.filter((item: string) => item !== tag);
|
|
@@ -261,6 +282,8 @@ const handleClose = (tag: string, type: string) => {
|
|
ipData.value = ipData.value.filter((item: string) => item !== tag);
|
|
ipData.value = ipData.value.filter((item: string) => item !== tag);
|
|
} else if (type === 'domain') {
|
|
} else if (type === 'domain') {
|
|
domainData.value = domainData.value.filter((item: string) => item !== tag);
|
|
domainData.value = domainData.value.filter((item: string) => item !== tag);
|
|
|
|
+ } else if (type === 'region') {
|
|
|
|
+ regionData.value = regionData.value.filter((item: any) => item !== tag);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
@@ -457,6 +480,30 @@ const getpushContent = () => {
|
|
return formData.value.pushContent;
|
|
return formData.value.pushContent;
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
+// 地区选择数据更新
|
|
|
|
+const handleRegionDataUpdate = (newRegionData: any[]) => {
|
|
|
|
+ const mapped = newRegionData
|
|
|
|
+ .map((item: any) => {
|
|
|
|
+ if (item || item == '全部国家') {
|
|
|
|
+ return (
|
|
|
|
+ (item?.city ? `${item.country} - ${item.state} - ${item.city}` : item?.state ? `${item.country} - ${item.state}` : item?.country) || item
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ })
|
|
|
|
+ .filter((v: any) => v !== undefined && v !== false && v !== null && v !== '');
|
|
|
|
+
|
|
|
|
+ const unique = Array.from(new Set(mapped)) as string[];
|
|
|
|
+ const hasNonAll = unique.some((v) => v !== '全部国家');
|
|
|
|
+
|
|
|
|
+ if (hasNonAll) {
|
|
|
|
+ regionData.value = unique.filter((v) => v !== '全部国家');
|
|
|
|
+ } else {
|
|
|
|
+ regionData.value = unique.length > 0 ? ['全部国家'] : [];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ regionInputVisible.value = false;
|
|
|
|
+};
|
|
|
|
|
|
const onSubmit = async () => {
|
|
const onSubmit = async () => {
|
|
// 触发表单校验(包含隐藏注册的 keyword/ip/domain 规则)
|
|
// 触发表单校验(包含隐藏注册的 keyword/ip/domain 规则)
|
|
@@ -478,6 +525,7 @@ const onSubmit = async () => {
|
|
ip: ipData.value,
|
|
ip: ipData.value,
|
|
keyword: keywordData.value,
|
|
keyword: keywordData.value,
|
|
domain: domainData.value,
|
|
domain: domainData.value,
|
|
|
|
+ pushAddr: regionData.value.length === 1 && regionData.value[0] === '全部国家' ? ['All'] : regionData.value,
|
|
pushContent: getpushContent(),
|
|
pushContent: getpushContent(),
|
|
pushType: formData.value.pushType || false,
|
|
pushType: formData.value.pushType || false,
|
|
pushFrequency: pushFrequency.toString(),
|
|
pushFrequency: pushFrequency.toString(),
|
|
@@ -526,8 +574,7 @@ watch(
|
|
keywordData.value = props.rowData.keyword || [];
|
|
keywordData.value = props.rowData.keyword || [];
|
|
domainData.value = props.rowData.domain || [];
|
|
domainData.value = props.rowData.domain || [];
|
|
oldUrl.value = props.rowData.pushContent;
|
|
oldUrl.value = props.rowData.pushContent;
|
|
- console.log(formData.value);
|
|
|
|
- console.log(props.rowData);
|
|
|
|
|
|
+ regionData.value = props.rowData.pushAddr || [];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
);
|