style: Update CustomRuleCard.vue to include rule name field

This commit is contained in:
jxxghp
2024-08-11 17:07:51 +08:00
parent 790a8bdb9a
commit 14afe59eeb
3 changed files with 256 additions and 7 deletions

View File

@@ -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="包含" />

View File

@@ -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>

View File

@@ -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>