mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-22 00:39:43 +08:00
style: Update CustomRuleCard.vue to include rule name field
This commit is contained in:
@@ -26,15 +26,20 @@ const ruleInfo = ref<CustomRule>({
|
||||
publish_time: '',
|
||||
})
|
||||
|
||||
// 规则名称
|
||||
const ruleName = ref('')
|
||||
|
||||
// 打开详情弹窗
|
||||
function openRuleInfoDialog() {
|
||||
ruleInfo.value = props.rule
|
||||
ruleName.value = props.rule.name
|
||||
ruleInfoDialog.value = true
|
||||
}
|
||||
|
||||
// 保存详情数据
|
||||
function saveRuleInfo() {
|
||||
ruleInfoDialog.value = false
|
||||
ruleInfo.value.name = ruleName.value
|
||||
emit('change', ruleInfo.value)
|
||||
}
|
||||
|
||||
@@ -63,7 +68,7 @@ function onClose() {
|
||||
<VForm>
|
||||
<VRow>
|
||||
<VCol cols="12">
|
||||
<VTextField v-model="ruleInfo.name" label="规则名称" />
|
||||
<VTextField v-model="ruleName" label="规则名称" />
|
||||
</VCol>
|
||||
<VCol cols="12">
|
||||
<VTextField v-model="ruleInfo.include" placeholder="关键字/正则表达式" label="包含" />
|
||||
|
||||
@@ -1,2 +1,239 @@
|
||||
<script setup lang="ts"></script>
|
||||
<template></template>
|
||||
<script lang="ts" setup>
|
||||
import draggable from 'vuedraggable'
|
||||
import { copyToClipboard } from '@/@core/utils/navigator'
|
||||
import { FilterRuleGroup } from '@/api/types'
|
||||
import FilterRuleCard from '@/components/cards/FilterRuleCard.vue'
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import ImportCodeDialog from '@/components/dialog/ImportCodeDialog.vue'
|
||||
|
||||
// 输入参数
|
||||
const props = defineProps({
|
||||
group: {
|
||||
type: Object as PropType<FilterRuleGroup>,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
// 规则卡片类型
|
||||
interface FilterCard {
|
||||
// 优先级
|
||||
pri: string
|
||||
// 已选规则
|
||||
rules: string[]
|
||||
}
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast()
|
||||
|
||||
// 定义触发的自定义事件
|
||||
const emit = defineEmits(['close', 'change'])
|
||||
|
||||
// 规则详情弹窗
|
||||
const groupInfoDialog = ref(false)
|
||||
|
||||
// 规则详情
|
||||
const groupInfo = ref<FilterRuleGroup>({
|
||||
name: '',
|
||||
rule_string: '',
|
||||
media_type: '',
|
||||
})
|
||||
|
||||
// 规则组名称
|
||||
const groupName = ref('')
|
||||
|
||||
// 媒体类型字典
|
||||
const mediaTypeItems = [
|
||||
{ title: '通用', value: '' },
|
||||
{ title: '电影', value: '电影' },
|
||||
{ title: '电视剧', value: '电视剧' },
|
||||
]
|
||||
|
||||
// 规则组规则卡片列表
|
||||
const filterRuleCards = ref<FilterCard[]>([])
|
||||
|
||||
// 导入代码弹窗
|
||||
const importCodeDialog = ref(false)
|
||||
|
||||
// 导入的代码
|
||||
const importCodeString = ref('')
|
||||
|
||||
// 更新规则卡片的值
|
||||
function updateFilterCardValue(pri: string, rules: string[]) {
|
||||
const card = filterRuleCards.value.find(card => card.pri === pri)
|
||||
if (card) card.rules = rules
|
||||
}
|
||||
|
||||
// 移除卡片
|
||||
function filterCardClose(pri: string) {
|
||||
// 将pri对应的卡片从列表中删除,并更新剩余卡片的序号
|
||||
const updatedCards = filterRuleCards.value
|
||||
.filter(card => card.pri !== pri)
|
||||
.map((card, index) => {
|
||||
card.pri = (index + 1).toString()
|
||||
return card
|
||||
})
|
||||
// 更新 filterRuleCards.value
|
||||
filterRuleCards.value = updatedCards
|
||||
}
|
||||
|
||||
// 分享规则
|
||||
function shareRules() {
|
||||
// 有值才处理
|
||||
if (filterRuleCards.value.length === 0) return
|
||||
|
||||
// 将卡片规则接装为字符串
|
||||
const value = filterRuleCards.value
|
||||
.filter(card => card.rules.length > 0)
|
||||
.map(card => card.rules.join('&'))
|
||||
.join('>')
|
||||
|
||||
// 复制到剪贴板
|
||||
try {
|
||||
copyToClipboard(value)
|
||||
$toast.success('优先级规则已复制到剪贴板')
|
||||
} catch (error) {
|
||||
$toast.error('优先级规则复制失败!')
|
||||
}
|
||||
}
|
||||
|
||||
// 导入规则
|
||||
async function importRules() {
|
||||
importCodeString.value = ''
|
||||
importCodeDialog.value = true
|
||||
}
|
||||
|
||||
// 监听导入代码变化
|
||||
watchEffect(() => {
|
||||
if (!importCodeString.value) return
|
||||
// 导入代码需要以空格开头和结束,没有则拼接
|
||||
if (!importCodeString.value.startsWith(' ')) importCodeString.value = ` ${importCodeString.value}`
|
||||
if (!importCodeString.value.endsWith(' ')) importCodeString.value = `${importCodeString.value} `
|
||||
// 将导入的代码转换为规则卡片
|
||||
const groups = importCodeString.value.split('>')
|
||||
filterRuleCards.value = groups.map((group: string, index: number) => {
|
||||
return {
|
||||
pri: (index + 1).toString(),
|
||||
rules: group.split('&'),
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 增加卡片
|
||||
function addFilterCard() {
|
||||
// 优先级
|
||||
const pri = (filterRuleCards.value.length + 1).toString()
|
||||
|
||||
// 新卡片
|
||||
const newCard: FilterCard = { pri, rules: [] }
|
||||
|
||||
// 添加到列表
|
||||
filterRuleCards.value.push(newCard)
|
||||
}
|
||||
|
||||
// 根据列表的拖动顺序更新优先级
|
||||
function dragOrderEnd() {
|
||||
filterRuleCards.value.map((card, index) => {
|
||||
card.pri = (index + 1).toString()
|
||||
return card
|
||||
})
|
||||
}
|
||||
|
||||
// 打开详情弹窗
|
||||
function opengroupInfoDialog() {
|
||||
groupInfo.value = props.group
|
||||
groupName.value = props.group.name
|
||||
if (props.group.rule_string) {
|
||||
filterRuleCards.value = props.group.rule_string.split('>').map((group: string, index: number) => {
|
||||
return {
|
||||
pri: (index + 1).toString(),
|
||||
rules: group.split('&'),
|
||||
}
|
||||
})
|
||||
}
|
||||
groupInfoDialog.value = true
|
||||
}
|
||||
|
||||
// 保存详情数据
|
||||
function savegroupInfo() {
|
||||
groupInfoDialog.value = false
|
||||
groupInfo.value.name = groupName.value
|
||||
// 更新到 groupInfo的rule_string
|
||||
groupInfo.value.rule_string = filterRuleCards.value
|
||||
.filter(card => card.rules.length > 0)
|
||||
.map(card => card.rules.join('&'))
|
||||
.join('>')
|
||||
emit('change', groupInfo.value)
|
||||
}
|
||||
|
||||
// 按钮点击
|
||||
function onClose() {
|
||||
emit('close')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<VCard variant="tonal" @click="opengroupInfoDialog">
|
||||
<DialogCloseBtn @click="onClose" />
|
||||
<VCardText class="flex justify-space-between align-center gap-3">
|
||||
<div class="align-self-start">
|
||||
<h5 class="text-h6 mb-1">{{ props.group.name }}</h5>
|
||||
<div class="text-body-1 mb-3">{{ props.group.media_type || '通用' }}</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<VDialog v-model="groupInfoDialog" scrollable max-width="80rem">
|
||||
<VCard :title="`${props.group.name} - 配置`" class="rounded-t">
|
||||
<DialogCloseBtn v-model="groupInfoDialog" />
|
||||
<VDivider />
|
||||
<VCardText>
|
||||
<VRow>
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField v-model="groupName" label="规则组名称" />
|
||||
</VCol>
|
||||
<VCol cols="12" md="6">
|
||||
<VSelect v-model="groupInfo.media_type" label="适用媒体类型" :items="mediaTypeItems" />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<draggable
|
||||
v-model="filterRuleCards"
|
||||
handle=".cursor-move"
|
||||
item-key="pri"
|
||||
tag="div"
|
||||
@end="dragOrderEnd"
|
||||
:component-data="{ 'class': 'grid gap-3 grid-filterrule-card' }"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<FilterRuleCard
|
||||
:pri="element.pri"
|
||||
:maxpri="filterRuleCards.length.toString()"
|
||||
:rules="element.rules"
|
||||
@changed="updateFilterCardValue"
|
||||
@close="filterCardClose(element.pri)"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
<div class="text-center" v-if="filterRuleCards.length == 0">请添加或导入规则</div>
|
||||
</VCardText>
|
||||
<VCardActions class="pt-3">
|
||||
<VBtn color="primary" variant="tonal" @click="addFilterCard">
|
||||
<VIcon icon="mdi-plus" />
|
||||
</VBtn>
|
||||
<VBtn color="success" variant="tonal" @click="importRules">
|
||||
<VIcon icon="mdi-import" />
|
||||
</VBtn>
|
||||
<VBtn color="info" variant="tonal" @click="shareRules">
|
||||
<VIcon icon="mdi-share" />
|
||||
</VBtn>
|
||||
<VSpacer />
|
||||
<VBtn @click="savegroupInfo" variant="elevated" prepend-icon="mdi-content-save" class="px-5"> 确定 </VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
<VDialog v-model="importCodeDialog" width="60rem" scrollable>
|
||||
<ImportCodeDialog v-model="importCodeString" title="导入优先级规则" @close="importCodeDialog = false" />
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -22,8 +22,9 @@ const $toast = useToast()
|
||||
|
||||
// 种子优先规则下拉框
|
||||
const TorrentPriorityItems = [
|
||||
{ title: '站点优先', value: 'site' },
|
||||
{ title: '做种数优先', value: 'seeder' },
|
||||
{ title: '站点排序优先', value: 'site' },
|
||||
{ title: '站点上传量优先', value: 'upload' },
|
||||
{ title: '资源做种数优先', value: 'seeder' },
|
||||
]
|
||||
|
||||
// 加载自定义规则
|
||||
@@ -105,6 +106,12 @@ function removeFilterRuleGroup(rule: FilterRuleGroup) {
|
||||
if (index !== -1) filterRuleGroups.value.splice(index, 1)
|
||||
}
|
||||
|
||||
// 规则组变化时赋值
|
||||
function changeRuleGroup(group: FilterRuleGroup) {
|
||||
const index = filterRuleGroups.value.findIndex(item => item.name === group.name)
|
||||
if (index !== -1) filterRuleGroups.value[index] = group
|
||||
}
|
||||
|
||||
// 查询种子优先规则
|
||||
async function queryTorrentPriority() {
|
||||
try {
|
||||
@@ -181,10 +188,10 @@ onMounted(() => {
|
||||
handle=".cursor-move"
|
||||
item-key="name"
|
||||
tag="div"
|
||||
:component-data="{ 'class': 'grid gap-3 grid-filterrule-card' }"
|
||||
:component-data="{ 'class': 'grid gap-3 grid-app-card' }"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<FilterRuleGroupCard :filterrule="element" @close="removeFilterRuleGroup(element)" />
|
||||
<FilterRuleGroupCard :group="element" @close="removeFilterRuleGroup(element)" @change="changeRuleGroup" />
|
||||
</template>
|
||||
</draggable>
|
||||
</VCardText>
|
||||
|
||||
Reference in New Issue
Block a user