diff --git a/ui/src/api/API_README.md b/ui/src/api/API_README.md index 72f45454fdb..19a771e89d1 100644 --- a/ui/src/api/API_README.md +++ b/ui/src/api/API_README.md @@ -149,6 +149,10 @@ v3 编辑表单提交 `{ name, description }`,标题上限 64、更新说明 `source: 'shared'` 与 `source: 'workspace'`。`SelectModel` 的接口选项统一通过此方法查询, 工作流通过 Store 同名方法使用缓存或强制刷新。模型管理列表继续使用 `getModelList`。 +`system/shared-resources/model.ts` 同样提供 `getModelListWithShared(query)`,沿用 +`/system/shared/model` 查询共享模型,为每项标记 `source: 'shared'`;不查询工作空间模型。 +共享工作流、代码生成和默认模型设置统一调用此方法,模型管理继续使用 `getModelList`。 + ### 工具列表查询 `workspace/tool/tool.ts` 的 `getAllTool(query)` 查询支持 `folder_id` 筛选的工作空间工具 @@ -189,6 +193,13 @@ Application API,直接转发生成请求,不使用查询缓存或请求去 ### 知识库维护 +关联问题生成按资源归属提交:`putGenerateKnowledgeQuestions` PUT 到 +`//generate_related`;`putGenerateDocumentQuestions` PUT 到 +`//document/batch_generate_related`,单项也使用单元素 `document_id_list`。 +`RelatedQuestionsConfig` 共用模型、模型参数及提示词,`KnowledgeGeneratePayload` 增加 +`state_list`,`DocumentGeneratePayload` 再增加 `document_id_list`,类型从 `@/api/types` 导入。 +公共配置弹窗只返回表单与状态,各 Action 调用各自完整业务 API。 + `getKnowledgeMcpConfig(knowledgeId)` 与 `postKnowledgeKeywordIndex(knowledgeId)` 为预留接口方法, 目前不发送 HTTP 请求:前者返回空配置文本,后者模拟成功。后续确认后端协议后替换方法内部实现。 MCP 入口加载配置后打开只读及复制弹窗;分词索引入口仅调用方法并在成功后提示“操作成功”。 @@ -214,6 +225,10 @@ MCP 入口加载配置后打开只读及复制弹窗;分词索引入口仅调 设置页更换向量模型时先确认、保存,再调用该接口;Web、飞书配置通过 `meta` 提交,保留未编辑的 已有配置,文件数量与大小限制仍作为知识库顶层字段提交。 +`putSyncWebKnowledge(knowledgeId, syncType)` 使用 PUT 请求 `//sync`, +查询参数 `sync_type` 为 `replace`(替换同步)或 `complete`(整体同步),不传请求体。 +仅用于 Web 知识库;页面负责方式选择、覆盖提示、loading 与任务提交成功提示。 + 知识库创建通过 `postKnowledge`、`postWebKnowledge` 分别提交到 `/base`、`/web`; `postLarkKnowledge` 沿用飞书扩展接口 `/lark/save`,当前开源后端未包含该实现。 基础创建字段由 `KnowledgeCreatePayload` 统一维护,Web、飞书请求扩展对应类型;工作流创建 @@ -509,6 +524,9 @@ System 接口由资源管理服务提供;本地开源后端没有对应扩展 单项向量化使用 `putDocumentRefresh(knowledgeId, documentId, stateList)` 请求 `//refresh`; 单项取消使用 `putCancelTask(knowledgeId, documentId, taskType)` 请求 `//cancel_task`,提交 `{ type }`。 批量向量化与取消分别沿用 `batch_refresh` 和 `batch_cancel_task`,不以单元素批量请求代替单项接口。 +单项分词使用 `putDocumentTokenize(knowledgeId, documentId, stateList)` 请求 `//tokenize`, +提交 `{ state_list }`;批量分词使用 `putBatchTokenizeDocuments` 请求 `batch_tokenize`, +提交 `{ id_list, state_list }`。两者均包含全部七种分段状态;单项取消分词复用 `putCancelTask`,任务类型为 `TOKENIZE`。 文档设置的共享载荷为 `DocumentSettingPayload`,生成问题使用 `DocumentGeneratePayload`; 单项设置通过 `meta` 保留来源数据,批量设置将 `allow_download` 放在顶层。 飞书同步沿用 v2 扩展接口 `/knowledge/lark//_batch`,需部署环境支持。 diff --git a/ui/src/api/admin/system/shared-resources/model.ts b/ui/src/api/admin/system/shared-resources/model.ts index f6f54642505..f62d0aa818c 100644 --- a/ui/src/api/admin/system/shared-resources/model.ts +++ b/ui/src/api/admin/system/shared-resources/model.ts @@ -11,6 +11,11 @@ const getModelList = (query?: Dict) => { return get(prefix, query) } +/** 获取 System 共享范围的模型选项,并标记共享来源。 */ +// TODO 资源共享的模型是不是都是共享的 +const getModelListWithShared = (query?: Dict): Promise => + getModelList(query).then((models) => models.map((model): ModelItem => ({ ...model, source: 'shared' }))) + /** 创建 System 共享模型。 */ const postModel = (payload: ModelPayload) => { return post(prefix, payload) @@ -51,4 +56,15 @@ const putPauseModelDownload = (modelId: string) => { return put(`${prefix}/${modelId}/pause_download`) } -export default { deleteModel, getModelDetail, getModelList, getModelMeta, getModelParamsForm, postModel, putModel, putModelParamsForm, putPauseModelDownload } +export default { + deleteModel, + getModelDetail, + getModelList, + getModelListWithShared, + getModelMeta, + getModelParamsForm, + postModel, + putModel, + putModelParamsForm, + putPauseModelDownload, +} diff --git a/ui/src/api/admin/workspace/knowledge/document.ts b/ui/src/api/admin/workspace/knowledge/document.ts index fa5581d7c59..cf64fdf13c9 100644 --- a/ui/src/api/admin/workspace/knowledge/document.ts +++ b/ui/src/api/admin/workspace/knowledge/document.ts @@ -42,14 +42,9 @@ const putBatchRefreshDocuments = (knowledgeId: string, documentIds: string[], st put(`${getPrefix(knowledgeId)}/batch_refresh`, { id_list: documentIds, state_list: stateList }) /** 单个文档分词索引。 */ -const putDocumentTokenize: (knowledge_id: string, document_id: string, state_list: Array, loading?: Ref) => Promise> = ( - knowledge_id, - document_id, - state_list, - loading, -) => { - return put(`${getPrefix(knowledge_id)}/${document_id}/tokenize`, { state_list }, undefined, loading) -} +const putDocumentTokenize = (knowledgeId: string, documentId: string, stateList: DocumentTaskState[]) => + put(`${getPrefix(knowledgeId)}/${documentId}/tokenize`, { state_list: stateList }) + /** 批量文档分词索引。 */ const putBatchTokenizeDocuments = (knowledgeId: string, documentIds: string[], stateList: DocumentTaskState[]) => put(`${getPrefix(knowledgeId)}/batch_tokenize`, { id_list: documentIds, state_list: stateList }) @@ -62,7 +57,6 @@ const putCancelTask = (knowledgeId: string, documentId: string, taskType: Docume const putBatchCancelDocumentTask = (knowledgeId: string, documentIds: string[], taskType: DocumentTaskType) => put(`${getPrefix(knowledgeId)}/batch_cancel_task`, { id_list: documentIds, type: taskType }) - /** 保存单个文档的召回及来源设置。 */ const putDocumentSetting = (knowledgeId: string, documentId: string, data: DocumentSettingPayload) => put(`${getPrefix(knowledgeId)}/${documentId}`, data) @@ -120,6 +114,7 @@ export default { putBatchDeleteDocuments, putDocumentRefresh, putBatchRefreshDocuments, + putDocumentTokenize, putBatchTokenizeDocuments, putCancelTask, putBatchCancelDocumentTask, diff --git a/ui/src/api/admin/workspace/knowledge/knowledge.ts b/ui/src/api/admin/workspace/knowledge/knowledge.ts index d75de553233..f97529147e7 100644 --- a/ui/src/api/admin/workspace/knowledge/knowledge.ts +++ b/ui/src/api/admin/workspace/knowledge/knowledge.ts @@ -5,6 +5,7 @@ import type { KnowledgeTagGroup, KnowledgeDetail, KnowledgeItem, + KnowledgeGeneratePayload, KnowledgeCreatePayload, WebKnowledgeCreatePayload, LarkKnowledgeCreatePayload, @@ -60,11 +61,21 @@ const putLarkKnowledge = (knowledgeId: string, payload: Partial) return put, KnowledgeItem>(`${getPrefix()}/lark/${knowledgeId}`, payload) } +/** 根据知识库中的分段生成关联问题。 */ +const putGenerateKnowledgeQuestions = (knowledgeId: string, payload: KnowledgeGeneratePayload) => { + return put(`${getPrefix()}/${knowledgeId}/generate_related`, payload) +} + /** 对知识库中的文档重新向量化。 */ const putReEmbeddingKnowledge = (knowledgeId: string) => { return put(`${getPrefix()}/${knowledgeId}/embedding`) } +/** 同步 Web 知识库。 */ +const putSyncWebKnowledge = (knowledgeId: string, syncType: 'replace' | 'complete') => { + return put(`${getPrefix()}/${knowledgeId}/sync`, undefined, { sync_type: syncType }) +} + /** 批量删除工作空间知识库。 */ const putBatchDeleteKnowledge = (knowledgeIds: string[]) => { return put<{ id_list: string[] }, boolean>(`${getPrefix()}/batch_delete`, { id_list: knowledgeIds }) @@ -127,6 +138,8 @@ export default { putKnowledge, putLarkKnowledge, putReEmbeddingKnowledge, + putGenerateKnowledgeQuestions, + putSyncWebKnowledge, putBatchDeleteKnowledge, putBatchMoveKnowledge, postKnowledgeImport, diff --git a/ui/src/api/types/document.ts b/ui/src/api/types/document.ts index 60b561a01f9..318f429c552 100644 --- a/ui/src/api/types/document.ts +++ b/ui/src/api/types/document.ts @@ -1,5 +1,5 @@ import type { DOCUMENT_HIT_HANDLING, DOCUMENT_TASK_STATE, DOCUMENT_TASK_TYPE } from '@/api/enums' -import type { KnowledgeType } from './knowledge' +import type { KnowledgeGeneratePayload, KnowledgeType } from './knowledge' export type DocumentHitHandling = (typeof DOCUMENT_HIT_HANDLING)[keyof typeof DOCUMENT_HIT_HANDLING] export type DocumentTaskState = (typeof DOCUMENT_TASK_STATE)[keyof typeof DOCUMENT_TASK_STATE] export type DocumentTaskType = (typeof DOCUMENT_TASK_TYPE)[keyof typeof DOCUMENT_TASK_TYPE] @@ -18,12 +18,8 @@ export interface DocumentSettingPayload { } /** 根据文档分段生成问题。 */ -export interface DocumentGeneratePayload { +export interface DocumentGeneratePayload extends KnowledgeGeneratePayload { document_id_list: string[] - model_id: string - model_params_setting: Record - prompt: string - state_list: DocumentTaskState[] } /** 文件各任务的分段计数及状态发生时间。 */ diff --git a/ui/src/api/types/knowledge.ts b/ui/src/api/types/knowledge.ts index eeb50a3a0f8..d7c66c291ca 100644 --- a/ui/src/api/types/knowledge.ts +++ b/ui/src/api/types/knowledge.ts @@ -3,6 +3,19 @@ import type LogicFlow from '@logicflow/core' import { KNOWLEDGE_TYPE } from '@/api/enums' import type { DefaultModelSettingPayload } from './model' +import type { DocumentTaskState } from './document' + +/** 生成关联问题共用的模型与提示词配置。 */ +export interface RelatedQuestionsConfig { + model_id: string + model_params_setting: Record + prompt: string +} + +/** 对知识库中指定任务状态的分段生成关联问题。 */ +export interface KnowledgeGeneratePayload extends RelatedQuestionsConfig { + state_list: DocumentTaskState[] +} export type KnowledgeType = (typeof KNOWLEDGE_TYPE)[keyof typeof KNOWLEDGE_TYPE] diff --git a/ui/src/assets/iconfont.js b/ui/src/assets/iconfont.js index f9240124287..75a9ad14b9f 100644 --- a/ui/src/assets/iconfont.js +++ b/ui/src/assets/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_5200172='',(h=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,v,t,i,c,d=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_5200172,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?d(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),o()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(t=o,i=h.document,c=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,e())})}function e(){c||(c=!0,t())}function m(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}e()}})(window); \ No newline at end of file +window._iconfont_svg_string_5200172='',(h=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,v,t,i,c,d=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_5200172,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?d(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),o()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(t=o,i=h.document,c=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,e())})}function e(){c||(c=!0,t())}function m(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}e()}})(window); \ No newline at end of file diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md index 617badd2459..0afe0d98085 100644 --- a/ui/src/components/COMPONENT_README.md +++ b/ui/src/components/COMPONENT_README.md @@ -64,11 +64,20 @@ import { MkDynamicsForm, MkDynamicsFormConstructor } from '@/components/mk-dynam - `el-input-number` 设置 `controls-position="right"` 时,同时设置 `align="left"`。 - Tooltip、Popover、Popconfirm、Dropdown 的触发插槽只保留一个有实际布局盒的根节点; 多个元素用 `span` 或 `div` 包裹,不使用 `template` 或 `display: contents` 代替。 -- 名称、标题、标签及必填业务文本使用独立的 `whitespace: true` 规则拒绝纯空白,保留原有 - `trim()` 清理逻辑。数字、布尔、选择项、数组和允许空白的原始参数值不统一套用;自定义 - `validator` 需要空白检查时拆成独立规则,避免覆盖内置校验。动态表单仅文本框、文本域的 +- 名称、标题、标签及必填业务文本将 `whitespace: true` 与 `required` 写在同一条规则中, + 统一使用原有“请输入…”提示,不拆分空白校验规则或单独提示空白错误,保留原有 `trim()` 清理逻辑。 + 数字、布尔、选择项、数组和允许空白的原始参数值不统一套用;自定义 `validator` 与内置 + 必填、空白校验规则分开,避免覆盖内置校验。动态表单仅文本框、文本域的 默认规则及构造器生成的必填规则启用该检查,密码和服务端显式校验协议保持原有行为。 -- 业务弹窗 `open()` 先重置再回填,关闭动画结束的 `closed` 统一清理表单、校验和临时状态。 +- 业务弹窗的生命周期按实际挂载方式处理,不在 `open()` 与 `closed` 两端重复重置: + - 保留业务组件实例时,默认值在声明处初始化,关闭动画结束的 `closed` 统一清理表单、编辑 ID、 + 校验和临时状态;`open()` 只回填本次数据、恢复业务缓存、发起必要查询并显示弹窗。 + - 所有调用方均在 `closed` 后卸载整个业务组件时,局部状态由下次挂载重新初始化,`closed` 只通知 + 父级卸载;计时器、订阅、流式请求等资源释放仍需保留。 + - 同时存在常驻和按需挂载调用方时,按常驻组件保留关闭清理;`MkDialog` 的 `destroyOnClose` + 只销毁内部内容,不等于销毁外层业务组件,不能据此删除外层状态重置。 + - `close()` 只发起关闭,表单清理放在 `closed`,避免关闭动画中内容跳变;依赖本次参数的默认值、 + 编辑快照、动态字段及每次打开必须重新查询的数据仍在 `open()` 初始化。 父级负责校验或请求时,子组件提交数据后由父级成功调用 `close()`,失败保持打开。 - 仅登录表单支持回车提交;其他业务表单使用 `@submit.prevent`,保存、添加由按钮触发。 自定义 `submit` 事件不等于原生表单提交。 @@ -775,6 +784,30 @@ Model 配置器的默认模型也使用 `SelectModel`,仅展示已选的可选 业务组件显式导入,可调用固定业务 API;页面保留自身的列表查询、路由和保存编排。 +### GenerateQuestionsDialog + +`business/generate-questions/GenerateQuestionsDialog.vue` 共用关联问题配置, +知识库和文档 Action 显式导入,打开时挂载、`closed` 后卸载,局部状态依赖重新挂载初始化。传入提交 +`loading`,通过 `open()` 打开、`close()` 关闭,不传 `modelApi`。 +弹窗通过 `isSystemResource()`、`isSystemSharedResource()` 选择 System 资源管理、System 共享资源 +或 Workspace Model API,统一查询当前范围的 LLM 选项和模型参数;供应商使用公共 API 查询, +并为 `SelectModel` 提供模型参数查询;支持创建模型后刷新, +下拉使用 `teleported`。模型选项与参数查询共用一个 `modelLoading`,通过 `finally` 释放; +表单禁用状态统一为 `loading || modelLoading`,失败提示由请求层处理。 +提交请求状态由 Action 传入的 `loading` 管理,表单校验后再次检查状态,避免重复提交。 + +弹窗只通过资源上下文工具判断范围,不持有知识库/文档/段落 ID,也不调用生成接口。`submit(config, stateList)` +返回 `RelatedQuestionsConfig` 与任务状态数组,由各 Action 补齐目标 ID、提交各自接口、提示、 +关闭和刷新。`showParagraphScope` 默认开启,每次打开默认仅处理未成功部分;段落场景传 +`false` 隐藏范围,返回空状态数组,调用方只提交配置与段落 ID,不传 `state_list`。 + +表单状态保留在 Dialog,同目录 `prompt-cache.ts` 负责按用户读取与保存模型、参数、提示词, +不注册专用 Store;每次打开读取缓存,提交时保留其他用户的最新记录。 +沿用 v2 的 `localStorage.PROMPT_CACHE` 及 `[{ user, formValue }]` 数组结构,直接读取已有配置, +保存时只替换当前用户记录,同一用户跨工作空间共用配置;不再传入工作空间 ID。 +不保存目标 ID 或分段范围;缓存用 `cloneDeep` 隔离,模型失效时清空模型及参数。 +取消不保存,提交前校验必填与纯空白提示词;提交失败保留表单,缓存不可用不阻止生成。 + ### GenerateContent `business/generate-content/index.vue` 封装生成入口按钮和弹窗,供提示词与 Python @@ -838,7 +871,7 @@ Workspace 的文件夹虚拟树业务组件。组件根据当前资源上下文 手动导入 `business/select-application-dialog/index.vue` 和 `business/select-tool-dialog/index.vue`。 两者沿用知识库选择弹窗的目录、名称搜索、三列卡片、悬停详情、跨目录选择和清空交互; `open()` 接收已选资源对象数组,`submit` 返回深拷贝后的资源对象数组,兼容只有 ID 的旧数据。 -每次打开先重置临时状态;取消不提交。 +打开时回填本次选择并查询资源,临时状态在 `closed` 清理;取消不提交。 智能体通过 `getAllApplication` 全量查询已发布资源,不展示共享目录。工具通过工作空间或共享 `getAllTool` 全量查询,仅展示启用资源;`toolTypes` 默认包含自定义、工作流和内置工具, diff --git a/ui/src/components/business/generate-questions/GenerateQuestionsDialog.vue b/ui/src/components/business/generate-questions/GenerateQuestionsDialog.vue new file mode 100644 index 00000000000..c2945c94b90 --- /dev/null +++ b/ui/src/components/business/generate-questions/GenerateQuestionsDialog.vue @@ -0,0 +1,132 @@ + + + diff --git a/ui/src/components/business/generate-questions/prompt-cache.ts b/ui/src/components/business/generate-questions/prompt-cache.ts new file mode 100644 index 00000000000..01e1d8f314b --- /dev/null +++ b/ui/src/components/business/generate-questions/prompt-cache.ts @@ -0,0 +1,56 @@ +/** 沿用 v2 PROMPT_CACHE,按用户记忆最近提交的关联问题配置。 */ +import { cloneDeep, isPlainObject } from 'lodash' +import type { RelatedQuestionsConfig } from '@/api/types' + +const PROMPT_CACHE_KEY = 'PROMPT_CACHE' + +interface PromptCacheEntry { + user: string + formValue: RelatedQuestionsConfig +} + +function defaultConfig(): RelatedQuestionsConfig { + return { + model_id: '', + model_params_setting: {}, + prompt: + '内容:{data}\n\n请总结上面的内容,并根据内容总结生成 5 个问题。\n回答要求:\n- 请只输出问题;\n- 请将每个问题放置标签中。', + } +} + +function readPromptCache(): PromptCacheEntry[] { + try { + const saved = JSON.parse(localStorage.getItem(PROMPT_CACHE_KEY) || '[]') + if (Array.isArray(saved)) { + return saved.filter( + (entry: PromptCacheEntry) => + typeof entry?.user === 'string' && + typeof entry.formValue?.model_id === 'string' && + typeof entry.formValue?.prompt === 'string' && + isPlainObject(entry.formValue?.model_params_setting), + ) + } + } catch { + // 缓存损坏或浏览器禁止存储时使用默认表单。 + } + return [] +} + +/** 每次打开读取当前用户配置,表单修改不影响已保存内容。 */ +export function getPromptConfig(userId: string): RelatedQuestionsConfig { + if (!userId) return defaultConfig() + const saved = readPromptCache().find(({ user }) => user === userId) + return saved ? cloneDeep(saved.formValue) : defaultConfig() +} + +/** 提交时仅替换当前用户记录,保留其他用户的配置。 */ +export function savePromptConfig(userId: string, config: RelatedQuestionsConfig) { + if (!userId) return + const configs = readPromptCache().filter(({ user }) => user !== userId) + configs.push({ user: userId, formValue: cloneDeep(config) }) + try { + localStorage.setItem(PROMPT_CACHE_KEY, JSON.stringify(configs)) + } catch { + // 存储不可用时跳过记忆,不阻止任务提交或修改当前表单。 + } +} diff --git a/ui/src/components/business/select-application-dialog/index.vue b/ui/src/components/business/select-application-dialog/index.vue index 4dd22ce7262..4c2a5650616 100644 --- a/ui/src/components/business/select-application-dialog/index.vue +++ b/ui/src/components/business/select-application-dialog/index.vue @@ -68,7 +68,6 @@ function selectFolder(folder?: FolderItem) { } function open(application: (Partial & { id: string })[]) { - resetData() selectedApplication.value = cloneDeep(application) visible.value = true void refreshApplication() diff --git a/ui/src/components/business/select-tool-dialog/index.vue b/ui/src/components/business/select-tool-dialog/index.vue index 34e18019953..bd0d08ddb79 100644 --- a/ui/src/components/business/select-tool-dialog/index.vue +++ b/ui/src/components/business/select-tool-dialog/index.vue @@ -78,7 +78,6 @@ function selectFolder(folder?: FolderItem) { } function open(tool: (Partial & { id: string })[]) { - resetData() selectedTool.value = cloneDeep(tool) visible.value = true void refreshTool() diff --git a/ui/src/components/mk-dynamics-form/constructor/items/TreeSelectConstructor.vue b/ui/src/components/mk-dynamics-form/constructor/items/TreeSelectConstructor.vue index ed28b2f6a75..d7d5ff54dc4 100644 --- a/ui/src/components/mk-dynamics-form/constructor/items/TreeSelectConstructor.vue +++ b/ui/src/components/mk-dynamics-form/constructor/items/TreeSelectConstructor.vue @@ -95,6 +95,9 @@ function openAddChildDialog(node: TreeNode) { function closeAddDialog() { addDialog.visible = false +} + +function handleAddClosed() { addDialog.mode = 'root' addDialog.parentNode = null addDialog.formList = [] @@ -142,6 +145,9 @@ function openEditDialog(node: TreeNode) { function closeEditDialog() { editDialog.visible = false +} + +function handleEditClosed() { editDialog.targetNode = null editDialog.form.label = '' editDialog.form.value = '' @@ -263,7 +269,7 @@ function removeNodeById(list: TreeNode[], targetId: string): boolean { /> - +