|
|
@@ -0,0 +1,146 @@
|
|
|
+<template>
|
|
|
+ <el-card class="mb-12px" body-class="p-8px!">
|
|
|
+ <template #header>
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <span>
|
|
|
+ 瓷砖
|
|
|
+ <el-tooltip content="瓷砖位置索引">
|
|
|
+ <LuInfo size="12px" class="text-accent-yellow" /> </el-tooltip
|
|
|
+ ></span>
|
|
|
+ <LuPlus class="cursor-pointer" size="16px" @click="handleAddRow" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <el-scrollbar max-height="120px">
|
|
|
+ <div
|
|
|
+ class="flex items-center gap-4px box-border pr-12px mb-4px"
|
|
|
+ v-for="(item, index) in children || []"
|
|
|
+ :key="index"
|
|
|
+ >
|
|
|
+ <div class="w-full flex items-center gap-4px relative group/item">
|
|
|
+ <el-radio v-model="activeIndex" :value="index" class="mr-0!" />
|
|
|
+ <el-input-number
|
|
|
+ controls-position="right"
|
|
|
+ :model-value="item.row"
|
|
|
+ @change="(val) => setRow(index, val)"
|
|
|
+ >
|
|
|
+ <template #prefix>
|
|
|
+ <span>行</span>
|
|
|
+ </template>
|
|
|
+ </el-input-number>
|
|
|
+ <el-input-number
|
|
|
+ controls-position="right"
|
|
|
+ :model-value="item.col"
|
|
|
+ @change="(val) => setColumn(index, val)"
|
|
|
+ >
|
|
|
+ <template #prefix>
|
|
|
+ <span>列</span>
|
|
|
+ </template>
|
|
|
+ </el-input-number>
|
|
|
+ <div class="cursor-pointer" @click="handleDeleteItem(index)">
|
|
|
+ <LuTrash2 size="14px" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-scrollbar>
|
|
|
+ </el-card>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { computed, type Ref } from 'vue'
|
|
|
+import { LuPlus, LuTrash2, LuInfo } from 'vue-icons-plus/lu'
|
|
|
+
|
|
|
+const props = defineProps<{
|
|
|
+ values: Ref<any>
|
|
|
+}>()
|
|
|
+
|
|
|
+// 子项
|
|
|
+const children = computed({
|
|
|
+ get() {
|
|
|
+ return (props.values?.value?.children || []) as any[]
|
|
|
+ },
|
|
|
+ set(list: any[]) {
|
|
|
+ if (props.values?.value?.children) {
|
|
|
+ props.values.value.children = list
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 当前激活
|
|
|
+const activeIndex = computed({
|
|
|
+ get() {
|
|
|
+ return props.values?.value?.props?.activeIndex
|
|
|
+ },
|
|
|
+ set(index: number) {
|
|
|
+ if (props.values?.value?.props) {
|
|
|
+ props.values.value.props.activeIndex = index
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+/*
|
|
|
+ * 设置行号
|
|
|
+ */
|
|
|
+const setRow = (index: number, val?: number) => {
|
|
|
+ if (typeof val === 'undefined') return
|
|
|
+
|
|
|
+ const record = children.value[index]
|
|
|
+
|
|
|
+ // 判断是否存在相同索引
|
|
|
+ const existIndex = children.value.findIndex((item) => item.row === val && item.col === record.col)
|
|
|
+
|
|
|
+ if (existIndex === -1) {
|
|
|
+ // 存在相同索引
|
|
|
+ record.row = val
|
|
|
+ record.name = `tile_${val}_${record.col}`
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * 设置列号
|
|
|
+ */
|
|
|
+const setColumn = (index: number, val?: number) => {
|
|
|
+ if (typeof val === 'undefined') return
|
|
|
+
|
|
|
+ const record = children.value[index]
|
|
|
+
|
|
|
+ // 判断是否存在相同索引
|
|
|
+ const existIndex = children.value.findIndex((item) => item.col === val && item.row === record.row)
|
|
|
+
|
|
|
+ if (existIndex === -1) {
|
|
|
+ // 存在相同索引
|
|
|
+ record.col = val
|
|
|
+ record.name = `tile_${record.row}_${val}`
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 删除一项
|
|
|
+ * @param index 索引
|
|
|
+ */
|
|
|
+const handleDeleteItem = (index: number) => {
|
|
|
+ children.value.splice(index, 1)
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 添加一项
|
|
|
+ */
|
|
|
+const handleAddRow = () => {
|
|
|
+ const maxRow = children.value.reduce((max, item) => {
|
|
|
+ return Math.max(max, item.row)
|
|
|
+ }, 0)
|
|
|
+ const maxCol = children.value
|
|
|
+ .filter((item) => item.row === maxRow)
|
|
|
+ .reduce((max, item) => {
|
|
|
+ return Math.max(max, item.col)
|
|
|
+ }, 0)
|
|
|
+ children.value?.push({
|
|
|
+ name: `tile_${maxRow}_${maxCol + 1}`,
|
|
|
+ type: 'tile',
|
|
|
+ row: maxRow,
|
|
|
+ col: maxCol + 1,
|
|
|
+ children: []
|
|
|
+ })
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped></style>
|