Remove unused legacy monitor helpers

This commit is contained in:
2026-06-09 22:43:10 +08:00
parent 885f87b6f8
commit 868a9ce2d3
3 changed files with 3 additions and 851 deletions
+3 -230
View File
@@ -39,46 +39,6 @@ export namespace WebSocketApi {
heartbeatInterval?: number;
}
/** 监控数据类型 */
export interface MonitorMessage {
type:
| 'get_overview'
| 'get_realtime'
| 'set_interval'
| 'start_monitor'
| 'stop_monitor'
| 'test_connection';
interval?: number;
timestamp?: string;
}
/** 服务器监控数据 */
export interface ServerMonitorData {
basic_info?: any;
cpu_info?: any;
memory_info?: any;
disk_info?: any;
network_info?: any;
process_info?: any;
system_load?: any;
boot_time?: any;
users_info?: any;
timestamp?: string;
}
/** Redis监控数据 */
export interface RedisMonitorData {
connection_id?: string;
connection_name?: string;
status?: string;
info?: any;
memory?: any;
stats?: any;
keyspace?: any[];
clients?: any[];
slow_log?: any[];
timestamp?: string;
}
}
/**
@@ -430,7 +390,7 @@ export function createWebSocket(
}
/**
* 创建测试WebSocket连接
* Create test WebSocket connection
*/
export function createTestWebSocket(
callbacks?: WebSocketApi.WebSocketCallbacks,
@@ -439,7 +399,7 @@ export function createTestWebSocket(
}
/**
* 创建通知WebSocket连接
* Create notification WebSocket connection
*/
export function createNotificationWebSocket(
callbacks?: WebSocketApi.WebSocketCallbacks,
@@ -448,197 +408,10 @@ export function createNotificationWebSocket(
}
/**
* 创建服务器监控WebSocket连接
*/
export function createServerMonitorWebSocket(
callbacks?: WebSocketApi.WebSocketCallbacks,
): WebSocketManager {
return createWebSocket('/ws/server-monitor/', callbacks);
}
/**
* 创建Redis监控WebSocket连接
*/
export function createRedisMonitorWebSocket(
callbacks?: WebSocketApi.WebSocketCallbacks,
): WebSocketManager {
return createWebSocket('/ws/redis-monitor/', callbacks);
}
/**
* 创建数据库监控WebSocket连接
*/
export function createDatabaseMonitorWebSocket(
callbacks?: WebSocketApi.WebSocketCallbacks,
): WebSocketManager {
return createWebSocket('/ws/database-monitor/', callbacks);
}
/**
* 监控WebSocket管理器类
*/
export class MonitorWebSocketManager extends WebSocketManager {
/**
* 获取概览信息
*/
getOverview(): boolean {
return this.send({
type: 'get_overview',
timestamp: new Date().toISOString(),
});
}
/**
* 获取实时统计
*/
getRealtime(): boolean {
return this.send({
type: 'get_realtime',
timestamp: new Date().toISOString(),
});
}
/**
* 开始监控
*/
startMonitoring(): boolean {
return this.send({
type: 'start_monitor',
timestamp: new Date().toISOString(),
});
}
/**
* 停止监控
*/
stopMonitoring(): boolean {
return this.send({
type: 'stop_monitor',
timestamp: new Date().toISOString(),
});
}
/**
* 测试连接(适用于Redis监控)
*/
testConnection(): boolean {
return this.send({
type: 'test_connection',
timestamp: new Date().toISOString(),
});
}
}
/**
* 创建服务器监控WebSocket管理器
*/
export function createServerMonitorManager(
callbacks?: WebSocketApi.WebSocketCallbacks,
): MonitorWebSocketManager {
const wsManager = createServerMonitorWebSocket(callbacks);
// 创建增强版管理器
return Object.setPrototypeOf(wsManager, MonitorWebSocketManager.prototype);
}
/**
* 创建Redis监控WebSocket管理器
*/
export function createRedisMonitorManager(
callbacks?: WebSocketApi.WebSocketCallbacks,
): MonitorWebSocketManager {
const wsManager = createRedisMonitorWebSocket(callbacks);
// 创建增强版管理器
return Object.setPrototypeOf(wsManager, MonitorWebSocketManager.prototype);
}
/**
* 数据库监控WebSocket管理器类
*/
export class DatabaseMonitorWebSocketManager extends WebSocketManager {
/**
* 获取数据库配置列表
*/
getConfigs(): boolean {
return this.send({
type: 'get_configs',
timestamp: new Date().toISOString(),
});
}
/**
* 获取概览信息
*/
getOverview(dbName: string): boolean {
return this.send({
type: 'get_overview',
db_name: dbName,
timestamp: new Date().toISOString(),
});
}
/**
* 获取实时统计
*/
getRealtime(dbName: string): boolean {
return this.send({
type: 'get_realtime',
db_name: dbName,
timestamp: new Date().toISOString(),
});
}
/**
* 开始监控
*/
startMonitoring(dbName: string): boolean {
return this.send({
type: 'start_monitor',
db_name: dbName,
timestamp: new Date().toISOString(),
});
}
/**
* 停止监控
*/
stopMonitoring(): boolean {
return this.send({
type: 'stop_monitor',
timestamp: new Date().toISOString(),
});
}
/**
* 测试连接
*/
testConnection(dbName: string): boolean {
return this.send({
type: 'test_connection',
db_name: dbName,
timestamp: new Date().toISOString(),
});
}
}
/**
* 创建聊天WebSocket连接
* Create chat WebSocket connection
*/
export function createChatWebSocket(
callbacks?: WebSocketApi.WebSocketCallbacks,
): WebSocketManager {
return createWebSocket('/ws/chat/', callbacks);
}
/**
* 创建数据库监控WebSocket管理器
*/
export function createDatabaseMonitorManager(
callbacks?: WebSocketApi.WebSocketCallbacks,
): DatabaseMonitorWebSocketManager {
const wsManager = createDatabaseMonitorWebSocket(callbacks);
// 创建增强版管理器
return Object.setPrototypeOf(
wsManager,
DatabaseMonitorWebSocketManager.prototype,
);
}
@@ -1,531 +0,0 @@
import type {
DataSourceParamConfig,
FormLifecycleHook,
FormLifecycleMode,
} from '#/components/form-design/store/formDesignStore';
import { ElMessage } from 'element-plus/es/components/message/index';
import { getWorkflowDetailApi, runWorkflowApi } from '#/api/ai-platform/ai-platform';
import { requestClient } from '#/api/request';
export interface FormLifecycleContext {
formCode: string;
formData: Record<string, any>;
editId?: string;
routeQuery?: Record<string, any>;
savedId?: string;
error?: any;
payload?: { main: Record<string, any>; sub_tables?: Record<string, any> };
response?: any;
}
export interface FormLifecycleResult {
blocked: boolean;
}
export interface FormLoadPipelineOptions {
hooks?: FormLifecycleHook[];
mode: FormLifecycleMode;
formCode: string;
formData: Record<string, any>;
editId?: string;
routeQuery?: Record<string, any>;
initForm: () => void;
applyDefaults?: () => void;
fetchDetail?: () => Promise<void>;
onBlocked: () => void;
}
const WORKFLOW_TYPES = ['data_process', 'automation'] as const;
const BLOCKING_EVENTS = new Set<FormLifecycleHook['event']>([
'beforeLoad',
'beforeSubmit',
]);
function isBlockingEvent(event: FormLifecycleHook['event']) {
return BLOCKING_EVENTS.has(event);
}
export function replaceLifecycleVariables(
template: string,
formData: Record<string, any>,
savedId?: string,
): string {
if (!template) return '';
let result = template.replaceAll(/\{id\}/g, savedId ? String(savedId) : '{id}');
result = result.replaceAll(/\{(\w+)\}/g, (match, key) => {
if (key === 'id') {
return savedId === undefined ? match : String(savedId);
}
return formData[key] === undefined ? match : String(formData[key]);
});
return result;
}
function createScriptHelpers(rootData: Record<string, any>) {
const $setValue = (field: string, value: any) => {
if (field.includes('.')) {
const [table, subField] = field.split('.');
if (Array.isArray(rootData[table!])) {
rootData[table!].forEach((row: any) => {
row[subField!] = value;
});
}
} else {
rootData[field] = value;
}
};
const $setValues = (obj: Record<string, any>) => {
for (const [field, value] of Object.entries(obj)) {
$setValue(field, value);
}
};
const $getValue = (field: string) => {
if (field.includes('.')) {
const [table, subField] = field.split('.');
if (Array.isArray(rootData[table!])) {
return rootData[table!].map((row: any) => row[subField!]);
}
return undefined;
}
return rootData[field];
};
const $getSubTable = (field: string) => rootData[field] || [];
const $setSubTable = (field: string, rows: any[]) => {
rootData[field] = rows;
};
const $addRow = (field: string, row: any) => {
if (!Array.isArray(rootData[field])) {
rootData[field] = [];
}
rootData[field].push({ _id: `${Date.now()}_${Math.random()}`, ...row });
};
const $removeRow = (field: string, index: number) => {
if (Array.isArray(rootData[field])) {
rootData[field].splice(index, 1);
}
};
const $updateRow = (field: string, index: number, data: any) => {
if (Array.isArray(rootData[field]) && rootData[field][index]) {
Object.assign(rootData[field][index], data);
}
};
const $clearSubTable = (field: string) => {
rootData[field] = [];
};
return {
$setValue,
$setValues,
$getValue,
$getSubTable,
$setSubTable,
$addRow,
$removeRow,
$updateRow,
$clearSubTable,
};
}
function buildDataSourceParams(
params: DataSourceParamConfig[] | undefined,
formData: Record<string, any>,
): Record<string, any> {
const result: Record<string, any> = {};
for (const p of params || []) {
if (p.valueSource === 'fixed') {
result[p.name] = p.fixedValue ?? p.default ?? '';
} else if (p.valueSource === 'field' && p.sourceField) {
result[p.name] = formData[p.sourceField] ?? '';
}
}
return result;
}
function buildWorkflowInputs(
hook: FormLifecycleHook,
context: FormLifecycleContext,
): Record<string, any> {
const inputs: Record<string, any> = {
form_code: context.formCode,
};
const dataId = context.savedId || context.editId;
if (dataId) {
inputs.form_data_id = dataId;
}
for (const mapping of hook.actionConfig.workflowInputs || []) {
if (mapping.valueSource === 'field' && mapping.sourceField) {
inputs[mapping.name] = context.formData[mapping.sourceField] ?? '';
} else {
inputs[mapping.name] = mapping.fixedValue ?? mapping.default ?? '';
}
}
return inputs;
}
function appendLoadScriptArgs(
hook: FormLifecycleHook,
context: FormLifecycleContext,
argNames: string[],
argValues: any[],
) {
if (hook.event === 'beforeLoad' || hook.event === 'afterLoadSuccess') {
argNames.push('$editId', '$query');
argValues.push(context.editId, context.routeQuery || {});
}
if (hook.event === 'afterLoadSuccess') {
argNames.push('$savedId');
argValues.push(context.savedId || context.editId);
}
if (hook.event === 'afterLoadFail' || hook.event === 'afterSubmitFail') {
argNames.push('$error');
argValues.push(context.error);
}
if (hook.event === 'afterSubmitSuccess') {
argNames.push('$savedId', '$response');
argValues.push(context.savedId, context.response);
}
}
async function executeScriptHook(
hook: FormLifecycleHook,
context: FormLifecycleContext,
mode: FormLifecycleMode,
): Promise<boolean | void> {
const script = hook.actionConfig.script;
if (!script?.trim()) return;
const rootData = context.formData;
const helpers = createScriptHelpers(rootData);
const argNames = [
'model',
'$root',
'$mode',
'$event',
'$setValue',
'$setValues',
'$getValue',
'$getSubTable',
'$setSubTable',
'$addRow',
'$removeRow',
'$updateRow',
'$clearSubTable',
];
const argValues: any[] = [
rootData,
rootData,
mode,
hook.event,
helpers.$setValue,
helpers.$setValues,
helpers.$getValue,
helpers.$getSubTable,
helpers.$setSubTable,
helpers.$addRow,
helpers.$removeRow,
helpers.$updateRow,
helpers.$clearSubTable,
];
appendLoadScriptArgs(hook, context, argNames, argValues);
const fn = new Function(...argNames, script);
return fn(...argValues);
}
async function executeDataSourceHook(
hook: FormLifecycleHook,
context: FormLifecycleContext,
mode: FormLifecycleMode,
): Promise<any> {
const dsCode = hook.actionConfig.dataSourceCode;
if (!dsCode) return;
const params = buildDataSourceParams(
hook.actionConfig.dataSourceParams,
context.formData,
);
const response = await requestClient.get(
`/api/core/data-source/execute/${dsCode}`,
{ params },
);
const callbackScript = hook.actionConfig.callbackScript;
if (callbackScript?.trim()) {
const rootData = context.formData;
const helpers = createScriptHelpers(rootData);
const argNames = [
'model',
'$root',
'$result',
'$mode',
'$event',
'$setValue',
'$setValues',
'$getValue',
'$getSubTable',
'$setSubTable',
'$addRow',
'$removeRow',
'$updateRow',
'$clearSubTable',
];
const argValues: any[] = [
rootData,
rootData,
response,
mode,
hook.event,
helpers.$setValue,
helpers.$setValues,
helpers.$getValue,
helpers.$getSubTable,
helpers.$setSubTable,
helpers.$addRow,
helpers.$removeRow,
helpers.$updateRow,
helpers.$clearSubTable,
];
appendLoadScriptArgs(hook, context, argNames, argValues);
const fn = new Function(...argNames, callbackScript);
const callbackResult = fn(...argValues);
if (isBlockingEvent(hook.event) && callbackResult === false) {
return false;
}
}
return response;
}
function executeRedirectHook(
hook: FormLifecycleHook,
context: FormLifecycleContext,
) {
const savedId = context.savedId || context.editId;
const url = replaceLifecycleVariables(
hook.actionConfig.url || '',
context.formData,
savedId,
);
if (!url) return;
if (hook.actionConfig.openInNewTab) {
window.open(url, '_blank');
} else {
window.location.href = url;
}
}
function executeMessageHook(
hook: FormLifecycleHook,
context: FormLifecycleContext,
) {
const savedId = context.savedId || context.editId;
const message = replaceLifecycleVariables(
hook.actionConfig.message || '',
context.formData,
savedId,
);
if (!message) return;
const messageType = hook.actionConfig.messageType || 'success';
ElMessage[messageType](message);
}
async function executeWorkflowHook(
hook: FormLifecycleHook,
context: FormLifecycleContext,
) {
const workflowId = hook.actionConfig.workflowId;
if (!workflowId) return;
const run = async () => {
const workflow = await getWorkflowDetailApi(workflowId);
if (
workflow.status !== 'published' ||
!WORKFLOW_TYPES.includes(
workflow.workflow_type as (typeof WORKFLOW_TYPES)[number],
)
) {
throw new Error('Workflow is not published or type not allowed');
}
const inputs = buildWorkflowInputs(hook, context);
const result = await runWorkflowApi(workflowId, inputs);
if (result.status === 'failed') {
throw new Error(result.error_message || 'Workflow execution failed');
}
return result;
};
if (hook.actionConfig.async) {
run().catch((error) => {
console.warn('[FormLifecycleHook] async workflow failed:', error);
});
return;
}
await run();
}
async function executeSingleHook(
hook: FormLifecycleHook,
context: FormLifecycleContext,
mode: FormLifecycleMode,
): Promise<{ blocked: boolean }> {
switch (hook.actionType) {
case 'script': {
const result = await executeScriptHook(hook, context, mode);
if (isBlockingEvent(hook.event) && result === false) {
return { blocked: true };
}
break;
}
case 'dataSource': {
const result = await executeDataSourceHook(hook, context, mode);
if (isBlockingEvent(hook.event) && result === false) {
return { blocked: true };
}
break;
}
case 'redirect': {
executeRedirectHook(hook, context);
if (hook.event === 'beforeLoad') {
return { blocked: true };
}
break;
}
case 'message': {
executeMessageHook(hook, context);
break;
}
case 'workflow': {
await executeWorkflowHook(hook, context);
break;
}
default:
break;
}
return { blocked: false };
}
function getActiveHooks(
hooks: FormLifecycleHook[] | undefined,
event: FormLifecycleHook['event'],
mode: FormLifecycleMode,
): FormLifecycleHook[] {
return (hooks || [])
.filter(
(hook) =>
hook.enabled &&
hook.event === event &&
Array.isArray(hook.modes) &&
hook.modes.includes(mode),
)
.sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0));
}
function getBlockErrorMessage(event: FormLifecycleHook['event']) {
if (event === 'beforeLoad') {
return '表单加载被阻止';
}
return '提交前校验未通过';
}
export async function executeFormLifecycleHooks(
hooks: FormLifecycleHook[] | undefined,
event: FormLifecycleHook['event'],
mode: FormLifecycleMode,
context: FormLifecycleContext,
): Promise<FormLifecycleResult> {
const activeHooks = getActiveHooks(hooks, event, mode);
for (const hook of activeHooks) {
try {
const result = await executeSingleHook(hook, context, mode);
if (result.blocked) {
return { blocked: true };
}
} catch (error) {
console.warn(`[FormLifecycleHook] ${hook.id} failed:`, error);
if (isBlockingEvent(hook.event) && hook.blockOnError) {
ElMessage.error(
error instanceof Error ? error.message : getBlockErrorMessage(hook.event),
);
return { blocked: true };
}
}
}
return { blocked: false };
}
export async function runFormLoadPipeline(
opts: FormLoadPipelineOptions,
): Promise<{ loaded: boolean }> {
const {
hooks,
mode,
formCode,
formData,
editId,
routeQuery,
initForm,
applyDefaults,
fetchDetail,
onBlocked,
} = opts;
const baseContext: FormLifecycleContext = {
formCode,
formData,
editId,
routeQuery,
};
const beforeResult = await executeFormLifecycleHooks(
hooks,
'beforeLoad',
mode,
baseContext,
);
if (beforeResult.blocked) {
onBlocked();
return { loaded: false };
}
initForm();
applyDefaults?.();
if (fetchDetail) {
try {
await fetchDetail();
} catch (error) {
await executeFormLifecycleHooks(hooks, 'afterLoadFail', mode, {
...baseContext,
error,
});
throw error;
}
}
await executeFormLifecycleHooks(hooks, 'afterLoadSuccess', mode, {
...baseContext,
savedId: editId,
});
return { loaded: true };
}
@@ -1,90 +0,0 @@
import type {
FormItemSchema,
ReverseAutoFillConfig,
} from '#/components/form-design/store/formDesignStore';
export interface ReverseAutoFillContext {
cfg: ReverseAutoFillConfig;
formCode?: string;
kind: 'form-selector' | 'select';
valueField: string;
}
/** 是否可在设计器配置关联自动填充 */
export function canConfigureReverseAutoFill(
item: { dataSource?: { type?: string }; type?: string } | null | undefined,
): boolean {
if (!item) return false;
if (item.type === 'form-selector') return true;
return item.type === 'select' && item.dataSource?.type === 'formData';
}
/** 是否已启用关联自动填充(含未完整配置) */
export function hasReverseAutoFillEnabled(
item: FormItemSchema | null | undefined,
): boolean {
if (!item) return false;
if (item.type === 'form-selector') {
return !!item.formSelectorConfig?.reverseAutoFill?.enabled;
}
if (item.type === 'select' && item.dataSource?.type === 'formData') {
return !!item.dataSource.reverseAutoFill?.enabled;
}
return false;
}
/** 读取关联自动填充配置(设计器用) */
export function getReverseAutoFillConfig(
item: FormItemSchema | null | undefined,
): ReverseAutoFillConfig | undefined {
if (!item) return undefined;
if (item.type === 'form-selector') {
return item.formSelectorConfig?.reverseAutoFill;
}
if (item.type === 'select' && item.dataSource?.type === 'formData') {
return item.dataSource.reverseAutoFill;
}
return undefined;
}
/** 运行时:获取已启用的关联自动填充上下文 */
export function getReverseAutoFillContext(
item: FormItemSchema | null | undefined,
): ReverseAutoFillContext | null {
if (!item) return null;
if (item.type === 'form-selector') {
const cfg = item.formSelectorConfig?.reverseAutoFill;
if (!cfg?.enabled || !cfg.sourceField) return null;
return {
cfg,
formCode: item.formSelectorConfig?.formCode,
valueField: item.formSelectorConfig?.valueField || 'id',
kind: 'form-selector',
};
}
if (item.type === 'select' && item.dataSource?.type === 'formData') {
const cfg = item.dataSource.reverseAutoFill;
if (!cfg?.enabled || !cfg.sourceField) return null;
return {
cfg,
formCode: item.dataSource.formCode,
valueField: item.dataSource.formValueField || 'id',
kind: 'select',
};
}
return null;
}
export function createDefaultReverseAutoFillConfig(): ReverseAutoFillConfig {
return {
enabled: false,
sourceField: '',
targetField: 'b_id',
filterType: 'eq',
pageSize: 500,
clearWhenEmpty: true,
};
}