新版本

This commit is contained in:
刘嘉伟 2024-08-17 17:22:46 +08:00
parent ed66824931
commit fb2a8ecd51
7 changed files with 101 additions and 74 deletions

View File

@ -29,9 +29,12 @@
- [x] 增加udp代理类型 - [x] 增加udp代理类型
- [x] 支持快速分享frps - [x] 支持快速分享frps
- [x] 增加快速选择本地端口 - [x] 增加快速选择本地端口
- [ ] 支持stcp代理类型 - [x] 支持stcp代理类型
- [ ] 支持配的导出导入 - [ ] 支持所有配置的导入导出
- [ ] 优化配置 - [ ] 支持代理的导出导入导出
- [ ] 一键清空所有配置
- [ ] 通过镜像站下载frp
- [ ] tcp、udp协议支持批量端口
## 常见问题 ## 常见问题
@ -39,6 +42,7 @@
执行命令:`sudo xattr -cr Frpc-Desktop.app` 执行命令:`sudo xattr -cr Frpc-Desktop.app`
## 里程碑 ## 里程碑
- 2024-08-17: 发布v1.0.8版本 支持stcp代理
- 2024-08-11: 发布v1.0.7版本 - 2024-08-11: 发布v1.0.7版本
- 2024-08-09: 发布v1.0.6版本 - 2024-08-09: 发布v1.0.6版本
- 2024-08-06: 发布v1.0.5版本 - 2024-08-06: 发布v1.0.5版本

View File

@ -1,6 +1,6 @@
{ {
"name": "Frpc-Desktop", "name": "Frpc-Desktop",
"version": "1.0.7", "version": "1.0.8",
"main": "dist-electron/main/index.js", "main": "dist-electron/main/index.js",
"description": "FRP跨平台桌面客户端可视化配置轻松实现内网穿透", "description": "FRP跨平台桌面客户端可视化配置轻松实现内网穿透",
"repository": "github:luckjiawei/frpc-desktop", "repository": "github:luckjiawei/frpc-desktop",

View File

@ -28,6 +28,7 @@ import Error from "@iconify-icons/material-symbols/error";
import ContentCopy from "@iconify-icons/material-symbols/content-copy"; import ContentCopy from "@iconify-icons/material-symbols/content-copy";
import ContentPasteGo from "@iconify-icons/material-symbols/content-paste-go"; import ContentPasteGo from "@iconify-icons/material-symbols/content-paste-go";
import Edit from "@iconify-icons/material-symbols/edit"; import Edit from "@iconify-icons/material-symbols/edit";
import CheckBox from "@iconify-icons/material-symbols/check-box";
addIcon("cloud", Cloud); addIcon("cloud", Cloud);
addIcon("rocket-launch-rounded", RocketLaunchRounded); addIcon("rocket-launch-rounded", RocketLaunchRounded);
@ -51,4 +52,5 @@ addIcon("error", Error);
addIcon("content-copy", ContentCopy); addIcon("content-copy", ContentCopy);
addIcon("content-paste-go", ContentPasteGo); addIcon("content-paste-go", ContentPasteGo);
addIcon("edit", Edit); addIcon("edit", Edit);
addIcon("check-box", CheckBox);

View File

@ -23,7 +23,7 @@ type ShareLinkConfig = {
}; };
const defaultFormData = ref<FrpConfig>({ const defaultFormData = ref<FrpConfig>({
currentVersion: "", currentVersion: -1,
serverAddr: "", serverAddr: "",
serverPort: 7000, serverPort: 7000,
authMethod: "", authMethod: "",
@ -155,7 +155,7 @@ const checkAndResetVersion = () => {
currentVersion && currentVersion &&
!versions.value.some(item => item.id === currentVersion) !versions.value.some(item => item.id === currentVersion)
) { ) {
formData.value.currentVersion = ""; formData.value.currentVersion = null;
} }
}; };

View File

@ -1,11 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import {defineComponent, onMounted, onUnmounted, ref} from "vue"; import { defineComponent, onMounted, onUnmounted, ref } from "vue";
import {ipcRenderer} from "electron"; import { ipcRenderer } from "electron";
import moment from "moment"; import moment from "moment";
import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue"; import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue";
import {ElMessage} from "element-plus"; import { ElMessage } from "element-plus";
import {useDebounceFn} from "@vueuse/core"; import { useDebounceFn } from "@vueuse/core";
defineComponent({ defineComponent({
name: "Download" name: "Download"
@ -14,7 +13,7 @@ defineComponent({
const versions = ref<Array<FrpVersion>>([]); const versions = ref<Array<FrpVersion>>([]);
const loading = ref(1); const loading = ref(1);
const downloadPercentage = ref(0); const downloadPercentage = ref(0);
const downloading = ref<Map<string, number>>(new Map<string, number>()); const downloading = ref<Map<number, number>>(new Map<number, number>());
/** /**
* 获取版本 * 获取版本
@ -47,30 +46,30 @@ const handleInitDownloadHook = () => {
ipcRenderer.on("Download.frpVersionHook", (event, args) => { ipcRenderer.on("Download.frpVersionHook", (event, args) => {
loading.value--; loading.value--;
versions.value = args.map(m => { versions.value = args.map(m => {
m.published_at = moment(m.published_at).format("YYYY-MM-DD HH:mm:ss") m.published_at = moment(m.published_at).format("YYYY-MM-DD");
return m as FrpVersion; return m as FrpVersion;
}) as Array<FrpVersion>; }) as Array<FrpVersion>;
console.log(versions, 'versions') console.log(versions, "versions");
}); });
// //
ipcRenderer.on("Download.frpVersionDownloadOnProgress", (event, args) => { ipcRenderer.on("Download.frpVersionDownloadOnProgress", (event, args) => {
const {id, progress} = args; const { id, progress } = args;
downloading.value.set( downloading.value.set(
id, id,
Number(Number(progress.percent * 100).toFixed(2)) Number(Number(progress.percent * 100).toFixed(2))
); );
}); });
ipcRenderer.on("Download.frpVersionDownloadOnCompleted", (event, args) => { ipcRenderer.on("Download.frpVersionDownloadOnCompleted", (event, args) => {
downloading.value.delete(args); downloading.value.delete(args);
const version: FrpVersion | undefined = versions.value.find( const version: FrpVersion | undefined = versions.value.find(
f => f.id === args f => f.id === args
); );
if (version) { if (version) {
version.download_completed = true; version.download_completed = true;
} }
}); });
ipcRenderer.on("Download.deleteVersion.hook", (event, args) => { ipcRenderer.on("Download.deleteVersion.hook", (event, args) => {
const {err, data} = args const { err, data } = args;
if (!err) { if (!err) {
loading.value++; loading.value++;
ElMessage({ ElMessage({
@ -79,8 +78,7 @@ const handleInitDownloadHook = () => {
}); });
handleLoadVersions(); handleLoadVersions();
} }
});
})
}; };
onMounted(() => { onMounted(() => {
@ -100,7 +98,7 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<div class="main"> <div class="main">
<breadcrumb/> <breadcrumb />
<!-- <breadcrumb>--> <!-- <breadcrumb>-->
<!-- <div class="flex items-center">--> <!-- <div class="flex items-center">-->
<!-- <el-checkbox>加速下载</el-checkbox>--> <!-- <el-checkbox>加速下载</el-checkbox>-->
@ -110,17 +108,17 @@ onUnmounted(() => {
<template v-if="versions && versions.length > 0"> <template v-if="versions && versions.length > 0">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col <el-col
v-for="version in versions" v-for="version in versions"
:key="version.id" :key="version.id"
:lg="8" :lg="8"
:md="8" :md="8"
:sm="12" :sm="12"
:xl="6" :xl="6"
:xs="24" :xs="24"
class="mb-[20px]" class="mb-[20px]"
> >
<div <div
class="w-full bg-white rounded p-4 drop-shadow-lg flex justify-between items-center" class="w-full bg-white rounded p-4 drop-shadow-lg flex justify-between items-center"
> >
<div class="left"> <div class="left">
<div class="mb-2"> <div class="mb-2">
@ -128,7 +126,7 @@ onUnmounted(() => {
<!-- <el-tag class="ml-2">原文件名{{ version.assets[0]?.name }}</el-tag>--> <!-- <el-tag class="ml-2">原文件名{{ version.assets[0]?.name }}</el-tag>-->
</div> </div>
<div class="text-sm"> <div class="text-sm">
发布时间<span class="text-gray-00">{{ 发布时间<span class="text-gray-00 text-sm text-primary font-bold">{{
// moment(version.published_at).format("YYYY-MM-DD HH:mm:ss") // moment(version.published_at).format("YYYY-MM-DD HH:mm:ss")
version.published_at version.published_at
}}</span> }}</span>
@ -136,23 +134,41 @@ onUnmounted(() => {
</div> </div>
<div class="right"> <div class="right">
<div v-if="version.download_completed"> <div v-if="version.download_completed">
<el-button type="text">已下载</el-button> <!-- <span class="text-[12px] text-primary font-bold mr-2"-->
<el-button type="text" class="danger-text" @click="handleDeleteVersion(version)"> <!-- >已下载</span-->
<IconifyIconOffline class="mr-1" icon="delete-rounded"/> <!-- >-->
<el-button
type="text"
@click="handleDeleteVersion(version)"
>
<IconifyIconOffline class="mr-1" icon="check-box" />
已下载
</el-button>
<!-- <el-button type="text"></el-button>-->
<el-button
type="text"
class="danger-text"
@click="handleDeleteVersion(version)"
>
<IconifyIconOffline class="mr-1" icon="delete-rounded" />
删除 删除
</el-button> </el-button>
</div> </div>
<template v-else> <template v-else>
<div class="w-32" v-if="downloading.has(version.id)"> <div class="w-32" v-if="downloading.has(version.id)">
<el-progress <el-progress
:percentage="downloading.get(version.id)" :percentage="downloading.get(version.id)"
:text-inside="false" :text-inside="false"
/> />
</div> </div>
<el-button v-else size="small" type="primary" @click="handleDownload(version)"> <el-button
<IconifyIconOffline class="mr-1" icon="download"/> v-else
size="small"
type="primary"
@click="handleDownload(version)"
>
<IconifyIconOffline class="mr-1" icon="download" />
下载 下载
</el-button> </el-button>
</template> </template>
@ -160,13 +176,12 @@ onUnmounted(() => {
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
</template> </template>
<div <div
v-else v-else
class="w-full h-full bg-white rounded p-2 overflow-hidden drop-shadow-xl flex justify-center items-center" class="w-full h-full bg-white rounded p-2 overflow-hidden drop-shadow-xl flex justify-center items-center"
> >
<el-empty description="暂无可用版本"/> <el-empty description="暂无可用版本" />
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,10 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import {defineComponent, onMounted, onUnmounted, ref} from "vue"; import { defineComponent, onMounted, onUnmounted, ref } from "vue";
import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue"; import Breadcrumb from "@/layout/compoenets/Breadcrumb.vue";
import {ipcRenderer} from "electron"; import { ipcRenderer } from "electron";
import {ElMessageBox} from "element-plus"; import { ElMessageBox } from "element-plus";
import router from "@/router"; import router from "@/router";
import {useDebounceFn} from "@vueuse/core"; import { useDebounceFn, useIntervalFn } from "@vueuse/core";
defineComponent({ defineComponent({
name: "Home" name: "Home"
@ -29,12 +29,12 @@ const handleButtonClick = useDebounceFn(() => {
}, 300); }, 300);
onMounted(() => { onMounted(() => {
setInterval(() => { useIntervalFn(() => {
ipcRenderer.invoke("frpc.running").then(data => { ipcRenderer.invoke("frpc.running").then(data => {
running.value = data; running.value = data;
console.log('进程状态', data) console.log("进程状态", data);
}); });
}, 300); }, 500);
ipcRenderer.on("Home.frpc.start.error.hook", (event, args) => { ipcRenderer.on("Home.frpc.start.error.hook", (event, args) => {
if (args) { if (args) {
@ -58,37 +58,37 @@ onUnmounted(() => {
<template> <template>
<div class="main"> <div class="main">
<breadcrumb/> <breadcrumb />
<div class="app-container-breadcrumb"> <div class="app-container-breadcrumb">
<div <div
class="w-full h-full bg-white p-4 rounded drop-shadow-lg overflow-y-auto flex justify-center items-center" class="w-full h-full bg-white p-4 rounded drop-shadow-lg overflow-y-auto flex justify-center items-center"
> >
<div class="flex"> <div class="flex">
<div <div
class="w-40 h-40 border-[#5A3DAA] text-[#5A3DAA] border-4 rounded-full flex justify-center items-center text-[100px] relative" class="w-40 h-40 border-[#5A3DAA] text-[#5A3DAA] border-4 rounded-full flex justify-center items-center text-[100px] relative"
> >
<transition name="fade"> <transition name="fade">
<div <div
v-show="running" v-show="running"
class="z-0 rounded-full opacity-20 left-circle bg-[#5A3DAA] w-full h-full animation-rotate-1" class="z-0 rounded-full opacity-20 left-circle bg-[#5A3DAA] w-full h-full animation-rotate-1"
/> />
</transition> </transition>
<transition name="fade"> <transition name="fade">
<div <div
v-show="running" v-show="running"
class="z-0 rounded-full opacity-20 right-circle top-[10px] bg-[#5A3DAA] w-full h-full animation-rotate-2" class="z-0 rounded-full opacity-20 right-circle top-[10px] bg-[#5A3DAA] w-full h-full animation-rotate-2"
/> />
</transition> </transition>
<transition name="fade"> <transition name="fade">
<div <div
v-show="running" v-show="running"
class="z-0 rounded-full opacity-20 top-circle bg-[#5A3DAA] w-full h-full animation-rotate-3" class="z-0 rounded-full opacity-20 top-circle bg-[#5A3DAA] w-full h-full animation-rotate-3"
/> />
</transition> </transition>
<div <div
class="bg-white z-10 w-full h-full absolute rounded-full flex justify-center items-center" class="bg-white z-10 w-full h-full absolute rounded-full flex justify-center items-center"
> >
<IconifyIconOffline icon="rocket-launch-rounded"/> <IconifyIconOffline icon="rocket-launch-rounded" />
</div> </div>
</div> </div>
<div class="flex justify-center items-center"> <div class="flex justify-center items-center">
@ -96,14 +96,15 @@ onUnmounted(() => {
<transition name="fade"> <transition name="fade">
<div class="font-bold text-2xl text-center"> <div class="font-bold text-2xl text-center">
<IconifyIconOffline <IconifyIconOffline
v-if="running" v-if="running"
class="text-[#7EC050] class="text-[#7EC050] inline-block relative top-1"
inline-block relative top-1" icon="check-circle-rounded"
icon="check-circle-rounded"/> />
<IconifyIconOffline <IconifyIconOffline
v-else v-else
class="text-[#E47470] inline-block relative top-1" class="text-[#E47470] inline-block relative top-1"
icon="error"/> icon="error"
/>
Frpc {{ running ? "已启动" : "已断开" }} Frpc {{ running ? "已启动" : "已断开" }}
</div> </div>
</transition> </transition>
@ -115,11 +116,16 @@ onUnmounted(() => {
<!-- >查看日志--> <!-- >查看日志-->
<!-- </el-button>--> <!-- </el-button>-->
<div class="w-full justify-center text-center"> <div class="w-full justify-center text-center">
<el-link v-if="running" type="primary" @click="$router.replace({ name: 'Logger' })">查看日志</el-link> <el-link
v-if="running"
type="primary"
@click="$router.replace({ name: 'Logger' })"
>查看日志</el-link
>
</div> </div>
<div <div
class="w-full h-8 bg-[#563EA4] rounded flex justify-center items-center text-white font-bold cursor-pointer" class="w-full h-8 bg-[#563EA4] rounded flex justify-center items-center text-white font-bold cursor-pointer"
@click="handleButtonClick" @click="handleButtonClick"
> >
{{ running ? "断 开" : "启 动" }} {{ running ? "断 开" : "启 动" }}
</div> </div>

4
types/global.d.ts vendored
View File

@ -25,7 +25,7 @@ declare global {
serverName: string; serverName: string;
secretKey: string; secretKey: string;
bindAddr: string; bindAddr: string;
bindPort: string; bindPort: number;
}; };
/** /**
@ -41,7 +41,7 @@ declare global {
* *
*/ */
type FrpVersion = { type FrpVersion = {
id: string; id: number;
name: string; name: string;
published_at: string; published_at: string;
download_completed: boolean; download_completed: boolean;