✨ 配置导出
This commit is contained in:
parent
6e028d377a
commit
9fed5fc844
@ -1,18 +1,23 @@
|
||||
import {app, ipcMain} from "electron";
|
||||
import {getConfig, saveConfig} from "../storage/config";
|
||||
import {listVersion} from "../storage/version";
|
||||
import { app, dialog, ipcMain } from "electron";
|
||||
import { getConfig, saveConfig } from "../storage/config";
|
||||
import { listVersion } from "../storage/version";
|
||||
import { generateConfig, genIniConfig, genTomlConfig } from "./frpc";
|
||||
import { exec } from "child_process";
|
||||
import { listProxy } from "../storage/proxy";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
const log = require('electron-log');
|
||||
const log = require("electron-log");
|
||||
|
||||
export const initConfigApi = () => {
|
||||
ipcMain.on("config.saveConfig", async (event, args) => {
|
||||
saveConfig(args, (err, numberOfUpdated, upsert) => {
|
||||
if (!err) {
|
||||
const start = args.systemSelfStart || false;
|
||||
log.info("开启自启状态", start)
|
||||
log.info("开启自启状态", start);
|
||||
app.setLoginItemSettings({
|
||||
openAtLogin: start, //win
|
||||
openAsHidden: start, //macOs
|
||||
openAsHidden: start //macOs
|
||||
});
|
||||
}
|
||||
event.reply("Config.saveConfig.hook", {
|
||||
@ -49,4 +54,49 @@ export const initConfigApi = () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on("config.exportConfig", async (event, args) => {
|
||||
const result = await dialog.showOpenDialog({
|
||||
properties: ["openDirectory"]
|
||||
});
|
||||
const outputDirectory = result.filePaths[0];
|
||||
log.info(`导出目录 ${outputDirectory} 类型:${args}`);
|
||||
getConfig((err1, config) => {
|
||||
if (!err1 && config) {
|
||||
listProxy((err2, proxys) => {
|
||||
if (!err2) {
|
||||
let configContent = "";
|
||||
if (args === "ini") {
|
||||
configContent = genIniConfig(config, proxys);
|
||||
} else if (args === "toml") {
|
||||
configContent = genTomlConfig(config, proxys);
|
||||
}
|
||||
const configPath = path.join(
|
||||
outputDirectory,
|
||||
`frpc-desktop.${args}`
|
||||
);
|
||||
fs.writeFile(
|
||||
configPath, // 配置文件目录
|
||||
configContent, // 配置文件内容
|
||||
{ flag: "w" },
|
||||
err => {
|
||||
if (!err) {
|
||||
// callback(filename);
|
||||
event.reply("config.exportConfig.hook", {
|
||||
data: "导出错误",
|
||||
err: err
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
event.reply("Config.exportConfig.hook", {
|
||||
data: {
|
||||
configPath: configPath
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -38,7 +38,7 @@ const getFrpcVersionWorkerPath = (
|
||||
* @param config
|
||||
* @param proxys
|
||||
*/
|
||||
const genTomlConfig = (config: FrpConfig, proxys: Proxy[]) => {
|
||||
export const genTomlConfig = (config: FrpConfig, proxys: Proxy[]) => {
|
||||
const proxyToml = proxys.map(m => {
|
||||
let toml = `
|
||||
[[${m.type === "stcp" && m.stcpModel === "visitors" ? "visitors" : "proxies"}]]
|
||||
@ -155,7 +155,7 @@ ${proxyToml.join("")}
|
||||
* @param config
|
||||
* @param proxys
|
||||
*/
|
||||
const genIniConfig = (config: FrpConfig, proxys: Proxy[]) => {
|
||||
export const genIniConfig = (config: FrpConfig, proxys: Proxy[]) => {
|
||||
const proxyIni = proxys.map(m => {
|
||||
let ini = `
|
||||
[${m.name}]
|
||||
|
@ -29,6 +29,9 @@ import ContentCopy from "@iconify-icons/material-symbols/content-copy";
|
||||
import ContentPasteGo from "@iconify-icons/material-symbols/content-paste-go";
|
||||
import Edit from "@iconify-icons/material-symbols/edit";
|
||||
import CheckBox from "@iconify-icons/material-symbols/check-box";
|
||||
import ExportNotesOutline from "@iconify-icons/material-symbols/export-notes-outline";
|
||||
import uploadRounded from "@iconify-icons/material-symbols/upload-rounded";
|
||||
import downloadRounded from "@iconify-icons/material-symbols/download-rounded";
|
||||
|
||||
addIcon("cloud", Cloud);
|
||||
addIcon("rocket-launch-rounded", RocketLaunchRounded);
|
||||
@ -53,4 +56,8 @@ addIcon("content-copy", ContentCopy);
|
||||
addIcon("content-paste-go", ContentPasteGo);
|
||||
addIcon("edit", Edit);
|
||||
addIcon("check-box", CheckBox);
|
||||
addIcon("export", ExportNotesOutline);
|
||||
addIcon("uploadRounded", uploadRounded);
|
||||
addIcon("downloadRounded", downloadRounded);
|
||||
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue";
|
||||
import { computed, defineComponent } from "vue";
|
||||
import router from "@/router";
|
||||
|
||||
|
||||
defineComponent({
|
||||
name: "Breadcrumb"
|
||||
});
|
||||
@ -14,16 +12,17 @@ const currentRoute = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-between">
|
||||
<div class="breadcrumb animate__animated animate__lightSpeedInLeft">
|
||||
<IconifyIconOffline class="inline-block mr-2" :icon="currentRoute.meta['icon'] as string"/>
|
||||
<!-- <Icon-->
|
||||
<!-- class="inline-block mr-2"-->
|
||||
<!-- :icon="currentRoute.meta['icon'] as string"-->
|
||||
<!-- />-->
|
||||
<div class="breadcrumb flex justify-between items-center">
|
||||
<div
|
||||
class="flex items-center justify-center breadcrumb-left animate__animated animate__lightSpeedInLeft"
|
||||
>
|
||||
<IconifyIconOffline
|
||||
class="inline-block mr-2"
|
||||
:icon="currentRoute.meta['icon'] as string"
|
||||
/>
|
||||
<span>{{ currentRoute.meta["title"] }}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="breadcrumb-right">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,9 +21,12 @@ $danger-color: #F56C6C;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
margin-bottom: 15px;
|
||||
|
||||
.breadcrumb-left {
|
||||
color: $primary-color;
|
||||
font-size: 36px;
|
||||
height: 50px;
|
||||
height: 30px;
|
||||
|
||||
svg {
|
||||
vertical-align: top;
|
||||
@ -34,11 +37,14 @@ $danger-color: #F56C6C;
|
||||
color: black;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
transform: translateY(5px);
|
||||
//transform: translateY(5px);
|
||||
display: inline-block;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.left-menu-container {
|
||||
@ -57,6 +63,7 @@ $danger-color: #F56C6C;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.version:hover {
|
||||
animation: heartBeat 1s;
|
||||
}
|
||||
@ -91,7 +98,6 @@ $danger-color: #F56C6C;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,6 +117,10 @@ $danger-color: #F56C6C;
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
.bg-primary {
|
||||
background: $primary-color;
|
||||
}
|
||||
|
||||
.danger-text {
|
||||
color: $danger-color !important;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue";
|
||||
import { useDebounceFn } from "@vueuse/core";
|
||||
import { clone } from "@/utils/clone";
|
||||
import { Base64 } from "js-base64";
|
||||
import IconifyIconOffline from "@/components/IconifyIcon/src/iconifyIconOffline";
|
||||
|
||||
defineComponent({
|
||||
name: "Config"
|
||||
@ -116,9 +117,12 @@ const protocol = ref("frp://");
|
||||
|
||||
const visibles = reactive({
|
||||
copyServerConfig: false,
|
||||
pasteServerConfig: false
|
||||
pasteServerConfig: false,
|
||||
exportConfig: false
|
||||
});
|
||||
|
||||
const exportConfigType = ref("toml");
|
||||
|
||||
const handleSubmit = useDebounceFn(() => {
|
||||
if (!formRef.value) return;
|
||||
formRef.value.validate(valid => {
|
||||
@ -195,6 +199,14 @@ onMounted(() => {
|
||||
checkAndResetVersion();
|
||||
}
|
||||
});
|
||||
ipcRenderer.on("Config.exportConfig.hook", (event, args) => {
|
||||
const { err, data } = args;
|
||||
console.log(err, data, "export");
|
||||
if (!err) {
|
||||
const { configPath } = data;
|
||||
ElMessageBox.alert(`配置路径:${configPath}`, `🎉 导出成功`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const handleSelectFile = (type: number, ext: string[]) => {
|
||||
@ -286,15 +298,34 @@ const handlePasteServerConfigBase64 = useDebounceFn(() => {
|
||||
visibles.pasteServerConfig = false;
|
||||
}, 300);
|
||||
|
||||
const handleShowExportDialog = () => {
|
||||
visibles.exportConfig = true;
|
||||
};
|
||||
|
||||
const handleExportConfig = useDebounceFn(() => {
|
||||
ipcRenderer.send("config.exportConfig", exportConfigType.value);
|
||||
visibles.exportConfig = false;
|
||||
}, 300);
|
||||
|
||||
const handleImportConfig = () => {};
|
||||
|
||||
onUnmounted(() => {
|
||||
ipcRenderer.removeAllListeners("Config.getConfig.hook");
|
||||
ipcRenderer.removeAllListeners("Config.saveConfig.hook");
|
||||
ipcRenderer.removeAllListeners("Config.versions.hook");
|
||||
ipcRenderer.removeAllListeners("Config.exportConfig.hook");
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="main">
|
||||
<breadcrumb />
|
||||
<breadcrumb>
|
||||
<el-button plain type="primary">
|
||||
<IconifyIconOffline icon="uploadRounded" />
|
||||
</el-button>
|
||||
<el-button plain type="primary" @click="handleShowExportDialog">
|
||||
<IconifyIconOffline icon="downloadRounded" />
|
||||
</el-button>
|
||||
</breadcrumb>
|
||||
<div class="app-container-breadcrumb pr-2" v-loading="loading > 0">
|
||||
<div class="w-full bg-white p-4 rounded drop-shadow-lg">
|
||||
<el-form
|
||||
@ -643,8 +674,8 @@ onUnmounted(() => {
|
||||
class="ml-2"
|
||||
type="primary"
|
||||
@click="handleSelectFile(1, ['crt'])"
|
||||
>选择</el-button
|
||||
>
|
||||
>选择
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
@ -682,8 +713,8 @@ onUnmounted(() => {
|
||||
class="ml-2"
|
||||
type="primary"
|
||||
@click="handleSelectFile(2, ['key'])"
|
||||
>选择</el-button
|
||||
>
|
||||
>选择
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
@ -721,8 +752,8 @@ onUnmounted(() => {
|
||||
class="ml-2"
|
||||
type="primary"
|
||||
@click="handleSelectFile(3, ['crt'])"
|
||||
>选择</el-button
|
||||
>
|
||||
>选择
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
@ -896,7 +927,7 @@ onUnmounted(() => {
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 链接导入服务器 -->
|
||||
<el-dialog
|
||||
v-model="visibles.copyServerConfig"
|
||||
title="复制链接"
|
||||
@ -916,7 +947,7 @@ onUnmounted(() => {
|
||||
:rows="8"
|
||||
></el-input>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 链接导出服务器-->
|
||||
<el-dialog
|
||||
v-model="visibles.pasteServerConfig"
|
||||
title="导入链接"
|
||||
@ -946,6 +977,39 @@ onUnmounted(() => {
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 配置导出-->
|
||||
<el-dialog
|
||||
v-model="visibles.exportConfig"
|
||||
title="导出配置"
|
||||
width="500"
|
||||
top="5%"
|
||||
>
|
||||
<el-alert
|
||||
class="mb-4"
|
||||
:title="`导出文件名为 frpc-desktop.${exportConfigType} 重复导出则覆盖`"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
/>
|
||||
<el-form>
|
||||
<el-form-item label="导出类型">
|
||||
<el-radio-group v-model="exportConfigType">
|
||||
<el-radio-button label="toml" value="toml" />
|
||||
<el-radio-button label="ini" value="ini" />
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button plain type="primary" @click="handleExportConfig">
|
||||
<IconifyIconOffline
|
||||
class="cursor-pointer mr-2"
|
||||
icon="downloadRounded"
|
||||
/>
|
||||
导 出
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -117,7 +117,7 @@ onUnmounted(() => {
|
||||
<breadcrumb>
|
||||
<div class="h-full flex items-center justify-center">
|
||||
<span class="text-sm font-bold">下载源: </span>
|
||||
<el-select class="w-24" v-model="currMirror">
|
||||
<el-select class="w-40" v-model="currMirror">
|
||||
<el-option
|
||||
v-for="m in mirrors"
|
||||
:label="m.name"
|
||||
|
@ -300,12 +300,9 @@ onUnmounted(() => {
|
||||
<!-- <coming-soon />-->
|
||||
<div class="main">
|
||||
<breadcrumb>
|
||||
<div
|
||||
class="cursor-pointer h-[36px] w-[36px] bg-[#5f3bb0] rounded text-white flex justify-center items-center"
|
||||
@click="handleOpenInsert"
|
||||
>
|
||||
<el-button class="mr-2" plain type="primary" @click="handleOpenInsert">
|
||||
<IconifyIconOffline icon="add" />
|
||||
</div>
|
||||
</el-button>
|
||||
</breadcrumb>
|
||||
<div class="app-container-breadcrumb pr-2" v-loading="loading.list > 0">
|
||||
<template v-if="proxys && proxys.length > 0">
|
||||
|
Loading…
Reference in New Issue
Block a user