|
|
@@ -1,166 +1,163 @@
|
|
|
-<template>
|
|
|
- <VanPopup
|
|
|
- v-model:show="show"
|
|
|
- class="search"
|
|
|
- :close-on-click-overlay="false"
|
|
|
- :overlay-style="{
|
|
|
- background: 'rgba(239, 232, 210, 0.90)',
|
|
|
- backdropFilter: 'blur(10px)',
|
|
|
- }"
|
|
|
- >
|
|
|
- <div class="search-top">
|
|
|
- <i class="search-close" @click="show = false" />
|
|
|
- <div class="search-input">
|
|
|
- <input
|
|
|
- ref="inputRef"
|
|
|
- v-model.trim="keyword"
|
|
|
- type="search"
|
|
|
- enterkeyhint="search"
|
|
|
- placeholder="请输入展览名称"
|
|
|
- @keydown.enter.prevent="blurInput"
|
|
|
- />
|
|
|
- <i class="search-icon" aria-hidden="true" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="search-panel">
|
|
|
- <template v-if="filteredList.length">
|
|
|
- <Card v-for="item in filteredList" :key="item.id" :item="item" />
|
|
|
- </template>
|
|
|
- <p v-else class="search-empty">
|
|
|
- {{ keyword.trim() ? "未找到相关展览" : "请输入展览名称进行搜索" }}
|
|
|
- </p>
|
|
|
- </div>
|
|
|
- </VanPopup>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup>
|
|
|
-import { computed, ref, watch, nextTick } from "vue";
|
|
|
-import Card from "./Card.vue";
|
|
|
-import { infoTemo } from "@/assets/data.js";
|
|
|
-
|
|
|
-const props = defineProps({
|
|
|
- visible: {
|
|
|
- type: Boolean,
|
|
|
- default: false,
|
|
|
- },
|
|
|
- /** 与首页列表同源,便于展示最新浏览量;不传则用本地数据 */
|
|
|
- items: {
|
|
|
- type: Array,
|
|
|
- default: null,
|
|
|
- },
|
|
|
-});
|
|
|
-const emit = defineEmits(["update:visible"]);
|
|
|
-const show = computed({
|
|
|
- get() {
|
|
|
- return props.visible;
|
|
|
- },
|
|
|
- set(value) {
|
|
|
- emit("update:visible", value);
|
|
|
- },
|
|
|
-});
|
|
|
-
|
|
|
-const inputRef = ref(null);
|
|
|
-const keyword = ref("");
|
|
|
-
|
|
|
-const sourceList = computed(() =>
|
|
|
- props.items?.length ? props.items : infoTemo.swArr,
|
|
|
-);
|
|
|
-
|
|
|
-const filteredList = computed(() => {
|
|
|
- const q = keyword.value.trim().toLowerCase();
|
|
|
- const list = sourceList.value;
|
|
|
- if (!q) return [];
|
|
|
- return list.filter((item) => {
|
|
|
- const name = String(item.name ?? "").toLowerCase();
|
|
|
- const part = String(item.partOf ?? "").toLowerCase();
|
|
|
- return name.includes(q) || part.includes(q);
|
|
|
- });
|
|
|
-});
|
|
|
-
|
|
|
-const blurInput = () => {
|
|
|
- inputRef.value?.blur();
|
|
|
-};
|
|
|
-
|
|
|
-watch(show, (open) => {
|
|
|
- if (open) {
|
|
|
- nextTick(() => inputRef.value?.focus());
|
|
|
- } else {
|
|
|
- keyword.value = "";
|
|
|
- }
|
|
|
-});
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="scss" scoped>
|
|
|
-.search {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- padding-top: 35px;
|
|
|
- width: 100%;
|
|
|
- max-width: 100%;
|
|
|
- height: 100%;
|
|
|
- background: none;
|
|
|
-
|
|
|
- &-top {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 22px;
|
|
|
- padding: 0 25px;
|
|
|
- }
|
|
|
- &-close {
|
|
|
- width: 16px;
|
|
|
- height: 36px;
|
|
|
- background: url("@/assets/images/back.png") no-repeat center / contain;
|
|
|
- }
|
|
|
- &-input {
|
|
|
- flex: 1;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 20px;
|
|
|
- padding: 0 27px 0 19px;
|
|
|
- height: 60px;
|
|
|
- border: 1px solid #76685e;
|
|
|
- background: #f9f7ef;
|
|
|
- border-radius: 7px;
|
|
|
-
|
|
|
- input {
|
|
|
- flex: 1;
|
|
|
- color: #76685e;
|
|
|
- font-size: 24px;
|
|
|
- background: none;
|
|
|
- border: none;
|
|
|
- outline: none;
|
|
|
- }
|
|
|
- }
|
|
|
- &-icon {
|
|
|
- width: 32px;
|
|
|
- height: 34px;
|
|
|
- background: url("@/assets/images/search.png") no-repeat center / contain;
|
|
|
- }
|
|
|
- &-panel {
|
|
|
- margin-top: 32px;
|
|
|
- padding: 0 25px 35px;
|
|
|
- flex: 1;
|
|
|
- min-height: 0;
|
|
|
- display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
- align-items: flex-start;
|
|
|
- gap: 33px;
|
|
|
- overflow-y: auto;
|
|
|
-
|
|
|
- :deep(.card) {
|
|
|
- width: calc(50% - 16.5px);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &-empty {
|
|
|
- grid-column: 1 / -1;
|
|
|
- margin: 80px 0 0;
|
|
|
- width: 100%;
|
|
|
- text-align: center;
|
|
|
- color: #76685e;
|
|
|
- font-size: 26px;
|
|
|
- line-height: 1.5;
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|
|
|
+<template>
|
|
|
+ <VanPopup
|
|
|
+ v-model:show="show"
|
|
|
+ class="search"
|
|
|
+ :close-on-click-overlay="false"
|
|
|
+ :overlay-style="{
|
|
|
+ background: 'rgba(239, 232, 210, 0.90)',
|
|
|
+ backdropFilter: 'blur(10px)',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <div class="search-top">
|
|
|
+ <i class="search-close" @click="show = false" />
|
|
|
+ <div class="search-input">
|
|
|
+ <input
|
|
|
+ ref="inputRef"
|
|
|
+ v-model.trim="keyword"
|
|
|
+ type="search"
|
|
|
+ enterkeyhint="search"
|
|
|
+ placeholder="请输入展览名称"
|
|
|
+ @keydown.enter.prevent="blurInput"
|
|
|
+ />
|
|
|
+ <i class="search-icon" aria-hidden="true" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="search-panel">
|
|
|
+ <template v-if="filteredList.length">
|
|
|
+ <Card v-for="item in filteredList" :key="item.id" :item="item" />
|
|
|
+ </template>
|
|
|
+ <p v-else class="search-empty">
|
|
|
+ {{ keyword.trim() ? "未找到相关展览" : "请输入展览名称进行搜索" }}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </VanPopup>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { computed, ref, watch, nextTick } from "vue";
|
|
|
+import Card from "./Card.vue";
|
|
|
+import { infoTemo } from "@/assets/data.js";
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ visible: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ /** 与首页列表同源,便于展示最新浏览量;不传则用本地数据 */
|
|
|
+ items: {
|
|
|
+ type: Array,
|
|
|
+ default: null,
|
|
|
+ },
|
|
|
+});
|
|
|
+const emit = defineEmits(["update:visible"]);
|
|
|
+const show = computed({
|
|
|
+ get() {
|
|
|
+ return props.visible;
|
|
|
+ },
|
|
|
+ set(value) {
|
|
|
+ emit("update:visible", value);
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+const inputRef = ref(null);
|
|
|
+const keyword = ref("");
|
|
|
+
|
|
|
+const sourceList = computed(() =>
|
|
|
+ props.items?.length ? props.items : infoTemo.swArr,
|
|
|
+);
|
|
|
+
|
|
|
+const filteredList = computed(() => {
|
|
|
+ const q = keyword.value.trim().toLowerCase();
|
|
|
+ const list = sourceList.value;
|
|
|
+ if (!q) return [];
|
|
|
+ return list.filter((item) => {
|
|
|
+ const name = String(item.name ?? "").toLowerCase();
|
|
|
+ const part = String(item.partOf ?? "").toLowerCase();
|
|
|
+ return name.includes(q) || part.includes(q);
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
+const blurInput = () => {
|
|
|
+ inputRef.value?.blur();
|
|
|
+};
|
|
|
+
|
|
|
+watch(show, (open) => {
|
|
|
+ if (open) {
|
|
|
+ nextTick(() => inputRef.value?.focus());
|
|
|
+ } else {
|
|
|
+ keyword.value = "";
|
|
|
+ }
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.search {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ padding-top: 35px;
|
|
|
+ width: 100%;
|
|
|
+ max-width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background: none;
|
|
|
+
|
|
|
+ &-top {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 22px;
|
|
|
+ padding: 0 25px;
|
|
|
+ }
|
|
|
+ &-close {
|
|
|
+ width: 16px;
|
|
|
+ height: 36px;
|
|
|
+ background: url("@/assets/images/back.png") no-repeat center / contain;
|
|
|
+ }
|
|
|
+ &-input {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 20px;
|
|
|
+ padding: 0 27px 0 19px;
|
|
|
+ height: 60px;
|
|
|
+ border: 1px solid #76685e;
|
|
|
+ background: #f9f7ef;
|
|
|
+ border-radius: 7px;
|
|
|
+
|
|
|
+ input {
|
|
|
+ flex: 1;
|
|
|
+ color: #76685e;
|
|
|
+ font-size: 24px;
|
|
|
+ background: none;
|
|
|
+ border: none;
|
|
|
+ outline: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &-icon {
|
|
|
+ width: 32px;
|
|
|
+ height: 34px;
|
|
|
+ background: url("@/assets/images/search.png") no-repeat center / contain;
|
|
|
+ }
|
|
|
+ &-panel {
|
|
|
+ margin-top: 32px;
|
|
|
+ padding: 0 25px 35px;
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 33px;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ :deep(.card) {
|
|
|
+ width: calc(50% - 16.5px);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &-empty {
|
|
|
+ grid-column: 1 / -1;
|
|
|
+ margin: 80px 0 0;
|
|
|
+ width: 100%;
|
|
|
+ text-align: center;
|
|
|
+ color: #76685e;
|
|
|
+ font-size: 26px;
|
|
|
+ line-height: 1.5;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|