454 lines
8.0 KiB
Vue
454 lines
8.0 KiB
Vue
<template>
|
|
<div class="assembly-rubik-cube">
|
|
<div class="w-120">显示模式</div>
|
|
<el-radio-group v-model="value.mode" @change="changeGroup">
|
|
<el-radio v-for="mode in modes" :key="mode.type" :value="mode.type">
|
|
{{ mode.label }}
|
|
</el-radio>
|
|
</el-radio-group>
|
|
|
|
<div class="w-120">图片间隔</div>
|
|
<assembly-slider
|
|
v-model="value.gap"
|
|
:min="0"
|
|
:max="40"
|
|
unit="rpx"
|
|
:step="1"
|
|
@change="changeSlider"
|
|
/>
|
|
|
|
<div
|
|
class="box"
|
|
:class="[`is-${value.mode}`]"
|
|
:style="{ gap: `${value.gap / 2}px`, '--gap': `${value.gap / 2}px` }"
|
|
>
|
|
<div
|
|
class="item"
|
|
v-for="(item, index) in value.list"
|
|
:key="index"
|
|
:class="[`is-${value.mode}-item-${index}`]"
|
|
@click="onTap(index)"
|
|
>
|
|
<div class="circle" v-if="activate === index">
|
|
<el-icon :size="20" color="#4165d7">
|
|
<circle-check-filled />
|
|
</el-icon>
|
|
</div>
|
|
<div class="tips" v-if="!item.icon">
|
|
{{ item.tips }}
|
|
</div>
|
|
<el-image class="icon" :src="item.icon" fit="fill" v-else></el-image>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="upload">
|
|
<div class="upload-box">
|
|
<cl-upload
|
|
text="上传图片"
|
|
v-model="value.list[activate].icon"
|
|
@success="onChange"
|
|
:size="[80, 80]"
|
|
/>
|
|
<div class="link">
|
|
<assembly-link
|
|
v-model="value.list[activate].link"
|
|
:prepend="false"
|
|
@change="onChange"
|
|
/>
|
|
<div class="tips">{{ value.list[activate].tips }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script lang="ts" setup name="assembly-rubik-cube">
|
|
import { ref, type PropType } from "vue";
|
|
import { Form } from "../../types/form";
|
|
import { CircleCheckFilled } from "@element-plus/icons-vue";
|
|
|
|
const props = defineProps({
|
|
modelValue: {
|
|
type: Object as PropType<Form.RubikCube>,
|
|
default: () => ({
|
|
mode: "mode-1",
|
|
gap: 0,
|
|
list: [
|
|
{
|
|
icon: "",
|
|
tips: "宽度375",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
},
|
|
{
|
|
icon: "",
|
|
tips: "宽度375",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
}
|
|
]
|
|
})
|
|
}
|
|
});
|
|
|
|
const emit = defineEmits(["update:modelValue"]);
|
|
const value = ref(props.modelValue);
|
|
|
|
const modes: Form.RubikCubeMode[] = [
|
|
{
|
|
type: "mode-1",
|
|
label: "一行两个",
|
|
list: [
|
|
{
|
|
icon: "",
|
|
tips: "宽度375",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
},
|
|
{
|
|
icon: "",
|
|
tips: "宽度375",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
type: "mode-2",
|
|
label: "一行三个",
|
|
list: [
|
|
{
|
|
icon: "",
|
|
tips: "宽度250",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
},
|
|
{
|
|
icon: "",
|
|
tips: "宽度250",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
},
|
|
{
|
|
icon: "",
|
|
tips: "宽度250",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
type: "mode-3",
|
|
label: "左一右二",
|
|
list: [
|
|
{
|
|
icon: "",
|
|
tips: "宽375\n高750",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
},
|
|
{
|
|
icon: "",
|
|
tips: "宽375\n高375",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
},
|
|
{
|
|
icon: "",
|
|
tips: "宽375\n高375",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
type: "mode-4",
|
|
label: "上一下二",
|
|
list: [
|
|
{
|
|
icon: "",
|
|
tips: "宽750\n高375",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
},
|
|
{
|
|
icon: "",
|
|
tips: "宽375\n高375",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
},
|
|
{
|
|
icon: "",
|
|
tips: "宽375\n高375",
|
|
link: {
|
|
name: "",
|
|
type: "",
|
|
appid: "",
|
|
page: ""
|
|
}
|
|
}
|
|
]
|
|
}
|
|
];
|
|
|
|
const activate = ref(0);
|
|
|
|
function changeGroup(mode: any) {
|
|
const selectedMode = modes.find((m) => m.type === mode);
|
|
if (selectedMode) {
|
|
value.value.list = selectedMode.list;
|
|
activate.value = 0;
|
|
changeSlider(value.value.gap);
|
|
onChange();
|
|
}
|
|
}
|
|
|
|
function onTap(index: number) {
|
|
activate.value = index;
|
|
}
|
|
|
|
// 图片间隔
|
|
function changeSlider(val: number) {
|
|
switch (value.value.mode) {
|
|
case "mode-1":
|
|
// 一行两个
|
|
value.value.list.forEach((e) => {
|
|
const width = 375;
|
|
e.tips = `宽度${width - (val ? val / 2 : 0)}\n高度不限`;
|
|
});
|
|
break;
|
|
case "mode-2":
|
|
// 一行三个
|
|
value.value.list.forEach((e) => {
|
|
const width = 250;
|
|
e.tips = `宽度${width - (val ? Math.floor(val / 3) : 0)}\n高度不限`;
|
|
});
|
|
break;
|
|
case "mode-3":
|
|
// 左一右二
|
|
value.value.list.forEach((e, index) => {
|
|
const width = 375;
|
|
const w = width - (val ? Math.floor(val / 2) : 0);
|
|
e.tips = index ? `宽${w}\n高度不限` : `宽${w}\n高度不限`;
|
|
});
|
|
break;
|
|
case "mode-4":
|
|
value.value.list.forEach((e, index) => {
|
|
if (index) {
|
|
const width = 375;
|
|
const w = width - (val ? Math.floor(val / 2) : 0);
|
|
e.tips = `宽${w}\n高度不限`;
|
|
} else {
|
|
e.tips = `宽750\n高度不限`;
|
|
}
|
|
});
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
value.value.list;
|
|
}
|
|
|
|
function onChange() {
|
|
emit("update:modelValue", value.value);
|
|
}
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.assembly-rubik-cube {
|
|
.w-120 {
|
|
width: 120px;
|
|
}
|
|
|
|
.box {
|
|
display: flex;
|
|
margin-top: 10px;
|
|
.item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 100px;
|
|
background-color: lightblue;
|
|
box-sizing: border-box;
|
|
cursor: pointer;
|
|
position: relative;
|
|
.icon {
|
|
width: 100%;
|
|
max-width: 100%;
|
|
border: 0;
|
|
vertical-align: middle;
|
|
}
|
|
.tips {
|
|
font-size: 14px;
|
|
text-align: center;
|
|
white-space: pre-line;
|
|
}
|
|
.circle {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
z-index: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
.is-mode-1 {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
.item {
|
|
&.is-mode-1-item-0 {
|
|
min-height: calc(150px - var(--gap) / 2);
|
|
background-color: lightgreen;
|
|
}
|
|
&.is-mode-1-item-1 {
|
|
min-height: calc(150px - var(--gap) / 2);
|
|
background-color: lightcoral;
|
|
}
|
|
}
|
|
}
|
|
|
|
.is-mode-2 {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
.item {
|
|
&.is-mode-2-item-0 {
|
|
min-height: calc(100px - var(--gap) / 3);
|
|
}
|
|
&.is-mode-2-item-1 {
|
|
min-height: calc(100px - var(--gap) / 3);
|
|
background-color: lightgreen;
|
|
}
|
|
&.is-mode-2-item-2 {
|
|
min-height: calc(100px - var(--gap) / 3);
|
|
background-color: lightcoral;
|
|
}
|
|
}
|
|
}
|
|
|
|
.is-mode-3 {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
grid-template-rows: 1fr 1fr;
|
|
.item {
|
|
&.is-mode-3-item-0 {
|
|
min-height: 300px;
|
|
grid-column: 1 / 2;
|
|
grid-row: 1 / 3;
|
|
background-color: lightblue;
|
|
}
|
|
&.is-mode-3-item-1 {
|
|
min-height: calc(150px - var(--gap) / 2);
|
|
grid-column: 2 / 3;
|
|
grid-row: 1 / 2;
|
|
background-color: lightgreen;
|
|
}
|
|
&.is-mode-3-item-2 {
|
|
min-height: calc(150px - var(--gap) / 2);
|
|
grid-column: 2 / 3;
|
|
grid-row: 2 / 3;
|
|
background-color: lightcoral;
|
|
}
|
|
}
|
|
}
|
|
|
|
.is-mode-4 {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
grid-template-rows: auto auto;
|
|
.item {
|
|
&.is-mode-4-item-0 {
|
|
min-height: calc(150px - var(--gap) / 2);
|
|
grid-column: 1 / 3;
|
|
grid-row: 1 / 2;
|
|
background-color: lightblue;
|
|
}
|
|
&.is-mode-4-item-1 {
|
|
min-height: calc(150px - var(--gap) / 2);
|
|
grid-column: 1 / 2;
|
|
grid-row: 2 / 3;
|
|
background-color: lightgreen;
|
|
}
|
|
&.is-mode-4-item-2 {
|
|
min-height: calc(150px - var(--gap) / 2);
|
|
grid-column: 2 / 3;
|
|
grid-row: 2 / 3;
|
|
background-color: lightcoral;
|
|
}
|
|
}
|
|
}
|
|
|
|
.upload {
|
|
margin-top: 20px;
|
|
box-sizing: border-box;
|
|
background-color: #f6f7fa;
|
|
border-radius: 10px;
|
|
padding: 6px;
|
|
margin-bottom: 10px;
|
|
|
|
.upload-box {
|
|
display: flex;
|
|
background-color: #ffffff;
|
|
padding: 10px;
|
|
border-radius: 6px;
|
|
|
|
.link {
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.tips {
|
|
font-size: 14px;
|
|
margin-top: 10px;
|
|
color: var(--el-color-warning);
|
|
text-align: center;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|