diff --git a/resource/i18n/en.json b/resource/i18n/en.json
index 52f017af6..59f179108 100644
--- a/resource/i18n/en.json
+++ b/resource/i18n/en.json
@@ -34,7 +34,9 @@
"export": "Export",
"import": "Import",
"share": "Share",
- "actionConfirm": "Are you sure you want to do this?"
+ "actionConfirm": "Are you sure you want to do this?",
+ "importFailed": "Import failed",
+ "importSuccess": "Import success"
},
"topbar": {
"title": "@:(app.name)",
@@ -534,7 +536,9 @@
"pages": "Applicable page",
"enable": "Enable",
"action": "Action"
- }
+ },
+ "importNameDuplicate": "The name [{name}] already exists. Please re-enter the new name:",
+ "invalidPlugin": "Invalid plugin"
}
},
"sites": {
diff --git a/resource/i18n/zh-CN.json b/resource/i18n/zh-CN.json
index 816eef69d..e62a07479 100644
--- a/resource/i18n/zh-CN.json
+++ b/resource/i18n/zh-CN.json
@@ -34,7 +34,9 @@
"export": "导出",
"import": "导入",
"share": "分享",
- "actionConfirm": "确认要进行此操作吗?"
+ "actionConfirm": "确认要进行此操作吗?",
+ "importFailed": "导入失败",
+ "importSuccess": "已成功导入"
},
"topbar": {
"title": "@:(app.name)",
@@ -534,7 +536,9 @@
"pages": "适用页面",
"enable": "启用",
"action": "操作"
- }
+ },
+ "importNameDuplicate": "该名称【{name}】已存在,请重新输入新的名称:",
+ "invalidPlugin": "无效的插件"
}
},
"sites": {
diff --git a/src/options/views/settings/SitePlugins/Index.vue b/src/options/views/settings/SitePlugins/Index.vue
index 4a520260d..eb55ca452 100644
--- a/src/options/views/settings/SitePlugins/Index.vue
+++ b/src/options/views/settings/SitePlugins/Index.vue
@@ -14,6 +14,23 @@
remove
{{$t('common.remove')}}
+
+
+
+
+
+ folder_open
+ {{$t('settings.sites.index.importConfig')}}
+
+
+
+
+
+ {{ errorMsg }}
+ {{ successMsg }}
@@ -119,7 +139,9 @@ import AddItem from "./Add.vue";
import EditItem from "./Edit.vue";
import { filters } from "@/service/filters";
-import { PPF } from "../../../../service/public";
+import { PPF } from "@/service/public";
+import FileSaver from "file-saver";
+
export default Vue.extend({
components: {
AddItem,
@@ -145,7 +167,12 @@ export default Vue.extend({
readonly: false
} as any,
dialogRemoveConfirm: false,
- plugins: [] as any
+ plugins: [] as any,
+ fileImport: null as any,
+ errorMsg: "",
+ haveError: false,
+ haveSuccess: false,
+ successMsg: ""
};
},
methods: {
@@ -244,8 +271,104 @@ export default Vue.extend({
this.plugins = plugins;
}
},
+
+ clearMessage() {
+ this.successMsg = "";
+ this.errorMsg = "";
+ },
+
+ /**
+ * 导出插件
+ */
share(item: Plugin) {
- console.log(item);
+ let fileName =
+ (this.site.host || this.site.name) + "-plugin-" + item.name + ".json";
+
+ const blob = new Blob([JSON.stringify(item)], {
+ type: "text/plain"
+ });
+ FileSaver.saveAs(blob, fileName);
+ },
+ /**
+ * 导入配置文件
+ */
+ importConfig() {
+ this.fileImport.click();
+ },
+
+ importConfigFile(event: Event) {
+ this.clearMessage();
+ let inputDOM: any = event.srcElement;
+ if (inputDOM.files.length > 0 && inputDOM.files[0].name.length > 0) {
+ for (let index = 0; index < inputDOM.files.length; index++) {
+ const file = inputDOM.files[index];
+ const r = new FileReader();
+ r.onload = (e: any) => {
+ try {
+ const result = JSON.parse(e.target.result);
+ this.importPlugin(result);
+ } catch (error) {
+ console.log(error);
+ this.errorMsg = this.$t("common.importFailed").toString();
+ }
+ };
+ r.onerror = () => {
+ this.errorMsg = this.$t("settings.backup.loadError").toString();
+ };
+ r.readAsText(file);
+ }
+
+ inputDOM.value = "";
+ }
+ },
+
+ /**
+ * 导入插件信息
+ */
+ importPlugin(source: Plugin) {
+ if (
+ !(
+ source.name &&
+ source.id &&
+ source.isCustom &&
+ source.pages &&
+ source.pages.length > 0
+ )
+ ) {
+ this.errorMsg = this.$t(
+ "settings.sitePlugins.index.invalidPlugin"
+ ).toString();
+ return;
+ }
+ const plugin = this.getPlugin(source);
+ if (plugin) {
+ const newName = window.prompt(
+ this.$t("settings.sitePlugins.index.importNameDuplicate", {
+ name: plugin.name
+ }).toString()
+ );
+
+ if (newName) {
+ source.name = newName;
+ this.importPlugin(source);
+ return;
+ } else {
+ return;
+ }
+ }
+ this.addItem(source);
+
+ this.successMsg = this.$t("common.importSuccess").toString();
+ },
+
+ getPlugin(source: Plugin) {
+ const plugins = this.site.plugins;
+ if (plugins && plugins.length > 0) {
+ return plugins.find((item: Plugin) => {
+ return item.name === source.name;
+ });
+ }
+ return null;
}
},
created() {
@@ -255,6 +378,13 @@ export default Vue.extend({
this.reloadPlugins(host);
}
},
+ mounted() {
+ this.fileImport = this.$refs.fileImport;
+ this.fileImport.addEventListener("change", this.importConfigFile);
+ },
+ beforeDestroy() {
+ this.fileImport.removeEventListener("change", this.importConfigFile);
+ },
computed: {
headers(): Array {
return [
@@ -280,6 +410,14 @@ export default Vue.extend({
}
];
}
+ },
+ watch: {
+ successMsg() {
+ this.haveSuccess = this.successMsg != "";
+ },
+ errorMsg() {
+ this.haveError = this.errorMsg != "";
+ }
}
});
diff --git a/src/options/views/settings/Sites/Index.vue b/src/options/views/settings/Sites/Index.vue
index 9bb9237fc..d1b46ea83 100644
--- a/src/options/views/settings/Sites/Index.vue
+++ b/src/options/views/settings/Sites/Index.vue
@@ -16,7 +16,13 @@
-
+
folder_open
@@ -466,8 +472,13 @@ export default Vue.extend({
const file = restoreFile.files[index];
const r = new FileReader();
r.onload = (e: any) => {
- const result = JSON.parse(e.target.result);
- this.importSite(result);
+ try {
+ const result = JSON.parse(e.target.result);
+ this.importSite(result);
+ } catch (error) {
+ console.log(error);
+ this.errorMsg = this.$t("common.importFailed").toString();
+ }
};
r.onerror = () => {
this.errorMsg = this.$t("settings.backup.loadError").toString();