Working on sub-editor

This commit is contained in:
Peng-YM 2020-08-28 15:00:45 +08:00
parent 8b4c972f77
commit a71914676e
17 changed files with 768 additions and 91 deletions

View File

@ -20,12 +20,22 @@
</component>
<component name="ChangeListManager">
<list default="true" id="8b97a098-48b2-4e64-a9ef-522fe2d30b52" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/../web/src/css/app.css" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../web/src/components/KeywordFilter.vue" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../web/src/components/KeywordRename.vue" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../web/src/components/KeywordSort.vue" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../web/src/components/RegexFilter.vue" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../web/src/components/RegexRename.vue" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../web/src/components/RegionFilter.vue" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../web/src/components/Sort.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/../web/package-lock.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/../web/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/App.vue" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/App.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/components/BottomNav.vue" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/components/BottomNav.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/components/TopToolbar.vue" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/components/TopToolbar.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/views/ProxyList.vue" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/components/ProxyList.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/components/ProxyList.vue" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/components/ProxyList.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/main.js" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/main.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/router/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/router/index.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/store/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/store/index.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/views/SubEditor.vue" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/views/SubEditor.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../web/src/views/Subscription.vue" beforeDir="false" afterPath="$PROJECT_DIR$/../web/src/views/Subscription.vue" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
@ -82,7 +92,7 @@
<workItem from="1598235270977" duration="126000" />
<workItem from="1598235738199" duration="3192000" />
<workItem from="1598323737081" duration="1913000" />
<workItem from="1598442849645" duration="4231000" />
<workItem from="1598442849645" duration="5715000" />
</task>
<servers />
</component>
@ -102,132 +112,132 @@
<option name="oldMeFiltersMigrated" value="true" />
</component>
<component name="WindowStateProjectService">
<state width="1709" height="374" key="GridCell.Tab.0.bottom" timestamp="1598446615905">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.0.bottom" timestamp="1598527987806">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.0.bottom/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358068" />
<state width="1709" height="374" key="GridCell.Tab.0.bottom/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615905" />
<state width="1709" height="374" key="GridCell.Tab.0.bottom/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328168" />
<state width="1709" height="374" key="GridCell.Tab.0.bottom/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987806" />
<state width="1704" height="374" key="GridCell.Tab.0.bottom/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654695" />
<state width="840" height="374" key="GridCell.Tab.0.bottom/70.23.1722.1097@70.23.1722.1097" timestamp="1598324500703" />
<state width="1709" height="374" key="GridCell.Tab.0.center" timestamp="1598446615903">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.0.center" timestamp="1598527987805">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.0.center/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358067" />
<state width="1709" height="374" key="GridCell.Tab.0.center/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615903" />
<state width="1709" height="374" key="GridCell.Tab.0.center/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328167" />
<state width="1709" height="374" key="GridCell.Tab.0.center/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987805" />
<state width="1704" height="374" key="GridCell.Tab.0.center/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654695" />
<state width="840" height="374" key="GridCell.Tab.0.center/70.23.1722.1097@70.23.1722.1097" timestamp="1598324500702" />
<state width="1709" height="374" key="GridCell.Tab.0.left" timestamp="1598446615899">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.0.left" timestamp="1598527987801">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.0.left/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358067" />
<state width="1709" height="374" key="GridCell.Tab.0.left/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615899" />
<state width="1709" height="374" key="GridCell.Tab.0.left/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328167" />
<state width="1709" height="374" key="GridCell.Tab.0.left/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987801" />
<state width="1704" height="374" key="GridCell.Tab.0.left/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654694" />
<state width="840" height="374" key="GridCell.Tab.0.left/70.23.1722.1097@70.23.1722.1097" timestamp="1598324500701" />
<state width="1709" height="374" key="GridCell.Tab.0.right" timestamp="1598446615904">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.0.right" timestamp="1598527987806">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.0.right/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358068" />
<state width="1709" height="374" key="GridCell.Tab.0.right/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615904" />
<state width="1709" height="374" key="GridCell.Tab.0.right/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328168" />
<state width="1709" height="374" key="GridCell.Tab.0.right/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987806" />
<state width="1704" height="374" key="GridCell.Tab.0.right/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654695" />
<state width="840" height="374" key="GridCell.Tab.0.right/70.23.1722.1097@70.23.1722.1097" timestamp="1598324500702" />
<state width="1709" height="374" key="GridCell.Tab.1.bottom" timestamp="1598446615752">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.1.bottom" timestamp="1598527987679">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.1.bottom/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358069" />
<state width="1709" height="374" key="GridCell.Tab.1.bottom/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615752" />
<state width="1709" height="374" key="GridCell.Tab.1.bottom/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328169" />
<state width="1709" height="374" key="GridCell.Tab.1.bottom/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987679" />
<state width="1704" height="374" key="GridCell.Tab.1.bottom/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654696" />
<state width="840" height="374" key="GridCell.Tab.1.bottom/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292666" />
<state width="1709" height="374" key="GridCell.Tab.1.center" timestamp="1598446615751">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.1.center" timestamp="1598527987678">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.1.center/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358069" />
<state width="1709" height="374" key="GridCell.Tab.1.center/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615751" />
<state width="1709" height="374" key="GridCell.Tab.1.center/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328168" />
<state width="1709" height="374" key="GridCell.Tab.1.center/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987678" />
<state width="1704" height="374" key="GridCell.Tab.1.center/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654696" />
<state width="840" height="374" key="GridCell.Tab.1.center/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292666" />
<state width="1709" height="374" key="GridCell.Tab.1.left" timestamp="1598446615751">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.1.left" timestamp="1598527987678">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.1.left/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358069" />
<state width="1709" height="374" key="GridCell.Tab.1.left/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615751" />
<state width="1709" height="374" key="GridCell.Tab.1.left/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328168" />
<state width="1709" height="374" key="GridCell.Tab.1.left/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987678" />
<state width="1704" height="374" key="GridCell.Tab.1.left/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654696" />
<state width="840" height="374" key="GridCell.Tab.1.left/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292665" />
<state width="1709" height="374" key="GridCell.Tab.1.right" timestamp="1598446615752">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.1.right" timestamp="1598527987679">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.1.right/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358069" />
<state width="1709" height="374" key="GridCell.Tab.1.right/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615752" />
<state width="1709" height="374" key="GridCell.Tab.1.right/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328168" />
<state width="1709" height="374" key="GridCell.Tab.1.right/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987679" />
<state width="1704" height="374" key="GridCell.Tab.1.right/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654696" />
<state width="840" height="374" key="GridCell.Tab.1.right/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292666" />
<state width="1709" height="374" key="GridCell.Tab.2.bottom" timestamp="1598446615753">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.2.bottom" timestamp="1598527987679">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.2.bottom/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358071" />
<state width="1709" height="374" key="GridCell.Tab.2.bottom/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615753" />
<state width="1709" height="374" key="GridCell.Tab.2.bottom/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328169" />
<state width="1709" height="374" key="GridCell.Tab.2.bottom/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987679" />
<state width="1704" height="374" key="GridCell.Tab.2.bottom/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654697" />
<state width="840" height="374" key="GridCell.Tab.2.bottom/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292666" />
<state width="1709" height="374" key="GridCell.Tab.2.center" timestamp="1598446615753">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.2.center" timestamp="1598527987679">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.2.center/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358070" />
<state width="1709" height="374" key="GridCell.Tab.2.center/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615753" />
<state width="1709" height="374" key="GridCell.Tab.2.center/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328169" />
<state width="1709" height="374" key="GridCell.Tab.2.center/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987679" />
<state width="1704" height="374" key="GridCell.Tab.2.center/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654696" />
<state width="840" height="374" key="GridCell.Tab.2.center/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292666" />
<state width="1709" height="374" key="GridCell.Tab.2.left" timestamp="1598446615752">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.2.left" timestamp="1598527987679">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.2.left/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358070" />
<state width="1709" height="374" key="GridCell.Tab.2.left/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615752" />
<state width="1709" height="374" key="GridCell.Tab.2.left/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328169" />
<state width="1709" height="374" key="GridCell.Tab.2.left/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987679" />
<state width="1704" height="374" key="GridCell.Tab.2.left/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654696" />
<state width="840" height="374" key="GridCell.Tab.2.left/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292666" />
<state width="1709" height="374" key="GridCell.Tab.2.right" timestamp="1598446615753">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.2.right" timestamp="1598527987679">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.2.right/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358070" />
<state width="1709" height="374" key="GridCell.Tab.2.right/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615753" />
<state width="1709" height="374" key="GridCell.Tab.2.right/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328169" />
<state width="1709" height="374" key="GridCell.Tab.2.right/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987679" />
<state width="1704" height="374" key="GridCell.Tab.2.right/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654697" />
<state width="840" height="374" key="GridCell.Tab.2.right/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292666" />
<state width="1709" height="374" key="GridCell.Tab.3.bottom" timestamp="1598446615755">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.3.bottom" timestamp="1598527987680">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.3.bottom/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358072" />
<state width="1709" height="374" key="GridCell.Tab.3.bottom/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615755" />
<state width="1709" height="374" key="GridCell.Tab.3.bottom/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328170" />
<state width="1709" height="374" key="GridCell.Tab.3.bottom/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987680" />
<state width="1704" height="374" key="GridCell.Tab.3.bottom/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654697" />
<state width="840" height="374" key="GridCell.Tab.3.bottom/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292667" />
<state width="1709" height="374" key="GridCell.Tab.3.center" timestamp="1598446615754">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.3.center" timestamp="1598527987680">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.3.center/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358071" />
<state width="1709" height="374" key="GridCell.Tab.3.center/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615754" />
<state width="1709" height="374" key="GridCell.Tab.3.center/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328170" />
<state width="1709" height="374" key="GridCell.Tab.3.center/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987680" />
<state width="1704" height="374" key="GridCell.Tab.3.center/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654697" />
<state width="840" height="374" key="GridCell.Tab.3.center/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292667" />
<state width="1709" height="374" key="GridCell.Tab.3.left" timestamp="1598446615753">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.3.left" timestamp="1598527987680">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.3.left/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358071" />
<state width="1709" height="374" key="GridCell.Tab.3.left/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615753" />
<state width="1709" height="374" key="GridCell.Tab.3.left/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328170" />
<state width="1709" height="374" key="GridCell.Tab.3.left/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987680" />
<state width="1704" height="374" key="GridCell.Tab.3.left/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654697" />
<state width="840" height="374" key="GridCell.Tab.3.left/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292667" />
<state width="1709" height="374" key="GridCell.Tab.3.right" timestamp="1598446615754">
<screen x="60" y="23" width="1732" height="1097" />
<state width="1709" height="374" key="GridCell.Tab.3.right" timestamp="1598527987680">
<screen x="62" y="23" width="1730" height="1097" />
</state>
<state width="840" height="374" key="GridCell.Tab.3.right/0.0.1792.1120@0.0.1792.1120" timestamp="1598115358072" />
<state width="1709" height="374" key="GridCell.Tab.3.right/60.23.1732.1097@60.23.1732.1097" timestamp="1598446615754" />
<state width="1709" height="374" key="GridCell.Tab.3.right/62.23.1730.1097@62.23.1730.1097" timestamp="1598445328170" />
<state width="1709" height="374" key="GridCell.Tab.3.right/62.23.1730.1097@62.23.1730.1097" timestamp="1598527987680" />
<state width="1704" height="374" key="GridCell.Tab.3.right/67.23.1725.1097@67.23.1725.1097" timestamp="1598325654697" />
<state width="840" height="374" key="GridCell.Tab.3.right/70.23.1722.1097@70.23.1722.1097" timestamp="1598233292667" />
</component>

15
web/package-lock.json generated
View File

@ -1078,6 +1078,21 @@
"to-fast-properties": "^2.0.0"
}
},
"@dzangolab/flag-icon-css": {
"version": "3.4.5",
"resolved": "https://registry.npmjs.org/@dzangolab/flag-icon-css/-/flag-icon-css-3.4.5.tgz",
"integrity": "sha512-XqVAi0O/KITtznpMK5TP4D+rWfwst5lrsbPbes5c5SPMGjwK7fuvlTdEmG2XUrxzYqDTIPshywyzdVYKooGdGA=="
},
"@dzangolab/vue-country-flag-icon": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@dzangolab/vue-country-flag-icon/-/vue-country-flag-icon-0.2.0.tgz",
"integrity": "sha512-o0MqokudSrr56haWk5acyfnFwRBjSH20ARzuLaWNak7Suw3QQXK1dyh0AJFQVuGYmScCI1qpLozvav9P2tg5RA==",
"requires": {
"@dzangolab/flag-icon-css": "^3.4.5",
"core-js": "^3.5.0",
"vue": "^2.6.11"
}
},
"@hapi/address": {
"version": "2.1.4",
"resolved": "https://registry.npm.taobao.org/@hapi/address/download/@hapi/address-2.1.4.tgz?cache=0&sync_timestamp=1593993895205&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40hapi%2Faddress%2Fdownload%2F%40hapi%2Faddress-2.1.4.tgz",

View File

@ -8,6 +8,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@dzangolab/vue-country-flag-icon": "^0.2.0",
"axios": "^0.20.0",
"core-js": "^3.6.5",
"lodash": "^4.17.20",

View File

@ -44,29 +44,29 @@ export default {
},
created() {
this.$vuetify.theme.dark = this.$store.state.isDarkMode;
this.$vuetify.theme.themes.dark.primary = '#ae51e3';
this.$vuetify.theme.dark = false;
this.$vuetify.theme.themes.dark.primary = '#0899ab';
this.$vuetify.theme.themes.light.primary = '#d73964';
initStore(this.$store);
},
computed: {
successMessage: function () {
successMessage() {
return this.$store.state.successMessage;
},
errorMessage: function () {
errorMessage() {
return this.$store.state.errorMessage;
}
},
watch: {
successMessage: function () {
successMessage() {
setTimeout(() => {
this.$store.commit("SET_SUCCESS_MESSAGE", "");
}, 1000);
},
errorMessage: function () {
errorMessage() {
setTimeout(() => {
this.$store.commit("SET_ERROR_MESSAGE", "");
}, 1000);

View 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">filter_list</v-icon>
关键词过滤
<v-spacer></v-spacer>
<v-btn icon>
<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-radio-group v-model="mode">
<v-row>
<v-col>
<v-radio label="保留" value="IN"/>
</v-col>
<v-col>
<v-radio label="过滤" value="OUT"/>
</v-col>
</v-row>
</v-radio-group>
关键词
<v-chip-group>
<v-chip
close
close-icon="mdi-delete"
v-for="(keyword, idx) in keywords"
:key="idx"
@click:close="remove(idx)"
>
{{ keyword }}
</v-chip>
</v-chip-group>
<v-text-field
placeholder="添加新关键词"
solo
v-model="form.keyword"
append-icon="mdi-send"
@click:append="add(form.keyword)"
@keyup.enter="add(form.keyword)"
/>
</v-card-text>
</v-card>
</template>
<script>
export default {
data: function () {
return {
mode: "IN",
form: {
keyword: ""
},
keywords: []
}
},
methods: {
add(keyword) {
if (keyword) {
this.keywords.push(keyword);
this.form.keyword = "";
} else {
this.$store.commit("SET_ERROR_MESSAGE", "关键词不能为空!");
}
},
remove(idx) {
this.keywords.splice(idx, 1);
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,13 @@
<template>
</template>
<script>
export default {
name: "KeywordRename"
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,97 @@
<template>
<v-card class="ml-1 mr-1 mb-1 mt-1">
<v-card-title>
<v-icon left color="primary">sort</v-icon>
关键词排序
<v-spacer></v-spacer>
<v-btn icon>
<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 column
>
<v-chip
draggable
close
close-icon="mdi-delete"
v-for="(keyword, idx) in keywords"
:key="idx"
@click:close="remove(idx)"
@dragstart="dragStart"
@dragend="dragEnd"
>
{{ keyword }}
</v-chip>
</v-chip-group>
<v-text-field
placeholder="添加新关键词"
solo
v-model="form.keyword"
append-icon="mdi-send"
@click:append="add(form.keyword)"
@keyup.enter="add(form.keyword)"
/>
</v-card-text>
</v-card>
</template>
<script>
export default {
data: function () {
return {
selection: null,
currentTag: null,
form: {
keyword: ""
},
keywords: []
}
},
methods: {
add(keyword) {
if (keyword) {
this.keywords.push(keyword);
this.form.keyword = "";
} else {
this.$store.commit("SET_ERROR_MESSAGE", "关键词不能为空!");
}
},
remove(idx) {
this.keywords.splice(idx, 1);
},
dragStart() {
if (this.keywords[this.selection]) this.currentTag = this.tags[this.selection].name;
else this.currentTag = null;
},
dragEnd() {
const self = this;
if (this.currentTag) {
this.keywords.forEach((x, i) => {
if (x.name === self.currentTag) self.selection = i;
});
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -3,7 +3,24 @@
<v-list-item v-for="proxy in proxies" :key="proxy.name">
<v-list-item-content>
<v-list-item-title v-text="proxy.name" class="wrap-text"></v-list-item-title>
<v-list-item-subtitle v-text="getType(proxy.type)"></v-list-item-subtitle>
<v-chip-group>
<v-chip x-small color="primary" outlined>
<v-icon left x-small>mdi-server</v-icon>
{{ proxy.type.toUpperCase() }}
</v-chip>
<v-chip x-small v-if="proxy.udp" color="blue" outlined>
<v-icon left x-small>mdi-fire</v-icon>
UDP
</v-chip>
<v-chip x-small v-if="proxy.tfo" color="success" outlined>
<v-icon left x-small>mdi-flash</v-icon>
TFO
</v-chip>
<v-chip x-small v-if="proxy.scert" color="error" outlined>
<v-icon left x-small>error</v-icon>
SCERT
</v-chip>
</v-chip-group>
</v-list-item-content>
<v-list-item-action>
<v-btn icon>
@ -19,16 +36,7 @@ export default {
name: "ProxyList",
props: ['proxies'],
methods: {
getType(type) {
switch (type) {
case 'ss':
return 'shadowsocks'
case 'ssr':
return 'shadowsocksr'
default:
return type
}
}
}
}
</script>

View File

@ -0,0 +1,95 @@
<template>
<v-card class="ml-1 mr-1 mb-1 mt-1">
<v-card-title>
<v-icon left color="primary">code</v-icon>
正则过滤
<v-spacer></v-spacer>
<v-btn icon>
<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>
根据正则表达式过滤节点如果设置为保留模式则匹配<b>任何一个</b>正则表达式的节点会被保留否则会被过滤
正则表达式需要注意转义
<br/>这里是一个合法的正则表达式:
<br/>
<b>IEPL|IPLC</b>
</v-card-text>
</v-card>
</v-dialog>
</v-card-title>
<v-card-text>
模式
<v-radio-group v-model="mode">
<v-row>
<v-col>
<v-radio label="保留" value="IN"/>
</v-col>
<v-col>
<v-radio label="过滤" value="OUT"/>
</v-col>
</v-row>
</v-radio-group>
正则表达式
<v-chip-group>
<v-chip
close
close-icon="mdi-delete"
v-for="(regex, idx) in regexps"
:key="idx"
@click:close="remove(idx)"
>
{{ regex }}
</v-chip>
</v-chip-group>
<v-text-field
placeholder="添加新正则表达式"
solo
v-model="form.regex"
append-icon="mdi-send"
@click:append="add(form.regex)"
@keyup.enter="add(form.regex)"
/>
</v-card-text>
</v-card>
</template>
<script>
export default {
data: function () {
return {
mode: "IN",
form: {
regex: ""
},
regexps: []
}
},
methods: {
add(keyword) {
if (keyword) {
this.regexps.push(keyword);
this.form.regex = "";
} else {
this.$store.commit("SET_ERROR_MESSAGE", "正则表达式不能为空!");
}
},
remove(idx) {
this.regexps.splice(idx, 1);
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,13 @@
<template>
</template>
<script>
export default {
name: "RegexRename"
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,81 @@
<template>
<v-card class="ml-1 mr-1 mb-1 mt-1">
<v-card-title>
<v-icon left color="primary">flag</v-icon>
区域过滤
<v-spacer></v-spacer>
<v-btn icon>
<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="region in regions"
label
:key="region.name"
:value="region.value"
>
{{ region.name }}
</v-chip>
</v-chip-group>
</v-card-text>
</v-card>
</template>
<script>
const regions = [
{
name: "🇭🇰 香港",
value: "HK"
},
{
name: "🇨🇳 台湾",
value: "TW"
},
{
name: "🇸🇬 新加坡",
value: "SG"
},
{
name: "🇯🇵 日本",
value: "JP"
},
{
name: "🇺🇸 美国",
value: "USA"
},
{
name: "🇬🇧 英国",
value: "UK"
}
];
export default {
data: function () {
return {
regions,
selection: []
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,57 @@
<template>
<v-card class="ml-1 mr-1 mb-1 mt-1">
<v-card-title>
<v-icon left color="primary">sort_by_alpha</v-icon>
节点排序
<v-spacer></v-spacer>
<v-btn icon>
<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-radio-group v-model="mode">
<v-row>
<v-col>
<v-radio label="正序" value="ASC"/>
</v-col>
<v-col>
<v-radio label="逆序" value="DESC"/>
</v-col>
<v-col>
<v-radio label="随机" value="RANDOM"/>
</v-col>
</v-row>
</v-radio-group>
</v-card-text>
</v-card>
</template>
<script>
export default {
data: function () {
return {
mode: "ASC"
}
}
}
</script>
<style scoped>
</style>

View File

@ -1,9 +1,9 @@
import Vue from 'vue'
import App from './App.vue'
import Clipboard from 'v-clipboard';
import vuetify from './plugins/vuetify';
import router from './router';
import store from './store';
import Clipboard from 'v-clipboard';
Vue.config.productionTip = false
Vue.use(Clipboard);

View File

@ -11,7 +11,6 @@ import CollectionEditor from "@/views/CollectionEditor";
Vue.use(Router);
const router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{

View File

@ -33,7 +33,7 @@ const store = new Vuex.Store({
SET_ERROR_MESSAGE(state, msg) {
state.errorMessage = msg;
},
}
},
actions: {

View File

@ -1,13 +1,194 @@
<template>
<v-container></v-container>
<v-container>
<v-card class="mb-4">
<v-subheader>基本信息</v-subheader>
<v-form class="pl-4 pr-4 pb-4" v-model="formState.basicValid">
<v-text-field
v-model="options.name"
class="mt-2"
:rules="validations.nameRules"
required
label="订阅名称"
placeholder="填入订阅名称,名称需唯一"
/>
<v-text-field
v-model="options.url"
class="mt-2"
:rules="validations.urlRules"
required
label="订阅链接"
placeholder="填入机场原始订阅链接"
/>
</v-form>
</v-card>
<v-card class="mb-4">
<v-subheader>常用选项</v-subheader>
<v-form class="pl-4 pr-4">
<v-item-group>
<v-radio-group
v-model="options.flag"
dense
class="mt-0 mb-0"
>
国旗
<v-row>
<v-col>
<v-radio label="添加国旗" value="ADD"/>
</v-col>
<v-col>
<v-radio label="删除国旗" value="REMOVE"/>
</v-col>
<v-col></v-col>
</v-row>
</v-radio-group>
<v-radio-group
v-model="options.udp"
dense
class="mt-0 mb-0"
>
UDP转发
<v-row>
<v-col>
<v-radio label="默认" value="DEFAULT"/>
</v-col>
<v-col>
<v-radio label="强制开启" value="FORCE_OPEN"/>
</v-col>
<v-col>
<v-radio label="强制关闭" value="FORCE_CLOSE"/>
</v-col>
</v-row>
</v-radio-group>
<v-radio-group
v-model="options.scert"
dense
class="mt-0 mb-0"
>
证书验证
<v-row>
<v-col>
<v-radio label="默认" value="DEFAULT"/>
</v-col>
<v-col>
<v-radio label="强制开启" value="FORCE_OPEN"/>
</v-col>
<v-col>
<v-radio label="强制关闭" value="FORCE_CLOSE"/>
</v-col>
</v-row>
</v-radio-group>
<v-radio-group
v-model="options.tfo"
dense
class="mt-0 mb-0"
>
TCP Fast Open
<v-row>
<v-col>
<v-radio label="默认" value="DEFAULT"/>
</v-col>
<v-col>
<v-radio label="强制开启" value="FORCE_OPEN"/>
</v-col>
<v-col>
<v-radio label="强制关闭" value="FORCE_CLOSE"/>
</v-col>
</v-row>
</v-radio-group>
</v-item-group>
</v-form>
</v-card>
<v-card class="mb-4">
<v-subheader>
节点操作
<v-spacer></v-spacer>
<v-btn icon>
<v-icon color="primary">add_circle</v-icon>
</v-btn>
</v-subheader>
<v-divider></v-divider>
<region-filter/>
<keyword-filter/>
<regex-filter/>
<sort></sort>
<keyword-sort></keyword-sort>
</v-card>
</v-container>
</template>
<script>
// const operations = [
// {
// type: "Region Filter",
// name: "",
// desc: "",
// }
// ];
import RegionFilter from "@/components/RegionFilter";
import KeywordFilter from "@/components/KeywordFilter";
import RegexFilter from "@/components/RegexFilter";
import Sort from "@/components/Sort";
import KeywordSort from "@/components/KeywordSort";
export default {
name: "SubEditor"
components: {KeywordSort, Sort, RegexFilter, KeywordFilter, RegionFilter},
data: function () {
return {
validations: {
nameRules: [
v => !!v || "订阅名称不能为空!",
v => /^[\w-_]*$/.test(v) || "订阅名称只能包含英文字符、横杠和下划线!"
],
urlRules: [
v => !!v || "订阅链接不能为空!",
v => /^https?:\/\//.test(v) || ""
]
},
formState: {
basicValid: false
},
options: {
name: "",
url: "",
udp: "DEFAULT",
flag: "ADD",
scert: "DEFAULT",
tfo: "DEFAULT",
process: [],
}
}
},
watch: {
options: {
handler(opt) {
if (this.formState.basicValid) {
console.log(`FORM UPDATED: ${JSON.stringify(opt)}`)
}
},
deep: true
}
},
created() {
const name = this.$route.params.name;
const sub = (!!name || name === 'UNTITLED') ? {} : this.$store.state.subscriptions[name];
this.$store.commit("SET_NAV_TITLE", sub.name ? `订阅编辑 -- ${sub.name}` : "新建订阅");
this.options = {
...this.options,
name: sub.name,
url: sub.url,
udp: "DEFAULT",
flag: "ADD",
scert: "DEFAULT",
tfo: "DEFAULT"
}
}
}
</script>
<style scoped>
<style>
.v-label {
font-size: small;
}
</style>

View File

@ -116,25 +116,30 @@
<v-btn
fab
color="primary"
@click="createSub"
>
<v-icon>mdi-plus</v-icon>
</v-btn>
</v-speed-dial>
</v-fab-transition>
<v-dialog fullscreen hide-overlay transition="dialog-bottom-transition" v-model="showProxyList">
<v-dialog fullscreen hide-overlay transition="dialog-bottom-transition" v-model="showProxyList" scrollable>
<v-card>
<v-toolbar dark color="primary">
<v-icon>mdi-cloud</v-icon>
<v-spacer></v-spacer>
<v-toolbar-title>节点列表</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn icon @click="showProxyList = false">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-toolbar-items>
</v-toolbar>
<proxy-list :proxies="proxies"></proxy-list>
<v-card-title class="pa-0">
<v-toolbar dark color="primary">
<v-icon>mdi-cloud</v-icon>
<v-spacer></v-spacer>
<v-toolbar-title>节点列表</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn icon @click="showProxyList = false">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-toolbar-items>
</v-toolbar>
</v-card-title>
<v-card-text class="pl-0 pr-0">
<proxy-list :proxies="proxies"></proxy-list>
</v-card-text>
</v-card>
</v-dialog>
</v-container>
@ -204,6 +209,7 @@ export default {
this.$store.commit("SET_SUCCESS_MESSAGE", "成功复制订阅链接");
break
case 'EDIT':
this.$router.push(`/sub-edit/${collection.name}`);
break
case 'DELETE':
this.$store.dispatch("DELETE_COLLECTION", collection.name);
@ -225,10 +231,20 @@ export default {
this.$store.commit("SET_ERROR_MESSAGE", err);
})
},
createSub() {
this.$router.push("/sub-edit/UNTITLED");
},
createCol() {
this.$router.push("/collection-edit/UNTITLED")
}
}
}
</script>
<style scoped>
.top-toolbar {
position: sticky;
top: 0;
z-index: 999;
}
</style>