From e29afce79e7e0f890d328b82fb1251ece67f5a23 Mon Sep 17 00:00:00 2001 From: luofann Date: Mon, 17 Aug 2026 09:54:30 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=E6=8C=87=E6=A0=87=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E7=BB=84=E4=BB=B6=E9=80=82=E9=85=8Dvue3=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E3=80=81=E8=87=AA=E5=AE=9A=E4=B9=89=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=80=99=E9=80=89=E5=80=BC=E5=87=BD=E6=95=B0=E3=80=81=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E5=8F=98=E9=87=8F=E4=BA=A4=E4=BA=92=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=89=A9=E5=B1=95=20#=20Reviewed,=20transaction=20id:=2084541?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../webpack/scripts/build.vue2.components.ts | 16 ++-- bkmonitor/webpack/scripts/package.vue2.json | 4 +- .../webpack/scripts/plugin-scope-vue2-css.ts | 95 +++++++++++++++++++ .../webpack/src/monitor-pc/components.ts | 3 +- .../components/cycle-input/cycle-input.scss | 4 +- .../components/cycle-input/cycle-input.tsx | 4 +- .../condition/condition-creator-options.tsx | 10 ++ .../condition/condition-creator-selector.tsx | 7 ++ .../condition/condition-creator.tsx | 60 +++++++++--- .../components/condition/value-options.tsx | 5 + .../condition/value-tag-selector.tsx | 4 + .../dimension/dimension-creator.tsx | 4 + .../expression-config-creator.tsx | 4 + .../expression-panel/expression-panel.tsx | 4 + .../function/function-creator-pop.tsx | 9 ++ .../components/function/function-creator.tsx | 4 + .../components/method/method-creator.tsx | 4 + .../query-config/query-config-creator.tsx | 15 +++ .../components/query-panel/query-panel.tsx | 12 +++ .../components/utils/add-variable-option.tsx | 13 +++ 20 files changed, 256 insertions(+), 25 deletions(-) create mode 100644 bkmonitor/webpack/scripts/plugin-scope-vue2-css.ts diff --git a/bkmonitor/webpack/scripts/build.vue2.components.ts b/bkmonitor/webpack/scripts/build.vue2.components.ts index 5a0e8dc7f2e..834e36f5f6e 100644 --- a/bkmonitor/webpack/scripts/build.vue2.components.ts +++ b/bkmonitor/webpack/scripts/build.vue2.components.ts @@ -28,8 +28,9 @@ import { getBabelOutputPlugin } from '@rollup/plugin-babel'; import vueTsx from '@vitejs/plugin-vue2-jsx'; import { resolve } from 'node:path'; import { defineConfig } from 'vite'; -import { analyzer } from 'vite-bundle-analyzer'; import { viteStaticCopy } from 'vite-plugin-static-copy'; + +import { scopeVue2Css } from './plugin-scope-vue2-css'; const outputDir = resolve(__dirname, '../monitor-vue2-components'); export default defineConfig({ define: { @@ -58,13 +59,16 @@ export default defineConfig({ dest: outputDir, rename: 'package.json', }, - // { - // src: resolve(__dirname, '../src/trace/components/retrieval-filter/readme.md'), - // dest: outputDir, - // }, + { + src: resolve(__dirname, './readme.vue2.md'), + dest: outputDir, + rename: 'readme.md', + }, ], }), - analyzer(), + // 供 vue3 宿主使用的作用域样式副本,避免包内 bkui-vue2 样式与宿主的 bkui-vue3 互相污染 + scopeVue2Css({ outDir: outputDir }), + // analyzer() 会在构建结束后常驻一个分析服务(默认 8888),命令不会退出,需要时再手动开启 ], build: { copyPublicDir: false, diff --git a/bkmonitor/webpack/scripts/package.vue2.json b/bkmonitor/webpack/scripts/package.vue2.json index a0182f083ee..a36844d84cf 100644 --- a/bkmonitor/webpack/scripts/package.vue2.json +++ b/bkmonitor/webpack/scripts/package.vue2.json @@ -1,9 +1,9 @@ { "name": "@blueking/monitor-vue2-components", - "version": "0.0.1", + "version": "0.0.0-beta.10", "description": "blueking monitor vue2 components builder", "scripts": {}, - "files": ["index.mjs", "index.css", "monitor-vue2.mjs", "readme.md"], + "files": ["index.mjs", "index.css", "index.scoped.css", "monitor-vue2.mjs", "readme.md"], "author": "bkfe", "license": "MIT", "main": "monitor-vue2.mjs", diff --git a/bkmonitor/webpack/scripts/plugin-scope-vue2-css.ts b/bkmonitor/webpack/scripts/plugin-scope-vue2-css.ts new file mode 100644 index 00000000000..bcc8792db4a --- /dev/null +++ b/bkmonitor/webpack/scripts/plugin-scope-vue2-css.ts @@ -0,0 +1,95 @@ +/* + * Tencent is pleased to support the open source community by making + * 蓝鲸智云PaaS平台 (BlueKing PaaS) available. + * + * Copyright (C) 2017-2025 Tencent. All rights reserved. + * + * 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License. + * + * License for 蓝鲸智云PaaS平台 (BlueKing PaaS): + * + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +import { existsSync, readFileSync, writeFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +import postcss from 'postcss'; + +import type { Plugin } from 'vite'; + +/** 宿主容器需要挂上的类名,与产出的选择器前缀一致 */ +export const VUE2_CSS_SCOPE = '.monitor-vue2-scope'; + +const ROOT_SELECTOR = /^(html|body|:root)$/; +const ROOT_DESCENDANT = /^(html|body)\b\s*/; + +const scopeSelector = (selector: string) => { + const value = selector.trim(); + if (!value || value.startsWith(VUE2_CSS_SCOPE)) return selector; + // 根级选择器落到容器自身,:root 上的 CSS 变量因此仍能被容器内元素继承 + if (ROOT_SELECTOR.test(value)) return VUE2_CSS_SCOPE; + if (ROOT_DESCENDANT.test(value)) return `${VUE2_CSS_SCOPE} ${value.replace(ROOT_DESCENDANT, '')}`; + return `${VUE2_CSS_SCOPE} ${value}`; +}; + +const isInsideKeyframes = (rule: postcss.Rule) => { + for (let node: postcss.Container | postcss.Document | undefined = rule.parent; node; node = node.parent) { + if (node.type === 'atrule' && /keyframes$/.test((node as postcss.AtRule).name)) return true; + } + return false; +}; + +interface IOptions { + outDir: string; + /** 构建产出的原始样式文件名 */ + source?: string; + /** 加了作用域前缀的副本文件名 */ + output?: string; +} + +/** + * 额外产出一份带作用域前缀的样式副本。 + * + * 包内自带整套 bkui-vue2 样式,其中数百个 .bk-* 类名与 bkui-vue3 同名, + * 宿主若是 vue3 项目,全局引入原始样式会双向污染。改用这份副本、并给组件的挂载容器 + * (以及 bk-magic-vue 挂在 body 下的全局弹层容器)加上 VUE2_CSS_SCOPE 类名, + * 规则就只在容器内生效,且特异性比裸类名高一级,容器内由 vue2 的样式胜出。 + */ +export function scopeVue2Css(options: IOptions): Plugin { + const { outDir, source = 'index.css', output = 'index.scoped.css' } = options; + return { + name: 'monitor-scope-vue2-css', + // lib 模式下多入口会多次触发 writeBundle,这里只需在全部产物落盘后跑一次 + closeBundle() { + const sourcePath = resolve(outDir, source); + if (!existsSync(sourcePath)) return; + + const root = postcss.parse(readFileSync(sourcePath, 'utf8')); + let scopedCount = 0; + root.walkRules(rule => { + // @keyframes 内是 from/to/百分比,加前缀会让动画失效 + if (isInsideKeyframes(rule)) return; + rule.selectors = rule.selectors.map(scopeSelector); + scopedCount += 1; + }); + + const result = root.toString(); + writeFileSync(resolve(outDir, output), result); + console.log(`${output} ${(result.length / 1024).toFixed(2)} kB │ ${scopedCount} 条规则加上 ${VUE2_CSS_SCOPE}`); + }, + }; +} diff --git a/bkmonitor/webpack/src/monitor-pc/components.ts b/bkmonitor/webpack/src/monitor-pc/components.ts index aad564088f3..8d793c0dbb2 100644 --- a/bkmonitor/webpack/src/monitor-pc/components.ts +++ b/bkmonitor/webpack/src/monitor-pc/components.ts @@ -29,6 +29,7 @@ import Vue2 from 'vue'; import './common/import-magicbox-ui'; +import ExpressionPanel from './pages/query-template/components/expression-panel/expression-panel'; import QueryPanel, { QueryPanelEmits } from './pages/query-template/components/query-panel/query-panel'; import './static/css/global.scss'; @@ -36,4 +37,4 @@ import './static/css/reset.scss'; import 'monitor-static/icons/monitor-icons.css'; export * from './pages/query-template/typings'; -export { i18n, QueryPanel, QueryPanelEmits, Vue2 }; +export { ExpressionPanel, i18n, QueryPanel, QueryPanelEmits, Vue2 }; diff --git a/bkmonitor/webpack/src/monitor-pc/components/cycle-input/cycle-input.scss b/bkmonitor/webpack/src/monitor-pc/components/cycle-input/cycle-input.scss index c4d639cd579..73cf0870de2 100644 --- a/bkmonitor/webpack/src/monitor-pc/components/cycle-input/cycle-input.scss +++ b/bkmonitor/webpack/src/monitor-pc/components/cycle-input/cycle-input.scss @@ -3,8 +3,10 @@ .input-popover { flex: 1; + width: 100%; - .bk-tooltip-ref { + .bk-tooltip-ref, + .input-text { width: 100%; } diff --git a/bkmonitor/webpack/src/monitor-pc/components/cycle-input/cycle-input.tsx b/bkmonitor/webpack/src/monitor-pc/components/cycle-input/cycle-input.tsx index b81ebf2a541..e052f2508d7 100644 --- a/bkmonitor/webpack/src/monitor-pc/components/cycle-input/cycle-input.tsx +++ b/bkmonitor/webpack/src/monitor-pc/components/cycle-input/cycle-input.tsx @@ -200,7 +200,7 @@ export default class CycleInput extends tsc { offset={-1} placement='bottom-start' theme='light cycle-list-wrapper' - tippyOptions={{ appendTo: this.appendTo === 'parent' ? 'parent' : document.body }} + tippyOptions={this.appendTo === 'parent' ? { appendTo: 'parent' } : {}} trigger='click' > @@ -243,7 +243,7 @@ export default class CycleInput extends tsc { offset={-1} placement='bottom-end' theme='light cycle-list-wrapper' - tippyOptions={{ appendTo: this.appendTo === 'parent' ? 'parent' : document.body }} + tippyOptions={this.appendTo === 'parent' ? { appendTo: 'parent' } : {}} trigger='click' onHide={() => { this.unitActive = false; diff --git a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/condition/condition-creator-options.tsx b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/condition/condition-creator-options.tsx index 758e5dd4244..8eaf3318e15 100644 --- a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/condition/condition-creator-options.tsx +++ b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/condition/condition-creator-options.tsx @@ -48,6 +48,7 @@ import './condition-creator-options.scss'; interface IProps { allVariables?: { name: string }[]; + createVariableFn?: (onCreated: (name: string) => void) => void; dimensionValueVariables?: { name: string }[]; fields: IFilterField[]; hasVariableOperate?: boolean; @@ -84,6 +85,8 @@ export default class UiSelectorOptions extends tsc { @Prop({ type: Array, default: () => [] }) dimensionValueVariables: { name: string }[]; /* 所有变量,用于校验变量名是否重复 */ @Prop({ default: () => [] }) allVariables: { name: string }[]; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; @Ref('allInput') allInputRef; @Ref('valueSelector') valueSelectorRef: ValueTagSelector; @@ -449,6 +452,12 @@ export default class UiSelectorOptions extends tsc { } handleClickCreateVariable() { + if (this.createVariableFn) { + this.createVariableFn((name: string) => { + if (name) this.$emit('createVariable', name); + }); + return; + } this.isCreateVariable = true; this.cursorIndex = 0; } @@ -547,6 +556,7 @@ export default class UiSelectorOptions extends tsc { key={this.rightRefreshKey} ref='valueSelector' allVariables={this.allVariables} + createVariableFn={this.createVariableFn} fieldInfo={this.valueSelectorFieldInfo} getValueFn={this.getValueFnProxy} hasVariableOperate={this.hasVariableOperate} diff --git a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/condition/condition-creator-selector.tsx b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/condition/condition-creator-selector.tsx index e9b21fc8faa..c31b217a1b5 100644 --- a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/condition/condition-creator-selector.tsx +++ b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/condition/condition-creator-selector.tsx @@ -45,6 +45,7 @@ import './condition-creator-selector.scss'; interface IProps { allVariables?: { name: string }[]; clearKey?: string; + createVariableFn?: (onCreated: (name: string) => void) => void; dimensionValueVariables?: { name: string }[]; fields?: IFilterField[]; hasVariableOperate?: boolean; @@ -78,6 +79,8 @@ export default class ConditionCreatorSelector extends tsc { @Prop({ default: () => [] }) allVariables: { name: string }[]; /** 是否展示条件标签 */ @Prop({ default: false, type: Boolean }) showConditionTag: boolean; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; @Ref('selector') selectorRef: HTMLDivElement; /* 是否显示弹出层 */ @@ -131,6 +134,9 @@ export default class ConditionCreatorSelector extends tsc { this.showSelector = true; } destroyPopoverInstance() { + /* 确定/取消属于主动关闭,不该被变量创建状态挡住, + 否则宿主的变量面板异常退出后这个弹层就再也关不掉了 */ + this.showCreateVariablePop = false; this.popoverInstance?.hide?.(); this.popoverInstance?.destroy?.(); this.popoverInstance = null; @@ -292,6 +298,7 @@ export default class ConditionCreatorSelector extends tsc {
void) => void; + getValueFn?: (params: IGetValueFnParams) => Promise; onChange?: (val: AggCondition[]) => void; onCreateValueVariable?: (val: { name: string; related_tag: string }) => void; onCreateVariable?: (val: string) => void; @@ -83,6 +89,12 @@ export default class ConditionCreator extends tsc { @Prop({ default: () => [] }) allVariables: { name: string }[]; /** 是否展示条件标签 */ @Prop({ default: false, type: Boolean }) showConditionTag: boolean; + /* 维度值获取方法,外部注入后可对接自有接口,未注入时走监控默认实现 */ + @Prop({ default: null, type: Function }) getValueFn: ( + params: IGetValueFnParams + ) => Promise; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; cacheDimensionValues = new Map(); @@ -141,6 +153,36 @@ export default class ConditionCreator extends tsc { ]; } + get valueFn() { + return this.getValueFn ? this.externalGetValueFn : this.defaultGetValueFn; + } + + searchOptions(search: string, list: { id: string; name: string }[]) { + if (!search) { + return list; + } + const searchLower = search.toLocaleLowerCase(); + return list.filter( + item => + item.name.toLocaleLowerCase().includes(searchLower) || item.id.toLocaleLowerCase().includes(searchLower) + ); + } + + /* 外部注入的取值函数只负责取候选值,维度值变量与搜索过滤仍由这里统一补上 */ + externalGetValueFn(params: IGetValueFnParams): any { + return Promise.resolve(this.getValueFn(params)).then((res: any) => { + const allOptions = [ + ...this.dimensionValueVariables.map(item => ({ name: item.name, id: item.name, isVariable: true })), + ...(res?.list || []), + ]; + const filterList = this.searchOptions(params?.where?.[0]?.value?.[0], allOptions); + return { + count: filterList.length, + list: filterList, + }; + }); + } + handleGetMethodList(type: 'number' | 'string') { if (type === 'number') { return NUMBER_CONDITION_METHOD_LIST; @@ -173,18 +215,9 @@ export default class ConditionCreator extends tsc { ); } - getValueFn(params: IGetValueFnParams): any { + defaultGetValueFn(params: IGetValueFnParams): any { return new Promise(resolve => { - const searchList = (search: string, list) => { - if (!search) { - return list; - } - const searchLower = search.toLocaleLowerCase(); - return list.filter( - item => - item.name.toLocaleLowerCase().includes(searchLower) || item.id.toLocaleLowerCase().includes(searchLower) - ); - }; + const searchList = (search: string, list) => this.searchOptions(search, list); const searchValue = params?.where?.[0]?.value?.[0]; const dimensionKey = params.fields[0]; const list = this.cacheDimensionValues.get(dimensionKey); @@ -227,9 +260,10 @@ export default class ConditionCreator extends tsc { {this.showLabel &&
{this.$slots?.label || this.$t('过滤条件')}
} void) => void; fieldInfo?: IFieldItem; getValueFn?: TGetValueFn; hasVariableOperate?: boolean; @@ -91,6 +92,8 @@ export default class ValueOptions extends tsc { @Prop({ type: Array, default: () => [] }) variables: { name: string }[]; /* 所有变量,用于校验变量名是否重复 */ @Prop({ default: () => [] }) allVariables: { name: string }[]; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; localOptions: IValue[] = []; loading = false; @@ -323,6 +326,7 @@ export default class ValueOptions extends tsc { > { > void) => void; fieldInfo?: IFieldItem; /* 获取数据 */ getValueFn?: TGetValueFn; @@ -80,6 +81,8 @@ export default class ValueTagSelector extends tsc { @Prop({ type: Boolean, default: false }) hasVariableOperate: boolean; /* 所有变量,用于校验变量名是否重复 */ @Prop({ default: () => [] }) allVariables: { name: string }[]; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; /* tag列表 */ localValue: IValue[] = []; @@ -377,6 +380,7 @@ export default class ValueTagSelector extends tsc { {this.isShowDropDown && ( void) => void; options?: IDimensionOptionsItem[]; showLabel?: boolean; showVariables?: boolean; @@ -63,6 +64,8 @@ export default class DimensionCreator extends tsc { @Prop({ default: () => [] }) value: string[]; /* 所有变量,用于校验变量名是否重复 */ @Prop({ default: () => [] }) allVariables: { name: string }[]; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; @Ref('inputRef') inputRef: AutoWidthInput; @@ -251,6 +254,7 @@ export default class DimensionCreator extends tsc { {this.showVariables && ( diff --git a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/expression-config/expression-config-creator.tsx b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/expression-config/expression-config-creator.tsx index b5a80f706ff..6ec064e3d44 100644 --- a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/expression-config/expression-config-creator.tsx +++ b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/expression-config/expression-config-creator.tsx @@ -40,6 +40,7 @@ import type { IFunctionOptionsItem } from '../type/query-config'; import './expression-config-creator.scss'; interface IProps { + createVariableFn?: (onCreated: (name: string) => void) => void; expressionConfig?: Expression; metricFunctions?: IFunctionOptionsItem[]; variables?: VariableModelType[]; @@ -53,6 +54,8 @@ export default class ExpressionConfigCreator extends tsc { @Prop({ default: () => null }) expressionConfig: Expression; @Prop({ default: () => [] }) metricFunctions: IFunctionOptionsItem[]; @Prop({ default: () => [] }) variables: VariableModelType[]; + /* 由外部接管变量创建(如宿主自带变量面板),未传时走监控内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; get getFunctionVariables() { return this.variables.filter(item => item.type === VariableTypeEnum.EXPRESSION_FUNCTIONS); @@ -104,6 +107,7 @@ export default class ExpressionConfigCreator extends tsc { /> void) => void; expressionConfig?: Expression; metricFunctions?: IFunctionOptionsItem[]; variables?: VariableModelType[]; @@ -49,6 +50,8 @@ export default class ExpressionPanel extends tsc { @Prop({ default: () => [] }) metricFunctions: IFunctionOptionsItem[]; @Prop({ default: () => [] }) variables: VariableModelType[]; @Prop({ default: () => null }) expressionConfig: Expression; + /* 由外部接管变量创建(如宿主自带变量面板),未传时走监控内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; handleCreateVariable(val: IVariableModel) { this.$emit('createVariable', val); @@ -66,6 +69,7 @@ export default class ExpressionPanel extends tsc {
void) => void; hasCreateVariable?: boolean; isExpSupport?: boolean; options?: IFunctionOptionsItem[]; @@ -59,6 +60,8 @@ export default class FunctionCreatorPop extends tsc { @Prop({ default: () => [] }) selected: IFunctionOptionsItem[]; /* 所有变量,用于校验变量名是否重复 */ @Prop({ default: () => [] }) allVariables: { name: string }[]; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; /* 搜索关键词 */ keyword = ''; @@ -109,6 +112,12 @@ export default class FunctionCreatorPop extends tsc { } handleClickCreateVar() { + if (this.createVariableFn) { + this.createVariableFn((name: string) => { + if (name) this.$emit('addVar', name); + }); + return; + } this.isCreateVar = true; this.activeFuncType = ''; this.activeFuncId = ''; diff --git a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/function/function-creator.tsx b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/function/function-creator.tsx index e37ee7ec89a..4ec2efb99a2 100644 --- a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/function/function-creator.tsx +++ b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/function/function-creator.tsx @@ -40,6 +40,7 @@ import './function-creator.scss'; interface IProps { allVariables?: { name: string }[]; + createVariableFn?: (onCreated: (name: string) => void) => void; isExpSupport?: boolean; needClear?: boolean; options?: IFunctionOptionsItem[]; @@ -68,6 +69,8 @@ export default class FunctionCreator extends tsc { /* 所有变量,用于校验变量名是否重复 */ @Prop({ default: () => [] }) allVariables: { name: string }[]; @Prop({ default: true }) needClear: boolean; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; showSelect = false; popClickHide = true; @@ -243,6 +246,7 @@ export default class FunctionCreator extends tsc { void) => void; options?: IMethodOptionsItem[]; showLabel?: boolean; showVariables?: boolean; @@ -60,6 +61,8 @@ export default class MethodCreator extends tsc { /* 是否展示变量 */ @Prop({ default: false }) showVariables: boolean; @Prop({ default: '' }) value: string; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; showSelect = false; /* 所有可选项(包含变量) */ @@ -161,6 +164,7 @@ export default class MethodCreator extends tsc { {this.showVariables && ( diff --git a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/query-config/query-config-creator.tsx b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/query-config/query-config-creator.tsx index 977b1844192..360e88a1cc9 100644 --- a/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/query-config/query-config-creator.tsx +++ b/bkmonitor/webpack/src/monitor-pc/pages/query-template/components/query-config/query-config-creator.tsx @@ -35,6 +35,7 @@ import IntervalCreator from '../interval/interval-creator'; import MethodCreator from '../method/method-creator'; import MetricCreator from '../metric/metric-creator'; +import type { IGetValueFnParams, IWhereValueOptionsItem } from '../../../../components/retrieval-filter/utils'; import type { AggCondition, AggFunction, MetricDetailV2, QueryConfig } from '../../typings'; import type { IGetMetricListData, IGetMetricListParams } from '../metric/components/types'; import type { @@ -47,11 +48,13 @@ import type { import './query-config-creator.scss'; interface IProps { + createVariableFn?: (onCreated: (name: string) => void) => void; hasVariableOperate?: boolean; metricFunctions?: IFunctionOptionsItem[]; queryConfig?: QueryConfig; variables?: IVariablesItem[]; getMetricList: (params: IGetMetricListParams) => Promise; + getValueFn?: (params: IGetValueFnParams) => Promise; onChangeCondition?: (val: AggCondition[]) => void; onChangeDimension?: (val: string[]) => void; onChangeFunction?: (val: AggFunction[]) => void; @@ -70,6 +73,13 @@ export default class QueryConfigCreator extends tsc { params: IGetMetricListParams ) => Promise; @Prop({ default: false }) hasVariableOperate: boolean; + /* 过滤条件维度值获取方法,透传给条件组件以支持外部数据源 */ + @Prop({ default: null, type: Function }) getValueFn: ( + params: IGetValueFnParams + ) => Promise; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再展开内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; + get getMethodVariables() { return this.variables.filter(item => item.type === VariableTypeEnum.METHOD); } @@ -175,6 +185,7 @@ export default class QueryConfigCreator extends tsc { { { { > void) => void; hasAdd?: boolean; hasDelete?: boolean; hasVariableOperate?: boolean; @@ -45,6 +47,7 @@ interface IProps { queryConfig?: QueryConfig; variables?: VariableModelType[]; getMetricList: (params: IGetMetricListParams) => Promise; + getValueFn?: (params: IGetValueFnParams) => Promise; onAdd?: () => void; onChangeCondition?: (val: AggCondition[]) => void; onChangeDimension?: (val: string[]) => void; @@ -78,6 +81,13 @@ export default class QueryPanel extends tsc { params: IGetMetricListParams ) => Promise; @Prop({ default: false }) hasVariableOperate: boolean; + /* 过滤条件维度值获取方法,未传时由条件组件走监控默认接口 */ + @Prop({ default: null, type: Function }) getValueFn: ( + params: IGetValueFnParams + ) => Promise; + /* 由外部接管变量创建(如宿主自带变量面板),未传时走监控内置的命名输入面板 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; + handleCreateVariable(val: IVariableModel) { this.$emit('createVariable', val); } @@ -114,7 +124,9 @@ export default class QueryPanel extends tsc { return (
void) => void; popDistance?: number; onAdd?: (val: string) => void; onOpenChange?: (v: boolean) => void; @@ -44,6 +45,8 @@ export default class AddVariableOption extends tsc { /* 所有变量,用于校验变量名是否重复 */ @Prop({ default: () => [] }) allVariables: { name: string }[]; @Prop({ default: 7 }) popDistance: number; + /* 由外部接管变量创建(如宿主自带变量面板),传入时不再弹出内置的命名输入框 */ + @Prop({ default: null, type: Function }) createVariableFn: (onCreated: (name: string) => void) => void; inputValue = ''; @@ -51,6 +54,16 @@ export default class AddVariableOption extends tsc { isShowPop = false; handleClick(e: Event) { + if (this.createVariableFn) { + /* 与内置命名弹层共用「创建中」状态:宿主面板打开期间点击外部不应收起上层弹层, + 否则编辑态被丢弃,变量创建完就没有回填的目标了。名字为空表示宿主取消了创建 */ + this.$emit('openChange', true); + this.createVariableFn((name: string) => { + if (name) this.$emit('add', name); + this.$emit('openChange', false); + }); + return; + } this.handleShowPopover(e); } From a5a388acb0afb716edee69eca95c423a1242722e Mon Sep 17 00:00:00 2001 From: luofann Date: Mon, 17 Aug 2026 10:30:16 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=E6=8C=87=E6=A0=87=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E7=BB=84=E4=BB=B6=E9=80=82=E9=85=8Dvue3=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E3=80=81=E8=87=AA=E5=AE=9A=E4=B9=89=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=80=99=E9=80=89=E5=80=BC=E5=87=BD=E6=95=B0=E3=80=81=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E5=8F=98=E9=87=8F=E4=BA=A4=E4=BA=92=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=89=A9=E5=B1=95=20#=20Reviewed,=20transaction=20id:=2084544?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bkmonitor/webpack/scripts/build.vue2.components.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bkmonitor/webpack/scripts/build.vue2.components.ts b/bkmonitor/webpack/scripts/build.vue2.components.ts index 834e36f5f6e..94994bf07f3 100644 --- a/bkmonitor/webpack/scripts/build.vue2.components.ts +++ b/bkmonitor/webpack/scripts/build.vue2.components.ts @@ -28,6 +28,7 @@ import { getBabelOutputPlugin } from '@rollup/plugin-babel'; import vueTsx from '@vitejs/plugin-vue2-jsx'; import { resolve } from 'node:path'; import { defineConfig } from 'vite'; +import { analyzer } from 'vite-bundle-analyzer'; import { viteStaticCopy } from 'vite-plugin-static-copy'; import { scopeVue2Css } from './plugin-scope-vue2-css'; @@ -60,15 +61,14 @@ export default defineConfig({ rename: 'package.json', }, { - src: resolve(__dirname, './readme.vue2.md'), + src: resolve(__dirname, '../src/trace/components/retrieval-filter/readme.md'), dest: outputDir, - rename: 'readme.md', }, ], }), // 供 vue3 宿主使用的作用域样式副本,避免包内 bkui-vue2 样式与宿主的 bkui-vue3 互相污染 scopeVue2Css({ outDir: outputDir }), - // analyzer() 会在构建结束后常驻一个分析服务(默认 8888),命令不会退出,需要时再手动开启 + analyzer() ], build: { copyPublicDir: false, From aad8924b331bd5aa4d9e757cc277ba1b41769388 Mon Sep 17 00:00:00 2001 From: luofann Date: Mon, 17 Aug 2026 10:32:03 +0800 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=E6=8C=87=E6=A0=87=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E7=BB=84=E4=BB=B6=E9=80=82=E9=85=8Dvue3=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E3=80=81=E8=87=AA=E5=AE=9A=E4=B9=89=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=80=99=E9=80=89=E5=80=BC=E5=87=BD=E6=95=B0=E3=80=81=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E5=8F=98=E9=87=8F=E4=BA=A4=E4=BA=92=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=89=A9=E5=B1=95=20#=20Reviewed,=20transaction=20id:=2084546?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bkmonitor/webpack/scripts/build.vue2.components.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bkmonitor/webpack/scripts/build.vue2.components.ts b/bkmonitor/webpack/scripts/build.vue2.components.ts index 94994bf07f3..9d0fbdd7d1b 100644 --- a/bkmonitor/webpack/scripts/build.vue2.components.ts +++ b/bkmonitor/webpack/scripts/build.vue2.components.ts @@ -60,10 +60,10 @@ export default defineConfig({ dest: outputDir, rename: 'package.json', }, - { - src: resolve(__dirname, '../src/trace/components/retrieval-filter/readme.md'), - dest: outputDir, - }, + // { + // src: resolve(__dirname, '../src/trace/components/retrieval-filter/readme.md'), + // dest: outputDir, + // }, ], }), // 供 vue3 宿主使用的作用域样式副本,避免包内 bkui-vue2 样式与宿主的 bkui-vue3 互相污染