hookehuyr

feat(CheckinTargetList): 添加目标列表展开收起功能

添加展开/收起功能以优化长列表展示,当列表高度超过3行时显示切换按钮
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 label-width="5rem" 15 label-width="5rem"
16 :label="field.label" 16 :label="field.label"
17 :placeholder="'请输入' + field.label" 17 :placeholder="'请输入' + field.label"
18 - :type="field.type === 'textarea' ? 'textarea' : 'text'" 18 + :type="field.type"
19 :rows="field.type === 'textarea' ? 2 : 1" 19 :rows="field.type === 'textarea' ? 2 : 1"
20 :autosize="field.type === 'textarea'" 20 :autosize="field.type === 'textarea'"
21 :class="{'border-b border-gray-100': index < localFields.length - 1}" 21 :class="{'border-b border-gray-100': index < localFields.length - 1}"
......
1 <!-- 1 <!--
2 * @Date: 2025-12-16 11:44:27 2 * @Date: 2025-12-16 11:44:27
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-12-16 18:19:56 4 + * @LastEditTime: 2025-12-16 23:26:18
5 * @FilePath: /mlaj/src/components/count/CheckinTargetList.vue 5 * @FilePath: /mlaj/src/components/count/CheckinTargetList.vue
6 * @Description: 打卡动态对象列表组件 6 * @Description: 打卡动态对象列表组件
7 --> 7 -->
...@@ -15,8 +15,12 @@ ...@@ -15,8 +15,12 @@
15 <van-button size="small" type="primary" plain icon="plus" @click="onAdd" class="!h-7">添加</van-button> 15 <van-button size="small" type="primary" plain icon="plus" @click="onAdd" class="!h-7">添加</van-button>
16 </div> 16 </div>
17 17
18 - <div class="bg-gray-50 rounded-lg p-2"> 18 + <div class="bg-gray-50 rounded-lg p-2 relative">
19 - <div class="flex flex-wrap gap-2"> 19 + <div
20 + ref="listContainerRef"
21 + class="flex flex-wrap gap-2 transition-all duration-300 overflow-hidden"
22 + :style="{ maxHeight: isExpanded ? 'none' : collapsedHeight }"
23 + >
20 <template v-if="targetList.length > 0"> 24 <template v-if="targetList.length > 0">
21 <div v-for="(item, index) in targetList" :key="index" 25 <div v-for="(item, index) in targetList" :key="index"
22 class="px-4 py-1.5 rounded-full text-sm transition-colors duration-200 border cursor-pointer select-none relative" 26 class="px-4 py-1.5 rounded-full text-sm transition-colors duration-200 border cursor-pointer select-none relative"
...@@ -52,6 +56,17 @@ ...@@ -52,6 +56,17 @@
52 暂无{{ dynamicFieldText }}列表,请点击上方添加按钮 56 暂无{{ dynamicFieldText }}列表,请点击上方添加按钮
53 </div> 57 </div>
54 </div> 58 </div>
59 +
60 + <!-- 展开/收起按钮 -->
61 + <div
62 + v-if="showExpandBtn"
63 + class="flex justify-center mt-2 cursor-pointer"
64 + @click="toggleExpand"
65 + >
66 + <div class="bg-white rounded-full p-1 shadow-sm border border-gray-200 flex items-center justify-center w-6 h-6 hover:bg-gray-50 active:bg-gray-100">
67 + <van-icon :name="isExpanded ? 'arrow-up' : 'arrow-down'" color="#9ca3af" size="12" />
68 + </div>
69 + </div>
55 </div> 70 </div>
56 71
57 <!-- 操作菜单 --> 72 <!-- 操作菜单 -->
...@@ -66,7 +81,7 @@ ...@@ -66,7 +81,7 @@
66 </template> 81 </template>
67 82
68 <script setup> 83 <script setup>
69 -import { ref } from 'vue' 84 +import { ref, onMounted, nextTick, watch } from 'vue'
70 import { showConfirmDialog } from 'vant' 85 import { showConfirmDialog } from 'vant'
71 86
72 /** 87 /**
...@@ -98,6 +113,49 @@ const props = defineProps({ ...@@ -98,6 +113,49 @@ const props = defineProps({
98 } 113 }
99 }) 114 })
100 115
116 +// 展开/收起相关
117 +const isExpanded = ref(false)
118 +const showExpandBtn = ref(false)
119 +const listContainerRef = ref(null)
120 +const collapsedHeight = ref('118px') // 默认值,会被动态计算覆盖
121 +
122 +const checkHeight = async () => {
123 + await nextTick()
124 + const container = listContainerRef.value
125 + if (!container || props.targetList.length === 0) {
126 + showExpandBtn.value = false
127 + return
128 + }
129 +
130 + // 获取第一个子元素的高度和容器的行间距
131 + const firstItem = container.children[0]
132 + if (firstItem) {
133 + const itemHeight = firstItem.offsetHeight
134 + const style = window.getComputedStyle(container)
135 + const rowGap = parseFloat(style.rowGap) || 8 // 获取 gap 值,默认为 8px
136 +
137 + // 计算3行的高度: 3个元素高度 + 2个间距
138 + const limitHeight = (itemHeight * 3) + (rowGap * 2)
139 + collapsedHeight.value = `${limitHeight}px`
140 +
141 + // 增加一点容差(2px),避免因为像素计算误差导致刚好3行时显示按钮
142 + showExpandBtn.value = container.scrollHeight > (limitHeight + 2)
143 + }
144 +}
145 +
146 +const toggleExpand = () => {
147 + isExpanded.value = !isExpanded.value
148 +}
149 +
150 +// 监听列表变化,重新计算高度
151 +watch(() => props.targetList, () => {
152 + checkHeight()
153 +}, { deep: true })
154 +
155 +onMounted(() => {
156 + checkHeight()
157 +})
158 +
101 const emit = defineEmits(['add', 'toggle', 'edit', 'delete']) 159 const emit = defineEmits(['add', 'toggle', 'edit', 'delete'])
102 160
103 /** 161 /**
......