mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-08 09:16:58 +08:00
Merge pull request #257 from Aqr-K/v2-rulessettings
This commit is contained in:
@@ -72,12 +72,17 @@ const getCategories = computed(() => {
|
|||||||
|
|
||||||
// 规则组规则卡片列表
|
// 规则组规则卡片列表
|
||||||
const filterRuleCards = ref<FilterCard[]>([])
|
const filterRuleCards = ref<FilterCard[]>([])
|
||||||
|
// 规则组类型,仅用于导入判断
|
||||||
|
const filterRuleCardsType = ref<FilterCard>({
|
||||||
|
pri: '',
|
||||||
|
rules: [],
|
||||||
|
})
|
||||||
|
|
||||||
// 导入代码弹窗
|
// 导入代码弹窗
|
||||||
const importCodeDialog = ref(false)
|
const importCodeDialog = ref(false)
|
||||||
|
|
||||||
// 导入的代码
|
// 导入代码类型
|
||||||
const importCodeString = ref('')
|
const importCodeType = ref('')
|
||||||
|
|
||||||
// 更新规则卡片的值
|
// 更新规则卡片的值
|
||||||
function updateFilterCardValue(pri: string, rules: string[]) {
|
function updateFilterCardValue(pri: string, rules: string[]) {
|
||||||
@@ -109,28 +114,37 @@ function shareRules() {
|
|||||||
$toast.success('优先级规则已复制到剪贴板')
|
$toast.success('优先级规则已复制到剪贴板')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$toast.error('优先级规则复制失败!')
|
$toast.error('优先级规则复制失败!')
|
||||||
|
console.error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导入规则
|
// 导入规则
|
||||||
async function importRules() {
|
async function importRules(ruleType: string) {
|
||||||
importCodeString.value = ''
|
importCodeType.value = ruleType
|
||||||
importCodeDialog.value = true
|
importCodeDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听导入代码变化
|
// 保存导入的代码,直接覆盖原有值
|
||||||
watchEffect(() => {
|
function saveCodeString(type: string, code: any) {
|
||||||
if (!importCodeString.value) return
|
try {
|
||||||
|
code = code.value
|
||||||
if (!importCodeString.value.startsWith(' ')) importCodeString.value = ` ${importCodeString.value}`
|
if (type === 'priority') {
|
||||||
if (!importCodeString.value.endsWith(' ')) importCodeString.value = `${importCodeString.value} `
|
// 解析值
|
||||||
|
if (!code) return
|
||||||
const groups = importCodeString.value.split('>')
|
// 首尾增加空格
|
||||||
|
if (!code.startsWith(' ')) code = ` ${code}`
|
||||||
|
if (!code.endsWith(' ')) code = `${code} `
|
||||||
|
const groups = code.split('>')
|
||||||
filterRuleCards.value = groups.map((group: string, index: number) => ({
|
filterRuleCards.value = groups.map((group: string, index: number) => ({
|
||||||
pri: (index + 1).toString(),
|
pri: (index + 1).toString(),
|
||||||
rules: group.split('&').filter(rule => rule),
|
rules: group.split('&').filter(rule => rule),
|
||||||
}))
|
}))
|
||||||
})
|
}
|
||||||
|
} catch (error) {
|
||||||
|
$toast.error('导入失败!')
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 增加卡片
|
// 增加卡片
|
||||||
function addFilterCard() {
|
function addFilterCard() {
|
||||||
@@ -268,7 +282,7 @@ function onClose() {
|
|||||||
<VBtn color="primary" variant="tonal" @click="addFilterCard">
|
<VBtn color="primary" variant="tonal" @click="addFilterCard">
|
||||||
<VIcon icon="mdi-plus" />
|
<VIcon icon="mdi-plus" />
|
||||||
</VBtn>
|
</VBtn>
|
||||||
<VBtn color="success" variant="tonal" @click="importRules">
|
<VBtn color="success" variant="tonal" @click="importRules('priority')">
|
||||||
<VIcon icon="mdi-import" />
|
<VIcon icon="mdi-import" />
|
||||||
</VBtn>
|
</VBtn>
|
||||||
<VBtn color="info" variant="tonal" @click="shareRules">
|
<VBtn color="info" variant="tonal" @click="shareRules">
|
||||||
@@ -279,8 +293,13 @@ function onClose() {
|
|||||||
</VCardActions>
|
</VCardActions>
|
||||||
</VCard>
|
</VCard>
|
||||||
</VDialog>
|
</VDialog>
|
||||||
<VDialog v-model="importCodeDialog" width="60rem" scrollable>
|
<ImportCodeDialog
|
||||||
<ImportCodeDialog v-model="importCodeString" title="导入优先级规则" @close="importCodeDialog = false" />
|
v-if="importCodeDialog"
|
||||||
</VDialog>
|
v-model="importCodeDialog"
|
||||||
|
title="导入规则优先级"
|
||||||
|
:dataType="importCodeType"
|
||||||
|
@close="importCodeDialog = false"
|
||||||
|
@save="saveCodeString"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -2,17 +2,18 @@
|
|||||||
// 输入参数
|
// 输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: String,
|
title: String,
|
||||||
|
dataType: String,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 定义事件
|
|
||||||
const emit = defineEmits(['update:modelValue', 'close'])
|
|
||||||
|
|
||||||
// 代码
|
// 代码
|
||||||
const codeString = ref('')
|
const codeString = ref('')
|
||||||
|
|
||||||
|
// 定义事件
|
||||||
|
const emit = defineEmits(['close', 'save'])
|
||||||
|
|
||||||
// 导入
|
// 导入
|
||||||
function handleImport() {
|
function handleImport() {
|
||||||
emit('update:modelValue', codeString.value)
|
emit('save', props.dataType, codeString)
|
||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -3,18 +3,46 @@
|
|||||||
import { useToast } from 'vue-toast-notification'
|
import { useToast } from 'vue-toast-notification'
|
||||||
import { copyToClipboard } from '@/@core/utils/navigator'
|
import { copyToClipboard } from '@/@core/utils/navigator'
|
||||||
import draggable from 'vuedraggable'
|
import draggable from 'vuedraggable'
|
||||||
import { VRow } from 'vuetify/lib/components/index.mjs'
|
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { CustomRule, FilterRuleGroup } from '@/api/types'
|
import { CustomRule, FilterRuleGroup } from '@/api/types'
|
||||||
import CustomerRuleCard from '@/components/cards/CustomRuleCard.vue'
|
import CustomerRuleCard from '@/components/cards/CustomRuleCard.vue'
|
||||||
import FilterRuleGroupCard from '@/components/cards/FilterRuleGroupCard.vue'
|
import FilterRuleGroupCard from '@/components/cards/FilterRuleGroupCard.vue'
|
||||||
import ImportCodeDialog from '@/components/dialog/ImportCodeDialog.vue'
|
import ImportCodeDialog from '@/components/dialog/ImportCodeDialog.vue'
|
||||||
|
import internal from 'stream'
|
||||||
|
|
||||||
// 自定义规则列表
|
// 自定义规则列表
|
||||||
const customRules = ref<CustomRule[]>([])
|
const customRules = ref<CustomRule[]>([])
|
||||||
|
// 自定义规则类型,仅用于导入判断
|
||||||
|
const customRulesType = ref<CustomRule>({
|
||||||
|
// 规则ID
|
||||||
|
id: '',
|
||||||
|
// 名称
|
||||||
|
name: '',
|
||||||
|
// 包含
|
||||||
|
include: '',
|
||||||
|
// 排除
|
||||||
|
exclude: '',
|
||||||
|
// 大小范围
|
||||||
|
size_range: '',
|
||||||
|
// 最少做种人数
|
||||||
|
seeders: '',
|
||||||
|
// 发布时间
|
||||||
|
publish_time: '',
|
||||||
|
})
|
||||||
|
|
||||||
// 所有规则组列表
|
// 所有规则组列表
|
||||||
const filterRuleGroups = ref<FilterRuleGroup[]>([])
|
const filterRuleGroups = ref<FilterRuleGroup[]>([])
|
||||||
|
// 规则组类型,仅用于导入判断
|
||||||
|
const filterRuleGroupsType = ref<FilterRuleGroup>({
|
||||||
|
// 名称
|
||||||
|
name: '',
|
||||||
|
// 规则串
|
||||||
|
rule_string: '',
|
||||||
|
// 适用类媒体类型 None-全部 电影/电视剧
|
||||||
|
media_type: '',
|
||||||
|
// # 适用媒体类别 None-全部 对应二级分类
|
||||||
|
category: '',
|
||||||
|
})
|
||||||
|
|
||||||
// 种子优先规则
|
// 种子优先规则
|
||||||
const selectedTorrentPriority = ref<string>('seeder')
|
const selectedTorrentPriority = ref<string>('seeder')
|
||||||
@@ -25,9 +53,6 @@ const mediaCategories = ref<{ [key: string]: any }>({})
|
|||||||
// 导入代码弹窗
|
// 导入代码弹窗
|
||||||
const importCodeDialog = ref(false)
|
const importCodeDialog = ref(false)
|
||||||
|
|
||||||
// 导入的代码
|
|
||||||
const importCodeString = ref('')
|
|
||||||
|
|
||||||
// 导入代码类型
|
// 导入代码类型
|
||||||
const importCodeType = ref('')
|
const importCodeType = ref('')
|
||||||
|
|
||||||
@@ -171,35 +196,67 @@ function shareRules(rules: CustomRule[] | FilterRuleGroup[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导入规则
|
// 打开弹窗
|
||||||
async function importRules(ruleType: string) {
|
async function importRules(ruleType: string) {
|
||||||
importCodeType.value = ruleType
|
importCodeType.value = ruleType
|
||||||
importCodeString.value = ''
|
|
||||||
importCodeDialog.value = true
|
importCodeDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听导入代码变化
|
// 保存导入的代码
|
||||||
watchEffect(() => {
|
function saveCodeString(type: string, codeString: any) {
|
||||||
if (!importCodeString.value) return
|
// codeString从子组件传递过来,从对象转换为JSON
|
||||||
// 导入代码需要json格式
|
let parsedCode
|
||||||
try {
|
try {
|
||||||
if (importCodeType.value === 'custom') {
|
parsedCode = JSON.parse(codeString.value)
|
||||||
// 将导入的代码转换为规则卡片,并追加到已有的 customRules
|
} catch (e) {
|
||||||
const newCustomRules = JSON.parse(importCodeString.value).map((item: any) => {
|
$toast.error('导入规则失败!无法解析输入的数据!')
|
||||||
|
console.error(e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新数据
|
||||||
|
try {
|
||||||
|
if (type === 'custom') {
|
||||||
|
for (const value of parsedCode) {
|
||||||
|
if (!validateValueAgainstInterface(value, customRulesType)) return false
|
||||||
|
}
|
||||||
|
const newCustomRules = extractCustomRules(parsedCode) || []
|
||||||
|
customRules.value = [...customRules.value, ...newCustomRules]
|
||||||
|
} else if (type === 'group') {
|
||||||
|
for (const value of parsedCode) {
|
||||||
|
if (!validateValueAgainstInterface(value, filterRuleGroupsType)) return false
|
||||||
|
}
|
||||||
|
const newFilterRuleGroups = extractFilterRuleGroups(parsedCode) || []
|
||||||
|
filterRuleGroups.value = [...filterRuleGroups.value, ...newFilterRuleGroups]
|
||||||
|
} else {
|
||||||
|
$toast.error('导入规则失败!未知的数据类型!')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
$toast.error('导入规则失败!')
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 赋值自定义规则,避免存在多余的属性
|
||||||
|
function extractCustomRules(value: any) {
|
||||||
|
try {
|
||||||
|
return value.map((item: any) => {
|
||||||
return {
|
return {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
include: item.include,
|
include: item.include,
|
||||||
exclude: item.exclude,
|
exclude: item.exclude,
|
||||||
publish_time: item.publish_time,
|
|
||||||
seeders: item.seeders,
|
|
||||||
size_range: item.size_range,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
customRules.value = [...customRules.value, ...newCustomRules] // 合并已有的和新导入的规则
|
} catch (e) {
|
||||||
} else if (importCodeType.value === 'group') {
|
console.error(e)
|
||||||
// 将导入的代码转换为规则卡片,并追加到已有的 filterRuleGroups
|
}
|
||||||
const newFilterRuleGroups = JSON.parse(importCodeString.value).map((item: any) => {
|
}
|
||||||
|
|
||||||
|
// 赋值规则组,避免存在多余的属性
|
||||||
|
function extractFilterRuleGroups(value: any) {
|
||||||
|
try {
|
||||||
|
return value.map((item: any) => {
|
||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
rule_string: item.rule_string,
|
rule_string: item.rule_string,
|
||||||
@@ -207,12 +264,28 @@ watchEffect(() => {
|
|||||||
category: item.category,
|
category: item.category,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
filterRuleGroups.value = [...filterRuleGroups.value, ...newFilterRuleGroups] // 合并已有的和新导入的规则
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
}
|
||||||
$toast.error('规则导入失败!')
|
|
||||||
|
function validateValueAgainstInterface(value: any, interfaceDefinition: any): boolean {
|
||||||
|
console.log(value)
|
||||||
|
console.log(interfaceDefinition)
|
||||||
|
try {
|
||||||
|
// 循环判断是否命中全部接口定义,暂时只检查是否存在,不检查是否多出
|
||||||
|
for (const key in interfaceDefinition.value) {
|
||||||
|
if (value[key] === undefined) {
|
||||||
|
$toast.error(`导入规则失败!输入了不符合要求的数据!`)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
return true
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 规则变化时赋值
|
// 规则变化时赋值
|
||||||
function onRuleChange(rule: CustomRule, id: string) {
|
function onRuleChange(rule: CustomRule, id: string) {
|
||||||
@@ -368,12 +441,17 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
</VForm>
|
</VForm>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
<VDialog v-model="importCodeDialog" width="60rem" scrollable>
|
|
||||||
<ImportCodeDialog v-model="importCodeString" title="导入规则" @close="importCodeDialog = false" />
|
|
||||||
</VDialog>
|
|
||||||
</VCard>
|
</VCard>
|
||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
|
<ImportCodeDialog
|
||||||
|
v-if="importCodeDialog"
|
||||||
|
v-model="importCodeDialog"
|
||||||
|
:title="`导入${importCodeType === 'custom' ? '自定义规则' : '规则组'}`"
|
||||||
|
:dataType="importCodeType"
|
||||||
|
@close="importCodeDialog = false"
|
||||||
|
@save="saveCodeString"
|
||||||
|
/>
|
||||||
<VRow>
|
<VRow>
|
||||||
<VCol cols="12">
|
<VCol cols="12">
|
||||||
<VCard>
|
<VCard>
|
||||||
|
|||||||
Reference in New Issue
Block a user