Merge pull request #257 from Aqr-K/v2-rulessettings

This commit is contained in:
jxxghp
2024-11-29 18:32:28 +08:00
committed by GitHub
3 changed files with 165 additions and 67 deletions
+36 -17
View File
@@ -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>
+5 -4
View File
@@ -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>
+105 -27
View File
@@ -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>