feat(proxy): add toggle functionality for proxies and update styles

This commit is contained in:
2026-06-06 16:13:40 +08:00
parent e952a64f35
commit 40cb4f838c
4 changed files with 93 additions and 11 deletions
+2 -1
View File
@@ -27,4 +27,5 @@ dist/
node_modules/
design.md
agent.md
api-backend.md
api-backend.md
CLAUDE.md
+3 -1
View File
@@ -107,7 +107,9 @@ export const instanceApi = {
modifyProxy: (instanceID, proxyInfo) =>
api.post('/frpcAct/proxyMgr/modify', { instanceID, proxyInfo }),
deleteProxy: (instanceID, proxyName) =>
api.post('/frpcAct/proxyMgr/delete', { instanceID, proxyName })
api.post('/frpcAct/proxyMgr/delete', { instanceID, proxyName }),
switchProxy: (instanceID, proxyName, action) =>
api.post('/frpcAct/proxyMgr/switch', { instanceID, proxyName, action })
};
export const logApi = {
+87 -8
View File
@@ -172,20 +172,30 @@
</button>
</h3>
<div v-if="proxies.length > 0" class="proxy-list">
<div v-for="proxy in proxies" :key="proxy.name" class="proxy-item">
<div v-for="proxy in proxies" :key="proxy.name" class="proxy-item" :class="{ 'proxy-disabled': !proxy.enabled }">
<div class="proxy-header">
<span class="proxy-name">{{ proxy.name }}</span>
<div class="proxy-header-left">
<span class="proxy-name">{{ proxy.name }}</span>
<label class="toggle-switch" @click.stop>
<input
type="checkbox"
:checked="proxy.enabled"
@change="toggleProxy(proxy)"
>
<span class="toggle-slider"></span>
</label>
</div>
<div class="proxy-actions-right">
<span class="proxy-type">{{ proxy.type }}</span>
<div class="proxy-actions">
<button
class="common-btn edit-btn"
<button
class="common-btn edit-btn"
@click="editProxy(proxy)"
>
<i class="fas fa-edit"></i> Edit
</button>
<button
class="common-btn delete-btn"
<button
class="common-btn delete-btn"
@click="deleteProxy(proxy)"
>
<i class="fas fa-trash"></i> Delete
@@ -442,7 +452,8 @@ export default {
type: proxy.type,
localIP: proxy.localIP,
localPort: proxy.localPort,
remotePort: proxy.remotePort
remotePort: proxy.remotePort,
enabled: proxy.enabled !== undefined ? proxy.enabled : true
}));
} catch (error) {
showNotification(error.message || 'Load proxy list failed', 'error');
@@ -581,6 +592,17 @@ export default {
showDeleteProxyModal.value = true;
}
const toggleProxy = async (proxy) => {
const action = proxy.enabled ? 0 : 1;
try {
const result = await instanceApi.switchProxy(+instanceID.value, proxy.name, action);
showNotification(result.message || `Proxy "${proxy.name}" ${proxy.enabled ? 'disabled' : 'enabled'}`, 'success');
await loadProxies();
} catch (error) {
showNotification(error.message || 'Failed to toggle proxy', 'error');
}
};
const closeDeleteProxyModal = () => {
showDeleteProxyModal.value = false;
selectedProxyName.value = '';
@@ -601,8 +623,8 @@ export default {
try {
const result = await instanceApi.deleteProxy(instanceID.value, selectedProxyName.value);
showNotification(result.message || 'Proxy deleted successfully', 'success');
closeDeleteProxyModal();
await loadProxies();
closeDeleteProxyModal();
} catch (error) {
showNotification(error.message || 'Delete proxy failed', 'error');
} finally {
@@ -751,6 +773,7 @@ export default {
addProxy,
editProxy,
deleteProxy,
toggleProxy,
closeAddProxyModal,
closeDeleteProxyModal,
confirmDeleteProxy,
@@ -810,6 +833,12 @@ export default {
gap: 12px;
}
.proxy-header-left {
display: flex;
align-items: center;
gap: 10px;
}
.proxy-name {
font-family: 'SF Pro Display', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 18px;
@@ -1204,4 +1233,54 @@ export default {
.section:last-child .logs-container::-webkit-scrollbar-thumb:hover {
background: rgba(0, 0, 0, 0.3);
}
.toggle-switch {
position: relative;
display: inline-block;
width: 44px;
height: 24px;
cursor: pointer;
flex-shrink: 0;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.toggle-slider {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--surface-hover);
border-radius: 24px;
transition: background 0.3s;
}
.toggle-slider::before {
content: '';
position: absolute;
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background: white;
border-radius: 50%;
transition: transform 0.3s;
}
.toggle-switch input:checked + .toggle-slider {
background: var(--primary-color);
}
.toggle-switch input:checked + .toggle-slider::before {
transform: translateX(20px);
}
.proxy-disabled {
opacity: 0.48;
}
</style>
+1 -1
View File
@@ -1,7 +1,7 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
const APP_TARGET = '192.168.1.4:7000'
const APP_TARGET = '192.168.20.4:19090'
export default defineConfig({
define: {