fix: 修复管理端前端类型校验问题
- 修正知识库与 Bot 设置页相关组件的类型定义和空值处理 - 补齐工作流与公开聊天页的前端类型约束和动态导入类型 - 收敛本次改动文件的局部格式与样式规范,确保 pnpm check:type 通过
This commit is contained in:
@@ -30,7 +30,9 @@ type NodeLike = {
|
||||
|
||||
type UpdateNodeData = (
|
||||
nodeId: string,
|
||||
data: Record<string, any> | ((node: Record<string, any>) => Record<string, any>),
|
||||
data:
|
||||
| Record<string, any>
|
||||
| ((node: Record<string, any>) => Record<string, any>),
|
||||
) => void;
|
||||
|
||||
type FlowInstance = {
|
||||
@@ -80,7 +82,9 @@ function getSourceKey(datasetRef?: DatasetRefPayload | null) {
|
||||
return datasetRef?.sourceId == null ? '' : String(datasetRef.sourceId);
|
||||
}
|
||||
|
||||
function createSourceOnlyDatasetRef(source: ManagedDatasetSourceOption): DatasetRefPayload {
|
||||
function createSourceOnlyDatasetRef(
|
||||
source: ManagedDatasetSourceOption,
|
||||
): DatasetRefPayload {
|
||||
return {
|
||||
sourceId: source.sourceId,
|
||||
catalogId: null,
|
||||
@@ -337,7 +341,10 @@ function buildStyles() {
|
||||
`;
|
||||
}
|
||||
|
||||
function filterTableOptions(options: ManagedDatasetOption[], searchText: string) {
|
||||
function filterTableOptions(
|
||||
options: ManagedDatasetOption[],
|
||||
searchText: string,
|
||||
) {
|
||||
const keyword = searchText.trim().toLowerCase();
|
||||
if (!keyword) {
|
||||
return options;
|
||||
@@ -350,7 +357,11 @@ function ensureOptionsLoaded(
|
||||
parent: HTMLElement,
|
||||
node: NodeLike,
|
||||
flowInstance: RenderContext,
|
||||
rerender: (parent: HTMLElement, node: NodeLike, flowInstance?: RenderContext) => void,
|
||||
rerender: (
|
||||
parent: HTMLElement,
|
||||
node: NodeLike,
|
||||
flowInstance?: RenderContext,
|
||||
) => void,
|
||||
) {
|
||||
if (state.loadingOptions || state.optionsLoaded) {
|
||||
return;
|
||||
@@ -394,7 +405,11 @@ function buildPickerListItem(
|
||||
`;
|
||||
}
|
||||
|
||||
function buildSourceList(options: ManagedDatasetSourceOption[], activeKey: string, emptyText: string) {
|
||||
function buildSourceList(
|
||||
options: ManagedDatasetSourceOption[],
|
||||
activeKey: string,
|
||||
emptyText: string,
|
||||
) {
|
||||
if (!options.length) {
|
||||
return `<div class="dataset-node-empty">${emptyText}</div>`;
|
||||
}
|
||||
@@ -412,7 +427,11 @@ function buildSourceList(options: ManagedDatasetSourceOption[], activeKey: strin
|
||||
.join('');
|
||||
}
|
||||
|
||||
function buildTableList(options: ManagedDatasetOption[], activeKey: string, emptyText: string) {
|
||||
function buildTableList(
|
||||
options: ManagedDatasetOption[],
|
||||
activeKey: string,
|
||||
emptyText: string,
|
||||
) {
|
||||
if (!options.length) {
|
||||
return `<div class="dataset-node-empty">${emptyText}</div>`;
|
||||
}
|
||||
@@ -443,20 +462,29 @@ function buildSearchSummary(currentSource?: ManagedDatasetSourceOption) {
|
||||
}
|
||||
|
||||
function bindInteractiveElements(parent: HTMLElement) {
|
||||
parent.querySelectorAll<HTMLElement>('button, input, select, textarea').forEach((element) => {
|
||||
element.onpointerdown = (event) => event.stopPropagation();
|
||||
element.onmousedown = (event) => event.stopPropagation();
|
||||
});
|
||||
parent
|
||||
.querySelectorAll<HTMLElement>('button, input, select, textarea')
|
||||
.forEach((element) => {
|
||||
element.onpointerdown = (event) => event.stopPropagation();
|
||||
element.onmousedown = (event) => event.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
export function rerenderSearchNode(parent: HTMLElement, node: NodeLike, flowInstance?: RenderContext) {
|
||||
export function rerenderSearchNode(
|
||||
parent: HTMLElement,
|
||||
node: NodeLike,
|
||||
flowInstance?: RenderContext,
|
||||
) {
|
||||
const state = getState(parent);
|
||||
const updateNodeData = getUpdateNodeData(parent, flowInstance);
|
||||
ensureOptionsLoaded(state, parent, node, flowInstance, rerenderSearchNode);
|
||||
|
||||
const datasetRef = (node.data?.datasetRef || null) as DatasetRefPayload | null;
|
||||
const datasetRef = (node.data?.datasetRef ||
|
||||
null) as DatasetRefPayload | null;
|
||||
const sourceKey = getSourceKey(datasetRef);
|
||||
const currentSource = state.sources.find((item) => String(item.sourceId) === sourceKey);
|
||||
const currentSource = state.sources.find(
|
||||
(item) => String(item.sourceId) === sourceKey,
|
||||
);
|
||||
|
||||
parent.innerHTML = `
|
||||
${buildStyles()}
|
||||
@@ -469,61 +497,75 @@ export function rerenderSearchNode(parent: HTMLElement, node: NodeLike, flowInst
|
||||
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z"></path></svg>
|
||||
</span>
|
||||
</button>
|
||||
${state.pickerOpen ? `
|
||||
${
|
||||
state.pickerOpen
|
||||
? `
|
||||
<div class="dataset-node-picker">
|
||||
<div class="dataset-node-picker-body">
|
||||
${state.loadingOptions ? '<div class="dataset-node-empty">正在加载连接服务...</div>' : buildSourceList(state.sources, sourceKey, '暂无可用连接服务')}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
`
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
bindInteractiveElements(parent);
|
||||
|
||||
parent.querySelector<HTMLElement>('[data-action="toggle-picker"]')?.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
state.pickerOpen = !state.pickerOpen;
|
||||
rerenderSearchNode(parent, node, flowInstance);
|
||||
});
|
||||
|
||||
parent.querySelectorAll<HTMLElement>('[data-action="select-source"]').forEach((element) => {
|
||||
element.addEventListener('click', (event) => {
|
||||
parent
|
||||
.querySelector<HTMLElement>('[data-action="toggle-picker"]')
|
||||
?.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const sourceId = element.dataset.sourceId;
|
||||
const source = state.sources.find((item) => String(item.sourceId) === String(sourceId));
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
state.pickerOpen = false;
|
||||
const nextDatasetRef = createSourceOnlyDatasetRef(source);
|
||||
node.data = {
|
||||
...(node.data || {}),
|
||||
datasetRef: nextDatasetRef,
|
||||
sourceName: source.sourceName,
|
||||
sourceType: source.sourceType,
|
||||
};
|
||||
updateNodeData?.(node.id, {
|
||||
datasetRef: nextDatasetRef,
|
||||
sourceName: source.sourceName,
|
||||
sourceType: source.sourceType,
|
||||
});
|
||||
state.pickerOpen = !state.pickerOpen;
|
||||
rerenderSearchNode(parent, node, flowInstance);
|
||||
});
|
||||
});
|
||||
|
||||
parent
|
||||
.querySelectorAll<HTMLElement>('[data-action="select-source"]')
|
||||
.forEach((element) => {
|
||||
element.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const sourceId = element.dataset.sourceId;
|
||||
const source = state.sources.find(
|
||||
(item) => String(item.sourceId) === String(sourceId),
|
||||
);
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
state.pickerOpen = false;
|
||||
const nextDatasetRef = createSourceOnlyDatasetRef(source);
|
||||
node.data = {
|
||||
...(node.data || {}),
|
||||
datasetRef: nextDatasetRef,
|
||||
sourceName: source.sourceName,
|
||||
sourceType: source.sourceType,
|
||||
};
|
||||
updateNodeData?.(node.id, {
|
||||
datasetRef: nextDatasetRef,
|
||||
sourceName: source.sourceName,
|
||||
sourceType: source.sourceType,
|
||||
});
|
||||
rerenderSearchNode(parent, node, flowInstance);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function rerenderSaveNode(parent: HTMLElement, node: NodeLike, flowInstance?: RenderContext) {
|
||||
export function rerenderSaveNode(
|
||||
parent: HTMLElement,
|
||||
node: NodeLike,
|
||||
flowInstance?: RenderContext,
|
||||
) {
|
||||
const state = getState(parent);
|
||||
const updateNodeData = getUpdateNodeData(parent, flowInstance);
|
||||
ensureOptionsLoaded(state, parent, node, flowInstance, rerenderSaveNode);
|
||||
|
||||
const datasetRef = (node.data?.datasetRef || null) as DatasetRefPayload | null;
|
||||
const datasetRef = (node.data?.datasetRef ||
|
||||
null) as DatasetRefPayload | null;
|
||||
const activeKey = getDatasetKey(datasetRef);
|
||||
const currentOption = state.options.find((item) => String(item.datasetRef.tableId) === activeKey);
|
||||
const filtered = filterTableOptions(state.options, state.tableSearchText);
|
||||
|
||||
parent.innerHTML = `
|
||||
@@ -541,33 +583,40 @@ export function rerenderSaveNode(parent: HTMLElement, node: NodeLike, flowInstan
|
||||
|
||||
bindInteractiveElements(parent);
|
||||
|
||||
parent.querySelector<HTMLInputElement>('[data-role="table-search"]')?.addEventListener('input', (event) => {
|
||||
event.stopPropagation();
|
||||
state.tableSearchText = (event.currentTarget as HTMLInputElement).value || '';
|
||||
rerenderSaveNode(parent, node, flowInstance);
|
||||
});
|
||||
|
||||
parent.querySelectorAll<HTMLElement>('[data-action="select-dataset"]').forEach((element) => {
|
||||
element.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
parent
|
||||
.querySelector<HTMLInputElement>('[data-role="table-search"]')
|
||||
?.addEventListener('input', (event) => {
|
||||
event.stopPropagation();
|
||||
const tableId = element.dataset.tableId;
|
||||
const option = state.options.find((item) => String(item.datasetRef.tableId) === String(tableId));
|
||||
if (!option) {
|
||||
return;
|
||||
}
|
||||
node.data = {
|
||||
...(node.data || {}),
|
||||
datasetRef: option.datasetRef,
|
||||
sourceName: option.sourceName,
|
||||
sourceType: option.sourceType,
|
||||
};
|
||||
updateNodeData?.(node.id, {
|
||||
datasetRef: option.datasetRef,
|
||||
sourceName: option.sourceName,
|
||||
sourceType: option.sourceType,
|
||||
});
|
||||
state.tableSearchText =
|
||||
(event.currentTarget as HTMLInputElement).value || '';
|
||||
rerenderSaveNode(parent, node, flowInstance);
|
||||
});
|
||||
});
|
||||
|
||||
parent
|
||||
.querySelectorAll<HTMLElement>('[data-action="select-dataset"]')
|
||||
.forEach((element) => {
|
||||
element.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const tableId = element.dataset.tableId;
|
||||
const option = state.options.find(
|
||||
(item) => String(item.datasetRef.tableId) === String(tableId),
|
||||
);
|
||||
if (!option) {
|
||||
return;
|
||||
}
|
||||
node.data = {
|
||||
...(node.data || {}),
|
||||
datasetRef: option.datasetRef,
|
||||
sourceName: option.sourceName,
|
||||
sourceType: option.sourceType,
|
||||
};
|
||||
updateNodeData?.(node.id, {
|
||||
datasetRef: option.datasetRef,
|
||||
sourceName: option.sourceName,
|
||||
sourceType: option.sourceType,
|
||||
});
|
||||
rerenderSaveNode(parent, node, flowInstance);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user