mirror of
https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-10 00:52:40 +00:00
UI添加两个过滤器: 区域过滤器和类型过滤器
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<v-icon left color="primary">flag</v-icon>
|
||||
区域过滤
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon>
|
||||
<v-btn icon @click="$emit('deleteProcess', idx)">
|
||||
<v-icon color="error">mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
<v-dialog>
|
||||
@@ -18,7 +18,7 @@
|
||||
区域过滤器
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
根据区域过滤节点,不选则默认保留所有节点。
|
||||
根据区域过滤节点,至少需要保留一个区域!
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
@@ -67,11 +67,25 @@ const regions = [
|
||||
}
|
||||
];
|
||||
export default {
|
||||
props: ["args"],
|
||||
data: function () {
|
||||
return {
|
||||
idx: this.$vnode.key,
|
||||
regions,
|
||||
selection: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.selection = this.args || [];
|
||||
},
|
||||
watch: {
|
||||
selection() {
|
||||
this.$emit("dataChanged", {
|
||||
idx: this.idx,
|
||||
type: "Region Filter",
|
||||
args: this.selection
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
91
web/src/components/TypeFilter.vue
Normal file
91
web/src/components/TypeFilter.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<v-card class="ml-1 mr-1 mb-1 mt-1">
|
||||
<v-card-title>
|
||||
<v-icon left color="primary">cloud_circle</v-icon>
|
||||
节点类型过滤
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click="$emit('deleteProcess', idx)">
|
||||
<v-icon color="error">mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
<v-dialog>
|
||||
<template #activator="{on}">
|
||||
<v-btn icon v-on="on">
|
||||
<v-icon>help</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card>
|
||||
<v-card-title class="headline">
|
||||
节点类型过滤器
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
根据节点类型过滤节点,至少需要保留一种类型!
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-chip-group multiple active-class="primary accent-4" v-model="selection" column>
|
||||
<v-chip
|
||||
class="ma-2"
|
||||
v-for="type in types"
|
||||
label
|
||||
:key="type.name"
|
||||
:value="type.value"
|
||||
>
|
||||
{{ type.name }}
|
||||
</v-chip>
|
||||
</v-chip-group>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const types = [
|
||||
{
|
||||
name: "Shadowsocks",
|
||||
value: "ss"
|
||||
},
|
||||
{
|
||||
name: "Shadowsocks R",
|
||||
value: "ssr"
|
||||
},
|
||||
{
|
||||
name: "V2Ray",
|
||||
value: "vmess"
|
||||
},
|
||||
{
|
||||
name: "Trojan",
|
||||
value: "trojan"
|
||||
},
|
||||
{
|
||||
name: "HTTP",
|
||||
value: "http"
|
||||
}
|
||||
];
|
||||
export default {
|
||||
props: ['args'],
|
||||
data: function () {
|
||||
return {
|
||||
idx: this.$vnode.key,
|
||||
types,
|
||||
selection: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.selection = this.args || [];
|
||||
},
|
||||
watch: {
|
||||
selection() {
|
||||
this.$emit("dataChanged", {
|
||||
idx: this.idx,
|
||||
type: "Type Filter",
|
||||
args: this.selection
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -23,8 +23,12 @@
|
||||
</v-form>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click="save"><v-icon>save_alt</v-icon></v-btn>
|
||||
<v-btn icon @click="discard"><v-icon>settings_backup_restore</v-icon></v-btn>
|
||||
<v-btn icon @click="save">
|
||||
<v-icon>save_alt</v-icon>
|
||||
</v-btn>
|
||||
<v-btn icon @click="discard">
|
||||
<v-icon>settings_backup_restore</v-icon>
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
<v-card class="mb-4">
|
||||
@@ -44,6 +48,7 @@
|
||||
<v-col>
|
||||
<v-radio label="删除" value="REMOVE"/>
|
||||
</v-col>
|
||||
<v-col></v-col>
|
||||
</v-row>
|
||||
</v-radio-group>
|
||||
<v-radio-group
|
||||
@@ -123,25 +128,69 @@
|
||||
</v-item-group>
|
||||
</v-form>
|
||||
</v-card>
|
||||
<v-card class="mb-4">
|
||||
<v-card class="mb-4" id="processors">
|
||||
<v-subheader>
|
||||
节点操作
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon>
|
||||
<v-icon color="primary">add_circle</v-icon>
|
||||
</v-btn>
|
||||
<v-dialog scrollable v-model="dialog">
|
||||
<template #activator="{on}">
|
||||
<v-btn icon v-on="on">
|
||||
<v-icon color="primary">add_circle</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card>
|
||||
<v-card-title>选择节点操作</v-card-title>
|
||||
<v-divider></v-divider>
|
||||
<v-card-text>
|
||||
<v-radio-group dense v-model="selectedProcess">
|
||||
<v-radio v-for="(k, idx) in Object.keys(availableProcessors)" :label="availableProcessors[k].name"
|
||||
:key="idx" :value="k"></v-radio>
|
||||
</v-radio-group>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="primary" text @click="addProcess(selectedProcess)">确认</v-btn>
|
||||
<v-btn text @click="dialog = false">取消</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
</v-subheader>
|
||||
<v-divider></v-divider>
|
||||
<component v-for="(p, idx) in processors"
|
||||
:is="p.component"
|
||||
:key="idx"
|
||||
:args="p.args"
|
||||
@dataChanged="dataChanged"
|
||||
@deleteProcess="deleteProcess"
|
||||
>
|
||||
</component>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {showError, showInfo} from "@/utils";
|
||||
import TypeFilter from "@/components/TypeFilter";
|
||||
import RegionFilter from "@/components/RegionFilter";
|
||||
|
||||
const AVAILABLE_PROCESSORS = {
|
||||
"Type Filter": {
|
||||
component: "TypeFilter",
|
||||
name: "类型过滤器"
|
||||
},
|
||||
"Region Filter": {
|
||||
component: "RegionFilter",
|
||||
name: "区域过滤器"
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {RegionFilter, TypeFilter},
|
||||
data: function () {
|
||||
return {
|
||||
selectedProcess: null,
|
||||
dialog: false,
|
||||
validations: {
|
||||
nameRules: [
|
||||
v => !!v || "订阅名称不能为空!",
|
||||
@@ -173,6 +222,20 @@ export default {
|
||||
this.$store.commit("SET_NAV_TITLE", sub.name ? `订阅编辑 -- ${sub.name}` : "新建订阅");
|
||||
this.options = loadSubscription(this.options, sub);
|
||||
},
|
||||
computed: {
|
||||
availableProcessors() {
|
||||
return AVAILABLE_PROCESSORS;
|
||||
},
|
||||
|
||||
processors() {
|
||||
return this.options.process.map(p => {
|
||||
return {
|
||||
component: AVAILABLE_PROCESSORS[p.type].component,
|
||||
args: p.args
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
if (this.options.name && this.options.url) {
|
||||
@@ -198,6 +261,19 @@ export default {
|
||||
|
||||
discard() {
|
||||
this.$router.back();
|
||||
},
|
||||
|
||||
dataChanged(content) {
|
||||
this.options.process[content.idx].args = content.args;
|
||||
},
|
||||
|
||||
addProcess(type) {
|
||||
this.options.process.push({type});
|
||||
this.dialog = false;
|
||||
},
|
||||
|
||||
deleteProcess(key) {
|
||||
this.options.process.splice(key, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,7 +282,8 @@ function loadSubscription(options, sub) {
|
||||
options = {
|
||||
...options,
|
||||
name: sub.name,
|
||||
url: sub.url
|
||||
url: sub.url,
|
||||
process: []
|
||||
}
|
||||
// flag
|
||||
for (const p of (sub.process || [])) {
|
||||
@@ -220,6 +297,8 @@ function loadSubscription(options, sub) {
|
||||
case 'Set Property Operator':
|
||||
options[p.args[0]] = p.args[1] ? "FORCE_OPEN" : "FORCE_CLOSE";
|
||||
break
|
||||
default:
|
||||
options.process.push(p);
|
||||
}
|
||||
}
|
||||
return options;
|
||||
@@ -253,9 +332,9 @@ function buildSubscription(options) {
|
||||
});
|
||||
}
|
||||
}
|
||||
// for (const p of options.process) {
|
||||
//
|
||||
// }
|
||||
for (const p of options.process) {
|
||||
sub.process.push(p);
|
||||
}
|
||||
return sub;
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user