nailart/na-frontend/src/pages/HomePage.vue
2025-08-18 00:04:55 +08:00

440 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="homepage">
<!-- 固定顶部导航栏 -->
<NavBar class="nav-bar" />
<div class="images">
<van-swipe class="swipe" :autoplay="2000" indicator-color="white">
<van-swipe-item v-for="(image, index) in info.headImgs" :key="index">
<img fill="contain" v-lazy="image.url" />
</van-swipe-item>
</van-swipe>
</div>
<div class="info">
<div class="title">
<div class="name">{{ info.name }}</div>
<div class="environment" @click="showEnvironmentPopup = true">
<span>查看店内环境</span>
</div>
</div>
<van-divider />
<div class="worktime">
<div>{{ info.status }} {{ info.worktime }}</div>
</div>
<van-divider />
<div class="location">
<div class="left">
<span style="color: black; font-size: 15px;">{{ info.location }}</span>
<br>
<van-icon name="location-o" size="12" />
<span>距您驾车或者打车8.0公里 需10分钟</span>
<br>
<van-icon name="guide-o" size="12" />
<span>距离1号线微电园站1号口步行400米 需8分钟</span>
</div>
<div class="right">
<van-icon name="wechat" size="25" @click="clickWechatAndPhone('wechat')" />
<van-icon name="phone" size="25" @click="clickWechatAndPhone('phone')" />
</div>
</div>
</div>
<van-divider>新品展示</van-divider>
<div class="new">
<van-swipe class="swipe" :autoplay="2000" indicator-color="white">
<van-swipe-item v-for="(image, index) in info.newPortfolioImgs" :key="index">
<img fill="contain" v-lazy="image.url" />
</van-swipe-item>
</van-swipe>
</div>
<van-popup v-model="showEnvironmentPopup" position="bottom" closeable style="height: 50vh;">
<div class="environment-images">
<van-swipe class="swipe" :autoplay="2000" indicator-color="white">
<van-swipe-item v-for="(image, index) in info.environmentImgs" :key="index">
<img fill="contain" v-lazy="image.url" />
</van-swipe-item>
</van-swipe>
</div>
</van-popup>
<van-overlay :show="showpublicityImg" @click="show = false">
<div class="wrapper" @click.stop>
<div class="block">
<img v-lazy="info.publicityImg.length > 0 ? info.publicityImg[0].url : ''" />
<div class="coress">
<van-icon name="add" @click="showpublicityImg = false" size="24" style="transform: rotate(45deg)"
color="white" />
</div>
</div>
</div>
</van-overlay>
<div style="height: 200px;"></div>
<!-- 固定底部TabBar -->
<TabBar class="tab-bar" />
</div>
</template>
<script>
import TabBar from '@/components/TabBar.vue';
import NavBar from '@/components/NavBar.vue';
export default {
name: 'HomePage',
components: {
TabBar,
NavBar
},
props: {},
data() {
return {
info: {
id: 1,
headImgs: [],
guide: '距离1号线微电园站1号口步行400米 需8分钟',
wechat: '',
phone: '',
newPortfolioImgs: [],
locationImgs: [],
environmentImgs: [
],
publicityImg: [],
status: ""
},
storageUrl: 'http://xiaowangnas.com:9000/yumiartnail',
showEnvironmentPopup: false,
showpublicityImg: false,
};
},
watch: {},
computed: {},
methods: {
async getInfo() {
const res = await this.$axios.get('/mainInfo/getMainInfo');
if (res.code == 200) {
this.id = res.data.id;
this.info.headImgs = this.convertToObjectArray(res.data.headImg.split('&&'));
this.info.name = res.data.name;
this.info.status = res.data.status == 0 ? '休息中' : '营业中';
this.info.worktime = res.data.worktime;
this.info.location = res.data.address;
this.info.wechat = res.data.wechat;
this.info.phone = res.data.phone;
this.info.locationImgs = this.convertToObjectArray(res.data.locationImg.split('&&'));
this.info.newPortfolioImgs = this.convertToObjectArray(res.data.newPortfolioImg.split('&&'));
this.info.environmentImgs = this.convertToObjectArray(res.data.environmentImg.split('&&'));
this.info.publicityImg = [{ url: this.storageUrl + res.data.publicityImg }];
}
if (this.info.publicityImg.length > 0) {
this.showpublicityImg = true;
} else {
this.showpublicityImg = false;
}
console.log(this.info);
},
convertToObjectArray(urls) {
return urls.map(url => {
if (!url) return { url: '' }; // 处理空字符串
const modifiedUrl = this.storageUrl + url;
return { url: modifiedUrl }
});
},
convertUrlsToString(arr) {
return arr.map(item => {
let modifiedUrl = item.url.replace(this.storageUrl, '');
return modifiedUrl;
}).join('&&');
},
clickWechatAndPhone(type) {
this.$dialog.confirm({
title: type == 'wechat' ? '微信号' : '电话号码',
message: type == 'wechat' ? this.info.wechat : this.info.phone,
confirmButtonText: '一键复制',
})
.then(() => {
this.textToCopy = type == 'wechat' ? this.info.wechat : this.info.phone;
this.handleCopy();
})
.catch(() => {
// on cancel
});
},
async handleCopy() {
try {
// 首先检查是否支持navigator.clipboard
if (navigator.clipboard) {
// 请求剪贴板写入权限(适用于需要权限的浏览器)
if ('permissions' in navigator) {
const permissionStatus = await navigator.permissions.query({ name: 'clipboard-write' });
if (permissionStatus.state === 'granted' || (permissionStatus.state === 'prompt' && await permissionStatus.request() === 'granted')) {
await navigator.clipboard.writeText(this.textToCopy);
this.$toast.success('已复制到剪贴板');
} else {
console.error('未获得剪贴板写入权限');
this.$toast.fail('未获得剪贴板写入权限,请手动复制');
}
} else {
// 如果不需要权限请求,直接复制
await navigator.clipboard.writeText(this.textToCopy);
this.$toast.success('已复制到剪贴板');
}
} else {
// 如果不支持navigator.clipboard尝试使用document.execCommand旧方法兼容性更好但有局限性
const textArea = document.createElement('textarea');
textArea.value = this.textToCopy;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
this.$toast.success('已复制到剪贴板');
} catch (err) {
console.error('复制失败:', err);
this.$toast.fail('复制失败,请手动复制');
}
document.body.removeChild(textArea);
}
} catch (err) {
console.error('复制失败:', err);
this.$toast.fail('复制失败,请手动复制');
}
},
// 记录当前时间到localStorage
recordCurrentTime(storageKey = 'recordedTime') {
// 获取当前时间的时间戳(毫秒)
const currentTime = new Date().getTime();
// 存储到localStorage
localStorage.setItem(storageKey, currentTime.toString());
return currentTime;
},
// 从localStorage获取记录的时间并计算与当前时间的差值
getTimeDifference(storageKey = 'recordedTime') {
// 从localStorage获取记录的时间
const storedTimeStr = localStorage.getItem(storageKey);
// 检查是否存在记录
if (!storedTimeStr) {
console.error('没有找到记录的时间');
return null;
}
// 转换为数字类型
const storedTime = parseInt(storedTimeStr, 10);
// 检查转换是否成功
if (isNaN(storedTime)) {
console.error('存储的时间格式不正确');
return null;
}
// 获取当前时间戳
const currentTime = new Date().getTime();
// 计算差值(毫秒)并转换为秒
const differenceInSeconds = Math.floor((currentTime - storedTime) / 1000);
return differenceInSeconds;
}
},
created() {
// 检查是否有记录的时间
const recordedTime = localStorage.getItem('recordedTime');
if (recordedTime) {
// 如果有记录的时间,计算与当前时间的差值
const timeDifference = this.getTimeDifference();
console.log(`与上次记录的时间差为 ${timeDifference}`);
if (timeDifference >= 60 * 60 * 24) {
// 超过24小时执行相应操作
this.recordCurrentTime();
this.showpublicityImg = true;
} else {
// 在24小时内执行相应操作
console.log('在24小时内');
this.showpublicityImg = false;
}
} else {
console.log('没有找到记录的时间');
}
},
mounted() {
this.getInfo();
},
beforeDestroy() {
// 在组件销毁前,可以清理一些资源或状态
this.showEnvironmentPopup = false;
this.showpublicityImg = false;
this.recordCurrentTime();
}
};
</script>
<style lang="less" scoped>
@base-bg: #f9fafb;
@card-bg: white;
@text-primary: #1f2937;
@text-secondary: #6b7280;
@accent-color: #3b82f6;
@accent-dark: #2563eb;
@danger-color: #ef4444;
@gray-light: #d1d5db;
@shadow-base: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
@shadow-active: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
.homepage {
width: 100vw;
height: 100vh;
overflow: auto;
max-width: 800px;
margin: 0 auto;
.images {
width: 100%;
height: 35vh;
overflow: hidden;
min-height: 200px;
max-height: 500px;
.swipe {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
}
.info {
width: 100%;
padding: 10px;
.title {
display: flex;
justify-content: space-between;
align-items: center;
.name {
font-size: 40px;
color: @text-primary;
font-weight: bold;
cursor: pointer;
}
.environment {
cursor: pointer;
span {
font-size: 12px;
color: #525050;
}
}
}
.location {
display: flex;
.left {
width: 70%;
span {
font-size: 12px;
color: #a19e9e;
margin-bottom: 10px;
}
}
.right {
width: 30%;
display: flex;
justify-content: space-evenly;
align-items: center;
color: #a19e9e;
}
}
}
.new {
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
width: 95%;
height: 25vh;
overflow: hidden;
min-height: 200px;
max-height: 500px;
margin: auto;
border-radius: 10px;
.swipe {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
}
.navigation {
width: 100%;
}
.environment-images {
width: 100%;
overflow: hidden;
max-height: 500px;
.swipe {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
}
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
width: 100%;
.block {
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
img {
width: 100%;
object-fit: contain;
border-radius: 10px;
}
.coress {
padding-top: 20px;
}
}
}
}
</style>