chore: initial commit
This commit is contained in:
566
frontend/packages/lib-shared/method/formCreate.ts
Normal file
566
frontend/packages/lib-shared/method/formCreate.ts
Normal file
@@ -0,0 +1,566 @@
|
||||
import type { CommonList, ModuleField } from '../models/common';
|
||||
import { FieldTypeEnum } from '../enums/formDesignEnum';
|
||||
import type { FormCreateField, FormDetail } from '@cordys/web/src/components/business/crm-form-create/types';
|
||||
import { formatTimeValue, getCityPath, getIndustryPath } from './index';
|
||||
import { useI18n } from '../hooks/useI18n';
|
||||
|
||||
export const linkAllAcceptTypes = [FieldTypeEnum.INPUT, FieldTypeEnum.TEXTAREA];
|
||||
export const dataSourceTypes = [FieldTypeEnum.DATA_SOURCE, FieldTypeEnum.DATA_SOURCE_MULTIPLE];
|
||||
export const hiddenTypes = [
|
||||
FieldTypeEnum.DIVIDER,
|
||||
FieldTypeEnum.PICTURE,
|
||||
FieldTypeEnum.ATTACHMENT,
|
||||
FieldTypeEnum.LINK,
|
||||
FieldTypeEnum.SUB_PRICE,
|
||||
FieldTypeEnum.SUB_PRODUCT,
|
||||
];
|
||||
export const needSameTypes = [
|
||||
FieldTypeEnum.PHONE,
|
||||
FieldTypeEnum.LOCATION,
|
||||
FieldTypeEnum.DATE_TIME,
|
||||
FieldTypeEnum.INPUT_NUMBER,
|
||||
FieldTypeEnum.INDUSTRY,
|
||||
FieldTypeEnum.SUB_PRICE,
|
||||
FieldTypeEnum.SUB_PRODUCT,
|
||||
];
|
||||
export const multipleTypes = [FieldTypeEnum.CHECKBOX, FieldTypeEnum.SELECT_MULTIPLE, FieldTypeEnum.INPUT_MULTIPLE];
|
||||
export const memberTypes = [FieldTypeEnum.MEMBER, FieldTypeEnum.MEMBER_MULTIPLE];
|
||||
export const departmentTypes = [FieldTypeEnum.DEPARTMENT, FieldTypeEnum.DEPARTMENT_MULTIPLE];
|
||||
export const singleTypes = [FieldTypeEnum.RADIO, FieldTypeEnum.SELECT];
|
||||
export const specialBusinessKeyMap: Record<string, string> = {
|
||||
customerId: 'customerName',
|
||||
contactId: 'contactName',
|
||||
clueId: 'clueName',
|
||||
businessId: 'businessName',
|
||||
contractId: 'contractName',
|
||||
owner: 'ownerName',
|
||||
opportunityId: 'opportunityName',
|
||||
paymentPlanId: 'paymentPlanName',
|
||||
businessTitleId: 'businessTitleName',
|
||||
};
|
||||
|
||||
export function getRuleType(item: FormCreateField) {
|
||||
if (
|
||||
item.type === FieldTypeEnum.SELECT_MULTIPLE ||
|
||||
item.type === FieldTypeEnum.CHECKBOX ||
|
||||
item.type === FieldTypeEnum.INPUT_MULTIPLE ||
|
||||
item.type === FieldTypeEnum.MEMBER_MULTIPLE ||
|
||||
item.type === FieldTypeEnum.DEPARTMENT_MULTIPLE ||
|
||||
item.type === FieldTypeEnum.DATA_SOURCE ||
|
||||
item.type === FieldTypeEnum.DATA_SOURCE_MULTIPLE ||
|
||||
item.type === FieldTypeEnum.PICTURE ||
|
||||
item.type === FieldTypeEnum.ATTACHMENT
|
||||
) {
|
||||
return 'array';
|
||||
}
|
||||
if (item.type === FieldTypeEnum.DATE_TIME) {
|
||||
return 'date';
|
||||
}
|
||||
if ([FieldTypeEnum.INPUT_NUMBER, FieldTypeEnum.FORMULA].includes(item.type)) {
|
||||
return 'number';
|
||||
}
|
||||
return 'string';
|
||||
}
|
||||
|
||||
export function getNormalFieldValue(item: FormCreateField, value: any) {
|
||||
if (item.type === FieldTypeEnum.DATA_SOURCE && !value) {
|
||||
return '';
|
||||
}
|
||||
if (
|
||||
[
|
||||
FieldTypeEnum.SELECT_MULTIPLE,
|
||||
FieldTypeEnum.MEMBER_MULTIPLE,
|
||||
FieldTypeEnum.DEPARTMENT_MULTIPLE,
|
||||
FieldTypeEnum.DATA_SOURCE_MULTIPLE,
|
||||
FieldTypeEnum.INPUT_MULTIPLE,
|
||||
].includes(item.type) &&
|
||||
!value
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
if (item.type === FieldTypeEnum.INPUT_MULTIPLE && !value) {
|
||||
return [];
|
||||
}
|
||||
if (item.multiple && !value) {
|
||||
return [];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数字
|
||||
* @param value 数字
|
||||
* @param item
|
||||
*/
|
||||
export function formatNumberValue(value: string | number, item: FormCreateField) {
|
||||
if (value !== undefined && value !== null && value !== '') {
|
||||
if (item.numberFormat === 'percent') {
|
||||
return item.precision ? `${Number(value).toFixed(item.precision)}%` : `${value}%`;
|
||||
}
|
||||
if (item.showThousandsSeparator) {
|
||||
return (item.precision ? Number(Number(value).toFixed(item.precision)) : Number(value)).toLocaleString('en-US');
|
||||
}
|
||||
return item.precision ? Number(value).toFixed(item.precision) : value.toString();
|
||||
}
|
||||
return '-';
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数字显示为字符串
|
||||
* @param value 数字
|
||||
* @param item
|
||||
*/
|
||||
export function formatNumberValueToString(value: number, item: FormCreateField) {
|
||||
if (value !== undefined && value !== null) {
|
||||
if (item.numberFormat === 'percent') {
|
||||
return item.precision ? `${Number(value).toFixed(item.precision)}%` : `${value}%`;
|
||||
}
|
||||
if (item.showThousandsSeparator) {
|
||||
if (typeof value === 'string') {
|
||||
return value;
|
||||
}
|
||||
return item.precision
|
||||
? `${value.toLocaleString('en-US').split('.')[0]}.${value.toFixed?.(item.precision).split('.')[1]}`
|
||||
: value.toLocaleString('en-US');
|
||||
}
|
||||
return item.precision ? Number(value).toFixed(item.precision) : value.toString();
|
||||
}
|
||||
return '-';
|
||||
}
|
||||
|
||||
export function initFieldValue(field: FormCreateField, value: string | number | (string | number)[]) {
|
||||
if (
|
||||
[FieldTypeEnum.DATA_SOURCE, FieldTypeEnum.DATA_SOURCE_MULTIPLE].includes(field.type) &&
|
||||
typeof value === 'string'
|
||||
) {
|
||||
return value ? [value] : [];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export function getFieldItemId(field: FormCreateField) {
|
||||
if (field.resourceFieldId) {
|
||||
return field.id.split('_ref_')[1]; // 处理数据源显示字段
|
||||
}
|
||||
return field.id;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param field
|
||||
* @param fieldValue
|
||||
* @returns 获取系统字段的值展示
|
||||
*/
|
||||
export function getDisplayFieldText(field: FormCreateField, fieldValue: any) {
|
||||
const { t } = useI18n();
|
||||
const fieldKey = field.businessKey || getFieldItemId(field);
|
||||
|
||||
if (fieldKey === 'invalid') {
|
||||
if (fieldValue === true || fieldValue === 'true') {
|
||||
return t('common.voided');
|
||||
}
|
||||
if (fieldValue === false || fieldValue === 'false') {
|
||||
return t('common.normal');
|
||||
}
|
||||
}
|
||||
|
||||
const currentOption = field.options?.find((option: any) => {
|
||||
if (option.value === fieldValue) {
|
||||
return true;
|
||||
}
|
||||
if (typeof option.value === 'boolean' && typeof fieldValue === 'string') {
|
||||
return String(option.value) === fieldValue;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
return currentOption ? currentOption.label : fieldValue;
|
||||
}
|
||||
|
||||
export function parseModuleFieldValue(item: FormCreateField, fieldValue: string | string[], options?: any[]) {
|
||||
if (fieldValue === undefined || fieldValue === null || fieldValue === '') {
|
||||
return '-';
|
||||
}
|
||||
const { t } = useI18n();
|
||||
let value: string | string[] = fieldValue;
|
||||
if (options) {
|
||||
// 若字段值是选项值,则取选项值的name
|
||||
if (Array.isArray(fieldValue)) {
|
||||
value = fieldValue.map((e) => {
|
||||
const option = options.find((opt) => opt.id === e);
|
||||
if (option) {
|
||||
return option.name || t('common.optionNotExist');
|
||||
}
|
||||
return t('common.optionNotExist');
|
||||
});
|
||||
} else {
|
||||
value = options.find((e) => e.id === fieldValue)?.name || t('common.optionNotExist');
|
||||
}
|
||||
} else if (
|
||||
[
|
||||
FieldTypeEnum.DATA_SOURCE,
|
||||
FieldTypeEnum.DATA_SOURCE_MULTIPLE,
|
||||
FieldTypeEnum.MEMBER,
|
||||
FieldTypeEnum.MEMBER_MULTIPLE,
|
||||
FieldTypeEnum.DEPARTMENT,
|
||||
FieldTypeEnum.DEPARTMENT_MULTIPLE,
|
||||
].includes(item.type)
|
||||
) {
|
||||
// 数据源/成员/部门类型字段,且没有匹配到 options,则显示不存在
|
||||
if (Array.isArray(fieldValue)) {
|
||||
value = fieldValue.map(() => t('common.optionNotExist'));
|
||||
} else {
|
||||
value = t('common.optionNotExist');
|
||||
}
|
||||
} else if (item.type === FieldTypeEnum.LOCATION) {
|
||||
const addressArr: string[] = (fieldValue as string)?.split('-')?.filter(Boolean) || [];
|
||||
if (!addressArr.length) {
|
||||
value = '-';
|
||||
} else {
|
||||
const country = addressArr[0];
|
||||
const rest = addressArr.filter((e, i) => i > 0).join('-');
|
||||
value = rest ? `${getCityPath(country, item.scope)}-${rest}` : getCityPath(country, item.scope);
|
||||
}
|
||||
} else if (item.type === FieldTypeEnum.INDUSTRY) {
|
||||
value = fieldValue ? getIndustryPath(fieldValue as string) : '-';
|
||||
} else if (item.type === FieldTypeEnum.INPUT_NUMBER) {
|
||||
value = formatNumberValueToString(fieldValue as unknown as number, item);
|
||||
if (value.includes('NaN') || value.includes('%%')) {
|
||||
value = fieldValue.toString();
|
||||
}
|
||||
} else if (item.type === FieldTypeEnum.DATE_TIME) {
|
||||
value = formatTimeValue(fieldValue as string, item.dateType);
|
||||
}
|
||||
if (Array.isArray(value) && item.resourceFieldId) {
|
||||
value = value.join(',');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export function parseFormDetailValue(item: FormCreateField, form: FormDetail, sourceName?: Ref<string>) {
|
||||
const { t } = useI18n();
|
||||
if (item.businessKey && !item.resourceFieldId) {
|
||||
// 引用数据源字段使用 id 读取数据,而不是 businessKey
|
||||
const options = form.optionMap?.[item.businessKey];
|
||||
// 业务标准字段读取最外层,读取form[item.businessKey]取到 id 值,然后去 options 里取 name
|
||||
let name: string | string[] = '';
|
||||
const value = form[item.businessKey];
|
||||
// 若字段值是选项值,则取选项值的name
|
||||
if (options) {
|
||||
if (Array.isArray(value)) {
|
||||
name = value.map((e) => {
|
||||
const option = options.find((opt) => opt.id === e);
|
||||
if (option) {
|
||||
return option.name || t('common.optionNotExist');
|
||||
}
|
||||
return t('common.optionNotExist');
|
||||
});
|
||||
} else if (value) {
|
||||
name = options.find((e) => e.id === value)?.name || t('common.optionNotExist');
|
||||
}
|
||||
}
|
||||
if (item.type === FieldTypeEnum.DATE_TIME) {
|
||||
return formatTimeValue(name || form[item.businessKey], item.dateType);
|
||||
}
|
||||
if (item.type === FieldTypeEnum.INPUT_NUMBER) {
|
||||
return formatNumberValueToString(name || form[item.businessKey], item);
|
||||
}
|
||||
if (item.type === FieldTypeEnum.ATTACHMENT) {
|
||||
return form.attachmentMap?.[item.businessKey] || [];
|
||||
}
|
||||
if (item.businessKey === 'name' && sourceName) {
|
||||
sourceName.value = name || form[item.businessKey];
|
||||
}
|
||||
return name || form[item.businessKey];
|
||||
}
|
||||
const options = form.optionMap?.[item.id];
|
||||
// 其他的字段读取moduleFields
|
||||
const field = form.moduleFields?.find((moduleField: ModuleField) => moduleField.fieldId === item.id);
|
||||
if (item.type === FieldTypeEnum.ATTACHMENT) {
|
||||
return form.attachmentMap?.[item.id] || [];
|
||||
}
|
||||
if (field) {
|
||||
return parseModuleFieldValue(item, field.fieldValue, options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单配置表格回显数据
|
||||
*/
|
||||
export function transformData({
|
||||
item,
|
||||
fields,
|
||||
originalData,
|
||||
excludeFieldIds,
|
||||
needParseSubTable = false,
|
||||
}: {
|
||||
fields: FormCreateField[];
|
||||
item: any;
|
||||
originalData?: CommonList<any>;
|
||||
excludeFieldIds?: string[];
|
||||
needParseSubTable?: boolean;
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const businessFieldAttr: Record<string, any> = {};
|
||||
const customFieldAttr: Record<string, any> = {};
|
||||
const addressFieldIds: string[] = [];
|
||||
const industryFieldIds: string[] = [];
|
||||
const dataSourceFieldIds: string[] = [];
|
||||
const memberFieldIds: string[] = [];
|
||||
const departmentFieldIds: string[] = [];
|
||||
const timeFieldIds: string[] = [];
|
||||
const fieldOptionMap: Record<string, any[]> = {};
|
||||
|
||||
fields.forEach((field) => {
|
||||
const fieldId = field.resourceFieldId ? field.id : field.businessKey || field.id;
|
||||
if (field.type === FieldTypeEnum.LOCATION) {
|
||||
addressFieldIds.push(fieldId);
|
||||
} else if (field.type === FieldTypeEnum.INDUSTRY) {
|
||||
industryFieldIds.push(fieldId);
|
||||
} else if (field.type === FieldTypeEnum.DATA_SOURCE || field.type === FieldTypeEnum.DATA_SOURCE_MULTIPLE) {
|
||||
dataSourceFieldIds.push(fieldId);
|
||||
} else if (field.type === FieldTypeEnum.MEMBER || field.type === FieldTypeEnum.MEMBER_MULTIPLE) {
|
||||
memberFieldIds.push(fieldId);
|
||||
} else if (field.type === FieldTypeEnum.DEPARTMENT || field.type === FieldTypeEnum.DEPARTMENT_MULTIPLE) {
|
||||
departmentFieldIds.push(fieldId);
|
||||
} else if (field.type === FieldTypeEnum.DATE_TIME) {
|
||||
timeFieldIds.push(fieldId);
|
||||
} else if ([FieldTypeEnum.SUB_PRICE, FieldTypeEnum.SUB_PRODUCT].includes(field.type) && needParseSubTable) {
|
||||
field.subFields?.forEach((subField) => {
|
||||
const subFieldData = (
|
||||
item[fieldId] || item.moduleFields?.find((mf: any) => mf.fieldId === fieldId)?.fieldValue
|
||||
)?.map((subItem: Record<string, any>) => {
|
||||
if (subField.resourceFieldId) {
|
||||
subItem[`${subField.id}_original`] = subItem[field.id]; // 备份原始值以供编辑时填充数据源
|
||||
subItem[subField.id] = parseModuleFieldValue(
|
||||
subField,
|
||||
subItem[subField.id],
|
||||
// 数据源显示字段不使用业务 key,直接使用字段 id 去取值
|
||||
originalData?.optionMap?.[subField.id]
|
||||
);
|
||||
fieldOptionMap[subField.id] = originalData?.optionMap?.[subField.id] || [];
|
||||
} else {
|
||||
subItem[`${subField.id}_original`] = subItem[subField.businessKey || subField.id]; // 备份原始值以供编辑时填充数据源
|
||||
subItem[subField.id] = parseModuleFieldValue(
|
||||
subField,
|
||||
subItem[subField.businessKey || subField.id],
|
||||
originalData?.optionMap?.[subField.businessKey || subField.id]
|
||||
);
|
||||
fieldOptionMap[subField.businessKey || subField.id] =
|
||||
originalData?.optionMap?.[subField.businessKey || subField.id] || [];
|
||||
}
|
||||
return subItem;
|
||||
});
|
||||
item[fieldId] = subFieldData;
|
||||
if (fieldId === field.businessKey) {
|
||||
// 子表格字段可能会被设置为数据源的显示字段,而数据源显示字段都通过 id 读取,所以这里需要用 id 备份一份数据以供数据源显示字段场景读取
|
||||
item[field.id] = subFieldData;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (field.businessKey && !field.resourceFieldId) {
|
||||
const fieldId = field.businessKey;
|
||||
const options = originalData?.optionMap?.[fieldId]?.map((e: any) => ({
|
||||
...e,
|
||||
name: e.name || t('common.optionNotExist'),
|
||||
}));
|
||||
fieldOptionMap[fieldId] = options || [];
|
||||
if (addressFieldIds.includes(fieldId)) {
|
||||
// 地址类型字段,解析代码替换成省市区
|
||||
const addressArr: string[] = item[fieldId]?.split('-')?.filter(Boolean) || [];
|
||||
let value = '';
|
||||
if (!addressArr.length) {
|
||||
value = '-';
|
||||
} else {
|
||||
const country = addressArr[0];
|
||||
const rest = addressArr.filter((e, i) => i > 0).join('-');
|
||||
value = rest ? `${getCityPath(country)}-${rest}` : getCityPath(country);
|
||||
}
|
||||
businessFieldAttr[fieldId] = value;
|
||||
} else if (industryFieldIds.includes(fieldId)) {
|
||||
// 行业类型字段,解析代码替换成行业名称
|
||||
businessFieldAttr[fieldId] = item[fieldId] ? getIndustryPath(item[fieldId] as string) : '-';
|
||||
} else if (timeFieldIds.includes(fieldId)) {
|
||||
// 时间类型字段,格式化时间显示
|
||||
businessFieldAttr[fieldId] = formatTimeValue(item[fieldId], field.dateType);
|
||||
} else if (options && options.length > 0) {
|
||||
let name: string | string[] = '';
|
||||
if (item[fieldId] === '' || item[fieldId] === null) {
|
||||
name = '-';
|
||||
} else if (dataSourceFieldIds.includes(fieldId)) {
|
||||
// 处理数据源字段,需要赋值为数组
|
||||
if (typeof item[fieldId] === 'string' || typeof item[fieldId] === 'number') {
|
||||
// 单选
|
||||
name = options?.find((e) => e.id === item[fieldId])?.name || t('common.optionNotExist');
|
||||
} else {
|
||||
// 多选
|
||||
name = options?.filter((e) => item[fieldId]?.includes(e.id)).map((e) => e.name) || [
|
||||
t('common.optionNotExist'),
|
||||
];
|
||||
}
|
||||
} else if (typeof item[fieldId] === 'string' || typeof item[fieldId] === 'number') {
|
||||
// 若值是单个字符串/数字
|
||||
name = options?.find((e) => e.id === item[fieldId])?.name || t('common.optionNotExist');
|
||||
} else {
|
||||
// 若值是数组
|
||||
name = options?.filter((e) => item[fieldId]?.includes(e.id)).map((e) => e.name) || [
|
||||
t('common.optionNotExist'),
|
||||
];
|
||||
if (Array.isArray(name) && name.length === 0) {
|
||||
name = [t('common.optionNotExist')];
|
||||
}
|
||||
}
|
||||
if (!excludeFieldIds?.includes(field.businessKey)) {
|
||||
if (specialBusinessKeyMap[fieldId]) {
|
||||
// 处理特殊业务 key 映射关系
|
||||
businessFieldAttr[specialBusinessKeyMap[fieldId]] = name || t('common.optionNotExist');
|
||||
} else {
|
||||
businessFieldAttr[fieldId] = name || t('common.optionNotExist');
|
||||
}
|
||||
}
|
||||
if (fieldId === 'owner') {
|
||||
businessFieldAttr.ownerId = item.owner;
|
||||
}
|
||||
} else if (specialBusinessKeyMap[fieldId]) {
|
||||
// 处理特殊业务 key 映射关系
|
||||
businessFieldAttr[specialBusinessKeyMap[fieldId]] = item[specialBusinessKeyMap[fieldId]];
|
||||
}
|
||||
businessFieldAttr[field.id] = businessFieldAttr[fieldId] || item[fieldId];
|
||||
}
|
||||
});
|
||||
|
||||
item.moduleFields?.forEach((field: ModuleField) => {
|
||||
const options = originalData?.optionMap?.[field.fieldId]?.map((e) => ({
|
||||
...e,
|
||||
name: e.name || t('common.optionNotExist'),
|
||||
}));
|
||||
fieldOptionMap[field.fieldId] = options || [];
|
||||
if (addressFieldIds.includes(field.fieldId)) {
|
||||
// 地址类型字段,解析代码替换成省市区
|
||||
const addressArr: string[] = (field?.fieldValue as string)?.split('-')?.filter(Boolean) || [];
|
||||
let value = '';
|
||||
if (!addressArr.length) {
|
||||
value = '-';
|
||||
} else {
|
||||
const country = addressArr[0];
|
||||
const scope = fields.find((f) => f.id === field.fieldId)?.scope;
|
||||
const rest = addressArr.filter((e, i) => i > 0).join('-');
|
||||
value = rest ? `${getCityPath(country, scope)}-${rest}` : getCityPath(country, scope);
|
||||
}
|
||||
customFieldAttr[field.fieldId] = value;
|
||||
} else if (industryFieldIds.includes(field.fieldId)) {
|
||||
// 行业类型字段,解析代码替换成行业名称
|
||||
customFieldAttr[field.fieldId] = field.fieldValue ? getIndustryPath(field.fieldValue as string) : '-';
|
||||
} else if (timeFieldIds.includes(field.fieldId)) {
|
||||
// 时间类型字段,格式化时间显示
|
||||
customFieldAttr[field.fieldId] = formatTimeValue(
|
||||
field.fieldValue as string,
|
||||
fields.find((f) => f.id === field.fieldId)?.dateType
|
||||
);
|
||||
} else if (options && options.length > 0) {
|
||||
let name: string | string[] = '';
|
||||
if (dataSourceFieldIds.includes(field.fieldId)) {
|
||||
// 处理数据源字段,需要赋值为数组
|
||||
if (typeof field.fieldValue === 'string' || typeof field.fieldValue === 'number') {
|
||||
// 单选
|
||||
name = [options.find((e) => e.id === field.fieldValue)?.name || t('common.optionNotExist')];
|
||||
} else {
|
||||
// 多选
|
||||
name = field.fieldValue?.map((e) => options.find((o) => o.id === e)?.name || t('common.optionNotExist'));
|
||||
}
|
||||
} else if (typeof field.fieldValue === 'string' || typeof field.fieldValue === 'number') {
|
||||
// 若值是单个字符串/数字
|
||||
name = options.find((e) => e.id === field.fieldValue)?.name || t('common.optionNotExist');
|
||||
} else {
|
||||
// 若值是数组
|
||||
name = field.fieldValue?.map((fv) => options.find((e) => e.id === fv)?.name || t('common.optionNotExist'));
|
||||
if (Array.isArray(name) && name.length === 0) {
|
||||
name = [t('common.optionNotExist')];
|
||||
}
|
||||
}
|
||||
customFieldAttr[field.fieldId] = name || [t('common.optionNotExist')];
|
||||
} else if (
|
||||
[...dataSourceFieldIds, ...memberFieldIds, ...departmentFieldIds].includes(field.fieldId) &&
|
||||
(!options || options.length === 0)
|
||||
) {
|
||||
// 处理匹配不到 optionsMap 的数据源/成员/部门字段
|
||||
if (typeof field.fieldValue === 'string' || typeof field.fieldValue === 'number') {
|
||||
// 单选
|
||||
customFieldAttr[field.fieldId] = field.fieldValue !== '' ? [t('common.optionNotExist')] : ['-'];
|
||||
} else {
|
||||
// 避免这里返回 [['选项不存在']] 这样的嵌套数组
|
||||
customFieldAttr[field.fieldId] = field.fieldValue?.map((e) => (e !== '' ? t('common.optionNotExist') : '-'));
|
||||
}
|
||||
} else {
|
||||
// 其他类型字段,直接赋值
|
||||
customFieldAttr[field.fieldId] = field.fieldValue;
|
||||
}
|
||||
});
|
||||
// 根据 moduleFields 集合判断 fields 完整字段集合中是否有自定义字段无值,因为无值后台不会在 moduleFields 里返回该字段,需要手动置空
|
||||
fields.forEach((field) => {
|
||||
if (!field.resourceFieldId && !field.businessKey) {
|
||||
const fieldId = field.id;
|
||||
// 避免将 0 有效计算结果误判为空
|
||||
if (customFieldAttr[fieldId] === undefined || customFieldAttr[fieldId] === null) {
|
||||
customFieldAttr[fieldId] = undefined;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
...item,
|
||||
...customFieldAttr,
|
||||
...businessFieldAttr,
|
||||
optionMap: fieldOptionMap,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单子表单计算汇总数值转换
|
||||
*/
|
||||
export function normalizeNumber(val: unknown): number {
|
||||
if (val === null || val === undefined || val === '') return 0;
|
||||
if (typeof val === 'number') {
|
||||
return Number.isFinite(val) ? val : 0;
|
||||
}
|
||||
if (typeof val === 'string') {
|
||||
let str = val.trim();
|
||||
if (!str) return 0;
|
||||
// 是否是百分比
|
||||
const isPercent = str.endsWith('%');
|
||||
// 去掉百分号
|
||||
if (isPercent) {
|
||||
str = str.slice(0, -1);
|
||||
}
|
||||
// 去掉千分位
|
||||
str = str.replace(/,/g, '');
|
||||
const num = Number(str);
|
||||
return Number.isNaN(num) ? 0 : num;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并初始选项和追加选项,去重后返回新的初始选项数组
|
||||
* @param sumInitialOptions
|
||||
* @param appendOptions
|
||||
* @returns
|
||||
*/
|
||||
export function mergeUniqueOptions(sumInitialOptions: Record<string, any>[], appendOptions: Record<string, any>[]) {
|
||||
const optionMap = new Map<any, Record<string, any>>();
|
||||
[...sumInitialOptions, ...appendOptions].forEach((option) => {
|
||||
if (!option) {
|
||||
return;
|
||||
}
|
||||
const optionKey = option.id ?? option.value;
|
||||
if (optionKey !== undefined) {
|
||||
if (optionMap.has(optionKey)) {
|
||||
Object.assign(optionMap.get(optionKey) || {}, option);
|
||||
} else {
|
||||
optionMap.set(optionKey, option);
|
||||
}
|
||||
}
|
||||
});
|
||||
sumInitialOptions = Array.from(optionMap.values());
|
||||
return sumInitialOptions;
|
||||
}
|
||||
Reference in New Issue
Block a user