diff --git a/package.json b/package.json
index 03b14ce80..2489a0e1d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "sub-store-front-end",
- "version": "2.14.228",
+ "version": "2.14.229",
"private": true,
"scripts": {
"dev": "vite --host",
diff --git a/src/components/SubListItem.vue b/src/components/SubListItem.vue
index 7fdbdf5f6..082977306 100644
--- a/src/components/SubListItem.vue
+++ b/src/components/SubListItem.vue
@@ -175,11 +175,11 @@
-
+
{
showNotify({ title: t("subPage.copyConfigNotify.succeed") });
swipe.value.close();
};
+// const onClickExport = async () => {
+// swipeController()
+// let data: Sub | Collection;
+// switch (props.type) {
+// case "sub":
+// data = JSON.parse(JSON.stringify(toRaw(props.sub)));
+// break;
+// case "collection":
+// data = JSON.parse(JSON.stringify(toRaw(props.collection)));
+// break;
+// }
+// data.name += `-exportedAt${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}`;
+
+// Toast.loading(t("subPage.copyConfigNotify.loading"), { id: "exportConfig" });
+// // await subsApi.createSub(props.type + "s", data);
+// // await subsStore.fetchSubsData();
+// Toast.hide("exportConfig");
+// showNotify({ title: t("subPage.copyConfigNotify.succeed") });
+// swipe.value.close();
+// };
const onClickEdit = () => {
router.push(`/edit/${props.type}s/${encodeURIComponent(name)}`);
diff --git a/src/locales/en.ts b/src/locales/en.ts
index 44df03db4..57e4711e9 100644
--- a/src/locales/en.ts
+++ b/src/locales/en.ts
@@ -9,6 +9,7 @@ export default {
unknown: 'Unknown',
all: 'All',
untagged: 'Untagged',
+ or: 'or',
},
globalNotify: {
refresh: {
@@ -99,6 +100,11 @@ export default {
},
// subscription management page
subPage: {
+ import: {
+ label: 'Import',
+ succeed: 'Successfully imported!',
+ failed: 'Failed to import!\n{e}',
+ },
addSubTitle: 'Which type you want to create?',
previewTitle: 'Copy/Preview a subscription',
@@ -152,6 +158,11 @@ export default {
succeed: 'Successfully cloned config!',
failed: 'Failed to clone config!\n{e}',
},
+ exportConfigNotify: {
+ loading: 'Exporting...',
+ succeed: 'Successfully exported config!',
+ failed: 'Failed to exporte config!\n{e}',
+ },
panel: {
general: 'General',
tips: {
diff --git a/src/locales/zh.ts b/src/locales/zh.ts
index 8d0d36e4a..e13cca2fe 100644
--- a/src/locales/zh.ts
+++ b/src/locales/zh.ts
@@ -9,6 +9,7 @@ export default {
unknown: '未知',
all: '全部',
untagged: '未分组',
+ or: '或',
},
globalNotify: {
refresh: {
@@ -99,6 +100,11 @@ export default {
},
// 订阅管理页
subPage: {
+ import: {
+ label: '导入',
+ succeed: '导入成功',
+ failed: '导入失败\n{e}',
+ },
addSubTitle: '选择要创建的订阅类型',
previewTitle: '预览/拷贝订阅',
@@ -151,6 +157,11 @@ export default {
succeed: '配置克隆成功!',
failed: '配置克隆失败!\n{e}',
},
+ exportConfigNotify: {
+ loading: '导出配置中...',
+ succeed: '导出成功!',
+ failed: '导出失败!\n{e}',
+ },
panel: {
general: '通用订阅',
tips: {
diff --git a/src/plugin/awesomeIcon.ts b/src/plugin/awesomeIcon.ts
index 7ff2beb50..08880cbb5 100644
--- a/src/plugin/awesomeIcon.ts
+++ b/src/plugin/awesomeIcon.ts
@@ -28,8 +28,12 @@ import {
faEraser,
faT,
faICursor,
+ faFileImport,
+ faFileExport,
} from '@fortawesome/free-solid-svg-icons';
+library.add(faFileImport);
+library.add(faFileExport);
library.add(faToggleOn);
library.add(faToggleOff);
library.add(faLanguage);
diff --git a/src/views/Sub.vue b/src/views/Sub.vue
index 0d93c5382..5f47593ac 100644
--- a/src/views/Sub.vue
+++ b/src/views/Sub.vue
@@ -21,7 +21,27 @@
closeable
round
>
- {{ $t(`subPage.addSubTitle`) }}
+
+
{{ $t(`subPage.addSubTitle`) }}
+
{{ $t(`specificWord.or`) }}
+
+
+
+ {{ $t(`subPage.import.label`) }}
+
+
+
-
@@ -225,7 +245,7 @@ import { ref, toRaw, computed } from "vue";
import draggable from "vuedraggable";
import { useAppNotifyStore } from "@/store/appNotify";
-// import { Dialog, Toast } from '@nutui/nutui';
+import { Dialog, Toast } from '@nutui/nutui';
import { useSubsApi } from "@/api/subs";
import SubListItem from "@/components/SubListItem.vue";
@@ -240,7 +260,9 @@ const { env } = useBackend();
const { showNotify } = useAppNotifyStore();
const subsApi = useSubsApi();
const { t } = useI18n();
-
+const fileInput = ref(null);
+const uploadIsLoading = ref(false);
+const restoreIsLoading = ref(false);
const addSubBtnIsVisible = ref(false);
// const isSubFold = ref(localStorage.getItem('sub-fold') === '1');
// const isColFold = ref(localStorage.getItem('col-fold') === '1');
@@ -453,6 +475,69 @@ const shouldShowElement = (element) => {
if(tag.value === 'untagged') return !Array.isArray(element.tag) || element.tag.length === 0
return element.tag.includes(tag.value)
};
+const upload = async() => {
+ try {
+ fileInput.value.click()
+ } catch (e) {
+ console.error(e);
+ }
+}
+
+const fileChange = async (event) => {
+ const file = event.target.files[0];
+ if(!file) return
+ try {
+ restoreIsLoading.value = true;
+ const reader = new FileReader();
+ reader.readAsText(file);
+ reader.onload = async () => {
+ const item = JSON.parse(String(reader.result))
+ const suffix = new Date().getTime()
+ item.name += `_${suffix}`
+ item.displayName += `_${suffix}`
+ item['display-name'] = item.displayName
+ const res = await subsApi.createSub('subs', item);
+ // await subsStore.fetchSubsData();
+
+ // const res = await useSettingsApi().restoreSettings({ content: String(reader.result) });
+ if (res?.data?.status === "success") {
+ await initStores(false, true, true);
+ showNotify({
+ type: "success",
+ title: t(`subPage.import.succeed`),
+ });
+ addSubBtnIsVisible.value = false
+ } else {
+ throw new Error('restore failed')
+ }
+ }
+
+ reader.onerror = e => {
+ throw e
+ }
+
+ } catch (e) {
+ showNotify({
+ type: "danger",
+ title: t(`subPage.import.failed`, { e: e.message ?? e }),
+ });
+ console.error(e);
+ } finally {
+ restoreIsLoading.value = false;
+ }
+};
+const importTips = () => {
+ addSubBtnIsVisible.value = false
+ Dialog({
+ title: '仅支持 Sub-Store 单条订阅数据',
+ content: '订阅管理页面, 在某个单条订阅左滑/右滑的更多项中, 点击导出图标按钮',
+ popClass: 'auto-dialog',
+ okText: 'OK',
+ noCancelBtn: true,
+ closeOnPopstate: true,
+ lockScroll: false,
+ });
+};