From 13369d44b48aafe279b38a88477560dba12e1abe Mon Sep 17 00:00:00 2001 From: jieliu52 Date: Wed, 26 Mar 2025 10:21:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(config-provider):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=90=88=E5=B9=B6=E4=B8=BB=E9=A2=98=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config-provider/merge-composition-api.vue | 204 +++++++++++++++++ .../pc/app/config-provider/merge.spec.ts | 25 ++ .../demos/pc/app/config-provider/merge.vue | 215 ++++++++++++++++++ .../config-provider/webdoc/config-provider.js | 13 ++ packages/utils/src/index.ts | 14 +- packages/utils/src/object/index.ts | 40 ++++ packages/vue/src/config-provider/package.json | 15 +- .../vue/src/config-provider/src/index.vue | 21 +- 8 files changed, 537 insertions(+), 10 deletions(-) create mode 100644 examples/sites/demos/pc/app/config-provider/merge-composition-api.vue create mode 100644 examples/sites/demos/pc/app/config-provider/merge.spec.ts create mode 100644 examples/sites/demos/pc/app/config-provider/merge.vue diff --git a/examples/sites/demos/pc/app/config-provider/merge-composition-api.vue b/examples/sites/demos/pc/app/config-provider/merge-composition-api.vue new file mode 100644 index 0000000000..8ddff649f4 --- /dev/null +++ b/examples/sites/demos/pc/app/config-provider/merge-composition-api.vue @@ -0,0 +1,204 @@ + + + + + diff --git a/examples/sites/demos/pc/app/config-provider/merge.spec.ts b/examples/sites/demos/pc/app/config-provider/merge.spec.ts new file mode 100644 index 0000000000..b6dcafb91a --- /dev/null +++ b/examples/sites/demos/pc/app/config-provider/merge.spec.ts @@ -0,0 +1,25 @@ +import { test, expect } from '@playwright/test' + +test('测试自定义事件', async ({ page }) => { + page.on('pageerror', (exception) => expect(exception).toBeNull()) + await page.goto('config-provider#merge') + + // 验证自定义方法 + const demo = page.locator('#merge') + await demo.locator('.tiny-config-provider .tiny-alert > .tiny-alert__close').click() + await page.waitForTimeout(500) + await expect(page.locator('.tiny-modal > .tiny-modal__box').nth(1)).toHaveText('触发自定方法') + + // 验证必填星号 + await expect(demo.locator('.tiny-form')).toBeVisible() + const beforeElement = await page.evaluate(() => { + const labelBefore = document.querySelector('.tiny-form .tiny-form-item__label') + const { display, content } = window.getComputedStyle(labelBefore, '::before') + return { display, content } + }) + expect(beforeElement.content).toBe('none') + + // 验证按钮点击禁用时间 + await demo.locator('.tiny-button').click() + await expect(demo.locator('.tiny-button')).not.toBeDisabled({ timeout: 300 }) +}) diff --git a/examples/sites/demos/pc/app/config-provider/merge.vue b/examples/sites/demos/pc/app/config-provider/merge.vue new file mode 100644 index 0000000000..5dd0d0916d --- /dev/null +++ b/examples/sites/demos/pc/app/config-provider/merge.vue @@ -0,0 +1,215 @@ + + + + + diff --git a/examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js b/examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js index b463ed71e0..dd93e30f01 100644 --- a/examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js +++ b/examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js @@ -18,6 +18,19 @@ export default { }, codeFiles: ['base.vue'] }, + { + demoId: 'merge', + name: { + 'zh-CN': '嵌套使用', + 'en-US': 'Merge' + }, + desc: { + 'zh-CN': '支持嵌套使用', + 'en-US': + 'Icons and logic for different design specifications can be customized through the design attribute configuration.' + }, + codeFiles: ['merge.vue'] + }, { demoId: 'text-direct', name: { diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index c6fb921347..f017d50931 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -110,7 +110,19 @@ export { } from './string' export { roundFixed, Decimal, toFixed as toFixedDecimal, formatNumber, recoverNumber } from './decimal' -export { each, getObj, setObj, copyField, copyArray, isEqual, isEachEqual, extend, toJsonStr, merge } from './object' +export { + each, + getObj, + setObj, + copyField, + copyArray, + isEqual, + isEachEqual, + extend, + toJsonStr, + merge, + deepMerge +} from './object' export { supportBigInt, diff --git a/packages/utils/src/object/index.ts b/packages/utils/src/object/index.ts index 7dbfabf25c..ea9607dcb5 100644 --- a/packages/utils/src/object/index.ts +++ b/packages/utils/src/object/index.ts @@ -434,3 +434,43 @@ export const merge = function (target: object, ...rest: object[]) { return target } + +/** + * 深度合并普通对象:递归合并所有普通对象的属性,嵌套对象也会被合并。 + * 覆盖非对象值:数组、日期、函数等非普通对象值会被直接覆盖。 + * 不修改原对象:所有合并操作都在新对象上进行,原对象保持不变。 + * 处理null和undefined源:忽略null和undefined类型的源对象。 + */ +export function deepMerge(...sources) { + function merge(target, source) { + if (!isObject(source)) { + return + } + Object.keys(source).forEach((key) => { + const sourceValue = source[key] + const targetValue = target[key] + + if (isObject(sourceValue)) { + if (isObject(targetValue)) { + // 递归合并对象 + merge(targetValue, sourceValue) + } else { + // 目标属性不是对象,创建新对象并递归合并 + target[key] = {} + merge(target[key], sourceValue) + } + } else { + // 直接赋值非对象或数组等类型的值 + target[key] = sourceValue + } + }) + } + + const target = {} + for (const source of sources) { + if (source !== null && source !== undefined) { + merge(target, source) + } + } + return target +} diff --git a/packages/vue/src/config-provider/package.json b/packages/vue/src/config-provider/package.json index 1032b24292..3dd47c4966 100644 --- a/packages/vue/src/config-provider/package.json +++ b/packages/vue/src/config-provider/package.json @@ -1,21 +1,22 @@ { "name": "@opentiny/vue-config-provider", + "type": "module", "version": "3.22.0", + "license": "MIT", + "sideEffects": false, "main": "lib/index.js", "module": "index.ts", - "sideEffects": false, - "type": "module", - "devDependencies": { - "@opentiny-internal/vue-test-utils": "workspace:*", - "vitest": "catalog:" - }, "scripts": { "build": "pnpm -w build:ui $npm_package_name", "//postversion": "pnpm build" }, "dependencies": { + "@opentiny/utils": "workspace:~", "@opentiny/vue-common": "workspace:~", "@opentiny/vue-theme": "workspace:~" }, - "license": "MIT" + "devDependencies": { + "@opentiny-internal/vue-test-utils": "workspace:*", + "vitest": "catalog:" + } } diff --git a/packages/vue/src/config-provider/src/index.vue b/packages/vue/src/config-provider/src/index.vue index 5747f84118..cdda7b2c5d 100644 --- a/packages/vue/src/config-provider/src/index.vue +++ b/packages/vue/src/config-provider/src/index.vue @@ -1,8 +1,17 @@