1.优惠券开发

sws 2024-08-28
v1.0.0
sws 2024-08-29 11:14:52 +08:00
parent 282eb0c1ff
commit 1c5bec7544
11 changed files with 119 additions and 37 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -24,7 +24,7 @@
<icon name="add" size="18" class="c-pointer" @click="add_type"></icon>
</div>
<el-scrollbar height="490px">
<el-tree ref="treeRef" class="filter-tree" :data="type_data" node-key="id" highlight-current :props="defaultProps" empty-text="" default-expand-all :filter-node-method="filter_node" @node-click="tree_node_event">
<el-tree ref="treeRef" v-loading="tree_loading" class="filter-tree" :data="type_data" node-key="id" highlight-current :props="defaultProps" empty-text="无数据" default-expand-all :filter-node-method="filter_node" @node-click="tree_node_event">
<template #default="{ node, data }">
<div class="custom-tree-node flex-row jc-sb gap-10 align-c w pr-10" :class="data.is_enable == 0 || node.parent.data.is_enable == 0 ? 'disabled bg-red' : ''">
<div class="flex-1 flex-width text-line-1 block">{{ data.name }}</div>
@ -67,7 +67,7 @@
</div>
<div class="img-content pr">
<!-- 574px -->
<el-scrollbar height="440px">
<el-scrollbar v-loading="img_loading" height="440px">
<div v-if="upload_list.length > 0" class="flex-row flex-wrap align-c gap-y-15 gap-x-10 pa-10">
<div v-for="(item, index) in upload_list" :key="index" class="item" @click="check_img_event(item)">
<el-badge :value="view_list_value.findIndex((i) => i.id === item.id) == -1 ? '' : view_list_value.findIndex((i) => i.id === item.id) + 1" class="badge flex-col gap-5 w" :hidden="view_list_value.findIndex((i) => i.id === item.id) == -1">
@ -360,16 +360,19 @@ const all_tree = {
sort: '',
};
const type_data_list = ref<Tree[]>([]);
const tree_loading = ref(false);
//
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);
tree_loading.value = true;
UploadAPI.getTree()
.then((res) => {
// all_treeres.data.category_listtype_data.value,all_tree
type_data.value = [all_tree, ...res.data.category_list];
type_data_list.value = res.data.category_list;
upload_store.set_category(type_data_list.value);
tree_loading.value = false;
})
.catch(() => {
upload_store.set_is_upload_api(false);
@ -411,7 +414,7 @@ const tree_node_event = (data: any, a: any, b: any) => {
//
// if (data.is_enable == 0) return;
//
if (data.items.length > 0) return;
if (data.items && data.items.length > 0) return;
category_id.value = data.id;
get_attachment_list();
};
@ -436,10 +439,11 @@ const edit_type_event = (data: Tree) => {
const remove_type_event = (node: any, data: Tree) => {
app?.appContext.config.globalProperties.$common.message_box('删除后不可恢复,确定继续吗?', 'warning').then(() => {
UploadAPI.delTree({ id: data.id }).then((res) => {
const parent = node.parent;
const children: Tree[] = parent.data.items || parent.data;
const index = children.findIndex((d) => d.id === data.id);
children.splice(index, 1);
// const parent = node.parent;
// const children: Tree[] = parent.data.items || parent.data;
// const index = children.findIndex((d) => d.id === data.id);
// children.splice(index, 1);
get_tree(true);
ElMessage({
type: 'success',
message: '删除成功!',
@ -460,11 +464,13 @@ const data_total = ref(0);
const search_name = ref('');
//
const upload_list = ref<uploadList[]>([]);
const img_loading = ref(false);
//
const get_attachment_list = (type?: string) => {
if (type) {
page.value = 1;
}
img_loading.value = true;
const new_data = {
page: page.value,
type: upload_type.value == 'img' ? 'image' : upload_type.value == 'video' ? 'video' : upload_type.value == 'file' ? 'file' : '',
@ -475,6 +481,7 @@ const get_attachment_list = (type?: string) => {
const data = res.data;
data_total.value = data.data_total;
upload_list.value = data.data_list;
img_loading.value = false;
});
};
//

View File

@ -1,26 +1,17 @@
<template>
<el-popover v-model:visible="visible_dialog" placement="bottom" width="400" trigger="click">
<template #reference>
<div class="flex-row align-c gap-10 br-d radius-sm plr-11 value-input">
<div class="flex-1 flex-width size-12 text-line-1">
<text v-if="label">{{ label }}</text>
<text v-else class="cr-9">{{ placeholder }}</text>
</div>
<div class="value-input-icon">
<template v-if="!label">
<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>
<el-input v-model="label" :placeholder="placeholder" class="pr-40" clearable @input="handle_input">
<template #suffix>
<div class="value-input-icon">
<icon name="arrow-top" class="re icon" :class="!visible_dialog ? 'active' : ''" size="12" color="9"></icon>
</div>
</template>
</el-input>
</template>
<div class="flex-col gap-10">
<div>
<el-cascader-panel v-model="cascader_val" :options="cascader_data" @change="cascader_change"></el-cascader-panel>
<el-cascader-panel v-model="cascader_val" :options="new_cascader" @change="cascader_change"></el-cascader-panel>
</div>
<div class="flex-row jc-e">
<el-button @click="visible_dialog = false">取消</el-button>
@ -48,6 +39,11 @@ const props = defineProps({
default: () => '',
},
});
interface cascaderData {
value: string;
label: string;
children?: cascaderData[];
}
// 使
const cascader_data = computed(() => {
return props.data.map((tree) => ({
@ -59,6 +55,7 @@ const cascader_data = computed(() => {
})),
}));
});
const new_cascader = ref<cascaderData[]>(cascader_data.value);
const visible_dialog = ref(false);
watch(
() => visible_dialog.value,
@ -99,6 +96,35 @@ const get_label = (item: any, val: any) => {
}
});
};
const handle_input = (val: any) => {
//
if (val) {
new_cascader.value = filterData(val, cascader_data.value);
} else {
new_cascader.value = cascader_data.value;
}
};
const filterData = (input: string, data: cascaderData[]) => {
let result = [];
//
for (let item of data) {
// name
if (item.label && item.label.includes(input)) {
result.push(item);
} else {
if (item.children) {
// data
let subResult = item.children.filter((subItem) => subItem.label && subItem.label.includes(input));
//
result.push({ ...item, children: subResult });
}
}
}
return result;
};
const emit = defineEmits(['call-back']);
//
const confirm = () => {
@ -134,12 +160,18 @@ const confirm = () => {
line-height: 3.2rem;
cursor: pointer;
position: relative;
.value-input-icon {
position: absolute;
right: 0;
width: 3.4rem;
z-index: 1;
text-align: center;
}
.value-input-icon {
position: absolute;
right: 0;
width: 3.4rem;
z-index: 1;
text-align: center;
.icon {
transition: transform 0.3s;
}
.active {
transform: rotate(-180deg);
}
}
:deep(.el-cascader-menu) {

View File

@ -17,7 +17,7 @@
</el-form-item>
<el-form-item label="上传至分组" prop="category_id">
<div class="form-item-width">
<el-cascader v-model="form.category_id" class="w" :options="cascader_data" placeholder="请选择" :show-all-levels="false" @change="category_id_change"></el-cascader>
<el-cascader v-model="form.category_id" class="w" :options="cascader_data" placeholder="请选择" :show-all-levels="false" filterable clearable change="category_id_change"></el-cascader>
</div>
</el-form-item>
<template v-if="form.type == 'loc'">

View File

@ -30,7 +30,7 @@
</el-select>
</el-form-item>
<el-form-item label="显示数量">
<el-input v-model="form.number" type="number" placeholder="请输入显示数量" clearable />
<el-input v-model="form.number" type="number" min="0" max="50" placeholder="请输入显示数量" clearable />
</el-form-item>
<el-form-item label="排序类型">
<el-radio-group v-model="form.sort">

View File

@ -48,7 +48,7 @@
</el-select>
</el-form-item>
<el-form-item label="显示数量">
<el-input v-model="row.number" type="number" placeholder="请输入显示数量" clearable />
<el-input v-model="row.number" type="number" min="0" max="50" placeholder="请输入显示数量" clearable />
</el-form-item>
<el-form-item label="排序类型">
<el-radio-group v-model="row.sort">

View File

@ -1,6 +1,26 @@
<template>
<div :style="style_container">
<div class="content re" :style="style_content"></div>
<div class="content re" :style="style_content">
<template v-if="theme == '1'">
<div class="oh flex-row">
<div class="coupon-theme-1">
<div class="coupon-theme-1-content tc">
<div class="name">满200元使用</div>
<div class="price">
<span class="size-9">¥</span>
<span class="size-24 fw-b pl-4">30</span>
</div>
</div>
</div>
</div>
</template>
<template v-else-if="theme == '2'"></template>
<template v-else-if="theme == '3'"></template>
<template v-else-if="theme == '4'"></template>
<template v-else-if="theme == '5'"></template>
<template v-else-if="theme == '6'"></template>
<template v-else-if="theme == '7'"></template>
</div>
</div>
</template>
<script setup lang="ts">
@ -24,9 +44,32 @@ watch(
},
{ immediate: true, deep: true }
);
const theme = computed(() => props.value?.content?.theme);
</script>
<style lang="scss" scoped>
.content {
height: 22rem;
.coupon-theme-1 {
background-color: #ff3830;
width: 9rem;
height: 9rem;
border-radius: 1rem;
margin-top: 1rem;
gap: 3rem;
.name {
padding: 0.5rem;
font-size: 1rem;
color: #ff3830;
}
.price {
color: #ff3830;
padding: 1rem 0;
}
.coupon-theme-1-content {
width: calc(100% - 1rem);
margin: 0 0.5rem;
background-image: url('../../assets/images/components/model-coupon/theme-1-bg.png');
background-size: 100% 100%;
position: relative;
top: -1rem;
}
}
</style>

View File

@ -44,7 +44,7 @@ const defaultCoupoin: DefaultCoupon = {
background: [{ color: '#FFF1E1', color_percentage: '' }],
direction: '90deg',
spacing: 10,
common_style: defaultCommon,
common_style: { ...defaultCommon, padding_left: 25, padding_right: 25, padding_top: 18, padding_bottom: 18 },
},
};