mirror of
https://git.mirrors.martin98.com/https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-12 04:59:03 +08:00
Added support for non-ascii characters in subscriptions, collections and artifacts
This commit is contained in:
parent
4dbafb77c5
commit
e28e440dc5
2
backend/dist/sub-store-parser.loon.min.js
vendored
2
backend/dist/sub-store-parser.loon.min.js
vendored
@ -6,7 +6,7 @@
|
|||||||
* ███████║╚██████╔╝██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║███████╗
|
* ███████║╚██████╔╝██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║███████╗
|
||||||
* ╚══════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
|
* ╚══════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
|
||||||
* Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket!
|
* Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket!
|
||||||
* @updated: 2022/5/26 上午11:17:01
|
* @updated: 2022/5/30 下午1:47:20
|
||||||
* @version: 1.6
|
* @version: 1.6
|
||||||
* @author: Peng-YM
|
* @author: Peng-YM
|
||||||
* @github: https://github.com/Peng-YM/Sub-Store
|
* @github: https://github.com/Peng-YM/Sub-Store
|
||||||
|
@ -30,7 +30,8 @@ export default function register($app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getArtifact(req, res) {
|
async function getArtifact(req, res) {
|
||||||
const name = req.params.name;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
const action = req.query.action;
|
const action = req.query.action;
|
||||||
const allArtifacts = $.read(ARTIFACTS_KEY);
|
const allArtifacts = $.read(ARTIFACTS_KEY);
|
||||||
const artifact = allArtifacts[name];
|
const artifact = allArtifacts[name];
|
||||||
@ -61,14 +62,15 @@ async function getArtifact(req, res) {
|
|||||||
console.log(JSON.stringify(artifact, null, 2));
|
console.log(JSON.stringify(artifact, null, 2));
|
||||||
try {
|
try {
|
||||||
const resp = await syncArtifact({
|
const resp = await syncArtifact({
|
||||||
[artifact.name]: { content: output },
|
[encodeURIComponent(artifact.name)]: {
|
||||||
|
content: output,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
artifact.updated = new Date().getTime();
|
artifact.updated = new Date().getTime();
|
||||||
const body = JSON.parse(resp.body);
|
const body = JSON.parse(resp.body);
|
||||||
artifact.url = body.files[artifact.name].raw_url.replace(
|
artifact.url = body.files[
|
||||||
/\/raw\/[^/]*\/(.*)/,
|
encodeURIComponent(artifact.name)
|
||||||
'/raw/$1',
|
].raw_url.replace(/\/raw\/[^/]*\/(.*)/, '/raw/$1');
|
||||||
);
|
|
||||||
$.write(allArtifacts, ARTIFACTS_KEY);
|
$.write(allArtifacts, ARTIFACTS_KEY);
|
||||||
res.json({
|
res.json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
@ -104,25 +106,19 @@ function createArtifact(req, res) {
|
|||||||
message: `远程配置${artifact.name}已存在!`,
|
message: `远程配置${artifact.name}已存在!`,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (/^[\w-_.]*$/.test(artifact.name)) {
|
allArtifacts[artifact.name] = artifact;
|
||||||
allArtifacts[artifact.name] = artifact;
|
$.write(allArtifacts, ARTIFACTS_KEY);
|
||||||
$.write(allArtifacts, ARTIFACTS_KEY);
|
res.status(201).json({
|
||||||
res.status(201).json({
|
status: 'success',
|
||||||
status: 'success',
|
data: artifact,
|
||||||
data: artifact,
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
res.status(500).json({
|
|
||||||
status: 'failed',
|
|
||||||
message: `远程配置名称 ${artifact.name} 中含有非法字符!名称中只能包含英文字母、数字、下划线、横杠。`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateArtifact(req, res) {
|
function updateArtifact(req, res) {
|
||||||
const allArtifacts = $.read(ARTIFACTS_KEY);
|
const allArtifacts = $.read(ARTIFACTS_KEY);
|
||||||
const oldName = req.params.name;
|
let oldName = req.params.name;
|
||||||
|
oldName = decodeURIComponent(oldName);
|
||||||
const artifact = allArtifacts[oldName];
|
const artifact = allArtifacts[oldName];
|
||||||
if (artifact) {
|
if (artifact) {
|
||||||
$.info(`正在更新远程配置:${artifact.name}`);
|
$.info(`正在更新远程配置:${artifact.name}`);
|
||||||
@ -215,7 +211,8 @@ async function cronSyncArtifacts(_, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function deleteArtifact(req, res) {
|
async function deleteArtifact(req, res) {
|
||||||
const name = req.params.name;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
$.info(`正在删除远程配置:${name}`);
|
$.info(`正在删除远程配置:${name}`);
|
||||||
const allArtifacts = $.read(ARTIFACTS_KEY);
|
const allArtifacts = $.read(ARTIFACTS_KEY);
|
||||||
try {
|
try {
|
||||||
@ -223,10 +220,11 @@ async function deleteArtifact(req, res) {
|
|||||||
if (!artifact) throw new Error(`远程配置:${name}不存在!`);
|
if (!artifact) throw new Error(`远程配置:${name}不存在!`);
|
||||||
if (artifact.updated) {
|
if (artifact.updated) {
|
||||||
// delete gist
|
// delete gist
|
||||||
await syncArtifact({
|
const files = {};
|
||||||
filename: name,
|
files[encodeURIComponent(artifact.name)] = {
|
||||||
content: '',
|
content: '',
|
||||||
});
|
};
|
||||||
|
await syncArtifact(files);
|
||||||
}
|
}
|
||||||
// delete local cache
|
// delete local cache
|
||||||
delete allArtifacts[name];
|
delete allArtifacts[name];
|
||||||
@ -235,9 +233,7 @@ async function deleteArtifact(req, res) {
|
|||||||
status: 'success',
|
status: 'success',
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// delete local cache
|
$.error(`无法删除远程配置:${name},原因:${err}`);
|
||||||
delete allArtifacts[name];
|
|
||||||
$.write(allArtifacts, ARTIFACTS_KEY);
|
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
status: 'failed',
|
status: 'failed',
|
||||||
message: `无法删除远程配置:${name}, 原因:${err}`,
|
message: `无法删除远程配置:${name}, 原因:${err}`,
|
||||||
|
@ -20,7 +20,9 @@ export default function register($app) {
|
|||||||
|
|
||||||
// collection API
|
// collection API
|
||||||
async function downloadCollection(req, res) {
|
async function downloadCollection(req, res) {
|
||||||
const { name } = req.params;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
|
|
||||||
const { raw } = req.query || 'false';
|
const { raw } = req.query || 'false';
|
||||||
const platform =
|
const platform =
|
||||||
req.query.target || getPlatformFromHeaders(req.headers) || 'JSON';
|
req.query.target || getPlatformFromHeaders(req.headers) || 'JSON';
|
||||||
@ -90,24 +92,17 @@ function createCollection(req, res) {
|
|||||||
message: `订阅集${collection.name}已存在!`,
|
message: `订阅集${collection.name}已存在!`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// validate name
|
allCol[collection.name] = collection;
|
||||||
if (/^[\w-_]*$/.test(collection.name)) {
|
$.write(allCol, COLLECTIONS_KEY);
|
||||||
allCol[collection.name] = collection;
|
res.status(201).json({
|
||||||
$.write(allCol, COLLECTIONS_KEY);
|
status: 'success',
|
||||||
res.status(201).json({
|
data: collection,
|
||||||
status: 'success',
|
});
|
||||||
data: collection,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
res.status(500).json({
|
|
||||||
status: 'failed',
|
|
||||||
message: `订阅集名称 ${collection.name} 中含有非法字符!名称中只能包含英文字母、数字、下划线、横杠。`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCollection(req, res) {
|
function getCollection(req, res) {
|
||||||
const { name } = req.params;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
const collection = $.read(COLLECTIONS_KEY)[name];
|
const collection = $.read(COLLECTIONS_KEY)[name];
|
||||||
if (collection) {
|
if (collection) {
|
||||||
res.json({
|
res.json({
|
||||||
@ -123,7 +118,8 @@ function getCollection(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateCollection(req, res) {
|
function updateCollection(req, res) {
|
||||||
const { name } = req.params;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
let collection = req.body;
|
let collection = req.body;
|
||||||
const allCol = $.read(COLLECTIONS_KEY);
|
const allCol = $.read(COLLECTIONS_KEY);
|
||||||
if (allCol[name]) {
|
if (allCol[name]) {
|
||||||
@ -149,7 +145,8 @@ function updateCollection(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteCollection(req, res) {
|
function deleteCollection(req, res) {
|
||||||
const { name } = req.params;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
$.info(`正在删除组合订阅:${name}`);
|
$.info(`正在删除组合订阅:${name}`);
|
||||||
let allCol = $.read(COLLECTIONS_KEY);
|
let allCol = $.read(COLLECTIONS_KEY);
|
||||||
delete allCol[name];
|
delete allCol[name];
|
||||||
|
@ -17,7 +17,9 @@ export default function register($app) {
|
|||||||
|
|
||||||
// subscriptions API
|
// subscriptions API
|
||||||
async function downloadSubscription(req, res) {
|
async function downloadSubscription(req, res) {
|
||||||
const { name } = req.params;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
|
|
||||||
const { raw } = req.query || 'false';
|
const { raw } = req.query || 'false';
|
||||||
const platform =
|
const platform =
|
||||||
req.query.target || getPlatformFromHeaders(req.headers) || 'JSON';
|
req.query.target || getPlatformFromHeaders(req.headers) || 'JSON';
|
||||||
@ -80,24 +82,17 @@ function createSubscription(req, res) {
|
|||||||
message: `订阅${sub.name}已存在!`,
|
message: `订阅${sub.name}已存在!`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// validate name
|
allSubs[sub.name] = sub;
|
||||||
if (/^[\w-_]*$/.test(sub.name)) {
|
$.write(allSubs, SUBS_KEY);
|
||||||
allSubs[sub.name] = sub;
|
res.status(201).json({
|
||||||
$.write(allSubs, SUBS_KEY);
|
status: 'success',
|
||||||
res.status(201).json({
|
data: sub,
|
||||||
status: 'success',
|
});
|
||||||
data: sub,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
res.status(500).json({
|
|
||||||
status: 'failed',
|
|
||||||
message: `订阅名称 ${sub.name} 中含有非法字符!名称中只能包含英文字母、数字、下划线、横杠。`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubscription(req, res) {
|
function getSubscription(req, res) {
|
||||||
const { name } = req.params;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
const sub = $.read(SUBS_KEY)[name];
|
const sub = $.read(SUBS_KEY)[name];
|
||||||
if (sub) {
|
if (sub) {
|
||||||
res.json({
|
res.json({
|
||||||
@ -113,7 +108,8 @@ function getSubscription(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateSubscription(req, res) {
|
function updateSubscription(req, res) {
|
||||||
const { name } = req.params;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
let sub = req.body;
|
let sub = req.body;
|
||||||
const allSubs = $.read(SUBS_KEY);
|
const allSubs = $.read(SUBS_KEY);
|
||||||
if (allSubs[name]) {
|
if (allSubs[name]) {
|
||||||
@ -152,7 +148,8 @@ function updateSubscription(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function deleteSubscription(req, res) {
|
function deleteSubscription(req, res) {
|
||||||
const { name } = req.params;
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
$.info(`删除订阅:${name}...`);
|
$.info(`删除订阅:${name}...`);
|
||||||
// delete from subscriptions
|
// delete from subscriptions
|
||||||
let allSubs = $.read(SUBS_KEY);
|
let allSubs = $.read(SUBS_KEY);
|
||||||
|
4
backend/sub-store.min.js
vendored
4
backend/sub-store.min.js
vendored
File diff suppressed because one or more lines are too long
@ -48,7 +48,7 @@ const router = new Router({
|
|||||||
name: "collection-edit",
|
name: "collection-edit",
|
||||||
component: SubEditor,
|
component: SubEditor,
|
||||||
props: {isCollection: true},
|
props: {isCollection: true},
|
||||||
meta: {title: "订阅编辑"}
|
meta: {title: "组合订阅编辑"}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="currentArtifact.name"
|
v-model="currentArtifact.name"
|
||||||
:disabled="editing"
|
:disabled="editing"
|
||||||
:rules="validations.nameRules"
|
|
||||||
clear-icon="clear"
|
clear-icon="clear"
|
||||||
clearable
|
clearable
|
||||||
label="配置名称"
|
label="配置名称"
|
||||||
@ -155,7 +154,7 @@
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<v-list dense>
|
<v-list dense>
|
||||||
<v-list-item v-if="artifact.url" @click="copy(artifact.url)">
|
<v-list-item v-if="artifact.url" @click="copy(artifact)">
|
||||||
<v-list-item-title>复制</v-list-item-title>
|
<v-list-item-title>复制</v-list-item-title>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item @click="editArtifact(artifact)">
|
<v-list-item @click="editArtifact(artifact)">
|
||||||
@ -200,10 +199,6 @@ export default {
|
|||||||
editing: null,
|
editing: null,
|
||||||
formValid: false,
|
formValid: false,
|
||||||
validations: {
|
validations: {
|
||||||
nameRules: [
|
|
||||||
v => !!v || "订阅名称不能为空!",
|
|
||||||
v => /^[\w-_.]*$/.test(v) || "订阅名称只能包含英文字符、横杠、点和下划线!"
|
|
||||||
],
|
|
||||||
required: [
|
required: [
|
||||||
v => !!v || "不能为空!"
|
v => !!v || "不能为空!"
|
||||||
]
|
]
|
||||||
@ -299,9 +294,11 @@ export default {
|
|||||||
this.editing = false;
|
this.editing = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
copy(url) {
|
copy(artifact) {
|
||||||
this.$clipboard(url);
|
if (artifact.url) {
|
||||||
this.$store.commit("SET_SUCCESS_MESSAGE", "成功复制配置链接");
|
this.$clipboard(artifact.url + (isPlainName(artifact.name) ? '' : `#${artifact.name}`));
|
||||||
|
this.$store.commit("SET_SUCCESS_MESSAGE", "成功复制配置链接");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
preview(name) {
|
preview(name) {
|
||||||
@ -360,6 +357,10 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPlainName(name) {
|
||||||
|
return /^[\w-_]*$/.test(name);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<v-card class="mb-4">
|
<v-card class="mb-4">
|
||||||
<v-subheader>订阅配置</v-subheader>
|
<v-subheader>订阅配置</v-subheader>
|
||||||
<v-form v-model="formState.basicValid" class="pl-4 pr-4 pb-0">
|
<v-form v-model="formState.basicValid" class="pl-4 pr-4 pb-0">
|
||||||
<v-text-field v-model="options.name" :rules="validations.nameRules" class="mt-2" clear-icon="clear" clearable
|
<v-text-field v-model="options.name" class="mt-2" clear-icon="clear" clearable
|
||||||
label="订阅名称" placeholder="填入订阅名称,名称需唯一" required />
|
label="订阅名称" placeholder="填入订阅名称,名称需唯一" required />
|
||||||
<!--For Subscription-->
|
<!--For Subscription-->
|
||||||
<v-radio-group v-if="!isCollection" v-model="options.source" class="mt-0 mb-0">
|
<v-radio-group v-if="!isCollection" v-model="options.source" class="mt-0 mb-0">
|
||||||
@ -20,7 +20,7 @@
|
|||||||
<v-col></v-col>
|
<v-col></v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-radio-group>
|
</v-radio-group>
|
||||||
<v-textarea v-if="options.source !== 'local'" v-model="options.url" :rules="validations.urlRules" auto-grow
|
<v-textarea v-if="!isCollection && options.source !== 'local'" v-model="options.url" :rules="validations.urlRules" auto-grow
|
||||||
class="mt-0" clear-icon="clear" clearable label="订阅链接" placeholder="填入机场原始订阅链接" required rows="2" />
|
class="mt-0" clear-icon="clear" clearable label="订阅链接" placeholder="填入机场原始订阅链接" required rows="2" />
|
||||||
<v-textarea v-if="options.source === 'local'" v-model="options.content" clear-icon="clear" clearable
|
<v-textarea v-if="options.source === 'local'" v-model="options.content" clear-icon="clear" clearable
|
||||||
label="订阅内容" placeholder="填入原始订阅内容" autogrow rows="5" row-height="15" class="mt-0">
|
label="订阅内容" placeholder="填入原始订阅内容" autogrow rows="5" row-height="15" class="mt-0">
|
||||||
@ -300,10 +300,6 @@ export default {
|
|||||||
imported: "",
|
imported: "",
|
||||||
dialog: false,
|
dialog: false,
|
||||||
validations: {
|
validations: {
|
||||||
nameRules: [
|
|
||||||
v => !!v || "订阅名称不能为空!",
|
|
||||||
v => /^[\w-_]*$/.test(v) || "订阅名称只能包含英文字符、横杠和下划线!"
|
|
||||||
],
|
|
||||||
urlRules: [
|
urlRules: [
|
||||||
v => this.options.source === 'remote' && (!!v || "订阅链接不能为空!"),
|
v => this.options.source === 'remote' && (!!v || "订阅链接不能为空!"),
|
||||||
v => this.options.source === 'remote' && (/^https?:\/\//.test(v) || "订阅链接不合法!")
|
v => this.options.source === 'remote' && (/^https?:\/\//.test(v) || "订阅链接不合法!")
|
||||||
@ -335,7 +331,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
const name = this.$route.params.name;
|
const name = decodeURIComponent(this.$route.params.name);
|
||||||
let source;
|
let source;
|
||||||
if (this.isCollection) {
|
if (this.isCollection) {
|
||||||
source = (typeof name === 'undefined' || name === 'UNTITLED') ? {} : this.$store.state.collections[name];
|
source = (typeof name === 'undefined' || name === 'UNTITLED') ? {} : this.$store.state.collections[name];
|
||||||
|
@ -195,19 +195,7 @@ export default {
|
|||||||
{
|
{
|
||||||
title: "删除",
|
title: "删除",
|
||||||
action: "DELETE"
|
action: "DELETE"
|
||||||
},
|
}
|
||||||
// {
|
|
||||||
// title: "副本",
|
|
||||||
// action: "DUPLICATE"
|
|
||||||
// }
|
|
||||||
// {
|
|
||||||
// title: "上移",
|
|
||||||
// action: "MOVE_UP"
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// title: "下移",
|
|
||||||
// action: "MOVE_DOWN"
|
|
||||||
// }
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -236,27 +224,22 @@ export default {
|
|||||||
console.log(`${action} --> ${sub.name}`);
|
console.log(`${action} --> ${sub.name}`);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'COPY':
|
case 'COPY':
|
||||||
this.$clipboard(`${this.subscriptionBaseURL}/download/${sub.name}`);
|
this.$clipboard(`${this.subscriptionBaseURL}/download/${encodeURIComponent(sub.name)}${isPlainName(sub.name) ? '' : '#' + sub.name}`);
|
||||||
this.$store.commit("SET_SUCCESS_MESSAGE", "成功复制订阅链接");
|
this.$store.commit("SET_SUCCESS_MESSAGE", "成功复制订阅链接");
|
||||||
break
|
break
|
||||||
case 'EDIT':
|
case 'EDIT':
|
||||||
this.$router.push(`/sub-edit/${sub.name}`);
|
this.$router.push(`/sub-edit/${encodeURIComponent(sub.name)}`);
|
||||||
break
|
break
|
||||||
case 'DELETE':
|
case 'DELETE':
|
||||||
this.$store.dispatch("DELETE_SUBSCRIPTION", sub.name);
|
this.$store.dispatch("DELETE_SUBSCRIPTION", sub.name);
|
||||||
break
|
break
|
||||||
case 'MOVE_UP':
|
|
||||||
this.moveUpSubscription(sub.name);
|
|
||||||
break
|
|
||||||
case 'MOVE_DOWN':
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
collectionMenu(action, collection) {
|
collectionMenu(action, collection) {
|
||||||
console.log(`${action} --> ${collection.name}`);
|
console.log(`${action} --> ${collection.name}`);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'COPY':
|
case 'COPY':
|
||||||
this.$clipboard(`${this.subscriptionBaseURL}/download/collection/${collection.name}`);
|
this.$clipboard(`${this.subscriptionBaseURL}/download/collection/${encodeURIComponent(collection.name)}${isPlainName(collection.name) ? '' : '#' + collection.name}`);
|
||||||
this.$store.commit("SET_SUCCESS_MESSAGE", "成功复制订阅链接");
|
this.$store.commit("SET_SUCCESS_MESSAGE", "成功复制订阅链接");
|
||||||
break
|
break
|
||||||
case 'EDIT':
|
case 'EDIT':
|
||||||
@ -269,10 +252,10 @@ export default {
|
|||||||
},
|
},
|
||||||
preview(item, type = 'sub') {
|
preview(item, type = 'sub') {
|
||||||
if (type === 'sub') {
|
if (type === 'sub') {
|
||||||
this.url = `${BACKEND_BASE}/download/${item.name}`;
|
this.url = `${BACKEND_BASE}/download/${encodeURIComponent(item.name)}`;
|
||||||
this.sub = item.url;
|
this.sub = item.url;
|
||||||
} else {
|
} else {
|
||||||
this.url = `${BACKEND_BASE}/download/collection/${item.name}`
|
this.url = `${BACKEND_BASE}/download/collection/${encodeURIComponent(item.name)}`
|
||||||
}
|
}
|
||||||
this.showProxyList = true;
|
this.showProxyList = true;
|
||||||
},
|
},
|
||||||
@ -295,6 +278,10 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPlainName(name) {
|
||||||
|
return /^[\w-_]*$/.test(name);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user