123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- <template>
- <div class="relic-list">
- <button
- class="return"
- @click="router.go(-1)"
- />
- <el-cascader
- v-model="cascaderValue"
- :options="cameraTree"
- :show-all-levels="false"
- :props="{
- expandTrigger: 'hover',
- }"
- />
- <div class="search-ui">
- <input
- v-model.trim="keyword"
- type="text"
- placeholder="请输入要搜索内容"
- @keydown.enter="onSearch"
- >
- <button
- class="search"
- />
- </div>
- <div
- class="the-list"
- :class="{
- scene1: cascaderValue[0] === '0',
- scene2: cascaderValue[0] === '1',
- scene3: cascaderValue[0] === '2',
- }"
- >
- <div
- ref="listEl"
- class="content-wrap"
- @scroll="handleScroll"
- >
- <div
- class="first-item"
- :class="{
- scene1: cascaderValue[0] === '0',
- scene2: cascaderValue[0] === '1',
- scene3: cascaderValue[0] === '2',
- }"
- />
- <div
- v-for="(item, idx) in relicData"
- :key="idx"
- class="relic-item"
- :class="{
- isScene1: item.sceneIdx === 0,
- isScene2: item.sceneIdx === 1,
- isScene3: item.sceneIdx === 2,
- isOdd: (idx) % 2 === 0,
- isEven: (idx) % 2 === 1,
- }"
- @click="onClickItem(item.idx)"
- >
- <div
- class="name"
- :class="{
- wide: item['名称'].length > 11
- }"
- :title="item['名称']"
- >
- {{ item['名称'] }}
- </div>
- <img
- class=""
- :src="getRelicThumbUrl(idx)"
- alt=""
- draggable="false"
- >
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- /**
- * todo: 自动恢复上次滚动位置
- */
- import { ref, computed, watch, watchEffect, onMounted, nextTick, defineComponent } from "vue"
- import { useRoute, useRouter } from "vue-router"
- import { useStore } from "vuex"
- import useSmoothSwipe from '@/useFunctions/useSmoothSwipe.js'
- import { useElementSize, useWindowSize } from '@vueuse/core'
- import { debounce } from "lodash"
- const SCROLL_KEY = 'relicListScrollLeft'
- const route = useRoute()
- const router = useRouter()
- const store = useStore()
- const { height: windowHeight } = useWindowSize()
- const cascaderValueInit = (route.query.sceneIdx && route.query.cameraIdx) ? [route.query.sceneIdx, route.query.cameraIdx] : ['0', '0']
- const cascaderValue = ref(cascaderValueInit)
- const cameraTree = ref([
- {
- value: '0',
- label: '天下大都',
- children: [
- {
- value: '0',
- label: '帝都',
- },
- {
- value: '1',
- label: '宫阙',
- },
- {
- value: '2',
- label: '览胜',
- },
- ]
- },
- {
- value: '1',
- label: '河润大都',
- children: [
- {
- value: '0',
- label: '河畅',
- },
- {
- value: '1',
- label: '航运',
- },
- {
- value: '2',
- label: '市井',
- },
- ]
- },
- {
- value: '2',
- label: '风雅大都',
- children: [
- {
- value: '0',
- label: '雅集',
- },
- {
- value: '1',
- label: '曲苑',
- },
- ]
- },
- ])
- const keyword = ref('')
- const sceneIdx = computed(() => {
- return route.query.sceneIdx
- })
- const cameraIdx = computed(() => {
- return route.query.cameraIdx
- })
- const relicData = computed(() => {
- return store.getters.relicData.filter((item) => {
- const selectedSceneIdx = Number(cascaderValue.value[0])
- if (selectedSceneIdx !== item.sceneIdx) {
- return false
- } else {
- const selectedCameraIdx = Number(cascaderValue.value[1])
- if (selectedCameraIdx === item.cameraIdx) {
- return true
- } else {
- return false
- }
- }
- }).filter((item) => {
- if (!keyword.value) {
- return true
- } else {
- if (item['名称'].includes(keyword.value)) {
- return true
- } else {
- return false
- }
- }
- })
- })
- function getRelicThumbUrl(idx) {
- if (Array.isArray(relicData.value[idx]['图片名']) && relicData.value[idx]['图片名'][0]) {
- return `${process.env.BASE_URL}relic-data/small-photo/${relicData.value[idx]['图片名'][0]}`
- } else {
- return ''
- }
- }
- const listEl = ref(null)
- let scrollLeft = Number(localStorage.getItem(SCROLL_KEY) || 0)
- const { width: listWidth, height: listHeight } = useElementSize(listEl)
- const { hasOperatedThisTime, updateWidth, updateTranslateLength } = useSmoothSwipe({
- scrollTargetRef: listEl,
- viewportWidth: listWidth,
- initTranslateLength: scrollLeft,
- })
- watch(relicData, (vNew) => {
- nextTick(() => {
- updateWidth()
- })
- }, {
- deep: true
- })
- function onClickItem(idx) {
- if (!hasOperatedThisTime.value) {
- router.push({
- name: 'RelicDetail',
- query: {
- sceneIdx: route.query.sceneIdx,
- cameraIdx: route.query.cameraIdx,
- relicIdx: idx,
- }
- })
- }
- }
- watch(cascaderValue, val => {
- router.replace({
- name: 'RelicList',
- query: {
- sceneIdx: val[0],
- cameraIdx: val[1]
- }
- })
- updateTranslateLength(0)
- })
- router.beforeEach((to) => {
- if (!['RelicDetail', 'RelicList'].includes(to.name)) {
- localStorage.removeItem(SCROLL_KEY)
- }
- })
- onMounted(() => {
- if (scrollLeft) {
- listEl.value.scrollLeft = scrollLeft
- }
- })
- const handleScroll = debounce(() => {
- listEl.value && localStorage.setItem(SCROLL_KEY, listEl.value.scrollLeft)
- }, 100)
- </script>
- <style lang="less" scoped>
- @page-height-design-px: 970;
- .relic-list {
- height: 100%;
- background-image: url(@/assets/images/relic-list-bg.jpg);
- background-size: cover;
- background-repeat: no-repeat;
- background-position: center center;
- >button.return {
- position: absolute;
- width: 58px;
- height: 58px;
- left: 42px;
- top: 68px;
- background-image: url(@/assets/images/btn-return.png);
- background-size: contain;
- background-repeat: no-repeat;
- background-position: center center;
- }
- :deep {
- .el-cascader {
- position: absolute;
- width: 200px;
- height: 58px;
- left: 160px;
- top: 68px;
- .el-input {
- height: 100%;
- background-image: url(@/assets/images/cascader-bg.png);
- background-size: 100% 100%;
- border: 0;
- .el-input__wrapper {
- background: none;
- border: 0;
- box-shadow: none;
- .el-input__inner {
- height: 100%;
- font-size: 30px;
- text-align: center;
- font-family: 'SourceHanSerifCN-Heavy';
- color: #6A3906;
- }
- .el-input__suffix {
- color: #6A3906;
- }
- }
- .icon-arrow-down {
- font-size: 24px;
- margin-top: 10px;
- }
- }
- }
- .el-popper .is-light {
- background: red;
- }
- }
- >.search-ui {
- position: absolute;
- top: 65px;
- right: 27px;
- width: 406px;
- height: 62px;
- background-image: url(@/assets/images/search-bg.png);
- background-size: cover;
- background-repeat: no-repeat;
- background-position: center center;
- >input {
- position: absolute;
- left: 50px;
- top: 50%;
- transform: translateY(-50%);
- height: 35px;
- width: 250PX;
- font-size: 24px;
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 400;
- color: rgba(255, 255, 255, 0.7);
- line-height: 28px;
- &::placeholder {
- font-size: 24px;
- font-family: Source Han Sans CN, Source Han Sans CN;
- font-weight: 400;
- color: rgba(255, 255, 255, 0.3);
- line-height: 28px;
- }
- }
- >button.search {
- position: absolute;
- width: 31px;
- height: 31px;
- position: absolute;
- top: 50%;
- right: 53px;
- transform: translateY(-50%);
- background-image: url(@/assets/images/icon-search.png);
- background-size: cover;
- background-repeat: no-repeat;
- background-position: center center;
- }
- }
- >.the-list {
- position: absolute;
- left: 0;
- top: 55%;
- translate: 0 -50%;
- width: 100%;
- height: calc(650 / @page-height-design-px * 100vh);
- background-size: auto 100%;
- background-repeat: no-repeat;
- background-position: left center;
- padding-left: calc(54 / @page-height-design-px * 100vh);
- box-sizing: border-box;
- >.content-wrap {
- &::-webkit-scrollbar {
- height: 0;
- }
- box-sizing: border-box;
- margin-top: calc(27 / @page-height-design-px * 100vh);
- height: calc(589 / @page-height-design-px * 100vh);
- width: 100%;
- overflow: auto;
- user-select: none;
- display: flex;
- align-items: center;
- background: rgba(230,232,224,0.375);
- >.first-item{
- flex: 0 0 auto;
- width: calc(277 / @page-height-design-px * 100vh * 0.83);
- height: calc(608 / @page-height-design-px * 100vh * 0.83);
- background-size: cover;
- background-repeat: no-repeat;
- background-position: center center;
- }
- >.first-item.scene1{
- background-image: url(@/assets/images/relic-first-item-bg-1.jpg);
- }
- >.first-item.scene2{
- background-image: url(@/assets/images/relic-first-item-bg-2.jpg);
- }
- >.first-item.scene3{
- background-image: url(@/assets/images/relic-first-item-bg-3.jpg);
- }
- >.relic-item {
- flex: 0 0 auto;
- width: calc(277 / @page-height-design-px * 100vh * 0.83);
- height: calc(608 / @page-height-design-px * 100vh * 0.83);
- cursor: pointer;
- background-size: cover;
- background-repeat: no-repeat;
- background-position: center center;
- position: relative;
- >.name {
- flex: 0 0 auto;
- position: absolute;
- top: calc(10 / @page-height-design-px * 100vh * 0.83);
- right: calc(32 / @page-height-design-px * 100vh * 0.83);
- width: calc(47 / @page-height-design-px * 100vh * 0.83);
- line-height: calc(47 / @page-height-design-px * 100vh * 0.83);
- height: calc(261 / @page-height-design-px * 100vh * 0.83);
- font-size: calc(19 / @page-height-design-px * 100vh * 0.83);
- font-family: Source Han Serif CN, Source Han Serif CN;
- font-weight: 800;
- color: #43310E;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- -webkit-line-clamp: 2;
- overflow: hidden;
- writing-mode: vertical-rl;
- background-image: url(@/assets/images/relic-item-title-bg.png);
- background-size: contain;
- background-repeat: no-repeat;
- background-position: center center;
- text-align: center;
- padding-top: calc(17 / @page-height-design-px * 100vh * 0.83);
- padding-bottom: calc(17 / @page-height-design-px * 100vh * 0.83);
- z-index: 1;
- }
- >.name.wide{
- right: calc(12 / @page-height-design-px * 100vh * 0.83);
- width: calc(82 / @page-height-design-px * 100vh * 0.83);
- height: calc(255 / @page-height-design-px * 100vh * 0.83);
- line-height: 1.5em;
- background-image: url(@/assets/images/relic-item-title-bg-wide.png);
- padding-right: 0.7em;
- z-index: 1;
- }
- >img {
- position: absolute;
- left: 0;
- left: 50%;
- translate: -50% 0;
- object-fit: contain;
- scale: calc(v-bind('windowHeight') / @page-height-design-px);
- transform-origin: center bottom;
- }
- }
- >.relic-item.isOdd{
- >img{
- bottom: calc(250 / @page-height-design-px * 100vh * 0.83);
- }
- }
- >.relic-item.isEven{
- >img{
- bottom: calc(120 / @page-height-design-px * 100vh * 0.83);
- }
- }
- >.relic-item.isScene1.isOdd{
- background-image: url(@/assets/images/relic-item-bg-1-odd.jpg);
- }
- >.relic-item.isScene1.isEven{
- background-image: url(@/assets/images/relic-item-bg-1-even.jpg);
- }
- >.relic-item.isScene2.isOdd{
- background-image: url(@/assets/images/relic-item-bg-2-odd.jpg);
- }
- >.relic-item.isScene2.isEven{
- background-image: url(@/assets/images/relic-item-bg-2-even.jpg);
- }
- >.relic-item.isScene3.isOdd{
- background-image: url(@/assets/images/relic-item-bg-3-odd.jpg);
- }
- >.relic-item.isScene3.isEven{
- background-image: url(@/assets/images/relic-item-bg-3-even.jpg);
- }
- }
- }
- >.the-list.scene1{
- background-image: url(@/assets/images/relic-list-bg-1-1.png);
- }
- >.the-list.scene2{
- background-image: url(@/assets/images/relic-list-bg-1-2.png);
- }
- >.the-list.scene3{
- background-image: url(@/assets/images/relic-list-bg-1-3.png);
- }
- }
- </style>
|