| | |
| | | const emit = defineEmits<{ (e: 'update:show', val: boolean): void }>() |
| | | |
| | | const keyword = ref('') |
| | | // 已提交的查询关键词:只在点击「查询」按钮时同步一次,用于列表过滤。 |
| | | // 输入框绑定的 keyword 只做输入回显,不参与实时过滤,避免边输入边刷新列表。 |
| | | const searchKeyword = ref('') |
| | | const list = ref<any[]>([]) |
| | | const newTypeName = ref('') |
| | | const newTypeError = ref('') |
| | |
| | | const orderChanged = ref(false) |
| | | |
| | | const filteredList = computed(() => { |
| | | if (!keyword.value) |
| | | if (!searchKeyword.value) |
| | | return list.value |
| | | return list.value.filter(item => item.typeName.includes(keyword.value)) |
| | | return list.value.filter(item => item.typeName.includes(searchKeyword.value)) |
| | | }) |
| | | |
| | | watch(() => props.show, (val) => { |
| | | if (val) { |
| | | loadList() |
| | | keyword.value = '' |
| | | searchKeyword.value = '' |
| | | newTypeName.value = '' |
| | | newTypeError.value = '' |
| | | showAddInput.value = false |
| | |
| | | } |
| | | |
| | | function handleSearch() { |
| | | // filteredList computed 已处理筛选 |
| | | // 只有点击「查询」按钮时才把当前输入同步为已提交的查询词,触发列表过滤 |
| | | searchKeyword.value = keyword.value.trim() |
| | | } |
| | | |
| | | function handleReset() { |
| | | keyword.value = '' |
| | | searchKeyword.value = '' |
| | | } |
| | | |
| | | function openAddModal() { |
| | |
| | | class="type-list-inner" |
| | | :animation="150" |
| | | handle=".drag-handle" |
| | | :disabled="!!keyword" |
| | | :disabled="!!searchKeyword" |
| | | @update="onSortUpdate" |
| | | > |
| | | <div |
| | | v-for="item in list" |
| | | v-show="!keyword || item.typeName.includes(keyword)" |
| | | v-show="!searchKeyword || item.typeName.includes(searchKeyword)" |
| | | :key="item.id" |
| | | class="type-item" |
| | | > |
| | |
| | | </div> |
| | | </VueDraggable> |
| | | </div> |
| | | <n-empty v-if="filteredList.length === 0" description="暂无数据" /> |
| | | <div v-if="filteredList.length === 0" class="empty-wrap"> |
| | | <n-empty description="暂无数据" /> |
| | | </div> |
| | | |
| | | <div v-if="filteredList.length > 0" class="pager-row"> |
| | | <span class="pager-info">共 {{ filteredList.length }} 条</span> |
| | |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .empty-wrap { |
| | | /* 「暂无数据」空态区:撑出足够高度并 flex 居中,避免图标紧贴表头看起来太靠上 */ |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | min-height: 240px; |
| | | padding: 24px 0; |
| | | } |
| | | |
| | | .pager-row { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | |
| | | overflow-y: auto; |
| | | overscroll-behavior: contain; |
| | | scrollbar-gutter: stable; |
| | | |
| | | .type-item { |
| | | display: flex; |
| | | align-items: center; |