修改首页

This commit is contained in:
zpc 2025-09-10 23:11:48 +08:00
parent 4b6f7641b6
commit 56f89e9ae2
8 changed files with 471 additions and 443 deletions

View File

@ -1,309 +1,333 @@
<template> <template>
<view class="grid-item" @click="handleCardClick"> <view class="grid" @click="handleCardClick">
<uni-card margin="0px" padding="0px" spacing="0px"> <view class="grid-item">
<view <view style="height: 251rpx;">
style="position:absolute;top:0;right:0;width:100%; background: linear-gradient(to bottom, rgba(255, 108, 0, 0.9), rgba(255, 108, 0, 0.7));box-shadow: 0 2px 8px rgba(235,135,58, 0.3);z-index:999;border-radius:4px 4px 0 0;font-size:24rpx;color:#fff;font-weight: 500; opacity: 0.7;"> <view class="nine-grid-container">
<text style="padding-left:10rpx;">{{ item.status }}</text> <view></view>
</view> <view class="item">
<view class="item-content column"> <view class="item-avatar">
<!-- 麻将桌区域 --> <image src="@@:app/static/add.png" class="avatar-img" mode="aspectFit">
<view class="mahjong-table"> </image>
<!-- 九宫格布局 -->
<view style="width:300rpx;height: 300rpx;">
<view class="nine-grid-container">
<!-- 第一行 -->
<view class="grid-cell"></view>
<view class="grid-cell" :class="getCellClass(0)">
<view v-if="getPlayerAtPosition(0)" class="player-avatar">
<image :src="getPlayerAtPosition(0).avatar || ''" class="avatar-img"></image>
</view>
<view v-else-if="canJoinAtPosition(0)" class="join-button" @click.stop="handleJoin">
<text class="join-text">+</text>
</view>
</view>
<view class="grid-cell"></view>
<!-- 第二行 -->
<view class="grid-cell" :class="getCellClass(1)">
<view v-if="getPlayerAtPosition(1)" class="player-avatar">
<image :src="getPlayerAtPosition(1).avatar || ''" class="avatar-img"></image>
</view>
<view v-else-if="canJoinAtPosition(1)" class="join-button" @click.stop="handleJoin">
<text class="join-text">+</text>
</view>
</view>
<view class="grid-cell center-cell">
<!-- 麻将桌背景图 -->
<image src="/static/9.png" class="table-bg" mode=""></image>
</view>
<view class="grid-cell" :class="getCellClass(2)">
<view v-if="getPlayerAtPosition(2)" class="player-avatar">
<image :src="getPlayerAtPosition(2).avatar || ''" class="avatar-img"></image>
</view>
<view v-else-if="canJoinAtPosition(2)" class="join-button" @click.stop="handleJoin">
<text class="join-text">+</text>
</view>
</view>
<!-- 第三行 -->
<view class="grid-cell"></view>
<view class="grid-cell" :class="getCellClass(3)">
<view v-if="getPlayerAtPosition(3)" class="player-avatar">
<image :src="getPlayerAtPosition(3).avatar || ''" class="avatar-img"></image>
</view>
<view v-else-if="canJoinAtPosition(3)" class="join-button" @click.stop="handleJoin">
<text class="join-text">+</text>
</view>
</view>
<view class="grid-cell"></view>
</view> </view>
</view> </view>
</view> <view></view>
<view class="item">
<!-- 信息区域 --> <view class="item-avatar">
<view class="info-section"> <image src="@@:app/static/add.png" class="avatar-img" mode="aspectFit">
<text class="info-text" style="font-size: 26rpx;font-weight: 600;color: #FA690B;">{{ </image>
item.description }}</text> </view>
<text class="info-text" style="margin-top: -7rpx;">{{ item.room }}</text> </view>
<text class="info-text" style="font-size: 22rpx;font-weight: 600;line-height:28rpx;">2025-09-06</text> <view></view>
<text class="info-text" style="font-size: 22rpx;font-weight: 600;line-height:28rpx;">{{ item.time }}</text> <view class="item">
<text class="info-text" style="color:#FA690B;line-height:30rpx;margin-top:6rpx;">{{ item.requirements }}</text> <view class="item-avatar">
<image src="@@:app/static/add.png" class="avatar-img" mode="aspectFit">
</image>
</view>
</view>
<view></view>
<view class="item">
<view class="item-avatar">
<image src="@@:app/static/add.png" class="avatar-img" mode="aspectFit">
</image>
</view>
</view>
<view></view>
</view> </view>
</view> </view>
</uni-card> <view style="width: 100%;display: flex;align-items: center;justify-content: center;">
<view style="width: 90%;">
<view
style="color: #000000;font-family: PingFang SC, PingFang SC;font-weight: 500;font-size: 28rpx;text-align: left;font-style: normal;text-transform: none;">
{{item.description}}
</view>
<view
style="font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 18rpx;color: #575757;text-align: left;font-style: normal;text-transform: none;">
{{item.time}}
</view>
<view
style="font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 18rpx;color: #575757;text-align: left;font-style: normal;text-transform: none;">
{{item.room}}
</view>
<view
style="font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 18rpx;color: #575757;text-align: left;font-style: normal;text-transform: none;">
{{item.requirements}}
</view>
</view>
</view>
</view>
</view> </view>
</template> </template>
<script setup> <script setup>
import { defineProps, defineEmits, computed } from 'vue' import {
defineProps,
defineEmits,
computed
} from 'vue'
// props // props
const props = defineProps({ const props = defineProps({
item: { item: {
type: Object, type: Object,
required: true, required: true,
default: () => ({ default: () => ({
id: '', id: '',
status: '', status: '',
description: '', description: '',
time: '', time: '',
room: '', room: '',
requirements: '', requirements: '',
personCount: 4,// personCount: 4, //
joinPerson: [ joinPerson: [{
{
id: 1, id: 1,
name: '张三', name: '张三',
avatar: '', avatar: '',
phone: '', phone: '',
} }], //
],// })
})
}
})
// emits
const emit = defineEmits(['click', 'join'])
//
const playerPositions = computed(() => {
const { personCount, joinPerson } = props.item
const joinedCount = joinPerson.length
//
if (personCount === 2) {
// 2
return {
positions: [null, joinPerson[0] || null, joinPerson[1] || null, null],
joinPositions: [null, !joinPerson[0], !joinPerson[1], null]
} }
} else if (personCount === 3) { })
// 3
return { // emits
positions: [joinPerson[2] || null, joinPerson[0] || null, joinPerson[1] || null, null], const emit = defineEmits(['click', 'join'])
joinPositions: [!joinPerson[2], !joinPerson[0], !joinPerson[1], null]
//
const playerPositions = computed(() => {
const {
personCount,
joinPerson
} = props.item
const joinedCount = joinPerson.length
//
if (personCount === 2) {
// 2
return {
positions: [null, joinPerson[0] || null, joinPerson[1] || null, null],
joinPositions: [null, !joinPerson[0], !joinPerson[1], null]
}
} else if (personCount === 3) {
// 3
return {
positions: [joinPerson[2] || null, joinPerson[0] || null, joinPerson[1] || null, null],
joinPositions: [!joinPerson[2], !joinPerson[0], !joinPerson[1], null]
}
} else {
// 4
return {
positions: [
joinPerson[2] || null, //
joinPerson[0] || null, //
joinPerson[1] || null, //
joinPerson[3] || null //
],
joinPositions: [
!joinPerson[2], //
!joinPerson[0], //
!joinPerson[1], //
!joinPerson[3] //
]
}
} }
} else { })
// 4
return { //
positions: [ const getPlayerAtPosition = (position) => {
joinPerson[2] || null, // return playerPositions.value.positions[position]
joinPerson[0] || null, // }
joinPerson[1] || null, //
joinPerson[3] || null // //
], const canJoinAtPosition = (position) => {
joinPositions: [ const {
!joinPerson[2], // personCount,
!joinPerson[0], // joinPerson
!joinPerson[1], // } = props.item
!joinPerson[3] // const joinedCount = joinPerson.length
]
//
if (joinedCount >= personCount) {
return false
} }
}
})
// // 使 joinPositions
const getPlayerAtPosition = (position) => { return playerPositions.value.joinPositions[position]
return playerPositions.value.positions[position]
}
//
const canJoinAtPosition = (position) => {
const { personCount, joinPerson } = props.item
const joinedCount = joinPerson.length
//
if (joinedCount >= personCount) {
return false
} }
// 使 joinPositions //
return playerPositions.value.joinPositions[position] const getCellClass = (position) => {
} if (getPlayerAtPosition(position)) {
return 'player-cell'
// } else if (canJoinAtPosition(position)) {
const getCellClass = (position) => { return 'join-cell'
if (getPlayerAtPosition(position)) { }
return 'player-cell' return ''
} else if (canJoinAtPosition(position)) {
return 'join-cell'
} }
return ''
}
// //
const handleCardClick = () => { const handleCardClick = () => {
emit('click', props.item) emit('click', props.item)
} }
// //
const handleJoin = () => { const handleJoin = () => {
emit('join', props.item) emit('join', props.item)
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.item-content { .grid {
height: 540rpx; width: 100%;
color: white; display: flex;
border-radius: 10rpx; align-content: center;
font-size: 32rpx; justify-content: center;
} }
.mahjong-table { .grid-item {
width: 100%; width: 320rpx;
background-color: #D4D4D4; height: 400rpx;
border-radius: 10rpx 10rpx 0 0; background: #FFFFFF;
display: flex; box-shadow: -4rpx 12rpx 7rpx 0rpx rgba(0, 0, 0, 0.25);
justify-content: center; border-radius: 27rpx 27rpx 27rpx 27rpx;
} border: 4rpx solid #006C1A
}
.status-tag { .item-content {
position: absolute; height: 540rpx;
left: 15rpx; color: white;
top: 15rpx; border-radius: 10rpx;
font-size: 16rpx; font-size: 32rpx;
color: black; }
z-index: 10;
}
/* 九宫格容器 */ .item {
.nine-grid-container { display: flex;
display: grid; align-content: center;
grid-template-columns: 1fr 1fr 1fr; justify-content: center;
grid-template-rows: 1fr 1fr 1fr; align-items: center;
width: 100%; }
height: 100%;
padding: 20rpx;
box-sizing: border-box;
}
/* 网格单元格 */ .item-avatar {
.grid-cell { width: 60rpx;
display: flex; height: 60rpx;
align-items: center; background-color: #60AA72;
justify-content: center; border-radius: 50rpx;
position: relative; }
}
/* 玩家头像单元格 */ .mahjong-table {
.player-cell { width: 100%;
display: flex; background-color: #D4D4D4;
align-items: center; border-radius: 10rpx 10rpx 0 0;
justify-content: center; display: flex;
} justify-content: center;
}
/* 中心单元格(麻将桌) */ .status-tag {
.center-cell { position: absolute;
display: flex; left: 15rpx;
align-items: center; top: 15rpx;
justify-content: center; font-size: 16rpx;
} color: black;
z-index: 10;
}
/* 加入按钮单元格 */ /* 九宫格容器 */
.join-cell { .nine-grid-container {
display: flex; display: grid;
align-items: center; grid-template-columns: 1fr 1fr 1fr;
justify-content: center; grid-template-rows: 1fr 1fr 1fr;
} width: 100%;
height: 100%;
box-sizing: border-box;
background: url('@@:app/static/index_logo.png') no-repeat center center;
background-size: 50%;
}
/* 麻将桌背景图 */ /* 网格单元格 */
.table-bg { .grid-cell {
width: 80rpx; display: flex;
height: 80rpx; align-items: center;
} justify-content: center;
position: relative;
}
/* 玩家头像 */ /* 玩家头像单元格 */
.player-avatar { .player-cell {
width: 60rpx; display: flex;
height: 60rpx; align-items: center;
background-color: white; justify-content: center;
border-radius: 50%; }
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.avatar-img { /* 中心单元格(麻将桌) */
width: 100%; .center-cell {
height: 100%; display: flex;
background-color: aqua; align-items: center;
border-radius: 50%; justify-content: center;
} }
/* 加入按钮 */ /* 加入按钮单元格 */
.join-button { .join-cell {
width: 60rpx; display: flex;
height: 60rpx; align-items: center;
background-color: white; justify-content: center;
border-radius: 50%; }
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.3s ease;
}
.join-button:hover { /* 麻将桌背景图 */
transform: scale(1.1); .table-bg {
background-color: #f0f0f0; width: 80rpx;
} height: 80rpx;
}
.join-text { /* 玩家头像 */
color: black; .player-avatar {
font-size: 24rpx; width: 60rpx;
font-weight: bold; height: 60rpx;
} background-color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.info-section { .avatar-img {
padding: 10rpx;
}
.info-text { border-radius: 50%;
font-size: 24rpx; width: 60rpx;
color: black; height: 60rpx;
display: block; }
}
</style> /* 加入按钮 */
.join-button {
width: 60rpx;
height: 60rpx;
background-color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.3s ease;
}
.join-button:hover {
transform: scale(1.1);
background-color: #f0f0f0;
}
.join-text {
color: black;
font-size: 24rpx;
font-weight: bold;
}
.info-section {
padding: 10rpx;
}
.info-text {
font-size: 24rpx;
color: black;
display: block;
}
</style>

View File

@ -4,10 +4,13 @@
<z-paging ref="pagePaging" v-model="dataList" @query="queryList" :refresher-enabled="true" <z-paging ref="pagePaging" v-model="dataList" @query="queryList" :refresher-enabled="true"
:loading-more-enabled="true" :auto="true" :empty-view-text="'暂无麻将局数据'" :empty-view-img="'/static/empty.png'" :loading-more-enabled="true" :auto="true" :empty-view-text="'暂无麻将局数据'" :empty-view-img="'/static/empty.png'"
:refresher-threshold="80" :loading-more-threshold="50" style="flex: 1; width: 95%; margin-top: 10rpx;"> :refresher-threshold="80" :loading-more-threshold="50" style="flex: 1; width: 95%; margin-top: 10rpx;">
<view style="z-index: 100;position: sticky;top :0;"> <template #top>
<view :style="{ height: statusBarHeight + 'px' }" style="background-color: #fff;" class="status-bar"> <view style="z-index: 100;position: sticky;top :0;">
<view :style="{ height: statusBarHeight + 'px' }" style="background-color: #fff;"
class="status-bar">
</view>
</view> </view>
</view> </template>
<view style="z-index: 100;margin-top:10rpx;height:532rpx;"> <view style="z-index: 100;margin-top:10rpx;height:532rpx;">
<view style="width: 100%;width:100%;display:flex;justify-content: center;" <view style="width: 100%;width:100%;display:flex;justify-content: center;"
@ -16,7 +19,8 @@
<swiper class="img-swiper" :indicator-dots="false" circular autoplay interval="3000"> <swiper class="img-swiper" :indicator-dots="false" circular autoplay interval="3000">
<swiper-item v-for="(item, index) in homeData.advertList" :key="index"> <swiper-item v-for="(item, index) in homeData.advertList" :key="index">
<image :src="item.imageUrl" mode="scaleToFill" class="slide-img" <image :src="item.imageUrl" mode="scaleToFill" class="slide-img"
style="border-radius:25rpx;"> </image> style="border-radius:25rpx;">
</image>
</swiper-item> </swiper-item>
</swiper> </swiper>
</view> </view>
@ -174,195 +178,195 @@
</template> </template>
<script setup> <script setup>
import { import {
ref, ref,
reactive, reactive,
onMounted onMounted
} from 'vue' } from 'vue'
import zPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue' import zPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
import MahjongCard from '@/components/index/MahjongCard.vue' import MahjongCard from '@/components/index/MahjongCard.vue'
import { import {
homeData, homeData,
preloadHomeData preloadHomeData
} from '@/common/server/index' } from '@/common/server/index'
import { import {
configData, configData,
getConfigData, getConfigData,
preloadConfigData preloadConfigData
} from '@/common/server/config' } from '@/common/server/config'
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight); const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight);
const getBackgroundImg = () => { const getBackgroundImg = () => {
return { return {
background: `url(${configData.value.config.defaultImage}) 100% 100% `, background: `url(${configData.value.config.defaultImage}) 100% 100% `,
backgroundSize: '100%', backgroundSize: '100%',
backgroundRepeat: "no-repeat", backgroundRepeat: "no-repeat",
backgroundRepeatX: "0px", backgroundRepeatX: "0px",
backgroundSize: "100%", backgroundSize: "100%",
backgroundRepeatY: "0px", backgroundRepeatY: "0px",
backgroundPositionX: "0px", backgroundPositionX: "0px",
backgroundPositionY: statusBarHeight.value + "px", backgroundPositionY: statusBarHeight.value + "px",
}; };
} }
// //
const title = ref('Hello') const title = ref('Hello')
const imgList = ref([1, 2, 3, 4, 5]) const imgList = ref([1, 2, 3, 4, 5])
const dataList = ref([]) // const dataList = ref([]) //
const rateValue = ref(3.5) const rateValue = ref(3.5)
const mockData = ref([]) // const mockData = ref([]) //
// //
const pagePaging = ref(null) const pagePaging = ref(null)
const cardInfo = ref(null) const cardInfo = ref(null)
const userInfo = ref(null) const userInfo = ref(null)
// //
const initMockData = () => { const initMockData = () => {
mockData.value = [] mockData.value = []
for (let i = 1; i <= 50; i++) { for (let i = 1; i <= 50; i++) {
// //
const personCount = [2, 3, 4][Math.floor(Math.random() * 3)] const personCount = [2, 3, 4][Math.floor(Math.random() * 3)]
const joinedCount = Math.floor(Math.random() * (personCount + 1)) const joinedCount = Math.floor(Math.random() * (personCount + 1))
// //
const joinPerson = [] const joinPerson = []
for (let j = 0; j < joinedCount; j++) { for (let j = 0; j < joinedCount; j++) {
joinPerson.push({ joinPerson.push({
id: j + 1, id: j + 1,
name: `玩家${j + 1}`, name: `玩家${j + 1}`,
avatar: '', avatar: '',
phone: `138****${String(j + 1).padStart(4, '0')}` phone: `138****${String(j + 1).padStart(4, '0')}`
})
}
mockData.value.push({
id: i,
title: `麻将局 ${i}`,
status: joinedCount >= personCount ? '已满员' : '组局中',
time: '2000 ~ 0430 共8小时30分钟',
room: `304包厢-大包,${personCount}`,
description: '休闲局,随便来',
requirements: '麻将、斗地主、不可吸烟、性别不限、信誉≧4.0',
personCount: personCount,
joinPerson: joinPerson
}) })
} }
}
// mockData.value.push({
const queryList = (pageNo, pageSize) => { id: i,
console.log(`加载第${pageNo}页,每页${pageSize}条数据`) title: `麻将局 ${i}`,
status: joinedCount >= personCount ? '已满员' : '组局中',
// time: '2000 ~ 0430 共8小时30分钟',
setTimeout(() => { room: `304包厢-大包,${personCount}`,
const startIndex = (pageNo - 1) * pageSize description: '休闲局,随便来',
const endIndex = startIndex + pageSize requirements: '麻将、斗地主、不可吸烟、性别不限、信誉≧4.0',
const pageData = mockData.value.slice(startIndex, endIndex) personCount: personCount,
joinPerson: joinPerson
// z-paging
pagePaging.value.complete(pageData)
//
// if (pageNo === 1) {
// uni.showToast({
// title: '',
// icon: 'success',
// duration: 1500
// })
// }
}, 100) // 1
}
//
const refreshData = () => {
pagePaging.value.reload()
}
//
const clearData = () => {
pagePaging.value.clear()
}
//
const openPop = () => {
cardInfo.value.open()
}
const clasePop = () => {
cardInfo.value.close()
}
const openUserPop = () => {
userInfo.value.open()
}
const closeUserPop = () => {
userInfo.value.close()
}
const onChange = (e) => {
console.log('rate发生改变:' + JSON.stringify(e))
}
//
const handleJoin = (item) => {
console.log('加入麻将局:', item)
// API
uni.showToast({
title: '加入成功',
icon: 'success',
duration: 1500
}) })
} }
}
// //
onMounted(() => { const queryList = (pageNo, pageSize) => {
// console.log(`加载第${pageNo}页,每页${pageSize}条数据`)
initMockData()
//
setTimeout(() => {
const startIndex = (pageNo - 1) * pageSize
const endIndex = startIndex + pageSize
const pageData = mockData.value.slice(startIndex, endIndex)
// z-paging
pagePaging.value.complete(pageData)
//
// if (pageNo === 1) {
// uni.showToast({
// title: '',
// icon: 'success',
// duration: 1500
// })
// }
}, 100) // 1
}
//
const refreshData = () => {
pagePaging.value.reload()
}
//
const clearData = () => {
pagePaging.value.clear()
}
//
const openPop = () => {
cardInfo.value.open()
}
const clasePop = () => {
cardInfo.value.close()
}
const openUserPop = () => {
userInfo.value.open()
}
const closeUserPop = () => {
userInfo.value.close()
}
const onChange = (e) => {
console.log('rate发生改变:' + JSON.stringify(e))
}
//
const handleJoin = (item) => {
console.log('加入麻将局:', item)
// API
uni.showToast({
title: '加入成功',
icon: 'success',
duration: 1500
}) })
}
onLoad(async () => { //
if (!homeData.value) preloadHomeData(); onMounted(() => {
if (!configData.value) preloadConfigData(); //
}); initMockData()
})
onLoad(async () => {
if (!homeData.value) preloadHomeData();
if (!configData.value) preloadConfigData();
});
</script> </script>
<style lang="scss"> <style lang="scss">
.content { .content {
height: 100vh; height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
} }
.img-swiper { .img-swiper {
width: 100%; width: 100%;
height: 386rpx; height: 386rpx;
} }
.slide-img { .slide-img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
/* 网格容器 - 2列布局 */ /* 网格容器 - 2列布局 */
.grid-container { .grid-container {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
/* 2列每列宽度相等 */ /* 2列每列宽度相等 */
gap: 20rpx; gap: 20rpx;
/* 网格间距(行列间距相同) */ /* 网格间距(行列间距相同) */
padding: 0 15rpx; padding: 0 15rpx;
} }
/* 网格项内容 */ /* 网格项内容 */
.item-content { .item-content {
height: 630rpx; height: 630rpx;
// background-color: #E6E6E6; // background-color: #E6E6E6;
color: white; color: white;
border-radius: 10rpx; border-radius: 10rpx;
font-size: 32rpx; font-size: 32rpx;
} }
</style> </style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB