1
All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 28s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 1m3s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 46s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 1m26s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 44s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 1m27s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 1m43s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m42s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 1m3s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 44s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 1m25s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 1m1s
All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 28s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 1m3s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 46s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 1m26s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 44s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 1m27s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 1m43s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m42s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 1m3s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 44s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 1m25s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 1m1s
This commit is contained in:
@@ -7,7 +7,8 @@ type ClientPlugin struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Config map[string]string `json:"config,omitempty"` // 插件配置
|
||||
Running bool `json:"running"` // 运行状态
|
||||
Config map[string]string `json:"config,omitempty"` // 插件配置
|
||||
}
|
||||
|
||||
// Client 客户端数据
|
||||
|
||||
@@ -299,14 +299,14 @@ func (h *ClientHandler) InstallPlugins(c *gin.Context) {
|
||||
|
||||
// PluginAction 客户端插件操作
|
||||
// @Summary 插件操作
|
||||
// @Description 对客户端插件执行操作(stop/restart/config/delete)
|
||||
// @Description 对客户端插件执行操作(start/stop/restart/config/delete)
|
||||
// @Tags 客户端
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security Bearer
|
||||
// @Param id path string true "客户端ID"
|
||||
// @Param pluginName path string true "插件名称"
|
||||
// @Param action path string true "操作类型" Enums(stop, restart, config, delete)
|
||||
// @Param action path string true "操作类型" Enums(start, stop, restart, config, delete)
|
||||
// @Param request body dto.ClientPluginActionRequest false "操作参数"
|
||||
// @Success 200 {object} Response
|
||||
// @Failure 400 {object} Response
|
||||
@@ -325,6 +325,8 @@ func (h *ClientHandler) PluginAction(c *gin.Context) {
|
||||
|
||||
var err error
|
||||
switch action {
|
||||
case "start":
|
||||
err = h.app.GetServer().StartClientPlugin(clientID, pluginName, req.RuleName)
|
||||
case "stop":
|
||||
err = h.app.GetServer().StopClientPlugin(clientID, pluginName, req.RuleName)
|
||||
case "restart":
|
||||
|
||||
@@ -36,6 +36,7 @@ type ServerInterface interface {
|
||||
SyncPluginConfigToClient(clientID string, pluginName string, config map[string]string) error
|
||||
InstallJSPluginToClient(clientID string, req JSPluginInstallRequest) error
|
||||
RestartClient(clientID string) error
|
||||
StartClientPlugin(clientID, pluginName, ruleName string) error
|
||||
StopClientPlugin(clientID, pluginName, ruleName string) error
|
||||
RestartClientPlugin(clientID, pluginName, ruleName string) error
|
||||
UpdateClientPluginConfig(clientID, pluginName, ruleName string, config map[string]string, restart bool) error
|
||||
|
||||
@@ -1231,6 +1231,20 @@ func (s *Server) RestartClient(clientID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartClientPlugin 启动客户端插件
|
||||
func (s *Server) StartClientPlugin(clientID, pluginName, ruleName string) error {
|
||||
s.mu.RLock()
|
||||
_, ok := s.clients[clientID]
|
||||
s.mu.RUnlock()
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("client %s not found or not online", clientID)
|
||||
}
|
||||
|
||||
// 重新发送安装请求来启动插件
|
||||
return s.reinstallJSPlugin(clientID, pluginName, ruleName)
|
||||
}
|
||||
|
||||
// StopClientPlugin 停止客户端插件
|
||||
func (s *Server) StopClientPlugin(clientID, pluginName, ruleName string) error {
|
||||
s.mu.RLock()
|
||||
|
||||
@@ -31,6 +31,8 @@ export const installPluginsToClient = (id: string, plugins: string[]) =>
|
||||
export const getRuleSchemas = () => get<RuleSchemasMap>('/rule-schemas')
|
||||
|
||||
// 客户端插件控制
|
||||
export const startClientPlugin = (clientId: string, pluginName: string, ruleName: string) =>
|
||||
post(`/client/${clientId}/plugin/${pluginName}/start`, { rule_name: ruleName })
|
||||
export const stopClientPlugin = (clientId: string, pluginName: string, ruleName: string) =>
|
||||
post(`/client/${clientId}/plugin/${pluginName}/stop`, { rule_name: ruleName })
|
||||
export const restartClientPlugin = (clientId: string, pluginName: string, ruleName: string) =>
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface ClientPlugin {
|
||||
name: string
|
||||
version: string
|
||||
enabled: boolean
|
||||
running: boolean
|
||||
config?: Record<string, string>
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ import {
|
||||
import {
|
||||
ArrowBackOutline, CreateOutline, TrashOutline,
|
||||
PushOutline, PowerOutline, AddOutline, SaveOutline, CloseOutline,
|
||||
SettingsOutline, StorefrontOutline, RefreshOutline, StopOutline
|
||||
SettingsOutline, StorefrontOutline, RefreshOutline, StopOutline, PlayOutline
|
||||
} from '@vicons/ionicons5'
|
||||
import {
|
||||
getClient, updateClient, deleteClient, pushConfigToClient, disconnectClient, restartClient,
|
||||
getClientPluginConfig, updateClientPluginConfig,
|
||||
getStorePlugins, installStorePlugin, getRuleSchemas, restartClientPlugin, stopClientPlugin, deleteClientPlugin
|
||||
getStorePlugins, installStorePlugin, getRuleSchemas, startClientPlugin, restartClientPlugin, stopClientPlugin, deleteClientPlugin
|
||||
} from '../api'
|
||||
import type { ProxyRule, ClientPlugin, ConfigField, StorePluginInfo, RuleSchemasMap } from '../types'
|
||||
|
||||
@@ -272,28 +272,43 @@ const handleRestartClient = () => {
|
||||
})
|
||||
}
|
||||
|
||||
// 启动客户端插件
|
||||
const handleStartPlugin = async (plugin: ClientPlugin) => {
|
||||
const rule = rules.value.find(r => r.type === plugin.name)
|
||||
const ruleName = rule?.name || plugin.name
|
||||
try {
|
||||
await startClientPlugin(clientId, plugin.name, ruleName)
|
||||
message.success(`已启动 ${plugin.name}`)
|
||||
plugin.running = true
|
||||
} catch (e: any) {
|
||||
message.error(e.message || '启动失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 重启客户端插件
|
||||
const handleRestartPlugin = async (plugin: ClientPlugin) => {
|
||||
// 找到使用此插件的规则
|
||||
const rule = rules.value.find(r => r.type === plugin.name)
|
||||
const ruleName = rule?.name || ''
|
||||
const ruleName = rule?.name || plugin.name
|
||||
try {
|
||||
await restartClientPlugin(clientId, plugin.name, ruleName)
|
||||
message.success(`已重启 ${plugin.name}`)
|
||||
plugin.running = true
|
||||
} catch (e: any) {
|
||||
message.error(e.response?.data || '重启失败')
|
||||
message.error(e.message || '重启失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 停止客户端插件
|
||||
const handleStopPlugin = async (plugin: ClientPlugin) => {
|
||||
const rule = rules.value.find(r => r.type === plugin.name)
|
||||
const ruleName = rule?.name || ''
|
||||
const ruleName = rule?.name || plugin.name
|
||||
try {
|
||||
await stopClientPlugin(clientId, plugin.name, ruleName)
|
||||
message.success(`已停止 ${plugin.name}`)
|
||||
plugin.running = false
|
||||
} catch (e: any) {
|
||||
message.error(e.response?.data || '停止失败')
|
||||
message.error(e.message || '停止失败')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,6 +586,7 @@ const handleDeletePlugin = (plugin: ClientPlugin) => {
|
||||
<th>名称</th>
|
||||
<th>版本</th>
|
||||
<th>状态</th>
|
||||
<th>启用</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -578,6 +594,10 @@ const handleDeletePlugin = (plugin: ClientPlugin) => {
|
||||
<tr v-for="plugin in clientPlugins" :key="plugin.name">
|
||||
<td>{{ plugin.name }}</td>
|
||||
<td>v{{ plugin.version }}</td>
|
||||
<td>
|
||||
<n-tag v-if="plugin.running" type="success" size="small">运行中</n-tag>
|
||||
<n-tag v-else type="default" size="small">已停止</n-tag>
|
||||
</td>
|
||||
<td>
|
||||
<n-switch :value="plugin.enabled" @update:value="toggleClientPlugin(plugin)" />
|
||||
</td>
|
||||
@@ -587,11 +607,15 @@ const handleDeletePlugin = (plugin: ClientPlugin) => {
|
||||
<template #icon><n-icon><SettingsOutline /></n-icon></template>
|
||||
配置
|
||||
</n-button>
|
||||
<n-button v-if="online && plugin.enabled" size="small" quaternary type="info" @click="handleRestartPlugin(plugin)">
|
||||
<n-button v-if="online && plugin.enabled && plugin.running" size="small" quaternary type="info" @click="handleRestartPlugin(plugin)">
|
||||
<template #icon><n-icon><RefreshOutline /></n-icon></template>
|
||||
重启
|
||||
</n-button>
|
||||
<n-button v-if="online && plugin.enabled" size="small" quaternary type="warning" @click="handleStopPlugin(plugin)">
|
||||
<n-button v-if="online && plugin.enabled && !plugin.running" size="small" quaternary type="success" @click="handleStartPlugin(plugin)">
|
||||
<template #icon><n-icon><PlayOutline /></n-icon></template>
|
||||
启动
|
||||
</n-button>
|
||||
<n-button v-if="online && plugin.enabled && plugin.running" size="small" quaternary type="warning" @click="handleStopPlugin(plugin)">
|
||||
<template #icon><n-icon><StopOutline /></n-icon></template>
|
||||
停止
|
||||
</n-button>
|
||||
|
||||
Reference in New Issue
Block a user