|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
|
@ -29,7 +29,6 @@ interface Props {
|
|||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
imgParams: 'cover',
|
||||
isouterClick: false,
|
||||
});
|
||||
|
||||
const drag_list = ref(props.list);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
<template>
|
||||
<el-dialog v-model="dialog_visible" class="radius-lg" width="1168" draggable append-to-body @close="close_event">
|
||||
<template #header>
|
||||
<div class="title center re">
|
||||
<div class="tc size-16 fw">主题选择</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="content pa-20 flex-row">
|
||||
<div class="img-content">
|
||||
<el-scrollbar height="480px" class="w">
|
||||
<el-row v-if="data.length > 0">
|
||||
<el-col v-for="(item, index) in data" :key="index" :span="8">
|
||||
<div class="pa-10">
|
||||
<div class="item plr-10 ptb-20 br-c radius-md tc flex-col jc-c gap-10" :class="{ active: item.name === temp_model_value }" @click="handle_select_theme(item)">
|
||||
<image-empty v-model="item.url" class="img-height-auto"></image-empty>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div v-else>
|
||||
<no-data height="500"></no-data>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button class="plr-28 ptb-10" @click="close_event">取消</el-button>
|
||||
<el-button class="plr-28 ptb-10" type="primary" @click="confirm_event">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<div class="flex-row align-c gap-10 br-d radius-sm plr-11 theme-input" @click="dialog_visible = true">
|
||||
<div class="flex-1 flex-width size-12 text-line-1">
|
||||
<text v-if="model_value">{{ model_value }}</text>
|
||||
<text v-else class="cr-9">{{ placeholder }}</text>
|
||||
</div>
|
||||
<div class="theme-icon">
|
||||
<template v-if="!model_value">
|
||||
<icon name="arrow-right" size="12" color="9"></icon>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div @click.stop="clear_model_value">
|
||||
<icon name="close-o" size="12" color="c"></icon>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { cloneDeep } from 'lodash';
|
||||
interface data {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
const props = defineProps({
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择主题',
|
||||
},
|
||||
data: {
|
||||
type: Array as PropType<data[]>,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
const model_value = defineModel({ type: String, default: '' });
|
||||
const { data } = toRefs(props);
|
||||
const dialog_visible = ref(false);
|
||||
watch(
|
||||
() => dialog_visible.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
temp_model_value.value = cloneDeep(model_value.value);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
//#region 主题数据 ---------------------------------------------------start
|
||||
const temp_model_value = ref('');
|
||||
const handle_select_theme = (data: data) => {
|
||||
temp_model_value.value = data.name;
|
||||
};
|
||||
//#endregion 主题数据 ---------------------------------------------------end
|
||||
|
||||
// 关闭
|
||||
const close_event = () => {
|
||||
dialog_visible.value = false;
|
||||
};
|
||||
// 确定
|
||||
const confirm_event = () => {
|
||||
if (temp_model_value.value !== null) {
|
||||
model_value.value = temp_model_value.value;
|
||||
close_event();
|
||||
} else {
|
||||
ElMessage.error('请先选择主题');
|
||||
}
|
||||
};
|
||||
// 清空
|
||||
const clear_model_value = () => {
|
||||
temp_model_value.value = '';
|
||||
model_value.value = '';
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
.img-content {
|
||||
margin: 0 -1rem;
|
||||
width: calc(100% + 2rem);
|
||||
.item {
|
||||
height: 22rem;
|
||||
transition: all 0.3s ease-in-out;
|
||||
background-color: #f4f4f4;
|
||||
&:hover {
|
||||
color: $cr-primary;
|
||||
border-color: $cr-primary;
|
||||
position: relative;
|
||||
scale: 1.02;
|
||||
}
|
||||
&.active {
|
||||
color: $cr-primary;
|
||||
border-color: $cr-primary;
|
||||
position: relative;
|
||||
scale: 1.02;
|
||||
}
|
||||
.img-height-auto {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.theme-input {
|
||||
width: 100%;
|
||||
height: 3.2rem;
|
||||
line-height: 3.2rem;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
.theme-icon {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 3.4rem;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -361,8 +361,8 @@ const all_tree = {
|
|||
};
|
||||
const type_data_list = ref<Tree[]>([]);
|
||||
// 查询分类列表
|
||||
const get_tree = () => {
|
||||
if (!upload_store.is_upload_api && upload_store.category.length === 0) {
|
||||
const get_tree = (bool: boolean = false) => {
|
||||
if ((!upload_store.is_upload_api && upload_store.category.length === 0) || bool) {
|
||||
upload_store.set_is_upload_api(true);
|
||||
UploadAPI.getTree()
|
||||
.then((res) => {
|
||||
|
|
@ -403,7 +403,7 @@ const add_type = () => {
|
|||
};
|
||||
// 分类操作确认回调
|
||||
const upload_category_confirm = () => {
|
||||
get_tree();
|
||||
get_tree(true);
|
||||
};
|
||||
const category_id = ref('');
|
||||
// 左侧分类树结构节点点击事件
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
<template>
|
||||
<div :style="style_container">
|
||||
<div class="content re" :style="style_content"></div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { common_styles_computer } from '@/utils';
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const style_content = ref('');
|
||||
const style_container = ref('');
|
||||
const content = ref('');
|
||||
watch(
|
||||
props.value,
|
||||
(newVal, oldValue) => {
|
||||
const new_content = newVal?.content || {};
|
||||
const new_style = newVal?.style || {};
|
||||
style_container.value = common_styles_computer(new_style.common_style);
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
height: 22rem;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<template>
|
||||
<div class="content">
|
||||
<el-form :model="form" label-width="70" class="m-h">
|
||||
<card-container class="mb-8">
|
||||
<div class="mb-12">展示设置</div>
|
||||
<el-form-item label="选择风格">
|
||||
<theme-select v-model="form.theme" :data="base_list.themeList"></theme-select>
|
||||
</el-form-item>
|
||||
</card-container>
|
||||
<card-container class="common-content-height">
|
||||
<div class="mb-12">优惠券数据</div>
|
||||
<el-form-item label="数据来源">
|
||||
<el-radio-group v-model="form.data_type">
|
||||
<el-radio v-for="item in base_list.data_type_list" :key="item.value" :value="item.value">{{ item.name }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<template v-if="form.data_type === '0'">
|
||||
<el-form-item label="手动选择">
|
||||
<div class="flex-col gap-20 w">
|
||||
<drag v-if="form.data_list.length > 0" :data="form.data_list" :space-col="20" @remove="remove" @on-sort="on_sort">
|
||||
<template #default="{ row }">
|
||||
<div class="flex-1 cr-6 size-12">{{ row.title }}</div>
|
||||
</template>
|
||||
</drag>
|
||||
<el-button class="w" @click="add">+添加</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<slider></slider>
|
||||
</template>
|
||||
<el-form-item label="内容标题">
|
||||
<el-input v-model="form.title" placeholder="请输入内容"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="内容描述">
|
||||
<el-input v-model="form.desc" type="textarea" :rows="4" placeholder="请输入内容"></el-input>
|
||||
</el-form-item>
|
||||
</card-container>
|
||||
</el-form>
|
||||
</div>
|
||||
<url-value-dialog v-model:dialog-visible="url_value_dialog_visible" :type="['article']" multiple @update:model-value="url_value_dialog_call_back"></url-value-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
const form = reactive(props.value);
|
||||
const url_value_dialog_visible = ref(false);
|
||||
const base_list = reactive({
|
||||
data_type_list: [
|
||||
{ name: '默认', value: '0' },
|
||||
{ name: '手动', value: '1' },
|
||||
],
|
||||
themeList: [
|
||||
{ name: '风格1', url: new URL(`../../assets/images/components/model-coupon/theme-1.png`, import.meta.url).href },
|
||||
{ name: '风格2', url: new URL(`../../assets/images/components/model-coupon/theme-2.png`, import.meta.url).href },
|
||||
{ name: '风格3', url: new URL(`../../assets/images/components/model-coupon/theme-3.png`, import.meta.url).href },
|
||||
{ name: '风格3', url: new URL(`../../assets/images/components/model-coupon/theme-3.png`, import.meta.url).href },
|
||||
{ name: '风格4', url: new URL(`../../assets/images/components/model-coupon/theme-4.png`, import.meta.url).href },
|
||||
{ name: '风格5', url: new URL(`../../assets/images/components/model-coupon/theme-5.png`, import.meta.url).href },
|
||||
{ name: '风格6', url: new URL(`../../assets/images/components/model-coupon/theme-6.png`, import.meta.url).href },
|
||||
{ name: '风格7', url: new URL(`../../assets/images/components/model-coupon/theme-7.png`, import.meta.url).href },
|
||||
],
|
||||
});
|
||||
const remove = (index: number) => {
|
||||
form.data_list.splice(index, 1);
|
||||
};
|
||||
const on_sort = (item: any) => {
|
||||
form.data_list = item;
|
||||
};
|
||||
const add = () => {
|
||||
url_value_dialog_visible.value = true;
|
||||
};
|
||||
const url_value_dialog_call_back = (item: any[]) => {
|
||||
item.forEach((child: any) => {
|
||||
form.data_list.push(child);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
width: 100%;
|
||||
.content-height {
|
||||
min-height: calc(100vh - 31.8rem);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<template>
|
||||
<div class="setting-content">
|
||||
<template v-if="type == '1'">
|
||||
<model-coupon-content :value="value.content" :styles="value.style" :default-config="default_config"></model-coupon-content>
|
||||
</template>
|
||||
<template v-else-if="type == '2'">
|
||||
<model-coupon-styles :value="value.style" :content="value.content" :default-config="default_config"></model-coupon-styles>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: '1',
|
||||
},
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
const default_config = {
|
||||
style: {
|
||||
theme_1: {
|
||||
price_color: '#FF3830',
|
||||
name_color: '#FF3830',
|
||||
// 主题1时不显示
|
||||
desc_color: '#FF3830',
|
||||
// 主题1时不显示
|
||||
limit_send_count: '#999',
|
||||
btn_background: [{ color: '#FF3830', color_percentage: '' }],
|
||||
btn_color: '#FF3830',
|
||||
background: [{ color: '#FFF1E1', color_percentage: '' }],
|
||||
spacing: 20,
|
||||
},
|
||||
theme_2: {
|
||||
price_color: '#FF3830',
|
||||
name_color: '#FF3830',
|
||||
desc_color: '#999',
|
||||
// 主题2时不显示
|
||||
limit_send_count: '#999',
|
||||
btn_background: [{ color: '#FFF1E1', color_percentage: '' }],
|
||||
btn_color: '#fff',
|
||||
// 当为主题2时,不显示
|
||||
background: [{ color: '#fff', color_percentage: '' }],
|
||||
spacing: 15,
|
||||
common_style: {
|
||||
background_img_url: [{ url: 'http://shopxo.com/static/upload/images/common/2024/08/28/1724815957918121.png' }],
|
||||
},
|
||||
},
|
||||
theme_3: {
|
||||
price_color: '#FF3830',
|
||||
name_color: '#FF3830',
|
||||
desc_color: '#FF3830',
|
||||
limit_send_count: '#999',
|
||||
btn_background: [{ color: '#FF3830', color_percentage: '' }],
|
||||
btn_color: '#FF3830',
|
||||
background: [{ color: '#FFF1E1', color_percentage: '' }],
|
||||
// 当为主题34时,间距不给予修改,优惠券沾满整行
|
||||
spacing: 0,
|
||||
},
|
||||
theme_4: {
|
||||
price_color: '#FF3830',
|
||||
name_color: '#FF3830',
|
||||
desc_color: '#333',
|
||||
// 主题4时不显示
|
||||
limit_send_count: '#999',
|
||||
btn_background: [{ color: '#fff', color_percentage: '' }],
|
||||
btn_color: '#FF3830',
|
||||
background: [{ color: '#FFF1E1', color_percentage: '' }],
|
||||
// 当为主题34时,间距不给予修改,优惠券沾满整行
|
||||
spacing: 0,
|
||||
},
|
||||
theme5: {
|
||||
price_color: '#FF3830',
|
||||
name_color: '#FF3830',
|
||||
// 主题5时不显示
|
||||
desc_color: '#333',
|
||||
// 主题5时不显示
|
||||
limit_send_count: '#999',
|
||||
// 主题5时不显示
|
||||
btn_background: [{ color: '#fff', color_percentage: '' }],
|
||||
btn_color: '#fff',
|
||||
background: [{ color: '#FFF1E1', color_percentage: '' }],
|
||||
spacing: 10,
|
||||
},
|
||||
theme6: {
|
||||
price_color: '#FF3830',
|
||||
name_color: '#666',
|
||||
// 主题6时不显示
|
||||
desc_color: '#333',
|
||||
// 主题6时不显示
|
||||
limit_send_count: '#999',
|
||||
// 主题6时不显示
|
||||
btn_background: [{ color: '#fff', color_percentage: '' }],
|
||||
btn_color: '#fff',
|
||||
background: [{ color: '#FF3830', color_percentage: '' }],
|
||||
spacing: 10,
|
||||
},
|
||||
theme7: {
|
||||
price_color: '#fff',
|
||||
name_color: '#fff',
|
||||
// 主题7时不显示
|
||||
desc_color: '#fff',
|
||||
// 主题7时不显示
|
||||
limit_send_count: '#999',
|
||||
// 主题7时不显示
|
||||
btn_background: [{ color: '#E1B47A', color_percentage: '' }],
|
||||
btn_color: '#fff',
|
||||
background: [
|
||||
{ color: '#FF3830', color_percentage: '' },
|
||||
{ color: '#E1B47A', color_percentage: '' },
|
||||
],
|
||||
spacing: 10,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<div class="styles">
|
||||
<common-styles class="styles-height" :value="form.common_style" @update:value="common_styles_update" />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['update:value']);
|
||||
// 默认值
|
||||
let form = reactive(props.value);
|
||||
const common_styles_update = (val: Object) => {
|
||||
form.common_style = val;
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.styles {
|
||||
width: 100%;
|
||||
.styles-height {
|
||||
min-height: calc(100vh - 16.8rem);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,16 +1,44 @@
|
|||
import defaultCommon from './index';
|
||||
interface DefaultCoupon {
|
||||
content: {
|
||||
theme: string;
|
||||
data_type: string;
|
||||
number: number;
|
||||
title: string;
|
||||
desc: string;
|
||||
data_list: object[];
|
||||
};
|
||||
style: {
|
||||
price_color: string;
|
||||
name_color: string;
|
||||
desc_color: string;
|
||||
limit_send_count: string;
|
||||
btn_background: color_list[];
|
||||
btn_color: string;
|
||||
background: color_list[];
|
||||
spacing: number;
|
||||
common_style: object;
|
||||
};
|
||||
}
|
||||
const defaultCoupoin: DefaultCoupon = {
|
||||
content: {
|
||||
theme: '风格1',
|
||||
data_type: '0',
|
||||
number: 4,
|
||||
title: '先领券 再购物',
|
||||
desc: '领券下单·享购物优惠',
|
||||
data_list: [],
|
||||
},
|
||||
style: {
|
||||
common_style: { ...defaultCommon, padding: 10, padding_top: 10, padding_bottom: 10, padding_left: 10, padding_right: 10 },
|
||||
price_color: '#FF3830',
|
||||
name_color: '#FF3830',
|
||||
desc_color: '#FF3830',
|
||||
limit_send_count: '#999',
|
||||
btn_background: [{ color: '#FFF1E1', color_percentage: '' }],
|
||||
btn_color: '#FF3830',
|
||||
background: [{ color: '#FFF1E1', color_percentage: '' }],
|
||||
spacing: 10,
|
||||
common_style: defaultCommon,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import defaultImgMagic from './default/img-magic';
|
|||
import defaultHotZone from './default/hot-zone';
|
||||
import defaultCustom from './default/custom';
|
||||
import defaultDataMagic from './default/data-magic';
|
||||
import defaultCoupon from './default/coupon';
|
||||
|
||||
// 系统设置
|
||||
interface DefaultSettings {
|
||||
|
|
@ -45,6 +46,7 @@ interface DefaultSettings {
|
|||
data_magic: object;
|
||||
hot_zone: object;
|
||||
custom: object;
|
||||
coupon: object;
|
||||
}
|
||||
|
||||
const defaultSettings: DefaultSettings = {
|
||||
|
|
@ -70,6 +72,7 @@ const defaultSettings: DefaultSettings = {
|
|||
data_magic: defaultDataMagic,
|
||||
hot_zone: defaultHotZone,
|
||||
custom: defaultCustom,
|
||||
coupon: defaultCoupon,
|
||||
};
|
||||
|
||||
export default defaultSettings;
|
||||
|
|
|
|||
|
|
@ -104,6 +104,11 @@
|
|||
<template v-else-if="item.key == 'custom'">
|
||||
<model-custom :key="item.com_data" :value="item.com_data" :show-tabs="item.show_tabs"></model-custom>
|
||||
</template>
|
||||
<!-- 营销组件 -->
|
||||
<!-- 优惠券 -->
|
||||
<template v-else-if="item.key == 'coupon'">
|
||||
<model-coupon :key="item.com_data" :value="item.com_data"></model-coupon>
|
||||
</template>
|
||||
<!-- 工具组件 -->
|
||||
<!-- 辅助线 -->
|
||||
<template v-else-if="item.key == 'row-line'">
|
||||
|
|
@ -222,8 +227,13 @@ const components = reactive([
|
|||
],
|
||||
},
|
||||
{
|
||||
title: '工具组件',
|
||||
title: '营销组件',
|
||||
key: '2',
|
||||
item: [{ key: 'coupon', name: '优惠券' }],
|
||||
},
|
||||
{
|
||||
title: '工具组件',
|
||||
key: '3',
|
||||
item: [
|
||||
{ key: 'float-window', name: '悬浮按钮' },
|
||||
{ key: 'text-title', name: '文本标题' },
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
</template>
|
||||
</card-container>
|
||||
<div class="setting-content">
|
||||
<!-- 基础组件 -->
|
||||
<!-- 页面设置 -->
|
||||
<template v-if="value.key == 'page-settings'">
|
||||
<page-content :value="value.com_data.content"></page-content>
|
||||
|
|
@ -79,6 +80,11 @@
|
|||
<template v-else-if="value.key == 'footer-nav'">
|
||||
<footer-nav-setting :type="radio" :value="value.com_data"></footer-nav-setting>
|
||||
</template>
|
||||
<!-- 营销组件 -->
|
||||
<!-- 优惠券 -->
|
||||
<template v-else-if="value.key == 'coupon'">
|
||||
<model-coupon-setting :type="radio" :value="value.com_data"></model-coupon-setting>
|
||||
</template>
|
||||
<!-- 工具组件 -->
|
||||
<!-- 辅助空白 -->
|
||||
<template v-else-if="value.key == 'auxiliary-blank'">
|
||||
|
|
|
|||