diff --git a/packages/vue3-util/CHANGELOG.md b/packages/vue3-util/CHANGELOG.md index fc0bfc0daf1817c76615c8be264daabc001c9904..059fdaf08957d2b72b17bfa3ead7123ef5b17370 100644 --- a/packages/vue3-util/CHANGELOG.md +++ b/packages/vue3-util/CHANGELOG.md @@ -13,6 +13,10 @@ ### Changed +- 语义化kook识别面板项注入属性并埋点 + +### Changed + - 面板组件样式按组件语义化结构进行样式变量拆分 ## [0.7.41-alpha.106] - 2026-06-16 diff --git a/packages/vue3-util/src/use/use-semantic-node/use-semantic-node.ts b/packages/vue3-util/src/use/use-semantic-node/use-semantic-node.ts index 181a459f20ecd9f8743a8b52eb0d7159f5c6a7e4..ec2fc1b8e3edc6f3f8ff1b3bdca9fb298ecc5677 100644 --- a/packages/vue3-util/src/use/use-semantic-node/use-semantic-node.ts +++ b/packages/vue3-util/src/use/use-semantic-node/use-semantic-node.ts @@ -4,6 +4,7 @@ import { PredefinedAttributes, ScriptFactory, } from '@ibiz-template/runtime'; +import { IControl } from '@ibiz/model-core'; import { useAttrs } from 'vue'; /** 语义化节点class */ @@ -19,120 +20,73 @@ export type UseSemanticStyleReturn = ( ) => IData | undefined; /** - * 解析 CSS 字符串为对象 - * @param cssString CSS 字符串,如 'color:red;font-size: 14px;' - * @returns 解析后的样式对象 - */ -const parseCssString = (cssString: string): IData => { - return cssString.split(';').reduce((acc: IData, item) => { - const trimmed = item.trim(); - if (trimmed.length === 0) { - return acc; - } - const [styleKey, styleValue] = trimmed.split(':'); - if (styleKey && styleValue) { - acc[styleKey.trim()] = styleValue.trim(); - } - return acc; - }, {}); -}; - -/** - * 创建语义化 class 处理器 - * @param classItems class 配置项 - * @param controller 控制器 - * @returns class 处理器函数 - */ -const createSemanticClass = ( - classItems: IData, - controller: ControlController | PanelItemController, -): UseSemanticClassReturn => { - return (key: string, ...args: unknown[]): string | undefined => { - const value = classItems?.[key]; - if (value === undefined) { - return undefined; - } - if (typeof value === 'string') { - return value; - } - return value(controller, ...args); - }; -}; - -/** - * 创建语义化 style 处理器 - * @param styleItems style 配置项 - * @param controller 控制器 - * @returns style 处理器函数 - */ -const createSemanticStyle = ( - styleItems: IData, - controller: ControlController | PanelItemController, -): UseSemanticStyleReturn => { - return (key: string, ...args: unknown[]): IData | undefined => { - const value = styleItems?.[key]; - if (value === undefined) { - return undefined; - } - if (typeof value === 'string') { - return parseCssString(value); - } - return value(controller, ...args); - }; -}; - -/** - * 合并 class 配置项 + * 语义化节点 * @param controller 控制器 - * @param context 脚本执行上下文 - * @param attrs Vue attrs - * @returns 合并后的 class 配置项 + * @returns */ -const mergeClassItems = ( +export function useSemanticNode( controller: ControlController | PanelItemController, - context: IData, - attrs: ReturnType, -): IData => { +): { + semanticClass: UseSemanticClassReturn; + semanticStyle: UseSemanticStyleReturn; +} { + // class埋点信息,可通过部件注入属性classNames设置,也可通过组件参数classNames设置,格式为字符串或函数,如 { root: 'semantic-mark-root' } 或 { root: (args) => 'semantic-mark-root' } let classItems: IData = {}; const classNameAttr = controller.model.controlAttributes?.find( item => item.attrName === PredefinedAttributes.CLASSNAMES, ); if (classNameAttr && classNameAttr.attrValue) { - classItems = ScriptFactory.execSingleLine( - classNameAttr.attrValue, - context, - ) as IData; + const { controlType } = controller.model as IControl; + // 存在部件类型即为部件 + if (controlType) { + classItems = ScriptFactory.execSingleLine(classNameAttr.attrValue, { + ...(controller as ControlController).getEventArgs(), + }) as IData; + } else { + const panelItem = controller as PanelItemController; + classItems = ScriptFactory.execSingleLine(classNameAttr.attrValue, { + data: [panelItem.data], + value: panelItem.data[panelItem.model.id!], + }) as IData; + } } + const attrs = useAttrs(); if (attrs.classNames) { classItems = { ...classItems, ...attrs.classNames, }; } - return classItems; -}; -/** - * 合并 style 配置项 - * @param controller 控制器 - * @param context 脚本执行上下文 - * @param attrs Vue attrs - * @returns 合并后的 style 配置项 - */ -const mergeStyleItems = ( - controller: ControlController | PanelItemController, - context: IData, - attrs: ReturnType, -): IData => { + /** + * 解析指定 key 的用户自定义 class: + * - 未配置:返回 undefined + * - 字符串:直接返回 + * - 函数:传入 controller 及 args 调用后返回 + */ + const semanticClass: UseSemanticClassReturn = ( + key: string, + ...args: unknown[] + ): string | undefined => { + const value = classItems?.[key]; + if (value === undefined) { + return undefined; + } + if (typeof value === 'string') { + return value; + } + return value(controller, ...args); + }; + + // style埋点信息,可通过部件注入属性styles设置,也可通过组件参数styles设置,格式为字符串或函数,如 { root: 'color:var(--ibiz-color-text-0);font-size: 14px;' } 或 { root: (args) => 'color:var(--ibiz-color-text-0);font-size: 14px;' } let styleItems: IData = {}; const styleAttr = controller.model.controlAttributes?.find( item => item.attrName === PredefinedAttributes.STYLES, ); if (styleAttr && styleAttr.attrValue) { - styleItems = ScriptFactory.execSingleLine( - styleAttr.attrValue, - context, - ) as IData; + styleItems = ScriptFactory.execSingleLine(styleAttr.attrValue, { + ...controller.getEventArgs(), + }) as IData; } if (attrs.styles) { styleItems = { @@ -140,50 +94,37 @@ const mergeStyleItems = ( ...attrs.styles, }; } - return styleItems; -}; - -/** - * 语义化节点 - * @param controller 控制器 - * @returns - */ -export function useSemanticNode(controller: ControlController): { - semanticClass: UseSemanticClassReturn; - semanticStyle: UseSemanticStyleReturn; -} { - const attrs = useAttrs(); - const context = controller.getEventArgs(); - const classItems = mergeClassItems(controller, context, attrs); - const styleItems = mergeStyleItems(controller, context, attrs); - - return { - semanticClass: createSemanticClass(classItems, controller), - semanticStyle: createSemanticStyle(styleItems, controller), - }; -} - -/** - * 面板语义化节点 - * @param controller 控制器 - * @returns - */ -export function usePanelSemanticNode(controller: PanelItemController): { - semanticClass: UseSemanticClassReturn; - semanticStyle: UseSemanticStyleReturn; -} { - const attrs = useAttrs(); - const context = { - data: controller.data, - value: controller.data[controller.model.id!], + /** + * 解析指定 key 的用户自定义 style: + * - 未配置:返回 undefined + * - 字符串:直接返回 + * - 函数:传入 controller 及 args 调用后返回 + */ + const semanticStyle: UseSemanticStyleReturn = ( + key: string, + ...args: unknown[] + ): IData | undefined => { + const value = styleItems?.[key]; + if (value === undefined) { + return undefined; + } + if (typeof value === 'string') { + const result = value.split(';').reduce((acc: IData, item) => { + if (item.trim().length === 0) { + return acc; + } + const [styleKey, styleValue] = item.split(':'); + acc[styleKey.trim()] = styleValue.trim(); + return acc; + }, {}); + return result; + } + return value(controller, ...args); }; - const classItems = mergeClassItems(controller, context, attrs); - const styleItems = mergeStyleItems(controller, context, attrs); - return { - semanticClass: createSemanticClass(classItems, controller), - semanticStyle: createSemanticStyle(styleItems, controller), + semanticClass, + semanticStyle, }; }