Files
frontend/apps/web-antd/src/components/form-create/helpers.ts
puhui999 1196dab9e4 feat(form-create): 【antd/ele】表单选择器支持默认选中当前用户/部门
- UserSelect 组件新增 defaultCurrentUser 配置,支持默认选中当前登录用户
- DeptSelect 组件重构为独立的树形选择器,支持 defaultCurrentDept 配置
- DeptSelect 支持 returnType 配置,可返回部门 ID 或部门名称
- 修复 useSelectRule 未将自定义 props 默认值传递给组件的问题
- 修复 DeptSelect 数据加载完成前回显失败的问题
- 同时支持 web-antd 和 web-ele 两个应用
2026-01-28 17:23:39 +08:00

268 lines
6.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Rule } from '@form-create/ant-design-vue';
import type { Ref } from 'vue';
import type { Menu } from '#/components/form-create/typing';
import { isRef, nextTick, onMounted } from 'vue';
import formCreate from '@form-create/ant-design-vue';
import { apiSelectRule } from '#/components/form-create/rules/data';
import {
useDictSelectRule,
useEditorRule,
useSelectRule,
useUploadFileRule,
useUploadImageRule,
useUploadImagesRule,
} from './rules';
/** 编码表单 Conf */
export function encodeConf(designerRef: any) {
// 关联案例https://gitee.com/yudaocode/yudao-ui-admin-vue3/pulls/834/
return formCreate.toJson(designerRef.value.getOption());
}
/** 解码表单 Conf */
export function decodeConf(conf: string) {
return formCreate.parseJson(conf);
}
/** 编码表单 Fields */
export function encodeFields(designerRef: any) {
const rule = designerRef.value.getRule();
const fields: string[] = [];
rule.forEach((item: any) => {
fields.push(formCreate.toJson(item));
});
return fields;
}
/** 解码表单 Fields */
export function decodeFields(fields: string[]) {
const rule: Rule[] = [];
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(decodeConf(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 = decodeConf(conf);
detailPreview.rule = decodeFields(fields);
if (value) {
detailPreview.value = value;
}
}
export function makeRequiredRule() {
return {
type: 'Required',
field: 'formCreate$required',
title: '是否必填',
};
}
export function localeProps(
t: (msg: string) => any,
prefix: string,
rules: any[],
) {
return rules.map((rule: { field: string; title: any }) => {
if (rule.field === 'formCreate$required') {
rule.title = t('props.required') || rule.title;
} else if (rule.field && rule.field !== '_optionType') {
rule.title = t(`components.${prefix}.${rule.field}`) || rule.title;
}
return rule;
});
}
/**
* 解析表单组件的 field, title 等字段(递归,如果组件包含子组件)
*
* @param rule 组件的生成规则 https://www.form-create.com/v3/guide/rule
* @param fields 解析后表单组件字段
* @param parentTitle 如果是子表单,子表单的标题,默认为空
*/
export function parseFormFields(
rule: Record<string, any>,
fields: Array<Record<string, any>> = [],
parentTitle: string = '',
) {
const { type, field, $required, title: tempTitle, children } = rule;
if (field && tempTitle) {
let title = tempTitle;
if (parentTitle) {
title = `${parentTitle}.${tempTitle}`;
}
let required = false;
if ($required) {
required = true;
}
fields.push({
field,
title,
type,
required,
});
// TODO 子表单 需要处理子表单字段
// if (type === 'group' && rule.props?.rule && Array.isArray(rule.props.rule)) {
// // 解析子表单的字段
// rule.props.rule.forEach((item) => {
// parseFields(item, fieldsPermission, title)
// })
// }
}
if (children && Array.isArray(children)) {
children.forEach((rule) => {
parseFormFields(rule, fields);
});
}
}
/**
* 表单设计器增强 hook
* 新增
* - 文件上传
* - 单图上传
* - 多图上传
* - 字典选择器
* - 用户选择器
* - 部门选择器
* - 富文本
*/
export async function useFormCreateDesigner(designer: Ref) {
const editorRule = useEditorRule();
const uploadFileRule = useUploadFileRule();
const uploadImageRule = useUploadImageRule();
const uploadImagesRule = useUploadImagesRule();
/** 构建表单组件 */
function buildFormComponents() {
// 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代
designer.value?.removeMenuItem('upload');
// 移除自带的富文本组件规则,使用 editorRule 替代
designer.value?.removeMenuItem('fc-editor');
const components = [
editorRule,
uploadFileRule,
uploadImageRule,
uploadImagesRule,
];
components.forEach((component) => {
// 插入组件规则
designer.value?.addComponent(component);
// 插入拖拽按钮到 `main` 分类下
designer.value?.appendMenuItem('main', {
icon: component.icon,
name: component.name,
label: component.label,
});
});
}
const userSelectRule = useSelectRule({
name: 'UserSelect',
label: '用户选择器',
icon: 'icon-eye',
props: [
{
type: 'switch',
field: 'defaultCurrentUser',
title: '默认选中当前用户',
value: true,
},
],
});
const deptSelectRule = useSelectRule({
name: 'DeptSelect',
label: '部门选择器',
icon: 'icon-tree',
props: [
{
type: 'select',
field: 'returnType',
title: '返回值类型',
value: 'id',
options: [
{ label: '部门编号', value: 'id' },
{ label: '部门名称', value: 'name' },
],
},
{
type: 'switch',
field: 'defaultCurrentDept',
title: '默认选中当前部门',
value: true,
},
],
});
const dictSelectRule = useDictSelectRule();
const apiSelectRule0 = useSelectRule({
name: 'ApiSelect',
label: '接口选择器',
icon: 'icon-json',
props: [...apiSelectRule],
event: ['click', 'change', 'visibleChange', 'clear', 'blur', 'focus'],
});
/** 构建系统字段菜单 */
function buildSystemMenu() {
// 移除自带的下拉选择器组件,使用 currencySelectRule 替代
// designer.value?.removeMenuItem('select')
// designer.value?.removeMenuItem('radio')
// designer.value?.removeMenuItem('checkbox')
const components = [
userSelectRule,
deptSelectRule,
dictSelectRule,
apiSelectRule0,
];
const menu: Menu = {
name: 'system',
title: '系统字段',
list: components.map((component) => {
// 插入组件规则
designer.value?.addComponent(component);
// 插入拖拽按钮到 `system` 分类下
return {
icon: component.icon,
name: component.name,
label: component.label,
};
}),
};
designer.value?.addMenu(menu);
}
onMounted(async () => {
await nextTick();
buildFormComponents();
buildSystemMenu();
});
}