fix(plugin): P1 跨插件引用修复 — DateTime generated column + resolve-labels UUID 类型 + EntitySelect manifest→UUID 映射
- manifest.rs: DateTime 类型 generated column 改为 TEXT 存储(PostgreSQL TIMESTAMPTZ cast 非 immutable) - data_handler.rs: resolve-labels 查询参数从 String 改为 UUID 类型避免类型不匹配 - data_dto.rs: PublicEntityResp 新增 plugin_id 字段 - EntitySelect.tsx: 跨插件查询先通过 registry 解析 manifest_id→plugin UUID - pluginData.ts: PublicEntity 接口增加 plugin_id - plugin_tests.rs: 适配 PluginField/PluginEntity 新增字段
This commit is contained in:
Binary file not shown.
@@ -198,6 +198,7 @@ export async function resolveRefLabels(
|
||||
|
||||
export interface PublicEntity {
|
||||
manifest_id: string;
|
||||
plugin_id: string;
|
||||
entity_name: string;
|
||||
display_name: string;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Select, Spin, Input, Tooltip } from 'antd';
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { listPluginData } from '../api/pluginData';
|
||||
import { listPluginData, getPluginEntityRegistry } from '../api/pluginData';
|
||||
|
||||
interface EntitySelectProps {
|
||||
pluginId: string;
|
||||
@@ -37,12 +37,38 @@ export default function EntitySelect({
|
||||
const [options, setOptions] = useState<{ value: string; label: string }[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [targetUnavailable, setTargetUnavailable] = useState(false);
|
||||
const [resolvedPluginId, setResolvedPluginId] = useState<string | null>(null);
|
||||
|
||||
// 跨插件时使用目标插件 ID 查询
|
||||
const effectivePluginId = refPlugin || pluginId;
|
||||
// 跨插件时:先解析 manifest_id → plugin UUID
|
||||
useEffect(() => {
|
||||
if (!refPlugin) {
|
||||
setResolvedPluginId(pluginId);
|
||||
return;
|
||||
}
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
try {
|
||||
const registry = await getPluginEntityRegistry();
|
||||
const match = registry.find((e) => e.manifest_id === refPlugin && e.entity_name === entity);
|
||||
if (!cancelled) {
|
||||
setResolvedPluginId(match ? match.plugin_id : null);
|
||||
if (!match) setTargetUnavailable(true);
|
||||
}
|
||||
} catch {
|
||||
if (!cancelled) {
|
||||
setTargetUnavailable(true);
|
||||
setResolvedPluginId(null);
|
||||
}
|
||||
}
|
||||
})();
|
||||
return () => { cancelled = true; };
|
||||
}, [refPlugin, pluginId, entity]);
|
||||
|
||||
const effectivePluginId = resolvedPluginId || pluginId;
|
||||
|
||||
const fetchData = useCallback(
|
||||
async (keyword?: string) => {
|
||||
if (!resolvedPluginId && refPlugin) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
const filter: Record<string, string> | undefined =
|
||||
@@ -70,12 +96,14 @@ export default function EntitySelect({
|
||||
setLoading(false);
|
||||
}
|
||||
},
|
||||
[effectivePluginId, entity, labelField, cascadeFrom, cascadeFilter, cascadeValue, refPlugin],
|
||||
[effectivePluginId, entity, labelField, cascadeFrom, cascadeFilter, cascadeValue, refPlugin, resolvedPluginId],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [fetchData]);
|
||||
if (resolvedPluginId || !refPlugin) {
|
||||
fetchData();
|
||||
}
|
||||
}, [fetchData, resolvedPluginId, refPlugin]);
|
||||
|
||||
// 目标插件未安装 → 降级显示
|
||||
if (targetUnavailable) {
|
||||
|
||||
Reference in New Issue
Block a user