diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 10fc939ea9c..352ed11e60f 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,7 +1,7 @@ name: 🐞 Bug Report description: Report an issue with Vben Admin to help us make it better. -title: "Bug: " -labels: ["bug: pending triage"] +title: 'Bug: ' +labels: ['bug: pending triage'] body: - type: markdown diff --git a/.github/ISSUE_TEMPLATE/docs.yml b/.github/ISSUE_TEMPLATE/docs.yml index de5e6f60f3a..d2bf16eff34 100644 --- a/.github/ISSUE_TEMPLATE/docs.yml +++ b/.github/ISSUE_TEMPLATE/docs.yml @@ -1,6 +1,6 @@ name: 📚 Documentation description: Report an issue with Vben Admin Website to help us make it better. -title: "Docs: " +title: 'Docs: ' labels: [documentation] body: - type: markdown diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index 6ad67a6f7aa..e40eac66c0c 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -1,7 +1,7 @@ name: ✨ New Feature Proposal description: Propose a new feature to be added to Vben Admin -title: "FEATURE: " -labels: ["enhancement: pending triage"] +title: 'FEATURE: ' +labels: ['enhancement: pending triage'] body: - type: markdown attributes: diff --git a/.github/actions/setup-node/action.yml b/.github/actions/setup-node/action.yml index d21c142767b..35fa41c8abd 100644 --- a/.github/actions/setup-node/action.yml +++ b/.github/actions/setup-node/action.yml @@ -1,9 +1,9 @@ -name: "Setup Node" +name: 'Setup Node' -description: "Setup node and pnpm" +description: 'Setup node and pnpm' runs: - using: "composite" + using: 'composite' steps: - name: Install pnpm uses: pnpm/action-setup@v4 @@ -12,7 +12,7 @@ runs: uses: actions/setup-node@v4 with: node-version-file: .node-version - cache: "pnpm" + cache: 'pnpm' - name: Get pnpm store directory shell: bash diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fa2e1abdbba..d1b6d3b44fe 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,7 @@ version: 2 updates: - package-ecosystem: npm - directory: "/" + directory: '/' schedule: interval: daily groups: @@ -9,7 +9,7 @@ updates: update-types: [minor, patch] - package-ecosystem: github-actions - directory: "/" + directory: '/' schedule: interval: weekly groups: diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 8cd7a1c8463..287ba1226f4 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,7 +1,7 @@ -name-template: "v$RESOLVED_VERSION" -tag-template: "v$RESOLVED_VERSION" +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' version-template: $MAJOR.$MINOR.$PATCH -change-template: "* $TITLE (#$NUMBER) @$AUTHOR" +change-template: '* $TITLE (#$NUMBER) @$AUTHOR' template: | # What's Changed @@ -10,52 +10,52 @@ template: | **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION categories: - - title: "🚀 Features" + - title: '🚀 Features' labels: - - "feature" - - title: "🐞 Bug Fixes" + - 'feature' + - title: '🐞 Bug Fixes' labels: - - "bug" - - title: "📈 Performance" + - 'bug' + - title: '📈 Performance' labels: - - "perf" - - "enhancement" + - 'perf' + - 'enhancement' - title: 📝 Documentation labels: - - "documentation" + - 'documentation' - title: 👻 Maintenance labels: - - "chore" - - "dependencies" + - 'chore' + - 'dependencies' # collapse-after: 12 - title: 🚦 Tests labels: - - "tests" - - title: "Breaking" - label: "breaking" + - 'tests' + - title: 'Breaking' + label: 'breaking' version-resolver: major: labels: - - "major" - - "breaking" + - 'major' + - 'breaking' minor: labels: - - "minor" + - 'minor' patch: labels: - - "feature" - - "patch" - - "bug" - - "maintenance" - - "docs" - - "dependencies" - - "security" + - 'feature' + - 'patch' + - 'bug' + - 'maintenance' + - 'docs' + - 'dependencies' + - 'security' exclude-labels: - - "skip-changelog" - - "no-changelog" - - "changelog" - - "bump versions" - - "reverted" - - "invalid" + - 'skip-changelog' + - 'no-changelog' + - 'changelog' + - 'bump versions' + - 'reverted' + - 'invalid' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b82fee1a0e6..276a3e8be65 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,7 +7,7 @@ on: - main env: - HUSKY: "0" + HUSKY: '0' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number }} diff --git a/.github/workflows/changeset-version.yml b/.github/workflows/changeset-version.yml index bd6be844872..4e85cd67d2f 100644 --- a/.github/workflows/changeset-version.yml +++ b/.github/workflows/changeset-version.yml @@ -36,7 +36,7 @@ jobs: uses: changesets/action@v1 with: version: pnpm run version - commit: "chore: bump versions" - title: "chore: bump versions" + commit: 'chore: bump versions' + title: 'chore: bump versions' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e8a7365897..e4fc70f687a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: push: branches: - main - - "releases/*" + - 'releases/*' permissions: contents: read diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5a1626dc3b0..53765ba6aa4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -9,15 +9,15 @@ # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # -name: "CodeQL" +name: 'CodeQL' on: push: - branches: ["main"] + branches: ['main'] pull_request: - branches: ["main"] + branches: ['main'] schedule: - - cron: "35 0 * * 0" + - cron: '35 0 * * 0' jobs: analyze: @@ -90,4 +90,4 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: - category: "/language:${{matrix.language}}" + category: '/language:${{matrix.language}}' diff --git a/.github/workflows/issue-close-require.yml b/.github/workflows/issue-close-require.yml index 7d925783453..3c7ad8e6169 100644 --- a/.github/workflows/issue-close-require.yml +++ b/.github/workflows/issue-close-require.yml @@ -4,7 +4,7 @@ name: Issue Close Require # 触发条件:每天零点 on: schedule: - - cron: "0 0 * * *" + - cron: '0 0 * * *' permissions: pull-requests: write @@ -19,7 +19,7 @@ jobs: - name: Close Inactive Issues uses: actions-cool/issues-helper@v3 with: - actions: "close-issues" # 执行动作:关闭 Issues + actions: 'close-issues' # 执行动作:关闭 Issues token: ${{ secrets.GITHUB_TOKEN }} # GitHub Token,用于认证 - labels: "needs reproduction" # 目标标签 + labels: 'needs reproduction' # 目标标签 inactive-day: 3 # 未活动天数阈值 diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml index bb398f03f93..c0010c7b4f0 100644 --- a/.github/workflows/issue-labeled.yml +++ b/.github/workflows/issue-labeled.yml @@ -19,27 +19,27 @@ jobs: if: github.event.label.name == 'enhancement' uses: actions-cool/issues-helper@v3 with: - actions: "remove-labels" + actions: 'remove-labels' token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} - labels: "enhancement: pending triage" + labels: 'enhancement: pending triage' - name: remove bug pending if: github.event.label.name == 'bug' uses: actions-cool/issues-helper@v3 with: - actions: "remove-labels" + actions: 'remove-labels' token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} - labels: "bug: pending triage" + labels: 'bug: pending triage' - name: needs reproduction if: github.event.label.name == 'needs reproduction' uses: actions-cool/issues-helper@v3 with: - actions: "create-comment, remove-labels" + actions: 'create-comment, remove-labels' token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }} body: | Hello @${{ github.event.issue.user.login }}. Please provide the complete reproduction steps and code. Issues labeled by `needs reproduction` will be closed if no activities in 3 days. - labels: "bug: pending triage" + labels: 'bug: pending triage' diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 27905514b56..c16764ad45b 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -2,7 +2,7 @@ name: Lock Threads on: schedule: - - cron: "0 0 * * *" + - cron: '0 0 * * *' workflow_dispatch: permissions: @@ -16,8 +16,8 @@ jobs: - uses: dessant/lock-threads@v5 with: github-token: ${{ secrets.GITHUB_TOKEN }} - issue-inactive-days: "30" - issue-lock-reason: "" - pr-inactive-days: "30" - pr-lock-reason: "" - process-only: "issues, prs" + issue-inactive-days: '30' + issue-lock-reason: '' + pr-inactive-days: '30' + pr-lock-reason: '' + process-only: 'issues, prs' diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index b36e1903f96..794bac9704f 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -3,10 +3,10 @@ name: Create Release Tag on: push: tags: - - "v*.*.*" # Push events to matching v*, i.e. v1.0, v20.15.10 + - 'v*.*.*' # Push events to matching v*, i.e. v1.0, v20.15.10 env: - HUSKY: "0" + HUSKY: '0' permissions: pull-requests: write diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d1acf5fbf51..86f7ee62c90 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,8 +1,8 @@ -name: "Close stale issues" +name: 'Close stale issues' on: schedule: - - cron: "0 1 * * *" + - cron: '0 1 * * *' jobs: stale: @@ -11,8 +11,8 @@ jobs: - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - stale-issue-message: "This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days" - stale-pr-message: "This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days" - exempt-issue-labels: "bug,enhancement" + stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' + stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' + exempt-issue-labels: 'bug,enhancement' days-before-stale: 60 days-before-close: 7 diff --git a/docs/src/commercial/community.md b/docs/src/commercial/community.md index 180d14dd916..83703fa1b70 100644 --- a/docs/src/commercial/community.md +++ b/docs/src/commercial/community.md @@ -10,16 +10,18 @@ 免费QQ群人数上限200,将会不定期清理。推荐加入QQ频道进行交流 +::: + ## 微信群 +作者主要通过微信群提供帮助,如果你有问题,可以通过以下方式加入微信群。 + +通过微信联系作者,注明加群来意: + ::: tip 因为微信群人数有限制,加微信群前,你可以通过[赞助](../sponsor/personal.md)任意金额,主动发送截图给作者,备注`加入微信群`即可。 ::: -作者主要通过微信群提供帮助,如果你有问题,可以通过以下方式加入微信群。 - -通过微信联系作者,注明加群来意: - diff --git a/internal/lint-configs/eslint-config/src/configs/javascript.ts b/internal/lint-configs/eslint-config/src/configs/javascript.ts index cae21b81969..0d87c1ba13a 100644 --- a/internal/lint-configs/eslint-config/src/configs/javascript.ts +++ b/internal/lint-configs/eslint-config/src/configs/javascript.ts @@ -147,7 +147,7 @@ export async function javascript(): Promise { 'no-template-curly-in-string': 'error', 'no-this-before-super': 'error', 'no-throw-literal': 'error', - 'no-undef': 'error', + 'no-undef': 'off', 'no-undef-init': 'error', 'no-unexpected-multiline': 'error', 'no-unmodified-loop-condition': 'error', diff --git a/internal/lint-configs/eslint-config/src/configs/vue.ts b/internal/lint-configs/eslint-config/src/configs/vue.ts index 8c45e8ad0c8..27cc3cf29c1 100644 --- a/internal/lint-configs/eslint-config/src/configs/vue.ts +++ b/internal/lint-configs/eslint-config/src/configs/vue.ts @@ -15,6 +15,22 @@ export async function vue(): Promise { { files: ['**/*.vue'], languageOptions: { + // globals: { + // computed: 'readonly', + // defineEmits: 'readonly', + // defineExpose: 'readonly', + // defineProps: 'readonly', + // onMounted: 'readonly', + // onUnmounted: 'readonly', + // reactive: 'readonly', + // ref: 'readonly', + // shallowReactive: 'readonly', + // shallowRef: 'readonly', + // toRef: 'readonly', + // toRefs: 'readonly', + // watch: 'readonly', + // watchEffect: 'readonly', + // }, parser: parserVue, parserOptions: { ecmaFeatures: { diff --git a/internal/lint-configs/prettier-config/index.mjs b/internal/lint-configs/prettier-config/index.mjs index 41d8ff26b4a..f6a20c8b4b6 100644 --- a/internal/lint-configs/prettier-config/index.mjs +++ b/internal/lint-configs/prettier-config/index.mjs @@ -8,12 +8,6 @@ export default { singleQuote: false, }, }, - { - files: ['*.yaml', '*.yml'], - options: { - singleQuote: false, - }, - }, ], plugins: ['prettier-plugin-tailwindcss'], printWidth: 80, diff --git a/internal/vite-config/src/typing.ts b/internal/vite-config/src/typing.ts index 7505ab3eb4a..37da46d2b44 100644 --- a/internal/vite-config/src/typing.ts +++ b/internal/vite-config/src/typing.ts @@ -137,12 +137,12 @@ type ApplicationOptions = ApplicationPluginOptions; type LibraryOptions = LibraryPluginOptions; -type DefineApplicationOptions = (config?: ConfigEnv) => Promise<{ +type DefineApplicationOptions = (config: ConfigEnv) => Promise<{ application?: ApplicationOptions; vite?: UserConfig; }>; -type DefineLibraryOptions = (config?: ConfigEnv) => Promise<{ +type DefineLibraryOptions = (config: ConfigEnv) => Promise<{ library?: LibraryOptions; vite?: UserConfig; }>; diff --git a/package.json b/package.json index 850f03da4ba..73ce6f86e80 100644 --- a/package.json +++ b/package.json @@ -95,10 +95,10 @@ "vue-tsc": "catalog:" }, "engines": { - "node": ">=20", + "node": ">=20.10.0", "pnpm": ">=9.5.0" }, - "packageManager": "pnpm@9.10.0", + "packageManager": "pnpm@9.11.0", "pnpm": { "peerDependencyRules": { "allowedVersions": { @@ -109,7 +109,7 @@ "@ctrl/tinycolor": "4.1.0", "clsx": "2.1.1", "pinia": "2.2.2", - "vue": "3.5.6" + "vue": "3.5.7" }, "neverBuiltDependencies": [ "canvas", diff --git a/packages/@core/ui-kit/form-ui/__tests__/form-api.test.ts b/packages/@core/ui-kit/form-ui/__tests__/form-api.test.ts index 79734d7c1fd..d61627d9d78 100644 --- a/packages/@core/ui-kit/form-ui/__tests__/form-api.test.ts +++ b/packages/@core/ui-kit/form-ui/__tests__/form-api.test.ts @@ -6,7 +6,7 @@ import { FormApi } from '../src/form-api'; vi.mock('@vben-core/shared/utils', () => ({ bindMethods: vi.fn(), createMerge: vi.fn((mergeFn) => { - return (stateOrFn, prev) => { + return (stateOrFn: any, prev: any) => { mergeFn(prev, 'key', stateOrFn); return { ...prev, ...stateOrFn }; }; @@ -144,3 +144,64 @@ describe('formApi', () => { expect(isValid).toBe(true); }); }); + +describe('updateSchema', () => { + let instance: FormApi; + + beforeEach(() => { + instance = new FormApi(); + instance.state = { + schema: [ + { component: 'text', fieldName: 'name' }, + { component: 'number', fieldName: 'age', label: 'Age' }, + ], + }; + }); + + it('should update the schema correctly when fieldName matches', () => { + const newSchema = [ + { component: 'text', fieldName: 'name' }, + { component: 'number', fieldName: 'age', label: 'Age' }, + ]; + + instance.updateSchema(newSchema); + + expect(instance.state?.schema?.[0]?.component).toBe('text'); + expect(instance.state?.schema?.[1]?.label).toBe('Age'); + }); + + it('should log an error if fieldName is missing in some items', () => { + const newSchema: any[] = [ + { component: 'textarea', fieldName: 'name' }, + { component: 'number' }, + ]; + + const consoleErrorSpy = vi + .spyOn(console, 'error') + .mockImplementation(() => {}); + + instance.updateSchema(newSchema); + + expect(consoleErrorSpy).toHaveBeenCalledWith( + 'All items in the schema array must have a valid `fieldName` property to be updated', + ); + }); + + it('should not update schema if fieldName does not match', () => { + const newSchema = [{ component: 'textarea', fieldName: 'unknown' }]; + + instance.updateSchema(newSchema); + + expect(instance.state?.schema?.[0]?.component).toBe('text'); + expect(instance.state?.schema?.[1]?.component).toBe('number'); + }); + + it('should not update schema if updatedMap is empty', () => { + const newSchema: any[] = [{ component: 'textarea' }]; + + instance.updateSchema(newSchema); + + expect(instance.state?.schema?.[0]?.component).toBe('text'); + expect(instance.state?.schema?.[1]?.component).toBe('number'); + }); +}); diff --git a/packages/@core/ui-kit/form-ui/src/form-api.ts b/packages/@core/ui-kit/form-ui/src/form-api.ts index 191f4233fd2..1476778f2dd 100644 --- a/packages/@core/ui-kit/form-ui/src/form-api.ts +++ b/packages/@core/ui-kit/form-ui/src/form-api.ts @@ -5,7 +5,7 @@ import type { ValidationOptions, } from 'vee-validate'; -import type { FormActions, VbenFormProps } from './types'; +import type { FormActions, FormSchema, VbenFormProps } from './types'; import { toRaw } from 'vue'; @@ -186,6 +186,37 @@ export class FormApi { this.stateHandler.reset(); } + updateSchema(schema: Partial[]) { + const updated: Partial[] = [...schema]; + const hasField = updated.every( + (item) => Reflect.has(item, 'fieldName') && item.fieldName, + ); + + if (!hasField) { + console.error( + 'All items in the schema array must have a valid `fieldName` property to be updated', + ); + return; + } + const currentSchema = [...(this.state?.schema ?? [])]; + + const updatedMap: Record = {}; + + updated.forEach((item) => { + if (item.fieldName) { + updatedMap[item.fieldName] = item; + } + }); + + currentSchema.forEach((schema, index) => { + const updatedData = updatedMap[schema.fieldName]; + if (updatedData) { + currentSchema[index] = merge(updatedData, schema) as FormSchema; + } + }); + this.setState({ schema: currentSchema }); + } + async validate(opts?: Partial) { const form = await this.getForm(); return await form.validate(opts); diff --git a/packages/effects/common-ui/src/ui/about/about.vue b/packages/effects/common-ui/src/ui/about/about.vue index b2ad06672c3..41189c17310 100644 --- a/packages/effects/common-ui/src/ui/about/about.vue +++ b/packages/effects/common-ui/src/ui/about/about.vue @@ -52,7 +52,6 @@ const { license, version, // vite inject-metadata 插件注入的全局变量 - // eslint-disable-next-line no-undef } = __VBEN_ADMIN_METADATA__ || {}; const vbenDescriptionItems: DescriptionItem[] = [ diff --git a/packages/effects/layouts/src/basic/layout.vue b/packages/effects/layouts/src/basic/layout.vue index fb58ba6c57c..28bd28a4794 100644 --- a/packages/effects/layouts/src/basic/layout.vue +++ b/packages/effects/layouts/src/basic/layout.vue @@ -143,6 +143,19 @@ watch( }, ); +watch( + () => preferences.app.layout, + async (val) => { + if (val === 'sidebar-mixed-nav' && preferences.sidebar.hidden) { + updatePreferences({ + sidebar: { + hidden: false, + }, + }); + } + }, +); + const slots = useSlots(); const headerSlots = computed(() => { return Object.keys(slots).filter((key) => key.startsWith('header-')); diff --git a/packages/effects/layouts/src/widgets/check-updates/check-updates.vue b/packages/effects/layouts/src/widgets/check-updates/check-updates.vue index 2f366e44912..5e6d7e97a33 100644 --- a/packages/effects/layouts/src/widgets/check-updates/check-updates.vue +++ b/packages/effects/layouts/src/widgets/check-updates/check-updates.vue @@ -7,12 +7,15 @@ import { ToastAction, useToast } from '@vben-core/shadcn-ui'; interface Props { // 轮训时间,分钟 checkUpdatesInterval?: number; + // 检查更新的地址 + checkUpdateUrl?: string; } defineOptions({ name: 'CheckUpdates' }); const props = withDefaults(defineProps(), { checkUpdatesInterval: 1, + checkUpdateUrl: import.meta.env.BASE_URL || '/', }); const lastVersionTag = ref(''); @@ -28,7 +31,7 @@ async function getVersionTag() { ) { return null; } - const response = await fetch('/', { + const response = await fetch(props.checkUpdateUrl, { cache: 'no-cache', method: 'HEAD', }); diff --git a/packages/styles/src/antd/index.css b/packages/styles/src/antd/index.css index b6246ea4206..c41716bcfcf 100644 --- a/packages/styles/src/antd/index.css +++ b/packages/styles/src/antd/index.css @@ -12,6 +12,6 @@ @apply dark:border-border/60 dark:border; } -.ant-app .form-valid-error .ant-select-selector { +.form-valid-error .ant-select-selector { border-color: hsl(var(--destructive)); } diff --git a/playground/src/views/examples/form/api.vue b/playground/src/views/examples/form/api.vue index 32f1222548b..8efcaaa90b6 100644 --- a/playground/src/views/examples/form/api.vue +++ b/playground/src/views/examples/form/api.vue @@ -41,12 +41,25 @@ const [BaseForm, formApi] = useVbenForm({ label: 'field2', }, { - component: 'Input', + component: 'Select', componentProps: { - placeholder: '请输入', + allowClear: true, + filterOption: true, + options: [ + { + label: '选项1', + value: '1', + }, + { + label: '选项2', + value: '2', + }, + ], + placeholder: '请选择', + showSearch: true, }, - fieldName: 'field3', - label: 'field3', + fieldName: 'fieldOptions', + label: '下拉选', }, ], // 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个 @@ -75,9 +88,35 @@ function handleClick( | 'showSubmitButton' | 'updateActionAlign' | 'updateResetButton' + | 'updateSchema' | 'updateSubmitButton', ) { switch (action) { + case 'updateSchema': { + formApi.updateSchema([ + { + componentProps: { + options: [ + { + label: '选项1', + value: '1', + }, + { + label: '选项2', + value: '2', + }, + { + label: '选项3', + value: '3', + }, + ], + }, + fieldName: 'fieldOptions', + }, + ]); + break; + } + case 'labelWidth': { formApi.setState({ commonConfig: { @@ -181,6 +220,7 @@ function handleClick(