---初始化后台管理web页面项目
This commit is contained in:
406
src/utils/helper/appDataDesignHelper.ts
Normal file
406
src/utils/helper/appDataDesignHelper.ts
Normal file
@ -0,0 +1,406 @@
|
||||
import { LocationType } from '/@/enums/desktop';
|
||||
import { DesktopInfoItem } from '/@/model/mobileDesign/designer';
|
||||
|
||||
/**
|
||||
* 构建app数据设计页代码
|
||||
* @param model
|
||||
* @param _tableInfo
|
||||
* @returns
|
||||
*/
|
||||
export function buildAppDataCode(model: Array<DesktopInfoItem>): string {
|
||||
const compMap: any[] = [];
|
||||
let importCode = '';
|
||||
let configCode = '';
|
||||
let code = `<template>
|
||||
<view class="data-display">
|
||||
`;
|
||||
if (model.length) {
|
||||
model.forEach((o, i) => {
|
||||
const key = o.type;
|
||||
if (!compMap.includes(key)) compMap.push(key);
|
||||
const config: any = o.config;
|
||||
const apiConfig = config.apiConfig
|
||||
? `apiConfig: {
|
||||
name: "${config.apiConfig.name}",
|
||||
method: "${config.apiConfig.method}",
|
||||
path: "${config.apiConfig.path}",
|
||||
requestParamsConfigs: ${JSON.stringify(config.apiConfig.requestParamsConfigs) || []},
|
||||
requestHeaderConfigs: ${JSON.stringify(config.apiConfig.requestHeaderConfigs) || []},
|
||||
requestBodyConfigs:${JSON.stringify(config.apiConfig.requestBodyConfigs) || []}
|
||||
},`
|
||||
: '';
|
||||
const idx = i > 0 ? `_${i}` : '';
|
||||
switch (key) {
|
||||
case 'Dashboard':
|
||||
code += `<Dashboard :config="dashboardConfig${idx}"></Dashboard>
|
||||
`;
|
||||
configCode += `const dashboardConfig${idx} = ref({
|
||||
${apiConfig}
|
||||
numColor: "${config.numColor}",
|
||||
labelColor: "${config.labelColor}",
|
||||
dashboard: ${JSON.stringify(config.dashboard) || []}
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'Banner':
|
||||
code += `<view style="margin: 0 -10px 10px;">
|
||||
<Banner :config="bannerConfig${idx}"></Banner>
|
||||
</view>
|
||||
`;
|
||||
|
||||
const imgs: string[] = config.imgs.map((k) => {
|
||||
return k.url;
|
||||
});
|
||||
configCode += `const bannerConfig${idx} = ref({
|
||||
height: ${o.h},
|
||||
imgs: ${JSON.stringify(imgs)},
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'ChartLine':
|
||||
code += `<LineChart :config="lineConfig${idx}"></LineChart>
|
||||
`;
|
||||
const Llegend = getLegend(config.legend);
|
||||
const dataList: any[] = [];
|
||||
config.dataList.forEach((k) => {
|
||||
const yAxis: any[] = [];
|
||||
config.yAxis.forEach((j, i) => {
|
||||
yAxis.push({
|
||||
type: 'value', //value数值,categories类别
|
||||
position: j.position,
|
||||
title: j.name,
|
||||
titleFontColor: j.nameTextStyle.color,
|
||||
titleFontSize: j.nameTextStyle.fontSize,
|
||||
// min: j.min,
|
||||
// max: j.max,
|
||||
format: i === 0 ? 'lineYAxis' : 'lineYAxisTwo',
|
||||
axisFormat: j.axisLabel.formatter,
|
||||
fontColor: j.axisLabel.color,
|
||||
axisLine: j.axisLine.show,
|
||||
axisLineColor: j.axisLine.lineStyle.color,
|
||||
});
|
||||
});
|
||||
|
||||
dataList.push({
|
||||
title: k.title,
|
||||
valueKey: k.valueKey,
|
||||
apiConfig: k.apiConfig,
|
||||
indicator: k.indicator,
|
||||
options: {
|
||||
extra: {
|
||||
mix: {
|
||||
column: {
|
||||
seriesGap: 120,
|
||||
},
|
||||
area: {
|
||||
gradient: true,
|
||||
opacity: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
data: yAxis,
|
||||
},
|
||||
xAxis: {
|
||||
title: config.xAxis[0].name,
|
||||
titleFontColor: config.xAxis[0].nameTextStyle.color,
|
||||
titleFontSize: config.xAxis[0].nameTextStyle.fontSize,
|
||||
fontColor: config.xAxis[0].axisLabel.color,
|
||||
axisLine: config.xAxis[0].axisLine.show,
|
||||
axisLineColor: config.xAxis[0].axisLine.lineStyle.color,
|
||||
format: 'lineXAxis',
|
||||
axisFormat: config.xAxis[0].axisLabel.formatter,
|
||||
},
|
||||
dataLabel: config.label.show,
|
||||
legend: Llegend,
|
||||
},
|
||||
});
|
||||
});
|
||||
configCode += `const lineConfig${idx} = ref({
|
||||
height: ${o.h},
|
||||
title: "${config.title}",
|
||||
condition: ${JSON.stringify(config.condition)},
|
||||
count: ${JSON.stringify(config.count)},
|
||||
dataList:${JSON.stringify(dataList)},
|
||||
line: ${JSON.stringify(config.line)},
|
||||
fontSize:${config.label.fontSize},
|
||||
fontColor:"${config.label.color}",
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'Pie':
|
||||
code += `<PieChart :config="pieConfig${idx}"></PieChart>
|
||||
`;
|
||||
const Plegend = getLegend(config.echarts.legend);
|
||||
const type =
|
||||
config.echarts.series[0].radius[0] &&
|
||||
config.echarts.series[0].radius[0].split('%')[0] > 0
|
||||
? 'ring'
|
||||
: config.echarts.series[0].roseType
|
||||
? 'rose'
|
||||
: 'pie';
|
||||
let opts = '';
|
||||
if (type == 'pie') {
|
||||
opts = `pie: {
|
||||
"customRadius": ${config.echarts.series[0].radius[1].split('%')[0]},
|
||||
"labelWidth": 10,
|
||||
"border": false
|
||||
}`;
|
||||
} else if (type == 'ring') {
|
||||
opts = `ring: {
|
||||
ringWidth: ${config.echarts.series[0].radius[0].split('%')[0]}, //内圈大小
|
||||
labelWidth: 10,
|
||||
border: false,
|
||||
customRadius:${config.echarts.series[0].radius[1].split('%')[0]} //外圈大小
|
||||
}`;
|
||||
} else {
|
||||
opts = `rose: {
|
||||
type: "${config.echarts.series[0].roseType}",
|
||||
minRadius: ${config.echarts.series[0].radius[0].split('%')[0]},
|
||||
labelWidth: 10,
|
||||
border: false,
|
||||
}`;
|
||||
}
|
||||
configCode += `const pieConfig${idx} = ref({
|
||||
${apiConfig}
|
||||
labelKey: "${config.labelKey}",
|
||||
valueKey: "${config.valueKey}",
|
||||
title: "${config.title}",
|
||||
height: ${o.h},
|
||||
fontSize:${config.echarts.series[0].label.fontSize},
|
||||
fontColor:"${config.echarts.series[0].label.color}",
|
||||
pieType:"${type}", //rose玫瑰图,pie饼图,ring环形图
|
||||
options:{
|
||||
dataLabel: ${config.echarts.series[0].label.show},
|
||||
labelFormat:"${config.echarts.series[0].label.formatter}",
|
||||
legend: ${JSON.stringify(Plegend)},
|
||||
color: ${JSON.stringify(config.colors)},
|
||||
extra: {${opts}}
|
||||
}
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'Radar':
|
||||
code += `<RadarChart :config="radarConfig${idx}"></RadarChart>
|
||||
`;
|
||||
const Rlegend = getLegend(config.echarts.legend);
|
||||
configCode += `const radarConfig${idx} = ref({
|
||||
${apiConfig}
|
||||
labelKey: "${config.labelKey}",
|
||||
title: "${config.title}",
|
||||
height: ${o.h},
|
||||
indicator:${JSON.stringify(config.echarts.radar.indicator) || []},
|
||||
pointShape:"${config.echarts.series[0].symbol}",
|
||||
options:{
|
||||
dataLabel: ${config.echarts.series[0].label.show},
|
||||
legend: ${JSON.stringify(Rlegend)},
|
||||
color: ${JSON.stringify(config.colors)},
|
||||
extra: {
|
||||
"radar": {
|
||||
radius:${config.echarts.radar.radius},
|
||||
"gridType": "circle",
|
||||
"gridColor": "#CCCCCC",
|
||||
border:true,
|
||||
"opacity": ${config.echarts.showAreaStyle},
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'Gauge':
|
||||
code += `<GaugeChart :config="gaugeConfig${idx}"></GaugeChart>
|
||||
`;
|
||||
configCode += `const gaugeConfig${idx} = ref({
|
||||
${apiConfig}
|
||||
labelKey: "${config.labelKey}",
|
||||
title: "${config.title}",
|
||||
height: ${o.h},
|
||||
valueKey: "${config.valueKey}",
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'Funnel':
|
||||
code += `<FunnelChart :config="funnelConfig${idx}"></FunnelChart>
|
||||
`;
|
||||
const Flegend = getLegend(config.echarts.legend);
|
||||
configCode += `const funnelConfig${idx} = ref({
|
||||
${apiConfig}
|
||||
fontSize:${config.echarts.series[0].label.fontSize},
|
||||
fontColor:"${config.echarts.series[0].label.color}",
|
||||
options:{
|
||||
labelFormat:"${config.echarts.series[0].label.formatter}",
|
||||
dataLabel:${config.echarts.series[0].label.show},
|
||||
color: ${JSON.stringify(config.colors)},
|
||||
padding: [${config.echarts.series[0].top || 0},${
|
||||
config.echarts.series[0].right || 0
|
||||
},${config.echarts.series[0].bottom || 0},${config.echarts.series[0].left || 0}],
|
||||
legend:${JSON.stringify(Flegend)},
|
||||
extra: {
|
||||
funnel: {
|
||||
activeOpacity: 0.3,
|
||||
activeWidth: 10,
|
||||
border: true,
|
||||
borderWidth: ${config.echarts.series[0].gap},
|
||||
borderColor: "#FFFFFF",
|
||||
fillOpacity: 1,
|
||||
labelAlign: "${
|
||||
config.echarts.series[0].label.show
|
||||
? config.echarts.series[0].label.position
|
||||
: 'left'
|
||||
}",
|
||||
type: "${
|
||||
config.echarts.series[0].sort == 'descending' ? 'triangle' : 'pyramid'
|
||||
}" //triangle倒三角,pyramid金字塔
|
||||
}
|
||||
}
|
||||
},
|
||||
labelKey: "${config.labelKey}",
|
||||
title: "${config.title}",
|
||||
height: ${o.h},
|
||||
valueKey: "${config.valueKey}",
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'ChartBar':
|
||||
code += `<BarChart :config="barConfig${idx}"></BarChart>
|
||||
`;
|
||||
configCode += `const barConfig${idx} = ref({
|
||||
${apiConfig}
|
||||
labelKey: "${config.labelKey}",
|
||||
targetKey:"${config.targetKey}",
|
||||
title: "${config.title}",
|
||||
height: ${o.h},
|
||||
unit: "${config.unit}",
|
||||
valueKey: "${config.valueKey}"
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'MyTask':
|
||||
code += `<MyTask :config="taskConfig${idx}"></MyTask>
|
||||
`;
|
||||
configCode += `const taskConfig${idx} = ref({
|
||||
title: "${config.title}",
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'TodoList':
|
||||
code += `<TodoList :config="todoConfig${idx}"></TodoList>
|
||||
`;
|
||||
configCode += `const todoConfig${idx} = ref({
|
||||
title: "${config.title}",
|
||||
maxRows: ${config.maxRows},
|
||||
});
|
||||
`;
|
||||
break;
|
||||
case 'Modules':
|
||||
code += `<Modules :config="modulesConfig${idx}"></Modules>
|
||||
`;
|
||||
configCode += `const modulesConfig${idx} = ref({
|
||||
title: "${config.title}",
|
||||
functions: ${JSON.stringify(config.functions)},
|
||||
});
|
||||
`;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
compMap.forEach((o) => {
|
||||
switch (o) {
|
||||
case 'Dashboard':
|
||||
importCode += `import Dashboard from '@/components/dataDisplay/Dashboard.vue';
|
||||
`;
|
||||
break;
|
||||
case 'Banner':
|
||||
importCode += `import Banner from '@/components/dataDisplay/Banner.vue';
|
||||
`;
|
||||
break;
|
||||
case 'ChartLine':
|
||||
importCode += `import LineChart from '@/components/dataDisplay/LineChart.vue';
|
||||
`;
|
||||
break;
|
||||
case 'Pie':
|
||||
importCode += `import PieChart from '@/components/dataDisplay/PieChart.vue';
|
||||
`;
|
||||
break;
|
||||
case 'Radar':
|
||||
importCode += `import RadarChart from '@/components/dataDisplay/RadarChart.vue';
|
||||
`;
|
||||
break;
|
||||
case 'Gauge':
|
||||
importCode += `import GaugeChart from '@/components/dataDisplay/GaugeChart.vue';
|
||||
`;
|
||||
break;
|
||||
case 'Funnel':
|
||||
importCode += `import FunnelChart from '@/components/dataDisplay/FunnelChart.vue';
|
||||
`;
|
||||
break;
|
||||
case 'ChartBar':
|
||||
importCode += `import BarChart from '@/components/dataDisplay/BarChart.vue';
|
||||
`;
|
||||
break;
|
||||
case 'MyTask':
|
||||
importCode += `import MyTask from '@/components/dataDisplay/MyTask.vue';
|
||||
`;
|
||||
break;
|
||||
case 'TodoList':
|
||||
importCode += `import TodoList from '@/components/dataDisplay/TodoList.vue';
|
||||
`;
|
||||
break;
|
||||
case 'Modules':
|
||||
importCode += `import Modules from '@/components/dataDisplay/Modules.vue';
|
||||
`;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
code += `</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
${importCode}
|
||||
${configCode}
|
||||
</script>
|
||||
|
||||
<style></style>`;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
function getLegend(config) {
|
||||
let left = 'left';
|
||||
let top = 'bottom';
|
||||
if (config.position == LocationType.LEFT_TOP) {
|
||||
left = config.orient == 'horizontal' ? 'left' : 'top';
|
||||
top = config.orient == 'horizontal' ? 'top' : 'left';
|
||||
} else if (config.position == LocationType.RIGHT_TOP) {
|
||||
left = config.orient == 'horizontal' ? 'right' : 'top';
|
||||
top = config.orient == 'horizontal' ? 'top' : 'right';
|
||||
} else if (config.position == LocationType.LEFT_BOTTOM) {
|
||||
left = config.orient == 'horizontal' ? 'left' : 'bottom';
|
||||
top = config.orient == 'horizontal' ? 'bottom' : 'left';
|
||||
} else if (config.position == LocationType.RIGHT_BOTTOM) {
|
||||
left = config.orient == 'horizontal' ? 'right' : 'bottom';
|
||||
top = config.orient == 'horizontal' ? 'bottom' : 'right';
|
||||
} else if (config.position == LocationType.TOP_CENTER) {
|
||||
left = 'center';
|
||||
top = config.orient == 'horizontal' ? 'top' : 'left';
|
||||
} else if (config.position == LocationType.BOTTOM_CENTER) {
|
||||
left = 'center';
|
||||
top = config.orient == 'horizontal' ? 'bottom' : 'left';
|
||||
}
|
||||
const legend = {
|
||||
show: config.show,
|
||||
position: top,
|
||||
float: left,
|
||||
margin: config.padding,
|
||||
legendShape: config.icon,
|
||||
fontColor: config.textStyle.color,
|
||||
};
|
||||
return legend;
|
||||
}
|
||||
1403
src/utils/helper/designHelper.ts
Normal file
1403
src/utils/helper/designHelper.ts
Normal file
File diff suppressed because it is too large
Load Diff
530
src/utils/helper/exportHelper.ts
Normal file
530
src/utils/helper/exportHelper.ts
Normal file
@ -0,0 +1,530 @@
|
||||
import { camelCaseString } from '/@/utils/event/design';
|
||||
|
||||
//查询为inputNumber的组件
|
||||
const iptNumComponents = ['number', 'slider', 'rate', 'computational', 'money-chinese'];
|
||||
|
||||
const remoteComponents = [
|
||||
'select',
|
||||
'associate-select',
|
||||
'associate-popup',
|
||||
'multiple-popup',
|
||||
'checkbox',
|
||||
'radio',
|
||||
];
|
||||
|
||||
export const handleSearchForm = (option, schema, item, isNeedTrans, convertCamel = true) => {
|
||||
if (!isNeedTrans) {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'Input',
|
||||
},`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'Input',
|
||||
};
|
||||
}
|
||||
if (iptNumComponents.includes(schema.type)) {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'InputNumber',
|
||||
componentProps:{
|
||||
style:{ width:'100%' }
|
||||
},
|
||||
},`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'InputNumber',
|
||||
componentProps: {
|
||||
style: { width: '100%' },
|
||||
},
|
||||
};
|
||||
}
|
||||
if (remoteComponents.includes(schema.type)) {
|
||||
if (option && option?.datasourceType === 'staticData') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'XjrSelect',
|
||||
componentProps: {
|
||||
datasourceType:'staticData',
|
||||
staticOptions: ${JSON.stringify(option.staticOptions)},
|
||||
labelField: '${option.labelField}',
|
||||
valueField: '${option.valueField}',
|
||||
${
|
||||
schema.type === 'checkbox' || schema.type === 'multiple-popup' ? "mode:'multiple'," : ''
|
||||
}
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'XjrSelect',
|
||||
componentProps: {
|
||||
datasourceType: 'staticData',
|
||||
staticOptions: option.staticOptions,
|
||||
labelField: option.labelField,
|
||||
valueField: option.valueField,
|
||||
mode:
|
||||
schema.type === 'checkbox' || schema.type === 'multiple-popup' ? 'multiple' : '',
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
};
|
||||
} else if (option && option?.datasourceType === 'dic') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'XjrSelect',
|
||||
componentProps: {
|
||||
datasourceType:'dic',
|
||||
params: ${JSON.stringify(option.params)},
|
||||
labelField: '${option.labelField}',
|
||||
valueField: '${option.valueField}',
|
||||
${
|
||||
schema.type === 'checkbox' || schema.type === 'multiple-popup' ? "mode:'multiple'," : ''
|
||||
}
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'XjrSelect',
|
||||
componentProps: {
|
||||
datasourceType: 'dic',
|
||||
params: option.params,
|
||||
labelField: option.labelField,
|
||||
valueField: option.valueField,
|
||||
mode:
|
||||
schema.type === 'checkbox' || schema.type === 'multiple-popup' ? 'multiple' : '',
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
};
|
||||
} else if (option && option?.datasourceType === 'api') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'XjrSelect',
|
||||
componentProps: {
|
||||
datasourceType:'api',
|
||||
apiConfig: ${JSON.stringify(option.apiConfig)},
|
||||
labelField: '${option.labelField}',
|
||||
valueField: '${option.valueField}',
|
||||
${schema.type === 'checkbox' || schema.type === 'multiple-popup' ? "mode:'multiple'," : ''}
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'XjrSelect',
|
||||
componentProps: {
|
||||
datasourceType: 'api',
|
||||
apiConfig: option.apiConfig,
|
||||
labelField: option.labelField,
|
||||
valueField: option.valueField,
|
||||
mode:
|
||||
schema.type === 'checkbox' || schema.type === 'multiple-popup' ? 'multiple' : '',
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
if (schema.type === 'switch') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'Select',
|
||||
componentProps:{
|
||||
getPopupContainer: () => document.body,
|
||||
options:[
|
||||
{
|
||||
label:'开',
|
||||
value: 1
|
||||
},{
|
||||
label:'关',
|
||||
value: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: [
|
||||
{
|
||||
label: '开',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: '关',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
if (schema.type === 'time') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'TimeRangePicker',
|
||||
componentProps:{
|
||||
format:'${option.format}',
|
||||
style: { width: '100%' },
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'TimeRangePicker',
|
||||
componentProps: {
|
||||
format: option.format,
|
||||
style: { width: '100%' },
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (schema.type === 'date') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'RangePicker',
|
||||
componentProps:{
|
||||
format:'${option.format}',
|
||||
style: { width: '100%' },
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},
|
||||
`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'RangePicker',
|
||||
componentProps: {
|
||||
format: option.format,
|
||||
style: { width: '100%' },
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (schema.type === 'user') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'User',
|
||||
componentProps:{
|
||||
suffix:'ant-design:setting-outlined',
|
||||
placeholder:'请选择'
|
||||
},
|
||||
},
|
||||
`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'User',
|
||||
componentProps: {
|
||||
suffix: 'ant-design:setting-outlined',
|
||||
placeholder: '请选择',
|
||||
},
|
||||
};
|
||||
}
|
||||
if (schema.type === 'area') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'Area',
|
||||
componentProps:{
|
||||
suffix:'ant-design:setting-outlined',
|
||||
placeholder:'请选择',
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},
|
||||
`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'Area',
|
||||
componentProps: {
|
||||
suffix: 'ant-design:setting-outlined',
|
||||
placeholder: '请选择',
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (schema.type === 'organization') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: '${schema!.component}',
|
||||
componentProps:{
|
||||
placeholder:'请选择',
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: schema!.component,
|
||||
componentProps: {
|
||||
placeholder: '请选择',
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (schema.type === 'cascader') {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: '${schema!.component}',
|
||||
componentProps: {
|
||||
apiConfig: ${JSON.stringify(option.apiConfig)},
|
||||
showFormat: '${option.showFormat}',
|
||||
separator: '${option.separator}',
|
||||
selectedConfig: 'any',
|
||||
},
|
||||
},
|
||||
`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: schema!.component,
|
||||
componentProps: {
|
||||
apiConfig: option.apiConfig,
|
||||
showFormat: option.showFormat,
|
||||
separator: option.separator,
|
||||
selectedConfig: 'any',
|
||||
},
|
||||
};
|
||||
}
|
||||
if (schema.type === 'info') {
|
||||
if (option && option.infoType === 0) {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'User',
|
||||
componentProps:{
|
||||
suffix:'ant-design:setting-outlined',
|
||||
placeholder:'请选择'
|
||||
},
|
||||
},
|
||||
`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'User',
|
||||
componentProps: {
|
||||
suffix: 'ant-design:setting-outlined',
|
||||
placeholder: '请选择',
|
||||
},
|
||||
};
|
||||
} else if (option && option.infoType === 1) {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'Dept',
|
||||
componentProps:{
|
||||
placeholder:'请选择',
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},
|
||||
`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'Dept',
|
||||
componentProps: {
|
||||
placeholder: '请选择',
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
};
|
||||
} else if (option && option.infoType === 2) {
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: 'RangePicker',
|
||||
componentProps: {
|
||||
showTime: true,
|
||||
style: { width: '100%' },
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},
|
||||
`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: 'RangePicker',
|
||||
componentProps: {
|
||||
showTime: true,
|
||||
style: { width: '100%' },
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
return convertCamel
|
||||
? `{
|
||||
field: '${camelCaseString(item.fieldName)}',
|
||||
label: '${schema!.label}',
|
||||
component: '${schema!.component}',
|
||||
},
|
||||
`
|
||||
: {
|
||||
field: item.fieldName,
|
||||
label: schema!.label,
|
||||
component: schema!.component,
|
||||
};
|
||||
};
|
||||
|
||||
export const handleAppSearchForm = (option, schema, item, isNeedTrans, convertCamel = true) => {
|
||||
if (!schema) return;
|
||||
const fieldName = convertCamel ? camelCaseString(item.fieldName) : item.fieldName;
|
||||
const field = `field: '${fieldName}',`;
|
||||
const params = `key: '${schema.key}',
|
||||
name: '${schema!.label}',
|
||||
label: '${schema!.label}',`;
|
||||
if (isNeedTrans) {
|
||||
if (schema.component == 'TimeRange') {
|
||||
return `{
|
||||
${params}
|
||||
field: '${fieldName + 'Start,' + fieldName + 'End'}',
|
||||
component: componentType.timeRange, //组件类型
|
||||
startTimeField:'${fieldName + 'Start'}',
|
||||
endTimeField:'${fieldName + 'End'}',
|
||||
componentProps: {
|
||||
startTimePlaceholder: '开始时间',
|
||||
endTimePlaceholder: '结束时间',
|
||||
isRange: true,
|
||||
}, //组件的所有配置信息
|
||||
},`;
|
||||
} else if (schema.component == 'DateTime') {
|
||||
return `{
|
||||
${params}
|
||||
field: '${fieldName + 'Start,' + fieldName + 'End'}',
|
||||
component: componentType.dateRange, //组件类型
|
||||
startTimeField:'${fieldName + 'Start'}',
|
||||
endTimeField:'${fieldName + 'End'}',
|
||||
componentProps: {
|
||||
formatType:'${
|
||||
option.format == 'YYYY-MM'
|
||||
? 'month'
|
||||
: option.format == 'YYYY'
|
||||
? 'year'
|
||||
: option.format == 'YYYY-MM-DD HH:mm:ss'
|
||||
? 'datetime'
|
||||
: 'date'
|
||||
}',
|
||||
type: "datetimerange", //日期时间范围选择器
|
||||
startPlaceholder: '开始日期',
|
||||
endPlaceholder: '结束日期',
|
||||
}, //组件的所有配置信息
|
||||
},`;
|
||||
} else if (schema.component == 'Switch') {
|
||||
return `{
|
||||
${params}
|
||||
${field}
|
||||
component: componentType.select, //组件类型
|
||||
componentProps: {
|
||||
localdata:[{text:'开',value:1},{text:'关',value:0}],
|
||||
},
|
||||
},`;
|
||||
} else if (
|
||||
schema.component == 'Checkbox' ||
|
||||
schema.component == 'Radio' ||
|
||||
schema.component == 'Select'
|
||||
) {
|
||||
return `{
|
||||
${params}
|
||||
${field}
|
||||
component: componentType.select, //组件类型
|
||||
componentProps: ${JSON.stringify(schema.componentProps)},
|
||||
},`;
|
||||
} else if (schema.component == 'colorPicker') {
|
||||
return `{
|
||||
${params}
|
||||
${field}
|
||||
component: componentType.color, //组件类型
|
||||
defaultValue:null,
|
||||
componentProps: {},
|
||||
},`;
|
||||
} else if (schema.component == 'InputNumber') {
|
||||
return `{
|
||||
${params}
|
||||
${field}
|
||||
component: componentType.input, //组件类型
|
||||
componentProps: {
|
||||
type: 'number',
|
||||
},
|
||||
},`;
|
||||
} else if (schema.component == 'Info') {
|
||||
if (schema.componentProps.infoType === 0) {
|
||||
return `{
|
||||
${params}
|
||||
${field}
|
||||
component: componentType.user, //组件类型
|
||||
componentProps: {
|
||||
placeholder: '请选择人员',
|
||||
suffixIcon: 'ant-design:setting-outlined',
|
||||
},
|
||||
},`;
|
||||
} else if (schema.componentProps.infoType === 1) {
|
||||
return `{
|
||||
${params}
|
||||
${field}
|
||||
component: componentType.organization, //组件类型
|
||||
componentProps: {
|
||||
placeholder: '请选择组织架构',
|
||||
},
|
||||
},`;
|
||||
} else if (schema.componentProps.infoType === 2) {
|
||||
return `{
|
||||
${params}
|
||||
field: '${fieldName + 'Start,' + fieldName + 'End'}',
|
||||
component: componentType.dateRange, //组件类型
|
||||
startTimeField:'${fieldName + 'Start'}',
|
||||
endTimeField:'${fieldName + 'End'}',
|
||||
componentProps: {
|
||||
formatType: 'datetime',
|
||||
type: 'datetimerange', //日期时间范围选择器
|
||||
startPlaceholder: '开始日期',
|
||||
endPlaceholder: '结束日期',
|
||||
},
|
||||
},`;
|
||||
}
|
||||
} else {
|
||||
return JSON.stringify(schema) + ',';
|
||||
}
|
||||
} else {
|
||||
return `{
|
||||
${params}
|
||||
${field}
|
||||
component: componentType.input, //组件类型
|
||||
componentProps: {
|
||||
placeholder: '请输入${schema.label}',
|
||||
}
|
||||
},`;
|
||||
}
|
||||
};
|
||||
153
src/utils/helper/generatorAppHelper.ts
Normal file
153
src/utils/helper/generatorAppHelper.ts
Normal file
@ -0,0 +1,153 @@
|
||||
import { camelCaseString } from '../event/design';
|
||||
import { buildAppFormProps } from './designHelper';
|
||||
import { ComponentOptionModel, FormJson } from '/@/model/generator/codeGenerator';
|
||||
|
||||
export const buildAppSchemeStrBySchema = (json: FormJson, convertCamel = true) => {
|
||||
const props = buildAppFormProps(json, convertCamel);
|
||||
return props;
|
||||
};
|
||||
|
||||
export const buildAppSchemeStr = (list: ComponentOptionModel[], convertCamel: boolean): string => {
|
||||
const code = `${list.map((item) => {
|
||||
if (item.type === 'divider') {
|
||||
return `{
|
||||
key: '${item.key}',
|
||||
field: ${convertCamel ? camelCaseString(item.bindField) : item.bindField}
|
||||
name: '${item.label}',
|
||||
component: componentType.divider,
|
||||
componentProps: {
|
||||
text: '${item.options!.defaultValue}',
|
||||
align: '${item.options!.orientation}',
|
||||
},
|
||||
}`;
|
||||
}
|
||||
//如果是栅格布局组件 手机端没有 必须要扁平化
|
||||
else if (item.type === 'grid') {
|
||||
let gridStr = ``;
|
||||
item.layout?.map((el) => {
|
||||
gridStr += buildAppSchemeStr(el.list, convertCamel);
|
||||
});
|
||||
|
||||
return gridStr;
|
||||
} //如果是tab组件 转换为手机端配置
|
||||
else if (item.type === 'tab') {
|
||||
return `{
|
||||
key: '${item.key}',
|
||||
name: '${item.label}',
|
||||
component: componentType.segmented,
|
||||
layout: [${item.layout?.map((el, index) => {
|
||||
return `{
|
||||
name: '${el.name}',
|
||||
value: '${index}',
|
||||
children: [${buildAppSchemeStr(el.list, convertCamel)}],
|
||||
}`;
|
||||
})}],
|
||||
}`;
|
||||
} else if (item.type === 'card') {
|
||||
return `{
|
||||
key: '${item.key}',
|
||||
name: '${item.label}',
|
||||
component: componentType.collapse,
|
||||
layout: [${item.layout?.map((el, index) => {
|
||||
return `{
|
||||
name: '${el.name}',
|
||||
value: '${index}',
|
||||
children: [${buildAppSchemeStr(el.list, convertCamel)}],
|
||||
}`;
|
||||
})}],
|
||||
}`;
|
||||
} else if (item.type === 'subForm') {
|
||||
return `{
|
||||
field: '${item.bindField}', //字段
|
||||
key: '${item.key}',
|
||||
name: '${item.label}',
|
||||
component: componentType.subForm,
|
||||
columns: [${buildAppSchemeStr(item.children!, convertCamel)}],
|
||||
}`;
|
||||
} else {
|
||||
return buildAppDefaultSchema(item, convertCamel);
|
||||
}
|
||||
})}`;
|
||||
return code;
|
||||
};
|
||||
|
||||
export function buildAppDefaultSchema(model: ComponentOptionModel, convertCamel: boolean): string {
|
||||
const compType = buildAppComponentTypeStr(model.type);
|
||||
const schema = `{
|
||||
key: '${model.key}',
|
||||
field: '${(convertCamel ? camelCaseString(model.bindField)! : model.bindField) || ''}',
|
||||
label: '${model.label}',
|
||||
component: '${compType}',
|
||||
defaultValue: '${model.options?.defaultValue}',
|
||||
componentProps: {
|
||||
placeholder: '请输入${model.label}',
|
||||
},
|
||||
name: '${model.label}',
|
||||
}`;
|
||||
return schema;
|
||||
}
|
||||
|
||||
export function buildAppComponentTypeStr(type: string): string {
|
||||
switch (type) {
|
||||
case 'input':
|
||||
return 'componentType.input';
|
||||
|
||||
case 'password':
|
||||
return 'componentType.input';
|
||||
|
||||
case 'textarea':
|
||||
return 'componentType.input';
|
||||
|
||||
case 'number':
|
||||
return 'componentType.inputNumber';
|
||||
|
||||
case 'radio':
|
||||
return 'componentType.radio';
|
||||
|
||||
case 'checkbox':
|
||||
return 'componentType.checkbox';
|
||||
|
||||
case 'select':
|
||||
return 'componentType.select';
|
||||
|
||||
case 'cascader':
|
||||
return 'componentType.select';
|
||||
|
||||
case 'time':
|
||||
return 'componentType.dateTime';
|
||||
case 'date':
|
||||
return 'componentType.dateTime';
|
||||
|
||||
case 'time-range':
|
||||
return 'componentType.dateRange';
|
||||
|
||||
case 'date-range':
|
||||
return 'componentType.dateRange';
|
||||
|
||||
case 'rate':
|
||||
return 'componentType.inputNumber';
|
||||
|
||||
case 'switch':
|
||||
return 'componentType.switch';
|
||||
|
||||
case 'slider':
|
||||
return 'componentType.inputNumber';
|
||||
|
||||
case 'divider':
|
||||
return 'componentType.divider';
|
||||
|
||||
case 'upload':
|
||||
return 'componentType.input';
|
||||
|
||||
case 'richtext-editor':
|
||||
return 'componentType.input';
|
||||
|
||||
case 'form':
|
||||
return 'componentType.subForm';
|
||||
case 'one-for-one':
|
||||
return 'componentType.subForm';
|
||||
|
||||
default:
|
||||
return 'componentType.input';
|
||||
}
|
||||
}
|
||||
3087
src/utils/helper/generatorHelper.ts
Normal file
3087
src/utils/helper/generatorHelper.ts
Normal file
File diff suppressed because it is too large
Load Diff
204
src/utils/helper/treeHelper.ts
Normal file
204
src/utils/helper/treeHelper.ts
Normal file
@ -0,0 +1,204 @@
|
||||
interface TreeHelperConfig {
|
||||
id: string;
|
||||
children: string;
|
||||
pid: string;
|
||||
}
|
||||
const DEFAULT_CONFIG: TreeHelperConfig = {
|
||||
id: 'id',
|
||||
children: 'children',
|
||||
pid: 'pid',
|
||||
};
|
||||
|
||||
const getConfig = (config: Partial<TreeHelperConfig>) => Object.assign({}, DEFAULT_CONFIG, config);
|
||||
|
||||
// tree from list
|
||||
export function listToTree<T = any>(list: any[], config: Partial<TreeHelperConfig> = {}): T[] {
|
||||
const conf = getConfig(config) as TreeHelperConfig;
|
||||
const nodeMap = new Map();
|
||||
const result: T[] = [];
|
||||
const { id, children, pid } = conf;
|
||||
|
||||
for (const node of list) {
|
||||
node[children] = node[children] || [];
|
||||
nodeMap.set(node[id], node);
|
||||
}
|
||||
for (const node of list) {
|
||||
const parent = nodeMap.get(node[pid]);
|
||||
(parent ? parent[children] : result).push(node);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function treeToList<T = any>(tree: any, config: Partial<TreeHelperConfig> = {}): T {
|
||||
config = getConfig(config);
|
||||
const { children } = config;
|
||||
const result: any = [...tree];
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
if (!result[i][children!]) continue;
|
||||
result.splice(i + 1, 0, ...result[i][children!]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function findNode<T = any>(
|
||||
tree: any,
|
||||
func: Fn,
|
||||
config: Partial<TreeHelperConfig> = {},
|
||||
): T | null {
|
||||
config = getConfig(config);
|
||||
const { children } = config;
|
||||
const list = [...tree];
|
||||
for (const node of list) {
|
||||
if (func(node)) return node;
|
||||
node[children!] && list.push(...node[children!]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function findNodeAll<T = any>(
|
||||
tree: any,
|
||||
func: Fn,
|
||||
config: Partial<TreeHelperConfig> = {},
|
||||
): T[] {
|
||||
config = getConfig(config);
|
||||
const { children } = config;
|
||||
const list = [...tree];
|
||||
const result: T[] = [];
|
||||
for (const node of list) {
|
||||
func(node) && result.push(node);
|
||||
node[children!] && list.push(...node[children!]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function findPath<T = any>(
|
||||
tree: any,
|
||||
func: Fn,
|
||||
config: Partial<TreeHelperConfig> = {},
|
||||
): T | T[] | null {
|
||||
config = getConfig(config);
|
||||
const path: T[] = [];
|
||||
const list = [...tree];
|
||||
const visitedSet = new Set();
|
||||
const { children } = config;
|
||||
while (list.length) {
|
||||
const node = list[0];
|
||||
if (visitedSet.has(node)) {
|
||||
path.pop();
|
||||
list.shift();
|
||||
} else {
|
||||
visitedSet.add(node);
|
||||
node[children!] && list.unshift(...node[children!]);
|
||||
path.push(node);
|
||||
if (func(node)) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function findPathAll(tree: any, func: Fn, config: Partial<TreeHelperConfig> = {}) {
|
||||
config = getConfig(config);
|
||||
const path: any[] = [];
|
||||
const list = [...tree];
|
||||
const result: any[] = [];
|
||||
const visitedSet = new Set(),
|
||||
{ children } = config;
|
||||
while (list.length) {
|
||||
const node = list[0];
|
||||
if (visitedSet.has(node)) {
|
||||
path.pop();
|
||||
list.shift();
|
||||
} else {
|
||||
visitedSet.add(node);
|
||||
node[children!] && list.unshift(...node[children!]);
|
||||
path.push(node);
|
||||
func(node) && result.push([...path]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function filter<T = any>(
|
||||
tree: T[],
|
||||
func: (n: T) => boolean,
|
||||
config: Partial<TreeHelperConfig> = {},
|
||||
): T[] {
|
||||
config = getConfig(config);
|
||||
const children = config.children as string;
|
||||
function listFilter(list: T[]) {
|
||||
return list
|
||||
.map((node: any) => ({ ...node }))
|
||||
.filter((node) => {
|
||||
node[children] = node[children] && listFilter(node[children]);
|
||||
return func(node) || (node[children] && node[children].length);
|
||||
});
|
||||
}
|
||||
return listFilter(tree);
|
||||
}
|
||||
|
||||
export function forEach<T = any>(
|
||||
tree: T[],
|
||||
func: (n: T) => any,
|
||||
config: Partial<TreeHelperConfig> = {},
|
||||
): void {
|
||||
config = getConfig(config);
|
||||
const list: any[] = [...tree];
|
||||
const { children } = config;
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
//func 返回true就终止遍历,避免大量节点场景下无意义循环,引起浏览器卡顿
|
||||
if (func(list[i])) {
|
||||
return;
|
||||
}
|
||||
children && list[i][children] && list.splice(i + 1, 0, ...list[i][children]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Extract tree specified structure
|
||||
*/
|
||||
export function treeMap<T = any>(treeData: T[], opt: { children?: string; conversion: Fn }): T[] {
|
||||
return treeData.map((item) => treeMapEach(item, opt));
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Extract tree specified structure
|
||||
*/
|
||||
export function treeMapEach(
|
||||
data: any,
|
||||
{ children = 'children', conversion }: { children?: string; conversion: Fn },
|
||||
) {
|
||||
const haveChildren = Array.isArray(data[children]) && data[children].length > 0;
|
||||
const conversionData = conversion(data) || {};
|
||||
if (haveChildren) {
|
||||
return {
|
||||
...conversionData,
|
||||
[children]: data[children].map((i: number) =>
|
||||
treeMapEach(i, {
|
||||
children,
|
||||
conversion,
|
||||
}),
|
||||
),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...conversionData,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归遍历树结构
|
||||
* @param treeDatas 树
|
||||
* @param callBack 回调
|
||||
* @param parentNode 父节点
|
||||
*/
|
||||
export function eachTree(treeDatas: any[], callBack: Fn, parentNode = {}) {
|
||||
treeDatas.forEach((element) => {
|
||||
const newNode = callBack(element, parentNode) || element;
|
||||
if (element.children) {
|
||||
eachTree(element.children, callBack, newNode);
|
||||
}
|
||||
});
|
||||
}
|
||||
35
src/utils/helper/tsxHelper.tsx
Normal file
35
src/utils/helper/tsxHelper.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { Slots } from 'vue';
|
||||
import { isFunction } from '/@/utils/is';
|
||||
|
||||
/**
|
||||
* @description: Get slot to prevent empty error
|
||||
*/
|
||||
export function getSlot(slots: Slots, slot = 'default', data?: any) {
|
||||
if (!slots || !Reflect.has(slots, slot)) {
|
||||
return null;
|
||||
}
|
||||
if (!isFunction(slots[slot])) {
|
||||
console.error(`${slot} is not a function!`);
|
||||
return null;
|
||||
}
|
||||
const slotFn = slots[slot];
|
||||
if (!slotFn) return null;
|
||||
return slotFn(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* extends slots
|
||||
* @param slots
|
||||
* @param excludeKeys
|
||||
*/
|
||||
export function extendSlots(slots: Slots, excludeKeys: string[] = []) {
|
||||
const slotKeys = Object.keys(slots);
|
||||
const ret: any = {};
|
||||
slotKeys.map((key) => {
|
||||
if (excludeKeys.includes(key)) {
|
||||
return null;
|
||||
}
|
||||
ret[key] = () => getSlot(slots, key);
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user