Merge pull request #183 from Aqr-K/dev

This commit is contained in:
jxxghp
2024-09-14 17:59:59 +08:00
committed by GitHub
6 changed files with 165 additions and 11 deletions

View File

@@ -1,15 +1,25 @@
<script lang="ts" setup>
import { CustomRule } from '@/api/types'
import { useToast } from 'vue-toast-notification'
import filter_svg from '@images/svg/filter.svg'
// 输入参数
const props = defineProps({
// 单条规则
rule: {
type: Object as PropType<CustomRule>,
required: true,
},
// 所有规则
rules: {
type: Array as PropType<CustomRule[]>,
required: true,
},
})
// 提示框
const $toast = useToast()
// 定义触发的自定义事件
const emit = defineEmits(['close', 'change'])
@@ -43,6 +53,30 @@ function openRuleInfoDialog() {
// 保存详情数据
function saveRuleInfo() {
// 有空值
if (!ruleId.value && !ruleName.value) {
if (!ruleId.value && ruleName.value) {
$toast.error('规则ID不能为空')
}
if (ruleId.value && !ruleName.value) {
$toast.error('规则名称不能为空')
}
if (!ruleId.value && !ruleName.value){
$toast.error('规则ID和规则名称不能为空')
}
return
}
// ID已存在
if (ruleId.value !== props.rule.id && props.rules.find((rule) => rule.id === ruleId.value)) {
$toast.error(`规则ID【${ruleId.value}】已存在,请替换`)
return
}
// 规则名称已存在
if (ruleName.value !== props.rule.name && props.rules.find((rule) => rule.name === ruleName.value)) {
$toast.error(`规则名称【${ruleName.value}】已存在,请替换`)
return
}
// 保存数据
ruleInfoDialog.value = false
ruleInfo.value.id = ruleId.value
ruleInfo.value.name = ruleName.value
@@ -78,18 +112,20 @@ function onClose() {
<VTextField
v-model="ruleId"
label="规则ID"
placeholder="规则编码"
placeholder="必填不可与其他规则ID重名"
hint="字符与数字组合,不能含空格"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
<VTextField
v-model="ruleName"
label="规则名称"
placeholder="名"
placeholder="必填;不可与其他规则名称重名"
hint="使用别名便于区分规则"
persistent-hint
active
/>
</VCol>
<VCol cols="12">
@@ -99,6 +135,7 @@ function onClose() {
label="包含"
hint="必须包含的关键字或正则表达式,多个值使用|分隔"
persistent-hint
active
/>
</VCol>
<VCol cols="12">
@@ -108,6 +145,7 @@ function onClose() {
label="排除"
hint="不能包含的关键字或正则表达式,多个值使用|分隔"
persistent-hint
active
/>
</VCol>
<VCol cols="6">
@@ -117,6 +155,7 @@ function onClose() {
label="资源体积MB"
hint="最小资源文件体积或文件体积范围"
persistent-hint
active
/>
</VCol>
<VCol cols="6">
@@ -126,6 +165,7 @@ function onClose() {
label="做种人数"
hint="最小做种人数或做种人数范围"
persistent-hint
active
/>
</VCol>
<VCol cols="6">
@@ -135,6 +175,7 @@ function onClose() {
label="发布时间(分钟)"
hint="距离资源发布的最小时间间隔"
persistent-hint
active
/>
</VCol>
</VRow>

View File

@@ -2,12 +2,14 @@
import api from '@/api'
import { formatFileSize } from '@/@core/utils/formatters'
import { DownloaderConf } from '@/api/types'
import { useToast } from 'vue-toast-notification'
import type { DownloaderInfo } from '@/api/types'
import qbittorrent_image from '@images/logos/qbittorrent.png'
import transmission_image from '@images/logos/transmission.png'
// 定义输入
const props = defineProps({
// 单个下载器
downloader: {
type: Object as PropType<DownloaderConf>,
required: true,
@@ -17,11 +19,19 @@ const props = defineProps({
type: Boolean,
default: true,
},
// 所有下载器
downloaders: {
type: Array as PropType<DownloaderConf[]>,
required: true,
},
})
// 定义触发的自定义事件
const emit = defineEmits(['close', 'done', 'change'])
// 提示框
const $toast = useToast()
// timeout定时器
let timeoutTimer: NodeJS.Timeout | undefined = undefined
@@ -81,6 +91,17 @@ function openDownloaderInfoDialog() {
// 保存详情数据
function saveDownloaderInfo() {
// 为空不保存,跳出警告框
if (!downloaderName.value) {
$toast.error('名称不能为空,请输入后再确定')
return
}
// 重名判断
if (props.downloaders.some(item => item.name === downloaderName.value && item!== props.downloader)) {
$toast.error(`${downloaderName.value}】已存在,请替换为其他名称`)
return
}
// 执行保存
downloaderInfoDialog.value = false
downloaderInfo.value.name = downloaderName.value
emit('change', downloaderInfo.value)
@@ -162,9 +183,10 @@ onUnmounted(() => {
<VTextField
v-model="downloaderName"
label="名称"
placeholder="名"
placeholder="必填;不可与其他名称重名"
hint="下载器的别名"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -174,6 +196,7 @@ onUnmounted(() => {
placeholder="http(s)://ip:port"
hint="服务端地址格式http(s)://ip:port"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -183,6 +206,7 @@ onUnmounted(() => {
placeholder="admin"
hint="登录使用的用户名"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -192,6 +216,7 @@ onUnmounted(() => {
label="密码"
hint="登录使用的密码"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -200,6 +225,7 @@ onUnmounted(() => {
label="自动分类管理"
hint="由下载器自动管理分类和下载目录"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -208,6 +234,7 @@ onUnmounted(() => {
label="顺序下载"
hint="按顺序依次下载文件"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -216,6 +243,7 @@ onUnmounted(() => {
label="强制继续"
hint="强制继续、强制上传模式"
persistent-hint
active
/>
</VCol>
</VRow>
@@ -224,9 +252,10 @@ onUnmounted(() => {
<VTextField
v-model="downloaderName"
label="名称"
placeholder="名"
placeholder="必填;不可与其他名称重名"
hint="下载器的别名"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -236,6 +265,7 @@ onUnmounted(() => {
placeholder="http(s)://ip:port"
hint="服务端地址格式http(s)://ip:port"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -245,6 +275,7 @@ onUnmounted(() => {
placeholder="admin"
hint="登录使用的用户名"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -254,6 +285,7 @@ onUnmounted(() => {
label="密码"
hint="登录使用的密码"
persistent-hint
active
/>
</VCol>
</VRow>

View File

@@ -9,14 +9,22 @@ import filter_group_svg from '@images/svg/filter-group.svg'
// 输入参数
const props = defineProps({
// 单个规则组
group: {
type: Object as PropType<FilterRuleGroup>,
required: true,
},
// 所有规则组
groups: {
type: Array as PropType<FilterRuleGroup[]>,
required: true,
},
// 媒体类型字典
categories: {
type: Object as PropType<{ [key: string]: any }>,
required: true,
},
// 自定义规则列表
custom_rules: Array as PropType<CustomRule[]>,
})
@@ -171,6 +179,17 @@ function opengroupInfoDialog() {
// 保存详情数据
function savegroupInfo() {
// 为空
if (!groupName.value) {
$toast.error('规则组名称不能为空')
return
}
// 重名判断
if (props.groups.some(item => item.name === groupName.value && item !== props.group)) {
$toast.error(`规则组名称【${groupName.value}】已存在,请替换`)
return
}
// 保存
groupInfoDialog.value = false
groupInfo.value.name = groupName.value
// 更新到 groupInfo的rule_string
@@ -209,13 +228,34 @@ function onClose() {
<VCardText>
<VRow>
<VCol cols="12" md="6">
<VTextField v-model="groupName" label="规则组名称" />
<VTextField
v-model="groupName"
label="规则组名称"
placeholder="必填;不可与其他规则组重名"
hint="自定义规则组名称"
persistent-hint
active
/>
</VCol>
<VCol cols="6" md="3">
<VSelect v-model="groupInfo.media_type" label="适用媒体类型" :items="mediaTypeItems" />
<VSelect
v-model="groupInfo.media_type"
label="适用媒体类型"
:items="mediaTypeItems"
hint="选择规则组适用的媒体类型"
persistent-hint
active
/>
</VCol>
<VCol cols="6" md="3">
<VSelect v-model="groupInfo.category" :items="getCategories" label="适用媒体类别" />
<VSelect
v-model="groupInfo.category"
:items="getCategories"
label="适用媒体类别"
hint="选择规则组适用的媒体类别"
persistent-hint
active
/>
</VCol>
</VRow>
</VCardText>

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import { MediaServerConf, MediaServerLibrary, MediaStatistic } from '@/api/types'
import { useToast } from 'vue-toast-notification'
import emby_image from '@images/logos/emby.png'
import jellyfin_image from '@images/logos/jellyfin.png'
import plex_image from '@images/logos/plex.png'
@@ -7,12 +8,21 @@ import api from '@/api'
// 定义输入
const props = defineProps({
// 单个媒体服务器
mediaserver: {
type: Object as PropType<MediaServerConf>,
required: true,
},
// 所有媒体服务器
mediaservers: {
type: Array as PropType<MediaServerConf[]>,
required: true
}
})
// 提示框
const $toast = useToast()
// 定义触发的自定义事件
const emit = defineEmits(['close', 'done', 'change'])
@@ -62,6 +72,17 @@ function openMediaServerInfoDialog() {
// 保存详情数据
function saveMediaServerInfo() {
// 为空不保存,跳出警告框
if (!mediaServerName.value) {
$toast.error('名称不能为空,请输入后再确定')
return
}
// 重名判断
if (props.mediaservers.some(item => item.name === mediaServerName.value && item!== props.mediaserver)) {
$toast.error(`${mediaServerName.value}】已存在,请替换为其他名称`)
return
}
// 执行保存
mediaServerInfoDialog.value = false
mediaServerInfo.value.name = mediaServerName.value
emit('change', mediaServerInfo.value)
@@ -169,9 +190,10 @@ onMounted(() => {
<VTextField
v-model="mediaServerName"
label="名称"
placeholder="名"
placeholder="必填;不可与其他名称重名"
hint="媒体服务器的别名"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -181,6 +203,7 @@ onMounted(() => {
placeholder="http(s)://ip:port"
hint="服务端地址格式http(s)://ip:port"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -190,6 +213,7 @@ onMounted(() => {
placeholder="http(s)://domain:port"
hint="跳转播放页面使用的地址格式http(s)://domain:port"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -198,6 +222,7 @@ onMounted(() => {
label="API密钥"
hint="Emby设置->高级->API密钥中生成的密钥"
persistent-hint
active
/>
</VCol>
</VRow>
@@ -206,9 +231,10 @@ onMounted(() => {
<VTextField
v-model="mediaServerName"
label="名称"
placeholder="名"
placeholder="必填;不可与其他名称重名"
hint="媒体服务器的别名"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -218,6 +244,7 @@ onMounted(() => {
placeholder="http(s)://ip:port"
hint="服务端地址格式http(s)://ip:port"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -227,6 +254,7 @@ onMounted(() => {
placeholder="http(s)://domain:port"
hint="跳转播放页面使用的地址格式http(s)://domain:port"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -235,6 +263,7 @@ onMounted(() => {
label="API密钥"
hint="Jellyfin设置->高级->API密钥中生成的密钥"
persistent-hint
active
/>
</VCol>
</VRow>
@@ -243,9 +272,10 @@ onMounted(() => {
<VTextField
v-model="mediaServerName"
label="名称"
placeholder="名"
placeholder="必填;不可与其他名称重名"
hint="媒体服务器的别名"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -255,6 +285,7 @@ onMounted(() => {
placeholder="http(s)://ip:port"
hint="服务端地址格式http(s)://ip:port"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -264,6 +295,7 @@ onMounted(() => {
placeholder="http(s)://domain:port"
hint="跳转播放页面使用的地址格式http(s)://domain:port"
persistent-hint
active
/>
</VCol>
<VCol cols="12" md="6">
@@ -272,6 +304,7 @@ onMounted(() => {
label="X-Plex-Token"
hint="浏览器F12->网络从Plex请求URL中获取的X-Plex-Token"
persistent-hint
active
/>
</VCol>
</VRow>
@@ -285,6 +318,7 @@ onMounted(() => {
multiple
hint="只有选中的媒体库才会被同步"
persistent-hint
active
append-inner-icon="mdi-refresh"
@click:append-inner="loadLibrary(mediaServerInfo.name)"
/>

View File

@@ -177,7 +177,11 @@ onMounted(() => {
:component-data="{ 'class': 'grid gap-3 grid-customrule-card' }"
>
<template #item="{ element }">
<CustomerRuleCard :rule="element" @close="removeCustomRule(element)" @change="onRuleChange" />
<CustomerRuleCard
:rule="element"
:rules="customRules"
@close="removeCustomRule(element)"
@change="onRuleChange" />
</template>
</draggable>
</VCardText>
@@ -206,6 +210,7 @@ onMounted(() => {
<template #item="{ element }">
<FilterRuleGroupCard
:group="element"
:groups="filterRuleGroups"
:custom_rules="customRules"
:categories="mediaCategories"
@close="removeFilterRuleGroup(element)"

View File

@@ -220,6 +220,7 @@ onDeactivated(() => {
<template #item="{ element }">
<DownloaderCard
:downloader="element"
:downloaders="downloaders"
@close="removeDownloader(element)"
@change="onDownloaderChange"
:allow-refresh="isRequest"
@@ -268,6 +269,7 @@ onDeactivated(() => {
<template #item="{ element }">
<MediaServerCard
:mediaserver="element"
:mediaservers="mediaServers"
@close="removeMediaServer(element)"
@change="onMediaServerChange"
/>