feat: form-create

This commit is contained in:
xingyu4j
2025-10-17 16:15:54 +08:00
parent 41baa56bf8
commit 7704aef4c8
13 changed files with 86 additions and 91 deletions

View File

@@ -15,7 +15,7 @@ import {
import { requestClient } from '#/api/request'; import { requestClient } from '#/api/request';
export const useApiSelect = (option: ApiSelectProps) => { export function useApiSelect(option: ApiSelectProps) {
return defineComponent({ return defineComponent({
name: option.name, name: option.name,
props: { props: {
@@ -317,4 +317,4 @@ export const useApiSelect = (option: ApiSelectProps) => {
); );
}, },
}); });
}; }

View File

@@ -2,7 +2,7 @@ import { defineComponent } from 'vue';
import ImageUpload from '#/components/upload/image-upload.vue'; import ImageUpload from '#/components/upload/image-upload.vue';
export const useImagesUpload = () => { export function useImagesUpload() {
return defineComponent({ return defineComponent({
name: 'ImagesUpload', name: 'ImagesUpload',
props: { props: {
@@ -22,4 +22,4 @@ export const useImagesUpload = () => {
); );
}, },
}); });
}; }

View File

@@ -2,7 +2,9 @@ import type { Ref } from 'vue';
import type { Menu } from '#/components/form-create/typing'; import type { Menu } from '#/components/form-create/typing';
import { nextTick, onMounted } from 'vue'; import { isRef, nextTick, onMounted } from 'vue';
import formCreate from '@form-create/ant-design-vue';
import { apiSelectRule } from '#/components/form-create/rules/data'; import { apiSelectRule } from '#/components/form-create/rules/data';
@@ -15,6 +17,59 @@ import {
useUploadImagesRule, useUploadImagesRule,
} from './rules'; } from './rules';
// 编码表单 Conf
export function encodeConf(designerRef: any) {
return JSON.stringify(designerRef.value.getOption());
}
// 编码表单 Fields
export function encodeFields(designerRef: any) {
const rule = JSON.parse(designerRef.value.getJson());
const fields: string[] = [];
rule.forEach((item: unknown) => {
fields.push(JSON.stringify(item));
});
return fields;
}
// 解码表单 Fields
export function decodeFields(fields: string[]) {
const rule: object[] = [];
fields.forEach((item) => {
rule.push(formCreate.parseJson(item));
});
return rule;
}
// 设置表单的 Conf 和 Fields适用 FcDesigner 场景
export function setConfAndFields(
designerRef: any,
conf: string,
fields: string | string[],
) {
designerRef.value.setOption(formCreate.parseJson(conf));
// 处理 fields 参数类型,确保传入 decodeFields 的是 string[] 类型
const fieldsArray = Array.isArray(fields) ? fields : [fields];
designerRef.value.setRule(decodeFields(fieldsArray));
}
// 设置表单的 Conf 和 Fields适用 form-create 场景
export function setConfAndFields2(
detailPreview: any,
conf: string,
fields: string[],
value?: any,
) {
if (isRef(detailPreview)) {
detailPreview = detailPreview.value;
}
detailPreview.option = formCreate.parseJson(conf);
detailPreview.rule = decodeFields(fields);
if (value) {
detailPreview.value = value;
}
}
export function makeRequiredRule() { export function makeRequiredRule() {
return { return {
type: 'Required', type: 'Required',
@@ -23,11 +78,11 @@ export function makeRequiredRule() {
}; };
} }
export const localeProps = ( export function localeProps(
t: (msg: string) => any, t: (msg: string) => any,
prefix: string, prefix: string,
rules: any[], rules: any[],
) => { ) {
return rules.map((rule: { field: string; title: any }) => { return rules.map((rule: { field: string; title: any }) => {
if (rule.field === 'formCreate$required') { if (rule.field === 'formCreate$required') {
rule.title = t('props.required') || rule.title; rule.title = t('props.required') || rule.title;
@@ -36,7 +91,7 @@ export const localeProps = (
} }
return rule; return rule;
}); });
}; }
/** /**
* 解析表单组件的 field, title 等字段(递归,如果组件包含子组件) * 解析表单组件的 field, title 等字段(递归,如果组件包含子组件)
@@ -45,11 +100,11 @@ export const localeProps = (
* @param fields 解析后表单组件字段 * @param fields 解析后表单组件字段
* @param parentTitle 如果是子表单,子表单的标题,默认为空 * @param parentTitle 如果是子表单,子表单的标题,默认为空
*/ */
export const parseFormFields = ( export function parseFormFields(
rule: Record<string, any>, rule: Record<string, any>,
fields: Array<Record<string, any>> = [], fields: Array<Record<string, any>> = [],
parentTitle: string = '', parentTitle: string = '',
) => { ) {
const { type, field, $required, title: tempTitle, children } = rule; const { type, field, $required, title: tempTitle, children } = rule;
if (field && tempTitle) { if (field && tempTitle) {
let title = tempTitle; let title = tempTitle;
@@ -79,7 +134,7 @@ export const parseFormFields = (
parseFormFields(rule, fields); parseFormFields(rule, fields);
}); });
} }
}; }
/** /**
* 表单设计器增强 hook * 表单设计器增强 hook
@@ -92,7 +147,7 @@ export const parseFormFields = (
* - 部门选择器 * - 部门选择器
* - 富文本 * - 富文本
*/ */
export const useFormCreateDesigner = async (designer: Ref) => { export async function useFormCreateDesigner(designer: Ref) {
const editorRule = useEditorRule(); const editorRule = useEditorRule();
const uploadFileRule = useUploadFileRule(); const uploadFileRule = useUploadFileRule();
const uploadImageRule = useUploadImageRule(); const uploadImageRule = useUploadImageRule();
@@ -101,7 +156,7 @@ export const useFormCreateDesigner = async (designer: Ref) => {
/** /**
* 构建表单组件 * 构建表单组件
*/ */
const buildFormComponents = () => { function buildFormComponents() {
// 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代 // 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代
designer.value?.removeMenuItem('upload'); designer.value?.removeMenuItem('upload');
// 移除自带的富文本组件规则,使用 editorRule 替代 // 移除自带的富文本组件规则,使用 editorRule 替代
@@ -122,7 +177,7 @@ export const useFormCreateDesigner = async (designer: Ref) => {
label: component.label, label: component.label,
}); });
}); });
}; }
const userSelectRule = useSelectRule({ const userSelectRule = useSelectRule({
name: 'UserSelect', name: 'UserSelect',
@@ -146,7 +201,7 @@ export const useFormCreateDesigner = async (designer: Ref) => {
/** /**
* 构建系统字段菜单 * 构建系统字段菜单
*/ */
const buildSystemMenu = () => { function buildSystemMenu() {
// 移除自带的下拉选择器组件,使用 currencySelectRule 替代 // 移除自带的下拉选择器组件,使用 currencySelectRule 替代
// designer.value?.removeMenuItem('select') // designer.value?.removeMenuItem('select')
// designer.value?.removeMenuItem('radio') // designer.value?.removeMenuItem('radio')
@@ -172,11 +227,11 @@ export const useFormCreateDesigner = async (designer: Ref) => {
}), }),
}; };
designer.value?.addMenu(menu); designer.value?.addMenu(menu);
}; }
onMounted(async () => { onMounted(async () => {
await nextTick(); await nextTick();
buildFormComponents(); buildFormComponents();
buildSystemMenu(); buildSystemMenu();
}); });
}; }

View File

@@ -1,3 +1,3 @@
export { useApiSelect } from './components/use-api-select'; export { useApiSelect } from './components/use-api-select';
export { useFormCreateDesigner } from './helpers'; export * from './helpers';

View File

@@ -12,7 +12,7 @@ import { selectRule } from '#/components/form-create/rules/data';
/** /**
* 字典选择器规则,如果规则使用到动态数据则需要单独配置不能使用 useSelectRule * 字典选择器规则,如果规则使用到动态数据则需要单独配置不能使用 useSelectRule
*/ */
export const useDictSelectRule = () => { export function useDictSelectRule() {
const label = '字典选择器'; const label = '字典选择器';
const name = 'DictSelect'; const name = 'DictSelect';
const rules = cloneDeep(selectRule); const rules = cloneDeep(selectRule);
@@ -67,4 +67,4 @@ export const useDictSelectRule = () => {
]); ]);
}, },
}; };
}; }

View File

@@ -5,7 +5,7 @@ import {
makeRequiredRule, makeRequiredRule,
} from '#/components/form-create/helpers'; } from '#/components/form-create/helpers';
export const useEditorRule = () => { export function useEditorRule() {
const label = '富文本'; const label = '富文本';
const name = 'Tinymce'; const name = 'Tinymce';
return { return {
@@ -33,4 +33,4 @@ export const useEditorRule = () => {
]); ]);
}, },
}; };
}; }

View File

@@ -13,7 +13,7 @@ import { selectRule } from '#/components/form-create/rules/data';
* *
* @param option 规则配置 * @param option 规则配置
*/ */
export const useSelectRule = (option: SelectRuleOption) => { export function useSelectRule(option: SelectRuleOption) {
const label = option.label; const label = option.label;
const name = option.name; const name = option.name;
const rules = cloneDeep(selectRule); const rules = cloneDeep(selectRule);
@@ -42,4 +42,4 @@ export const useSelectRule = (option: SelectRuleOption) => {
]); ]);
}, },
}; };
}; }

View File

@@ -5,7 +5,7 @@ import {
makeRequiredRule, makeRequiredRule,
} from '#/components/form-create/helpers'; } from '#/components/form-create/helpers';
export const useUploadFileRule = () => { export function useUploadFileRule() {
const label = '文件上传'; const label = '文件上传';
const name = 'FileUpload'; const name = 'FileUpload';
return { return {
@@ -81,4 +81,4 @@ export const useUploadFileRule = () => {
]); ]);
}, },
}; };
}; }

View File

@@ -5,7 +5,7 @@ import {
makeRequiredRule, makeRequiredRule,
} from '#/components/form-create/helpers'; } from '#/components/form-create/helpers';
export const useUploadImageRule = () => { export function useUploadImageRule() {
const label = '单图上传'; const label = '单图上传';
const name = 'ImageUpload'; const name = 'ImageUpload';
return { return {
@@ -90,4 +90,4 @@ export const useUploadImageRule = () => {
]); ]);
}, },
}; };
}; }

View File

@@ -5,7 +5,7 @@ import {
makeRequiredRule, makeRequiredRule,
} from '#/components/form-create/helpers'; } from '#/components/form-create/helpers';
export const useUploadImagesRule = () => { export function useUploadImagesRule() {
const label = '多图上传'; const label = '多图上传';
const name = 'ImagesUpload'; const name = 'ImagesUpload';
return { return {
@@ -86,4 +86,4 @@ export const useUploadImagesRule = () => {
]); ]);
}, },
}; };
}; }

View File

@@ -1,59 +0,0 @@
/**
* 针对 https://github.com/xaboy/form-create-designer 封装的工具类
*/
// TODO @芋艿:后续这些 form-create 的优化;另外需要使用 form-create-helper 会好点
import { isRef } from 'vue';
import formCreate from '@form-create/ant-design-vue';
// 编码表单 Conf
export function encodeConf(designerRef: any) {
return JSON.stringify(designerRef.value.getOption());
}
// 编码表单 Fields
export function encodeFields(designerRef: any) {
const rule = JSON.parse(designerRef.value.getJson());
const fields: string[] = [];
rule.forEach((item: unknown) => {
fields.push(JSON.stringify(item));
});
return fields;
}
// 解码表单 Fields
export function decodeFields(fields: string[]) {
const rule: object[] = [];
fields.forEach((item) => {
rule.push(formCreate.parseJson(item));
});
return rule;
}
// 设置表单的 Conf 和 Fields适用 FcDesigner 场景
export function setConfAndFields(
designerRef: any,
conf: string,
fields: string | string[],
) {
designerRef.value.setOption(formCreate.parseJson(conf));
// 处理 fields 参数类型,确保传入 decodeFields 的是 string[] 类型
const fieldsArray = Array.isArray(fields) ? fields : [fields];
designerRef.value.setRule(decodeFields(fieldsArray));
}
// 设置表单的 Conf 和 Fields适用 form-create 场景
export function setConfAndFields2(
detailPreview: any,
conf: string,
fields: string[],
value?: any,
) {
if (isRef(detailPreview)) {
detailPreview = detailPreview.value;
}
detailPreview.option = formCreate.parseJson(conf);
detailPreview.rule = decodeFields(fields);
if (value) {
detailPreview.value = value;
}
}

View File

@@ -1,3 +1,2 @@
export * from './formCreate';
export * from './rangePickerProps'; export * from './rangePickerProps';
export * from './routerHelper'; export * from './routerHelper';

View File

@@ -11,8 +11,8 @@ import { message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form'; import { useVbenForm } from '#/adapter/form';
import { createForm, updateForm } from '#/api/bpm/form'; import { createForm, updateForm } from '#/api/bpm/form';
import { encodeConf, encodeFields } from '#/components/form-create';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { encodeConf, encodeFields } from '#/utils';
import { useFormSchema } from '../data'; import { useFormSchema } from '../data';