Browse Source

feat: 兼容4k

ShangHai_LongXiang
jiannibang 2 years ago
parent
commit
0708d14013
  1. BIN
      public/static/img/guide.glb
  2. BIN
      public/static/img/zhong.glb
  3. 4
      src/components/QRCodeFromText/QRCodeFromText.vue
  4. 5
      src/components/Search/Search.vue
  5. 14
      src/components/Written/Written.vue
  6. 11
      src/composables/useInitConfigAndMallInfo.js
  7. 20
      src/views/Billboard/Billboard.vue
  8. 2
      webpack/loaders/retina-loader.js

BIN
public/static/img/guide.glb

Binary file not shown.

BIN
public/static/img/zhong.glb

Binary file not shown.

4
src/components/QRCodeFromText/QRCodeFromText.vue

@ -1,11 +1,13 @@
<template> <template>
<div> <div>
<img :src="qrcode" alt="QR Code" :style="`width: ${size}px;height: ${size}px`" />
<img :src="qrcode" alt="QR Code" :style="`width: ${computedSize}vmin;height: ${computedSize}vmin`" />
</div> </div>
</template> </template>
<script setup> <script setup>
import { useQRCode } from '@vueuse/integrations/useQRCode' import { useQRCode } from '@vueuse/integrations/useQRCode'
import { computed } from 'vue'
const props = defineProps({ size: Number, text: String }) const props = defineProps({ size: Number, text: String })
const qrcode = useQRCode(props.text, { errorCorrectionLevel: 'L', margin: 0 }) const qrcode = useQRCode(props.text, { errorCorrectionLevel: 'L', margin: 0 })
const computedSize = computed(() => (props.size / 1080) * 100)
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

5
src/components/Search/Search.vue

@ -239,6 +239,7 @@ function close() {
justify-content: center; justify-content: center;
color: var(--search-tabColor, rgba(0, 0, 0, 0.6)); color: var(--search-tabColor, rgba(0, 0, 0, 0.6));
border-radius: var(--global-radius, 12px); border-radius: var(--global-radius, 12px);
font-size: 16px;
&.active { &.active {
background: var(--search-tabActiveBg, #ffffff); background: var(--search-tabActiveBg, #ffffff);
color: var(--search-tabActiveColor, rgba(0, 0, 0, 0.8)); color: var(--search-tabActiveColor, rgba(0, 0, 0, 0.8));
@ -266,6 +267,10 @@ function close() {
padding-left: 56px; padding-left: 56px;
.title { .title {
color: var(--search-hotSearchTitleColor); color: var(--search-hotSearchTitleColor);
font-size: 24px;
font-style: normal;
font-weight: 900;
line-height: normal;
} }
.hot-scroll { .hot-scroll {
padding-top: 16px; padding-top: 16px;

14
src/components/Written/Written.vue

@ -1,11 +1,17 @@
<template> <template>
<canvas :style="{ backgroundColor: backgroundColor, borderRadius: borderRadius }" ref="inkCanvasRef" :width="width" :height="height" id="ink-canvas"></canvas>
<canvas
:style="{ backgroundColor: backgroundColor, borderRadius: borderRadius }"
ref="inkCanvasRef"
:width="width * scale"
:height="height * scale"
id="ink-canvas"
></canvas>
</template> </template>
<script setup> <script setup>
import { reactive, computed, onMounted, onBeforeUnmount, watch, ref } from 'vue' import { reactive, computed, onMounted, onBeforeUnmount, watch, ref } from 'vue'
import { getHandWriting } from '@/http/api' import { getHandWriting } from '@/http/api'
const scale = Math.min(window.innerWidth, window.innerHeight) / 1080
const props = defineProps({ const props = defineProps({
width: { width: {
type: Number, type: Number,
@ -127,11 +133,11 @@ function reload() {
state.clickC = [] state.clickC = []
ctxRef.value.strokeStyle = props.strokeStyle ctxRef.value.strokeStyle = props.strokeStyle
ctxRef.value.fillStyle = props.fillStyle ctxRef.value.fillStyle = props.fillStyle
ctxRef.value.clearRect(0, 0, props.width, props.height)
ctxRef.value.clearRect(0, 0, props.width * scale, props.height * scale)
ctxRef.value.font = `bold ${props.fillFontSize} Arial` ctxRef.value.font = `bold ${props.fillFontSize} Arial`
ctxRef.value.textAlign = 'center' ctxRef.value.textAlign = 'center'
ctxRef.value.textBaseline = 'middle' ctxRef.value.textBaseline = 'middle'
ctxRef.value.fillText(props.fillText, props.width / 2, props.height / 2, 1000)
ctxRef.value.fillText(props.fillText, (props.width / 2) * scale, (props.height / 2) * scale, 1000)
} }
function _getHandWriting() { function _getHandWriting() {
const params = { const params = {

11
src/composables/useInitConfigAndMallInfo.js

@ -1,6 +1,7 @@
import { getConfig, getCurrentFloor, getGuideList, getTheme, getQMGoShopData, getMenuList, getFoodIIndustryList, getWeather } from '@/http/api' import { getConfig, getCurrentFloor, getGuideList, getTheme, getQMGoShopData, getMenuList, getFoodIIndustryList, getWeather } from '@/http/api'
import { useStore } from '@/store/root' import { useStore } from '@/store/root'
import VConsole from 'vconsole' import VConsole from 'vconsole'
const matchPXExp = /([0-9.]+px)/g
export const useInitConfigAndMallInfo = async () => { export const useInitConfigAndMallInfo = async () => {
const { const {
@ -13,7 +14,15 @@ export const useInitConfigAndMallInfo = async () => {
const r = document.querySelector(':root') const r = document.querySelector(':root')
Object.entries(theme).forEach(([cat, obj]) => { Object.entries(theme).forEach(([cat, obj]) => {
Object.entries(obj).forEach(([k, v]) => r.style.setProperty(`--${cat}-${k}`, v))
Object.entries(obj).forEach(([k, v]) =>
r.style.setProperty(
`--${cat}-${k}`,
v.replace(matchPXExp, (_match, m1) => {
const pixels = Number(m1.slice(0, m1.length - 2))
return (pixels / 1080) * 100 + 'vmin'
})
)
)
}) })
theme.images = Object.entries(theme.image) theme.images = Object.entries(theme.image)
.map(([k, v]) => [k, './static/offline' + v]) .map(([k, v]) => [k, './static/offline' + v])

20
src/views/Billboard/Billboard.vue

@ -8,11 +8,16 @@
<div <div
class="list" class="list"
:style="{ :style="{
height: `${columnHeight}px`,
width: `${(isH ? 286 : 484) * Math.ceil(columns.length / 2) * 2 + (isH ? 38 : 68)}px`
height: `${(columnHeight / scale / 1080) * 100}vmin`,
width: `${(((isH ? 286 : 484) * Math.ceil(columns.length / 2) * 2 + (isH ? 38 : 68)) / 1080) * 100}vmin`
}" }"
> >
<div v-for="(col, i) of columns" :key="'col' + i" class="column" :style="{ height: `${columnHeight}px`, opacity: Math.floor(i / 2) === index ? 1 : 0.5 }">
<div
v-for="(col, i) of columns"
:key="'col' + i"
class="column"
:style="{ height: `${(columnHeight / scale / 1080) * 100}vmin`, opacity: Math.floor(i / 2) === index ? 1 : 0.5 }"
>
<template v-for="(data, j) of col.list"> <template v-for="(data, j) of col.list">
<div v-if="data.type === 'format'" class="format" :key="data.name"> <div v-if="data.type === 'format'" class="format" :key="data.name">
{{ data.name }} {{ data.name }}
@ -71,11 +76,12 @@ import { getBrandListByFormat } from '@/http/brand/api'
import QRCodeFromText from '@/components/QRCodeFromText/QRCodeFromText.vue' import QRCodeFromText from '@/components/QRCodeFromText/QRCodeFromText.vue'
import { useMediaQuery, useWindowSize } from '@vueuse/core' import { useMediaQuery, useWindowSize } from '@vueuse/core'
import { setShopInactive } from '@/composables/useInitMap' import { setShopInactive } from '@/composables/useInitMap'
const vmin = Math.min(window.innerWidth, window.innerHeight)
const scale = vmin / 1080
const isH = useMediaQuery('(min-aspect-ratio: 1/1)') const isH = useMediaQuery('(min-aspect-ratio: 1/1)')
const { width } = useWindowSize() const { width } = useWindowSize()
const timeout = 30000 const timeout = 30000
const heights = { shop: 44, format: 49, placeholder: 40 }
const heights = { shop: 44 * scale, format: 49 * scale, placeholder: 40 * scale }
const setValue = refInstance => value => Object.assign(refInstance, { value }) const setValue = refInstance => value => Object.assign(refInstance, { value })
const store = useStore() const store = useStore()
const router = useRouter() const router = useRouter()
@ -96,7 +102,7 @@ const remainingMinutes = ref(Math.ceil(timeout / 1000))
const setRemainingMinutes = setValue(remainingMinutes) const setRemainingMinutes = setValue(remainingMinutes)
const showBullets = computed(() => scrollLefts.value.length > 1) const showBullets = computed(() => scrollLefts.value.length > 1)
const columnHeight = computed(() => (isH.value ? 706 : 746))
const columnHeight = computed(() => (isH.value ? 706 : 746) * scale)
Promise.all([getBrandListByFormat()]).then(([{ data: brandListByFormat }]) => { Promise.all([getBrandListByFormat()]).then(([{ data: brandListByFormat }]) => {
shops.value = brandListByFormat.list.map(brand => { shops.value = brandListByFormat.list.map(brand => {
@ -212,7 +218,7 @@ watch(index, (nxt, _, onCleanup) => {
watch(scrollWidth, _scrollWidth => { watch(scrollWidth, _scrollWidth => {
if (_scrollWidth > 0) { if (_scrollWidth > 0) {
const list = Array.from(document.querySelectorAll('.shop')) const list = Array.from(document.querySelectorAll('.shop'))
.map(el => el.getBoundingClientRect().left - (isH.value ? 1326 : 68))
.map(el => el.getBoundingClientRect().left - (isH.value ? 1326 : 68) * scale)
.reduce((acc, nxt) => { .reduce((acc, nxt) => {
const last = acc[acc.length - 1] const last = acc[acc.length - 1]
return nxt === last ? acc : [...acc, nxt] return nxt === last ? acc : [...acc, nxt]

2
webpack/loaders/retina-loader.js

@ -10,6 +10,6 @@ module.exports = function (source) {
return source.replace(matchPXExp, (_match, m1) => { return source.replace(matchPXExp, (_match, m1) => {
const pixels = Number(m1.slice(0, m1.length - 2)) const pixels = Number(m1.slice(0, m1.length - 2))
return pixels * 2 + 'px'
return (pixels / 1080) * 100 + 'vmin'
}) })
} }

Loading…
Cancel
Save