自定义数据优化

v1.1.0
于肖磊 2024-12-09 17:29:33 +08:00
parent d6fb007129
commit 03e29c9eb8
10 changed files with 147 additions and 49 deletions

View File

@ -2,19 +2,19 @@
<div class="w h re custom-other">
<div v-for="(item, index) in list" :key="item.id" class="main-content" :style="{'left': percentage_count(item.location.x) , 'top': percentage_count(item.location.y), 'width': percentage_count(item.com_data.com_width), 'height': percentage_count(item.com_data.com_height), 'z-index': (customList.length - 1) - index}">
<template v-if="item.key == 'text'">
<model-text :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :title-params="showData?.data_name || 'name'" :is-percentage="true"></model-text>
<model-text :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :title-params="showData?.data_name || 'name'" :is-display-panel="true"></model-text>
</template>
<template v-else-if="item.key == 'img'">
<model-image :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :img-params="showData?.data_logo || ''" :is-percentage="true"></model-image>
<model-image :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :img-params="showData?.data_logo || ''" :is-display-panel="true"></model-image>
</template>
<template v-else-if="item.key == 'auxiliary-line'">
<model-lines :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :is-percentage="true"></model-lines>
<model-lines :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :is-display-panel="true"></model-lines>
</template>
<template v-else-if="item.key == 'icon'">
<model-icon :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :is-percentage="true"></model-icon>
<model-icon :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :is-display-panel="true"></model-icon>
</template>
<template v-else-if="item.key == 'panel'">
<model-panel :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :is-percentage="true"></model-panel>
<model-panel :key="item.id" :value="item.com_data" :scale="scale" :source-list="sourceList" :is-custom="isCustom" :is-display-panel="true"></model-panel>
</template>
</div>
</div>

View File

@ -9,7 +9,7 @@
</div>
</template>
<script setup lang="ts">
import { radius_computer, padding_computer, gradient_handle } from '@/utils';
import { radius_computer, padding_computer, gradient_handle, get_nested_property } from '@/utils';
import { isEmpty } from 'lodash';
const props = defineProps({
value: {
@ -25,7 +25,7 @@ const props = defineProps({
return {};
}
},
isPercentage: {
isDisplayPanel: {
type: Boolean,
default: false
},
@ -46,11 +46,23 @@ const icon_class = computed(() => {
return form.value.icon_class;
} else {
if (!isEmpty(props.sourceList)) {
//
let icon = props.sourceList[form.value.data_source_id];
// , data
if (!isEmpty(props.sourceList.data) && props.isCustom) {
icon = props.sourceList.data[form.value.data_source_id];
let icon = '';
// ID
const data_source_id = form.value.data_source_id;
if (!data_source_id.includes('.')) {
//
icon = props.sourceList[data_source_id];
// , data
if (!isEmpty(props.sourceList.data) && props.isCustom) {
icon = props.sourceList.data[data_source_id];
}
} else {
//
icon = get_nested_property(props.sourceList, data_source_id);
// , data
if (!isEmpty(props.sourceList.data) && props.isCustom) {
icon = get_nested_property(props.sourceList.data, data_source_id);
}
}
return icon;
} else {
@ -73,7 +85,7 @@ const com_style = computed(() => {
return style;
});
const set_count = () => {
if (props.isPercentage) {
if (props.isDisplayPanel) {
return '';
} else {
return `width: ${ form.value.com_width }px; height: ${ form.value.com_height }px;`;

View File

@ -4,7 +4,7 @@
</div>
</template>
<script setup lang="ts">
import { percentage_count, radius_computer } from '@/utils';
import { percentage_count, radius_computer, get_nested_property } from '@/utils';
import { isEmpty } from 'lodash';
const props = defineProps({
value: {
@ -20,7 +20,7 @@ const props = defineProps({
return {};
}
},
isPercentage: {
isDisplayPanel: {
type: Boolean,
default: false
},
@ -45,14 +45,30 @@ const img = computed(() => {
return form.value.img[0];
} else {
if (!isEmpty(props.sourceList)) {
//
let image_url = props.sourceList[form.value.data_source_id];
// , data
if (!isEmpty(props.sourceList.data) && props.isCustom) {
if (form.value.data_source_id == props.imgParams) {
image_url = !isEmpty(props.sourceList.new_cover)? props.sourceList.new_cover[0]?.url || '' : props.sourceList.data[props.imgParams];
} else {
image_url = props.sourceList.data[form.value.data_source_id];
let image_url = '';
// ID
const data_source_id = form.value.data_source_id;
if (!data_source_id.includes('.')) {
//
image_url = props.sourceList[data_source_id];
// , data
if (!isEmpty(props.sourceList.data) && props.isCustom) {
if (data_source_id == props.imgParams) {
image_url = !isEmpty(props.sourceList.new_cover)? props.sourceList.new_cover[0]?.url || '' : props.sourceList.data[data_source_id];
} else {
image_url = props.sourceList.data[data_source_id];
}
}
} else {
// ,使reduce
image_url = get_nested_property(props.sourceList, data_source_id);
// , data
if (!isEmpty(props.sourceList.data) && props.isCustom) {
if (data_source_id == props.imgParams) {
image_url = !isEmpty(props.sourceList.new_cover)? props.sourceList.new_cover[0]?.url || '' : get_nested_property(props.sourceList.data, data_source_id);
} else {
image_url = get_nested_property(props.sourceList.data, data_source_id);
}
}
}
return image_url;
@ -74,7 +90,7 @@ const border_style = computed(() => {
return style;
});
const set_count = () => {
if (props.isPercentage) {
if (props.isDisplayPanel) {
return `width: ${ percentage_count(form.value.img_width, form.value.com_width) }; height: ${ percentage_count(form.value.img_height, form.value.com_height) };`;
} else {
return `width: ${form.value.img_width}px; height: ${form.value.img_height}px;`;

View File

@ -10,7 +10,7 @@ const props = defineProps({
},
required: true,
},
isPercentage: {
isDisplayPanel: {
type: Boolean,
default: false,
},

View File

@ -19,7 +19,7 @@ const props = defineProps({
return {};
}
},
isPercentage: {
isDisplayPanel: {
type: Boolean,
default: false
},
@ -47,7 +47,7 @@ const com_img_style = computed(() => {
return background_computer(data);
});
const set_count = () => {
if (props.isPercentage) {
if (props.isDisplayPanel) {
return '';
} else {
return `width: ${ form.value.com_width }px; height: ${ form.value.com_height }px;`;

View File

@ -11,7 +11,7 @@
</div>
</template>
<script setup lang="ts">
import { radius_computer, padding_computer, gradient_handle } from '@/utils';
import { radius_computer, padding_computer, gradient_handle, get_nested_property } from '@/utils';
import { isEmpty } from 'lodash';
const props = defineProps({
value: {
@ -27,7 +27,7 @@ const props = defineProps({
return {};
}
},
isPercentage: {
isDisplayPanel: {
type: Boolean,
default: false
},
@ -42,32 +42,79 @@ const props = defineProps({
titleParams: {
type: String,
default: ''
},
options: {
type: Array<any>,
default: () => [],
}
});
//
const form = computed(() => props.value);
const text_title = computed(() => {
let text = '';
let text_title = props.sourceList[form.value.data_source_id];
//
if (!isEmpty(props.sourceList.data) && props.isCustom) {
// data
if (form.value.data_source_id == props.titleParams) {
text_title = !isEmpty(props.sourceList.new_title) ? props.sourceList.new_title : props.sourceList.data[props.titleParams];
return getTextTitle(form.value, props);
});
/**
* 根据表单值和属性获取文本标题
* 此函数用于根据提供的表单值和组件属性在不同的条件下返回相应的文本标题
* 主要处理逻辑包括检查表单值和数据源列表的存在性处理数据源ID以获取标题处理自定义标题情况错误处理以及最终文本的确定
*
* @param formValue 表单的当前值包含数据源ID和可能的文本标题
* @param props 组件的属性包括数据源列表是否显示面板是否自定义标题等
* @returns {string} 根据不同条件返回的文本标题
*/
const getTextTitle = (formValue: any, props: any): string => {
//
if (!formValue || !props.sourceList) {
if (!props.isDisplayPanel) {
return '请在此输入文字';
} else {
text_title = props.sourceList.data[form.value.data_source_id];
return '';
}
}
if (!isEmpty(form.value.text_title)) {
text = form.value.text_title;
} else if(text_title != undefined) {
text = text_title;
} else if(!props.isPercentage){
text = '请在此输入文字';
// ID
const data_source_id = formValue.data_source_id;
let text_title = '';
try {
// ID
if (!data_source_id.includes('.')) {
//
text_title = props.sourceList[data_source_id];
//
if (props.sourceList.data && props.isCustom) {
if (data_source_id === props.titleParams) {
text_title = props.sourceList.new_title || props.sourceList.data[data_source_id];
} else {
text_title = props.sourceList.data[data_source_id];
}
}
} else {
text_title = get_nested_property(props.sourceList, data_source_id);
//
if (props.sourceList.data && props.isCustom) {
if (data_source_id === props.titleParams) {
text_title = props.sourceList.new_title || get_nested_property(props.sourceList.data, data_source_id);
} else {
text_title = get_nested_property(props.sourceList.data, data_source_id);
}
}
}
} catch (error) {
//
console.error('Error in getTextTitle:', error);
if (!props.isDisplayPanel) {
return '请在此输入文字';
} else {
return '';
}
}
// 使使
let text = formValue.text_title || text_title;
if (text === '' && !props.isDisplayPanel) {
text = props.options.find((item: any) => item.field === data_source_id)?.name || '请在此输入文字';
}
return text;
});
}
const text_style = computed(() => {
let style = `font-size: ${ form.value.text_size * props.scale }px;line-height: ${ (typeof form.value.line_text_size === "number" ? form.value.line_text_size : form.value.text_size) * props.scale}px;color: ${ form.value.text_color }; text-align: ${ form.value.text_location }; transform: rotate(${form.value.text_rotate}deg);text-decoration: ${ form.value.text_option };${ padding_computer(form.value.text_padding, props.scale) };`;
@ -91,7 +138,7 @@ const com_style = computed(() => {
return style;
});
const set_count = () => {
if (props.isPercentage) {
if (props.isDisplayPanel) {
return '';
} else {
return `width: ${ form.value.com_width }px; height: ${ form.value.com_height }px;`;

View File

@ -7,7 +7,7 @@
<template v-if="item.type == 'select'">
<template v-if="+item?.config?.is_level == 1">
<div class="flex-row gap-10">
<el-cascader v-model="new_dataInterface[item.form_name]" :placeholder="placeholder_config(item, 'select')" clearable class="w h" collapse-tags popper-class="filter-form-cascader" :placement="+item?.config?.is_level == 1 && props.direction == 'vertical' ? 'left' : 'bottom'" :props="{ 'expandTrigger': 'hover', 'multiple': +item?.config?.is_multiple == 1, 'checkStrictly': true, 'emitPath': false, 'value': item?.data_key || 'id', 'label': item?.data_name || 'name', 'children': item?.config?.children || '' }" :options="selectData(item)" />
<el-cascader v-model="new_dataInterface[item.form_name]" :placeholder="placeholder_config(item, 'select')" :show-all-levels="false" filterable clearable class="w h" collapse-tags popper-class="filter-form-cascader" :placement="+item?.config?.is_level == 1 && props.direction == 'vertical' ? 'left' : 'bottom'" :props="{ 'expandTrigger': 'hover', 'multiple': +item?.config?.is_multiple == 1, 'checkStrictly': true, 'emitPath': false, 'value': item?.data_key || 'id', 'label': item?.data_name || 'name', 'children': item?.config?.children || '' }" :options="selectData(item)" />
<template v-if="+item?.config?.is_multiple == 1">
<el-tooltip effect="dark" :show-after="200" :hide-after="200" content="父级选中包含所有子级" raw-content placement="top">
<icon name="miaosha-hdgz" size="12" color="#999"></icon>
@ -16,7 +16,7 @@
</div>
</template>
<template v-else>
<el-select v-model="new_dataInterface[item.form_name]" :multiple="+item?.config?.is_multiple == 1" collapse-tags :placeholder="placeholder_config(item, 'select')" clearable>
<el-select v-model="new_dataInterface[item.form_name]" :multiple="+item?.config?.is_multiple == 1" filterable collapse-tags :placeholder="placeholder_config(item, 'select')" clearable>
<el-option v-for="item1 in selectData(item)" :key="item1[item?.data_key || 'id']" :label="item1[item?.data_name || 'name']" :value="item1[item?.data_key || 'id']" />
</el-select>
</template>

View File

@ -70,7 +70,7 @@
<Vue3DraggableResizable v-for="(item, index) in diy_data" :key="item.id" v-model:w="item.com_data.com_width" v-model:h="item.com_data.com_height" :min-w="0" :min-h="0" :class="{'plug-in-show-component-line': is_show_component_line, 'plug-in-show-tabs': item.show_tabs == '1', 'vdr-handle-z-index': item.com_data.bottom_up == '1' }" :style="{ 'z-index': (diy_data.length - 1) - index }" :init-w="item.com_data.com_width" :init-h="item.com_data.com_height" :x="item.location.x" :y="item.location.y" :parent="true" :draggable="is_draggable" @mousedown.stop="on_choose(index, item.show_tabs)" @click.stop="on_choose(index, item.show_tabs)" @drag-end="dragEndHandle($event, index)" @resizing="resizingHandle($event, item.key, index)" @resize-end="resizingHandle($event, item.key, index)">
<div :class="['main-content', { 'plug-in-border': item.show_tabs == '1' }]">
<template v-if="item.key == 'text'">
<model-text :key="item.id" :value="item.com_data" :source-list="props.sourceList" :is-custom="isCustom" :title-params="showData?.data_name || 'name'"></model-text>
<model-text :key="item.id" :value="item.com_data" :source-list="props.sourceList" :is-custom="isCustom" :title-params="showData?.data_name || 'name'" :options="options"></model-text>
</template>
<template v-else-if="item.key == 'img'">
<model-image :key="item.id" :value="item.com_data" :source-list="props.sourceList" :is-custom="isCustom" :img-params="showData?.data_logo || ''"></model-image>
@ -122,6 +122,7 @@ interface Props {
sourceList: object;
isCustom: boolean;
showData: any;
options: any;
}
const props = defineProps<Props>();
//#endregion

View File

@ -61,7 +61,7 @@
<Dialog ref="dialog" @accomplish="accomplish">
<div class="flex-row h w">
<!-- 左侧和中间区域 -->
<DragIndex ref="draglist" :key="dragkey" v-model:height="center_height" v-model:width="custom_width" :source-list="!isEmpty(data_source_content_list) ? data_source_content_list[0] : {}" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }" :list="custom_list" @right-update="right_update"></DragIndex>
<DragIndex ref="draglist" :key="dragkey" v-model:height="center_height" v-model:width="custom_width" :source-list="!isEmpty(data_source_content_list) ? data_source_content_list[0] : {}" :options="model_data_source" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }" :list="custom_list" @right-update="right_update"></DragIndex>
<!-- 右侧配置区域 -->
<div class="settings">
<template v-if="diy_data.key === 'img'">

View File

@ -23,6 +23,28 @@ export function is_obj_empty(obj: object): boolean {
export function is_number(val: string | number): boolean {
return typeof val == 'number' && !isNaN(val);
}
/**
*
*
*
*
*
* @param {Object} obj -
* @param {string} path - 使
* @returns {string} -
*/
export function get_nested_property(obj: any, path: string): string {
// 检查路径参数是否为字符串且非空,若不满足条件则返回空字符串
if (typeof path !== 'string' || !path) return '';
// 将属性路径字符串拆分为属性键数组
const keys = path.split('.');
// 使用reduce方法遍历属性键数组逐层访问对象属性
// 如果当前对象存在且拥有下一个属性键,则继续访问;否则返回空字符串
return keys.reduce((o, key) => (o && o[key] ? o[key] : ''), obj) || '';
}
/**
*
*