vr-uniapp/src/components/model-custom/model-custom-content.vue

456 lines
19 KiB
Vue
Raw Normal View History

<template>
<div class="auxiliary-line">
2024-08-26 03:26:32 +00:00
<el-form :model="form" label-width="70">
2024-08-29 07:18:32 +00:00
<card-container>
<div class="mb-20">数据源</div>
<el-form-item label="动态数据">
2024-08-26 07:13:47 +00:00
<el-select v-model="form.data_source" value-key="id" placeholder="请选择数据源" filterable clearable @change="changeDataSource">
2024-08-20 01:35:57 +00:00
<el-option v-for="item in options" :key="item.type" :label="item.name" :value="item.type" />
</el-select>
</el-form-item>
2024-11-13 09:27:27 +00:00
</card-container>
<!-- 筛选数据 -->
2024-11-28 06:38:42 +00:00
<template v-if="!isEmpty(default_type_data)">
<div class="divider-line"></div>
<card-container>
<div class="mb-12">显示设置</div>
<el-form-item label="铺满方式">
<el-radio-group v-model="form.data_source_direction">
2024-11-28 06:38:42 +00:00
<el-radio v-for="(item, index) in default_type_data.show_type" :key="index" :value="item">{{ item == 'vertical' ? '' : item == 'vertical-scroll' ? '' : '' }}</el-radio>
</el-radio-group>
</el-form-item>
2024-11-28 06:38:42 +00:00
<el-form-item v-if="['vertical-scroll', 'horizontal'].includes(form.data_source_direction)" label="每屏显示">
<el-radio-group v-model="form.data_source_carousel_col">
2024-11-28 06:38:42 +00:00
<el-radio v-for="(item, index) in default_type_data.show_number" :key="index" :value="item">{{ item }}{{ form.data_source_direction == 'vertical-scroll' ? '' : '' }}</el-radio>
</el-radio-group>
</el-form-item>
</card-container>
2024-11-28 06:38:42 +00:00
<template v-if="!isEmpty(default_type_data.data_type)">
<div class="divider-line"></div>
<card-container>
<div class="mb-12">数据设置</div>
<div class="flex-col">
<el-form-item label="读取方式">
<el-radio-group v-model="form.data_source_content.data_type">
2024-11-28 10:30:57 +00:00
<el-radio v-for="(item, index) in default_type_data.data_type" :key="index" :value="item">{{ item === 0 ? '' : '' }}</el-radio>
2024-11-28 06:38:42 +00:00
</el-radio-group>
</el-form-item>
2024-11-28 10:30:57 +00:00
<template v-if="Number(form.data_source_content.data_type) === 0">
2024-11-28 06:38:42 +00:00
<div class="nav-list">
<drag-group :list="form.data_source_content.data_list" :img-params="default_type_data?.appoint_config?.show_data?.data_logo || ''" :title-params="default_type_data?.appoint_config?.show_data?.data_name || 'name'" type="custom" @onsort="data_list_sort" @remove="data_list_remove" @replace="data_list_replace"></drag-group>
<el-button class="mt-20 w" @click="add">+</el-button>
</div>
</template>
<template v-else>
2024-11-28 10:30:57 +00:00
<filter-form :filter-data="default_type_data?.filter_config?.filter_form_config || {}" direction="vertical" :title-width="70" :data-interface="form.data_source_content" @form-change="filter_form_change"></filter-form>
2024-11-28 06:38:42 +00:00
</template>
</div>
</card-container>
</template>
2024-11-13 09:27:27 +00:00
</template>
<div class="divider-line"></div>
<card-container>
<div class="mb-20">内容设置</div>
<el-button class="w" size="large" @click="custom_edit"><icon name="edit" size="12"></icon>自定义编辑</el-button>
</card-container>
</el-form>
<Dialog ref="dialog" @accomplish="accomplish">
<div class="flex-row h w">
2024-10-19 03:33:06 +00:00
<!-- 左侧和中间区域 -->
<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] : {}" :source-type="form?.data_source || ''" :list="custom_list" @right-update="right_update"></DragIndex>
2024-10-19 03:33:06 +00:00
<!-- 右侧配置区域 -->
<div class="settings">
<template v-if="diy_data.key === 'img'">
2024-08-20 01:35:57 +00:00
<model-image-style :key="key" v-model:height="center_height" :options="model_data_source" :value="diy_data"></model-image-style>
</template>
<template v-else-if="diy_data.key == 'text'">
2024-08-20 01:35:57 +00:00
<model-text-style :key="key" v-model:height="center_height" :options="model_data_source" :value="diy_data"></model-text-style>
</template>
<template v-else-if="diy_data.key == 'auxiliary-line'">
<model-lines-style :key="key" v-model:height="center_height" :value="diy_data"></model-lines-style>
</template>
2024-09-23 09:31:38 +00:00
<template v-else-if="diy_data.key == 'icon'">
2024-11-14 08:14:51 +00:00
<model-icon-style :key="key" v-model:height="center_height" :options="model_data_source" :value="diy_data"></model-icon-style>
2024-09-23 09:31:38 +00:00
</template>
2024-10-10 08:16:31 +00:00
<template v-else-if="diy_data.key == 'panel'">
<model-panel-style :key="key" v-model:height="center_height" :value="diy_data"></model-panel-style>
</template>
2024-08-12 09:12:26 +00:00
<template v-else>
2024-08-16 10:01:59 +00:00
<div class="w h flex align-c bg-f">
<no-data></no-data>
</div>
2024-08-12 09:12:26 +00:00
</template>
</div>
</div>
</Dialog>
2024-11-28 06:38:42 +00:00
<custom-dialog v-model:dialog-visible="url_value_dialog_visible" :config="default_type_data.appoint_config" :multiple="url_value_multiple_bool" @confirm_event="url_value_dialog_call_back"></custom-dialog>
</div>
</template>
<script setup lang="ts">
import Dialog from './components/dialog.vue';
import DragIndex from './components/index.vue';
2024-11-28 06:38:42 +00:00
import { isEmpty, cloneDeep, omit } from 'lodash';
import request from '@/utils/request';
2024-08-20 01:35:57 +00:00
import CustomAPI from '@/api/custom';
2024-11-28 06:38:42 +00:00
import { DataSourceStore } from '@/store';
2024-11-13 10:35:22 +00:00
import { get_math } from '@/utils';
2024-08-22 07:05:39 +00:00
const data_source_store = DataSourceStore();
2024-08-19 10:19:42 +00:00
const props = defineProps({
value: {
type: Object,
default: () => {},
},
2024-11-06 06:49:25 +00:00
magicWidth: {
type: Number,
default: 390,
}
});
const dialog = ref<expose | null>(null);
2024-08-12 08:10:56 +00:00
const draglist = ref<diy_data | null>(null);
2024-11-14 09:04:57 +00:00
const form = ref(props.value);
2024-11-06 06:49:25 +00:00
const center_width = ref(props.magicWidth);
const custom_width = computed(() => {
2024-11-28 06:38:42 +00:00
// 如果是横向展示,那么就需要根据每屏显示的数量来计算宽度 data_source_direction == horizontal 为横向滑动
if (form.value.is_custom_data == '1' && form.value.data_source_direction == 'horizontal') {
return center_width.value / form.value.data_source_carousel_col;
} else {
return center_width.value;
}
})
// 弹出框里的内容
let custom_list = reactive([]);
const center_height = ref(0);
2024-11-28 06:38:42 +00:00
interface custom_config {
show_type: string[],
show_number: number[],
data_type: string[],
filter_config: object,
appoint_config: object,
}
2024-08-20 01:35:57 +00:00
interface data_list {
name: string;
field: string;
type: string;
2024-09-05 03:05:57 +00:00
}
2024-11-13 09:27:27 +00:00
interface options_item {
2024-11-28 06:38:42 +00:00
custom_config?: custom_config;
2024-10-08 10:12:55 +00:00
appoint_data?: object;
2024-08-20 01:35:57 +00:00
name: string;
data: data_list[];
type: string;
2024-09-05 03:05:57 +00:00
}
2024-11-13 09:27:27 +00:00
const options = ref<options_item[]>([]);
//#region 初始化数据处理
2024-08-22 07:05:39 +00:00
const getCustominit = () => {
2024-08-20 01:35:57 +00:00
CustomAPI.getCustominit().then((res) => {
const { data_source } = res.data;
options.value = data_source;
2024-08-22 07:05:39 +00:00
data_source_store.set_data_source(data_source);
2024-08-26 08:51:20 +00:00
// 数据处理
2024-11-14 09:04:57 +00:00
processing_data(form.value.data_source);
2024-11-28 06:38:42 +00:00
data_processing();
2024-08-20 01:35:57 +00:00
});
2024-09-05 03:05:57 +00:00
};
2024-08-20 01:35:57 +00:00
onBeforeMount(() => {
2024-08-22 07:05:39 +00:00
if (!data_source_store.is_data_source_api) {
data_source_store.set_is_data_source_api(true);
getCustominit();
2024-08-20 01:35:57 +00:00
} else {
2024-08-22 07:05:39 +00:00
options.value = data_source_store.data_source_list;
// 如果历史的值出现,根据历史选中的值处理一下传递的数据结构
2024-11-14 09:04:57 +00:00
processing_data(form.value.data_source);
2024-11-28 06:38:42 +00:00
data_processing();
2024-08-20 01:35:57 +00:00
}
});
2024-11-28 06:38:42 +00:00
// 回显数据处理
const data_processing = () => {
// 如果有历史的值,那么就需要根据历史的值来处理一下数据
const type_data = options.value.filter((item) => item.type == form.value.data_source);
if (type_data.length > 0 && !isEmpty(type_data[0].custom_config)) {
default_type_data.value = type_data[0].custom_config;
2024-11-28 10:30:57 +00:00
default_data();
2024-11-28 06:38:42 +00:00
}
};
2024-11-28 10:30:57 +00:00
// 默认数据处理
const default_data = () => {
const { show_type = [], show_number = [], data_type = []} = default_type_data.value;
const { data_source_direction, data_source_carousel_col, data_source_content} = form.value;
// 如果存在默认数据类型的时候, 并且跟当前的不一致时,默认选中第一个
if (!isEmpty(show_type) && !show_type.includes(data_source_direction)) {
form.value.data_source_direction = show_type[0];
}
// 如果存在默认数据类型的时候, 并且跟当前的不一致时,默认选中第一个
if (!isEmpty(show_number) && !show_number.includes(data_source_carousel_col)) {
form.value.data_source_carousel_col = show_number[0];
}
// 如果存在默认数据类型的时候, 并且跟当前的不一致时,默认选中第一个
if (!isEmpty(data_type) && isEmpty(data_source_content.data_type) && !data_type.includes(data_source_content.data_type)) {
form.value.data_source_content.data_type = data_type[0];
}
}
2024-08-22 07:05:39 +00:00
// 处理显示的图片和传递到下去的数据结构
2024-09-05 03:05:57 +00:00
const model_data_source = ref<data_list[]>([]);
2024-08-22 07:05:39 +00:00
const processing_data = (key: string) => {
2024-09-05 03:05:57 +00:00
const list = options.value.filter((item) => item.type == key);
2024-08-22 07:05:39 +00:00
if (list.length > 0) {
model_data_source.value = list[0].data;
} else {
model_data_source.value = [];
}
};
//#endregion
//#region 自定义编辑的内部处理逻辑
const diy_data = ref<diy>({
key: '',
location: {
x: 0,
y: 0,
2024-08-16 10:01:59 +00:00
record_x: 0,
record_y: 0,
staging_y: 0,
},
com_data: {},
});
const key = ref('');
const dragkey = ref('');
const right_update = (item: any) => {
diy_data.value = item;
// 生成随机id
key.value = Math.random().toString(36).substring(2);
};
2024-08-22 07:05:39 +00:00
// 自定义编辑的逻辑
const custom_edit = () => {
if (!dialog.value) return;
dialog.value.dialogVisible = true;
dragkey.value = Math.random().toString(36).substring(2);
2024-11-14 09:04:57 +00:00
custom_list = cloneDeep(form.value.custom_list);
center_height.value = cloneDeep(form.value.height);
};
2024-08-22 07:05:39 +00:00
// 点击完成的处理逻辑
const accomplish = () => {
2024-08-12 08:10:56 +00:00
if (!draglist.value) {
return;
} else {
2024-11-14 09:04:57 +00:00
form.value.custom_list = draglist.value.diy_data;
2024-08-12 08:10:56 +00:00
}
2024-11-14 09:04:57 +00:00
form.value.height = center_height.value;
};
2024-08-22 07:05:39 +00:00
//#endregion
//#region 数据源更新逻辑处理
// 打开弹出框
const url_value_dialog_visible = ref(false);
2024-11-28 06:38:42 +00:00
const default_type_data = ref<any>({})
const url_value_multiple_bool = ref(true);
2024-08-22 07:05:39 +00:00
const changeDataSource = (key: string) => {
2024-11-28 06:38:42 +00:00
form.value.is_custom_data = '0';
2024-10-08 10:12:55 +00:00
const type_data = options.value.filter((item) => item.type == key);
2024-08-22 07:05:39 +00:00
processing_data(key);
2024-11-28 06:38:42 +00:00
// 默认数据类型
form.value.data_source_content = {
// 存放手动输入的id
data_ids: [],
data_list: [],
// 自动
data_auto_list: [],
}
// 默认数据, 避免不选报错
default_type_data.value = {};
form.value.data_source_direction = 'vertical';
// 如果存在默认数据类型的时候就直接赋值给data_list
2024-10-08 10:12:55 +00:00
if (type_data.length > 0 && !isEmpty(type_data[0].appoint_data)) {
2024-11-28 06:38:42 +00:00
form.value.data_source_content.data_list = [ type_data[0].appoint_data ];
} else if (type_data.length > 0 && !isEmpty(type_data[0].custom_config)) {
// 是自定义数据类型
form.value.is_custom_data = '1';
// 自定义数据取值
const custom_config = type_data[0].custom_config;
// 默认赋值第一个
form.value.data_source_direction = custom_config.show_type[0];
// 处理数据
const staging_data : any = {
2024-11-14 05:50:51 +00:00
// 存放手动输入的id
data_ids: [],
2024-11-13 09:27:27 +00:00
// 手动输入
data_list: [],
// 自动
data_auto_list: [],
2024-11-28 06:38:42 +00:00
// 类型
data_type: custom_config.data_type[0],
2024-11-13 09:27:27 +00:00
};
2024-11-28 06:38:42 +00:00
// 将数据赋值给默认数据
default_type_data.value = custom_config;
2024-11-28 10:30:57 +00:00
default_data();
2024-11-28 06:38:42 +00:00
// 如果不存在的时候默认取id
form.value.data_list_key = default_type_data.value?.appoint_config?.show_data?.data_key || 'id';
// 根据不同的类型,初始化不同的数据, 并将对象处理成对应的值
default_type_data.value.filter_config.filter_form_config.forEach((item: any) => {
let value : number | string | Array<any> = '';
if (item.type == 'checkbox' || item.type == 'select' && item.config.is_multiple == '1') { // 多选
value = item.config.default ? item.config.default : [];
} else if (item.type == 'input' && item.config.type == 'number') { // 数字
value = item.config.default ? item.config.default : 0;
} else if (item.type == 'switch') {
value = item.config.default ? item.config.default : "0";
}
staging_data[item.form_name] = value;
})
// 循环完之后赋值,避免多次赋值,传递给子组件出现多次调用和回调问题
form.value.data_source_content = staging_data;
2024-08-22 07:05:39 +00:00
}
2024-09-05 03:05:57 +00:00
};
2024-11-28 06:38:42 +00:00
const filter_form_change = (val: any) => {
form.value.data_source_content = val;
}
2024-11-13 09:27:27 +00:00
//#endregion
2024-11-13 10:35:22 +00:00
//#region 数据源内容多选处理
2024-11-13 09:27:27 +00:00
const data_list_replace_index = ref(0);
const data_list_replace = (index: number) => {
2024-11-28 06:38:42 +00:00
// 替换的时候index为选择的索引
2024-11-13 09:27:27 +00:00
data_list_replace_index.value = index;
2024-11-28 06:38:42 +00:00
// 替换的时候,是单选
2024-11-13 09:27:27 +00:00
url_value_multiple_bool.value = false;
url_value_dialog_visible.value = true;
};
const add = () => {
2024-11-28 06:38:42 +00:00
// 添加的时候index为-1
data_list_replace_index.value = -1;
// 添加是单选还是多选由后台配置决定
url_value_multiple_bool.value = default_type_data.value.appoint_config.is_multiple.toString() == '1' ? true : false;
2024-11-13 09:27:27 +00:00
url_value_dialog_visible.value = true;
};
// 拖拽更新之后,更新数据
const data_list_sort = (new_list: any) => {
2024-11-14 09:04:57 +00:00
form.value.data_source_content.data_list = new_list;
2024-11-13 09:27:27 +00:00
};
const data_list_remove = (index: number) => {
2024-11-14 09:04:57 +00:00
form.value.data_source_content.data_list.splice(index, 1);
2024-11-13 09:27:27 +00:00
};
2024-08-22 07:05:39 +00:00
// 弹出框选择的内容
const url_value_dialog_call_back = (item: any[]) => {
2024-11-28 06:38:42 +00:00
// 如果是单选当时data_list_replace_index 为-1说明是添加否则是替换
if (url_value_multiple_bool.value || data_list_replace_index.value == -1) {
2024-11-13 09:27:27 +00:00
item.forEach((item: any) => {
2024-11-14 09:04:57 +00:00
form.value.data_source_content.data_list.push({
2024-11-13 09:27:27 +00:00
id: get_math(),
new_cover: [],
new_title: '',
data: item,
});
});
} else {
2024-11-14 09:04:57 +00:00
form.value.data_source_content.data_list[data_list_replace_index.value] = {
2024-11-13 09:27:27 +00:00
id: get_math(),
new_cover: [],
new_title: '',
data: item[0],
};
2024-08-22 07:05:39 +00:00
}
2024-09-05 03:05:57 +00:00
};
2024-11-13 09:56:11 +00:00
// 数据来源的内容
let data_source_content_list = computed(() => {
2024-11-28 06:38:42 +00:00
if (form.value.is_custom_data == '1') {
2024-11-28 10:30:57 +00:00
if (Number(form.value.data_source_content.data_type) === 0) {
2024-11-14 09:04:57 +00:00
return form.value.data_source_content.data_list;
2024-11-13 09:56:11 +00:00
} else {
2024-11-14 09:04:57 +00:00
return form.value.data_source_content.data_auto_list;
2024-11-13 09:56:11 +00:00
}
} else {
2024-11-14 09:04:57 +00:00
return form.value.data_source_content.data_list;
2024-11-13 09:56:11 +00:00
}
})
// 获取商品自动数据
2024-11-28 06:38:42 +00:00
const get_auto_data = () => {
if (!isEmpty(default_type_data.value) && !isEmpty(default_type_data.value.filter_config) && !isEmpty(default_type_data.value.filter_config.data_url)) {
const data = omit(cloneDeep(form.value.data_source_content), ['data_ids', 'data_list', 'data_auto_list', 'data_type']);
request({
url: default_type_data.value.filter_config.data_url, // 请求地址
method: 'post', // 请求方式
data // 请求数据
}).then((res) => {
if (res.data) {
form.value.data_source_content.data_auto_list = res.data;
2024-11-28 10:30:57 +00:00
} else {
// 清空数据, 避免接口报错等显示的还是老数据
form.value.data_source_content.data_auto_list = [];
2024-11-28 06:38:42 +00:00
}
2024-11-28 10:30:57 +00:00
}).catch((err) => {
// 清空数据, 避免接口报错等显示的还是老数据
form.value.data_source_content.data_auto_list = [];
});
} else {
// 清空数据, 避免接口报错等显示的还是老数据
form.value.data_source_content.data_auto_list = [];
2024-11-13 09:56:11 +00:00
}
};
2024-11-28 06:38:42 +00:00
// 将不需要监听的数据移除,只监听需要监听的数据
2024-11-14 05:50:51 +00:00
const data_source_content_value = computed(() => {
2024-11-28 06:38:42 +00:00
// 从对象中移除不需要监听的 'data_ids', 'data_list', 'data_auto_list'三个值
const data: any = {};
for (const key in form.value.data_source_content) {
if (!['data_ids', 'data_list', 'data_auto_list'].includes(key)) {
data[key] = form.value.data_source_content[key];
}
}
return data;
2024-11-14 05:50:51 +00:00
})
2024-11-28 06:38:42 +00:00
// 数据发生变化时,调用接口获取数据
watch(() => data_source_content_value.value, (new_val, old_val) => {
2024-11-14 03:34:13 +00:00
// 数据发生变化时,如果是自动获取数据,则调用接口获取数据
2024-11-28 10:30:57 +00:00
if (JSON.stringify(new_val) != JSON.stringify(old_val) && Number(new_val.data_type) !== 0) {
2024-11-28 06:38:42 +00:00
get_auto_data();
2024-11-13 09:56:11 +00:00
}
2024-11-14 03:34:13 +00:00
},{ deep: true });
2024-08-22 07:05:39 +00:00
//#endregion
</script>
<style lang="scss" scoped>
.settings {
width: 46rem;
overflow: auto;
display: flex;
flex-direction: column;
}
2024-08-30 10:48:27 +00:00
@media screen and (max-width: 1560px) {
.settings {
width: 40rem;
}
}
:deep(.el-dialog) {
margin-top: 0;
padding: 0;
overflow: hidden;
.el-dialog__header {
2024-09-05 03:05:57 +00:00
padding: 2.3rem 2rem;
.el-dialog__title {
font-size: 16px;
}
.el-dialog__headerbtn {
font-size: 2.4rem;
2024-09-05 03:05:57 +00:00
padding: 2rem;
height: auto;
width: auto;
}
}
.el-dialog__body {
background: #f5f5f5;
2024-09-05 03:05:57 +00:00
height: calc(100% - 15rem);
}
.el-dialog__footer {
padding: 2.4rem 3rem;
}
}
2024-08-22 07:05:39 +00:00
.replace-data {
2024-09-06 03:12:33 +00:00
height: 2.4rem;
bottom: 0.5rem;
left: 2.1rem;
2024-09-06 08:43:56 +00:00
line-height: 2.2rem;
2024-08-22 07:05:39 +00:00
border-radius: 2rem;
2024-09-06 08:43:56 +00:00
border: 1px solid #ddd;
2024-09-06 03:12:33 +00:00
cursor: pointer;
2024-08-22 07:05:39 +00:00
}
</style>