Remove unused legacy monitor helpers
This commit is contained in:
@@ -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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user