Browse Source

feat: 皮肤配置改造

dev
jiannibang 4 years ago
parent
commit
e594f28a07
  1. 4
      src/base/Temperature/Temperature.vue
  2. 5
      src/base/Time/Time.vue
  3. 4
      src/components/BrandScroll/BrandScroll.vue
  4. 4
      src/components/CarouselWithIntro/CarouselWithIntro.vue
  5. 1
      src/components/Map/Map.vue
  6. 6
      src/components/PublicComponent/PublicComponent.vue
  7. 15
      src/components/PublicComponent/SearchBar.vue
  8. 61
      src/components/PublicComponent/Tabs.vue
  9. 2
      src/layouts/View.vue
  10. 8
      src/store/root/actions.js
  11. 3
      src/store/root/getters.js
  12. 5
      src/store/root/state.js
  13. BIN
      src/themes/fashion/activity.png
  14. BIN
      src/themes/fashion/back.png
  15. BIN
      src/themes/fashion/billBoardBg.png
  16. 10
      src/themes/fashion/index.js
  17. BIN
      src/themes/fashion/mall.png
  18. BIN
      src/themes/fashion/member.png
  19. BIN
      src/themes/fashion/movie.png
  20. BIN
      src/themes/fashion/parking.png
  21. 63
      src/themes/fashion/style.json
  22. 4
      src/themes/index.js
  23. BIN
      src/themes/main/activity.png
  24. 0
      src/themes/main/back.png
  25. BIN
      src/themes/main/billBoardBg.png
  26. 10
      src/themes/main/index.js
  27. BIN
      src/themes/main/mall.png
  28. BIN
      src/themes/main/member.png
  29. BIN
      src/themes/main/movie.png
  30. BIN
      src/themes/main/parking.png
  31. 63
      src/themes/main/style.json
  32. 8
      src/views/Billboard/Billboard.vue
  33. 4
      src/views/Guide/Guide.vue
  34. 46
      src/views/Index/Index.vue

4
src/base/Temperature/Temperature.vue

@ -22,7 +22,7 @@ const { weather, icon } = useWeather()
z-index: 11;
}
.weather-icon {
color: #000000;
color: var(--weather-iconColor);
font-size: 36px;
font-weight: bolder;
font-family: 'font_bold';
@ -34,7 +34,7 @@ const { weather, icon } = useWeather()
font-size: 36px;
line-height: 44px;
letter-spacing: 0.05em;
color: #000000;
color: var(--weather-textColor);
margin-right: 12px;
}
</style>

5
src/base/Time/Time.vue

@ -23,7 +23,7 @@ const { dateRef, whichWeekRef } = useDay()
font-weight: 700;
font-size: 36px;
line-height: 44px;
color: #000;
color: var(--time-timeColor);
z-index: 11;
}
.month {
@ -36,6 +36,7 @@ const { dateRef, whichWeekRef } = useDay()
font-size: 13px;
line-height: 16px;
z-index: 11;
color: var(--time-monthColor);
}
.week {
position: fixed;
@ -46,7 +47,7 @@ const { dateRef, whichWeekRef } = useDay()
font-weight: 700;
font-size: 13px;
line-height: 16px;
color: #516dd8;
color: var(--time-weekColor);
z-index: 11;
}
</style>

4
src/components/BrandScroll/BrandScroll.vue

@ -128,7 +128,7 @@ watch([scroll, () => props.shop], () => {
font-weight: 900;
font-size: 32px;
line-height: 38px;
color: rgba(0, 0, 0, 0.8);
color: var(--brand-floorNameColor);
padding-bottom: 24px;
display: flex;
align-items: baseline;
@ -137,7 +137,7 @@ watch([scroll, () => props.shop], () => {
font-weight: 500;
font-size: 20px;
line-height: 23px;
color: rgba(0, 0, 0, 0.6);
color: var(--brand-floorMetaColor);
}
.current {
display: flex;

4
src/components/CarouselWithIntro/CarouselWithIntro.vue

@ -94,7 +94,7 @@ const qr = computed(() => props.data.qrFileList ?? [])
font-weight: 700;
font-size: 28px;
line-height: 150%;
color: rgba(0, 0, 0, 0.8);
color: var(--carousel-titleColor);
}
.intro-scroll {
@ -111,7 +111,7 @@ const qr = computed(() => props.data.qrFileList ?? [])
font-size: 16px;
line-height: 200%;
text-align: justify;
color: rgba(0, 0, 0, 0.6);
color: var(--carousel-introColor);
}
}
</style>

1
src/components/Map/Map.vue

@ -33,6 +33,7 @@ const { shop } = storeToRefs(store)
width: 1080px;
z-index: 10;
overflow: hidden;
background: var(--map-background);
&.billboard {
pointer-events: none;
}

6
src/components/PublicComponent/PublicComponent.vue

@ -75,6 +75,12 @@ onMounted(() => {
timer.value = setInterval(() => {
send(`type:online`)
}, 30000)
let i = 0
store.SET_CURRENT_THEME('main')
setInterval(() => {
i++
store.SET_CURRENT_THEME(['main', 'fashion'][i % 2])
}, 10000)
window.addEventListener('touchend', checkHandleScreen)
})
onBeforeUnmount(() => {

15
src/components/PublicComponent/SearchBar.vue

@ -1,6 +1,6 @@
<template>
<div class="row">
<div class="back" v-if="$route.path !== '/index'" @click="() => $router.push('/index')"></div>
<div class="back" :style="{ backgroundImage: `url(${theme.images.back})` }" v-if="$route.path !== '/index'" @click="() => $router.push('/index')"></div>
<div class="bar" @click="handleSearch">
<div class="icon"></div>
<div class="stick"></div>
@ -11,8 +11,10 @@
<script setup>
import { useStore } from '@/store/root'
import { storeToRefs } from 'pinia'
const store = useStore()
const handleSearch = () => store.SET_SHOW_SEARCH(true)
const { theme } = storeToRefs(store)
</script>
<style lang="scss" scoped>
@ -28,16 +30,17 @@ const handleSearch = () => store.SET_SHOW_SEARCH(true)
width: 130px;
height: 100px;
margin-right: 40px;
background: center / cover no-repeat url(./back.png);
background: center / cover no-repeat;
box-shadow: 0px 15px 24px rgba(0, 0, 0, 0.05);
border-radius: 24px;
border-radius: var(--searchBar-backBorderRadius);
}
.bar {
flex: 1;
height: 100px;
background: #ffffff;
background: var(--searchBar-background);
border: var(--searchBar-border);
box-shadow: 0px 15px 24px rgba(0, 0, 0, 0.05);
border-radius: 24px;
border-radius: var(--searchBar-borderRadius);
display: flex;
padding-left: 40px;
align-items: center;
@ -58,7 +61,7 @@ const handleSearch = () => store.SET_SHOW_SEARCH(true)
font-weight: 700;
font-size: 20px;
line-height: 23px;
color: rgba(0, 0, 0, 0.2);
color: var(--searchBar-placeholderColor);
}
}
}

61
src/components/PublicComponent/Tabs.vue

@ -1,7 +1,7 @@
<template>
<div class="tabs" v-if="sidebarList.find(({ path }) => path === $route.path)">
<div :class="['item', tab.path === $route.path ? 'active' : '']" v-for="tab of sidebarList" :key="tab.title" @click="goPage(tab)">
<div class="icon"><img :src="tab.icon" /></div>
<div class="icon"><img :src="theme.images[tab.moduleName]" /></div>
<div class="title">{{ switchLanguage(tab, 'title') }}</div>
</div>
</div>
@ -13,7 +13,7 @@ import { storeToRefs } from 'pinia'
import { useRouter } from 'vue-router'
const router = useRouter()
const store = useStore()
const { sidebarList } = storeToRefs(store)
const { sidebarList, theme } = storeToRefs(store)
const goPage = item => {
store.SET_SELECTED_MODULE(item.title)
router.push(item.path)
@ -27,6 +27,56 @@ const goPage = item => {
left: 68px;
right: 68px;
display: flex;
.item:nth-child(5n + 1) {
&.active {
.icon {
background: var(--menu-activeBg1);
}
}
.icon {
background: var(--menu-bg1);
}
}
.item:nth-child(5n + 2) {
&.active {
.icon {
background: var(--menu-activeBg2);
}
}
.icon {
background: var(--menu-bg2);
}
}
.item:nth-child(5n + 3) {
&.active {
.icon {
background: var(--menu-activeBg3);
}
}
.icon {
background: var(--menu-bg3);
}
}
.item:nth-child(5n + 4) {
&.active {
.icon {
background: var(--menu-activeBg4);
}
}
.icon {
background: var(--menu-bg4);
}
}
.item:nth-child(5n + 5) {
&.active {
.icon {
background: var(--menu-activeBg5);
}
}
.icon {
background: var(--menu-bg5);
}
}
.item {
position: relative;
display: flex;
@ -50,15 +100,12 @@ const goPage = item => {
font-size: 18px;
line-height: 21px;
text-align: center;
color: rgba(0, 0, 0, 0.4);
color: var(--menu-color);
margin-top: 12px;
}
&.active {
.icon {
background: #ffffff;
}
.title {
color: rgba(0, 0, 0, 0.8);
color: var(--menu-activeColor);
}
&::after {
content: '';

2
src/layouts/View.vue

@ -24,7 +24,7 @@ defineProps({
flex-direction: column;
width: 100vw;
height: 100vh;
background: #dee6f6;
background: var(--global-background);
.bgTop {
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.5) 100%);
border-bottom: 1px solid rgba(255, 255, 255, 0.8);

8
src/store/root/actions.js

@ -1,4 +1,5 @@
import { i18n } from '@/i18n'
import themes from '@/themes'
export const actions = {
SET_SHOP_LIST(list) {
@ -49,5 +50,12 @@ export const actions = {
},
SET_MAP_DATA(data) {
this.mapData = data
},
SET_CURRENT_THEME(data) {
this.currentThemeName = data
const r = document.querySelector(':root')
Object.entries(themes[data]).forEach(([cat, obj]) => {
Object.entries(obj).forEach(([k, v]) => r.style.setProperty(`--${cat}-${k}`, v))
})
}
}

3
src/store/root/getters.js

@ -50,3 +50,6 @@ export const currentFloorShopMap = ({ currentFloor: device, shopList, mapData })
return { ...acc, [shop.shopId]: result }
}, {})
}
export const theme = state => {
return state.themes[state.currentThemeName]
}

5
src/store/root/state.js

@ -1,4 +1,5 @@
import { sidebarList } from '@/components/Sidebar/list'
import themes from '@/themes'
export const state = () => ({
sidebarList,
@ -17,7 +18,9 @@ export const state = () => ({
currentFloor: {}, //设备所属的当前楼栋的当前楼层信息
isUseFace: 0, //是否使用人脸 0:不使用 1: 使用
isUseSpeech: 1, //是否使用语音 0:不使用 1: 使用
mapData: null
mapData: null,
themes,
currentThemeName: 'main'
})
export const is4k = () => {

BIN
src/themes/fashion/activity.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/themes/fashion/back.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
src/themes/fashion/billBoardBg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

10
src/themes/fashion/index.js

@ -0,0 +1,10 @@
import style from './style.json'
function importAll(r) {
const obj = {}
r.keys().forEach(key => {
obj[key.replace('./', '').replace('.png', '')] = r(key)
})
return obj
}
const images = importAll(require.context('./', false, /\.(png|jpe?g|svg)$/))
export default { ...style, images }

BIN
src/themes/fashion/mall.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/themes/fashion/member.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
src/themes/fashion/movie.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/themes/fashion/parking.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

63
src/themes/fashion/style.json

@ -0,0 +1,63 @@
{
"global": {
"background": "linear-gradient(180deg, #6257d7 0%, #f191c0 100%)"
},
"weather": {
"iconColor": "#fff",
"textColor": "#fff"
},
"time": {
"timeColor": "#fff",
"monthColor": "#fff",
"weekColor": "#f0b92b"
},
"searchBar": {
"backBorderRadius": "100px",
"background": "rgba(255, 255, 255, 0.6)",
"border": "2px solid #ffffff",
"borderRadius": "100px",
"placeholderColor": "rgba(0, 0, 0, 0.6)"
},
"menu": {
"bg1": "linear-gradient(180deg, #e97893 0%, #f48bca 100%)",
"bg2": "linear-gradient(180deg, #f29348 0%, #f9ba61 100%)",
"bg3": "linear-gradient(180deg, #53ba82 0%, #89d963 100%)",
"bg4": "linear-gradient(180deg, #c57df1 0%, #ec86f2 100%)",
"bg5": "linear-gradient(180deg, #418fea 0%, #59b0f2 94.79%)",
"activeBg1": "linear-gradient(180deg, #e97893 0%, #f48bca 100%)",
"activeBg2": "linear-gradient(180deg, #f29348 0%, #f9ba61 100%)",
"activeBg3": "linear-gradient(180deg, #53ba82 0%, #89d963 100%)",
"activeBg4": "linear-gradient(180deg, #c57df1 0%, #ec86f2 100%)",
"activeBg5": "linear-gradient(180deg, #418fea 0%, #59b0f2 94.79%)",
"color": "#ffffff",
"activeColor": "#ffffff"
},
"index": {
"recTitleColor": "#fff",
"guideBackground": "rgba(255, 255, 255, 0.6)",
"guideBorder": "2px solid rgba(255, 255, 255, 0.6)",
"guideTopBg": "linear-gradient(180deg, #6257d7 0%, #f191c0 100%)",
"guideQrcodeBg": "#ffffff",
"foodBg": "rgba(255, 255, 255, 0.6)",
"recBg": "rgba(255, 255, 255, 0.6)",
"recBorder": "2px solid rgba(255, 255, 255, 0.6)"
},
"brand": {
"floorNameColor": "#fff",
"floorMetaColor": "rgba(255, 255, 255, 0.8)"
},
"carousel": {
"titleColor": "#fff",
"introColor": "#fff"
},
"map": {
"background": "#dee2f6"
},
"billboard": {
"background": "linear-gradient(180deg, #6257d7 0%, #f191c0 100%)"
},
"guide": {
"floorBg": "linear-gradient(90deg, #302159 0%, #7756b4 96.35%)",
"allFloorBg": "left / 150px 100% no-repeat linear-gradient(180deg, #6257d7 0%, #f191c0 100%), #dee6f6"
}
}

4
src/themes/index.js

@ -0,0 +1,4 @@
import main from './main/index'
import fashion from './fashion/index'
export default { main, fashion }

BIN
src/themes/main/activity.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

0
src/components/PublicComponent/back.png → src/themes/main/back.png

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
src/themes/main/billBoardBg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

10
src/themes/main/index.js

@ -0,0 +1,10 @@
import style from './style.json'
function importAll(r) {
const obj = {}
r.keys().forEach(key => {
obj[key.replace('./', '').replace('.png', '')] = r(key)
})
return obj
}
const images = importAll(require.context('./', false, /\.(png|jpe?g|svg)$/))
export default { ...style, images }

BIN
src/themes/main/mall.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
src/themes/main/member.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
src/themes/main/movie.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
src/themes/main/parking.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

63
src/themes/main/style.json

@ -0,0 +1,63 @@
{
"global": {
"background": "#dee6f6"
},
"weather": {
"iconColor": "#000",
"textColor": "#000"
},
"time": {
"timeColor": "#000",
"monthColor": "#000",
"weekColor": "#516dd8"
},
"searchBar": {
"backBorderRadius": "24px",
"background": "#fff",
"border": "none",
"borderRadius": "24px",
"placeholderColor": "rgba(0, 0, 0, 0.2)"
},
"menu": {
"bg1": "rgba(255, 255, 255, 0.4)",
"bg2": "rgba(255, 255, 255, 0.4)",
"bg3": "rgba(255, 255, 255, 0.4)",
"bg4": "rgba(255, 255, 255, 0.4)",
"bg5": "rgba(255, 255, 255, 0.4)",
"activeBg1": "#ffffff",
"activeBg2": "#ffffff",
"activeBg3": "#ffffff",
"activeBg4": "#ffffff",
"activeBg5": "#ffffff",
"color": "rgba(0, 0, 0, 0.4)",
"activeColor": "rgba(0, 0, 0, 0.8)"
},
"index": {
"recTitleColor": "rgba(0, 0, 0, 0.8)",
"guideBackground": "linear-gradient(99.5deg, #f0b92b 0%, #f9d556 100%)",
"guideBorder": "none",
"guideTopBg": "linear-gradient(180deg, #435acd 0%, #749cf3 100%)",
"guideQrcodeBg": "rgba(255, 255, 255, 0.2)",
"foodBg": "linear-gradient(180deg, #ffffff 0%, #f2f4f8 100%)",
"recBg": "linear-gradient(180deg, #ffffff 0%, #f2f4f8 100%)",
"recBorder": "none"
},
"brand": {
"floorNameColor": "rgba(0, 0, 0, 0.8)",
"floorMetaColor": "rgba(0, 0, 0, 0.6)"
},
"carousel": {
"titleColor": "rgba(0, 0, 0, 0.8)",
"introColor": "rgba(0, 0, 0, 0.6)"
},
"map": {
"background": "none"
},
"billboard": {
"background": "#dee6f6"
},
"guide": {
"floorBg": "linear-gradient(113.71deg, #435acd 0%, #749cf3 100%)",
"allFloorBg": "left / 150px 100% no-repeat linear-gradient(180deg, #6c7ca6 0%, #879aca 100%), #dee6f6"
}
}

8
src/views/Billboard/Billboard.vue

@ -2,7 +2,7 @@
<div class="billboard">
<div class="ip"></div>
<div class="guide" @click="goPage({ title: '地图导览', path: '/guide' })"></div>
<div class="header">
<div class="header" :style="{ backgroundImage: `url(${theme.images.billBoardBg})` }">
<div class="r1">当前位置 <img src="./loc.png" alt="" /></div>
<div class="r2">{{ bf }}</div>
<div class="r3"></div>
@ -68,7 +68,7 @@ const store = useStore()
const router = useRouter()
const shops = ref([])
const listRef = ref(null)
const { currentFloor, buildingList, currentFloorShopMap, config } = storeToRefs(store)
const { currentFloor, buildingList, currentFloorShopMap, config, theme } = storeToRefs(store)
const bf = computed(() => (buildingList.length > 1 ? currentFloor.value.building + '-' : '') + currentFloor.value.floor)
const scrollWidth = ref(0)
@ -220,7 +220,7 @@ watch(scrollLefts, _scrollLefts => {
left: 0;
right: 0;
bottom: 0;
background: #dee6f6;
background: var(--billboard-background);
z-index: 100;
.ip {
position: absolute;
@ -244,7 +244,7 @@ watch(scrollLefts, _scrollLefts => {
height: 200px;
padding-top: 48px;
padding-left: 68px;
background: top / contain no-repeat url(./bg.png);
background: top / contain no-repeat;
z-index: 0;
.r1 {
display: flex;

4
src/views/Guide/Guide.vue

@ -251,7 +251,7 @@ watch(
left: 0;
right: 0;
height: 642px;
background: left / 150px 100% no-repeat linear-gradient(180deg, #6c7ca6 0%, #879aca 100%), #dee6f6;
background: var(--guide-allFloorBg);
z-index: 100;
.row {
height: 76px;
@ -350,7 +350,7 @@ watch(
z-index: 60;
display: block;
overflow: hidden;
background: linear-gradient(113.71deg, #435acd 0%, #749cf3 100%);
background: var(--guide-floorBg);
&::-webkit-scrollbar {
display: none;

46
src/views/Index/Index.vue

@ -55,7 +55,7 @@
</div>
<div class="r2">
<div class="item" v-for="tab of sidebarList" :key="tab.title" @click="goPage(tab)">
<div class="icon"><img :src="tab.icon" /></div>
<div class="icon"><img :src="theme.images[tab.moduleName]" /></div>
<div class="title">{{ switchLanguage(tab, 'title') }}</div>
</div>
</div>
@ -90,7 +90,7 @@ import QRCodeFromText from '@/components/QRCodeFromText/QRCodeFromText.vue'
const router = useRouter()
const store = useStore()
const { indexList, currentFloor, buildingList, shopList, sidebarList, config } = storeToRefs(store)
const { indexList, currentFloor, buildingList, shopList, sidebarList, config, theme } = storeToRefs(store)
const guideDesc = ref('')
const foodList = computed(() => shopList.value.filter(({ isSpecial }) => isSpecial).slice(0, 12) ?? [])
const hotRecommend = computed(() => indexList.value.hotSearch.slice(0, 5) ?? [])
@ -138,7 +138,7 @@ getActivityList(3).then(({ data }) => {
font-weight: 900;
font-size: 20px;
line-height: 23px;
color: rgba(0, 0, 0, 0.8);
color: var(--index-recTitleColor);
}
.row {
margin-top: 16px;
@ -188,7 +188,8 @@ getActivityList(3).then(({ data }) => {
flex: 0 0 339px;
width: 339px;
height: 557px;
background: linear-gradient(99.5deg, #f0b92b 0%, #f9d556 100%);
background: var(--index-guideBackground);
border: var(--index-guideBorder);
border-radius: 32px;
overflow: hidden;
padding: 460px 0 0 40px;
@ -199,7 +200,7 @@ getActivityList(3).then(({ data }) => {
left: 0;
width: 100%;
height: 432px;
background: linear-gradient(180deg, #435acd 0%, #749cf3 100%);
background: var(--index-guideTopBg);
border-radius: 32px;
padding: 40px;
z-index: 1;
@ -229,7 +230,7 @@ getActivityList(3).then(({ data }) => {
height: 156px;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.2);
background: var(--index-guideQrcodeBg);
padding-top: 132px;
font-weight: 700;
font-size: 14px;
@ -305,7 +306,7 @@ getActivityList(3).then(({ data }) => {
width: 100%;
height: 100%;
margin-left: 40px;
background: linear-gradient(180deg, #ffffff 0%, #f2f4f8 100%);
background: var(--index-foodBg);
border-radius: 32px;
border: 4px solid rgba(246, 139, 81, 1);
align-items: center;
@ -327,7 +328,8 @@ getActivityList(3).then(({ data }) => {
width: 100%;
height: 100%;
margin-left: 40px;
background: linear-gradient(180deg, #ffffff 0%, #f2f4f8 100%);
background: var(--index-recBg);
border: var(--index-recBorder);
border-radius: 32px;
align-items: center;
overflow: hidden;
@ -346,6 +348,31 @@ getActivityList(3).then(({ data }) => {
.r2 {
display: flex;
margin-top: 40px;
.item:nth-child(5n + 1) {
.icon {
background: var(--menu-activeBg1);
}
}
.item:nth-child(5n + 2) {
.icon {
background: var(--menu-activeBg2);
}
}
.item:nth-child(5n + 3) {
.icon {
background: var(--menu-activeBg3);
}
}
.item:nth-child(5n + 4) {
.icon {
background: var(--menu-activeBg4);
}
}
.item:nth-child(5n + 5) {
.icon {
background: var(--menu-activeBg5);
}
}
.item {
display: flex;
flex-direction: column;
@ -357,7 +384,6 @@ getActivityList(3).then(({ data }) => {
justify-content: center;
align-items: center;
height: 118px;
background: #ffffff;
border-radius: 24px;
img {
width: 80px;
@ -369,7 +395,7 @@ getActivityList(3).then(({ data }) => {
font-size: 18px;
line-height: 21px;
text-align: center;
color: rgba(0, 0, 0, 0.8);
color: var(--menu-activeColor);
}
}
.item + .item {

Loading…
Cancel
Save