automated_uniapp/uni_modules/cool-fixtures/components/fix-positioning/fix-positioning.vue

379 lines
8.3 KiB
Vue
Raw Normal View History

2025-01-09 16:40:44 +08:00
<template>
<fix-base-style :styleSpacing="styleSpacing" :styleColor="styleColor" :index="index">
<view class="fix-positioning">
<view :class="[`is-${mode}`]" class="header">
<view class="item">
<view v-if="mode == 'mode-1'">
<view>{{ locationData.name }},{{ locationData.time }}</view>
<view class="mt-10 text-size-m row-center" @click="moreStore">
<cl-icon name="location"></cl-icon>
<text class="mx-6">{{ locationData.store }}</text>
<text class="text-grey">{{ locationData.distance }}</text>
<text class="mx-6">更多门店</text>
<cl-icon name="arrow-bottom"></cl-icon>
</view>
<view></view>
</view>
<view v-if="mode == 'mode-2'" @click="moreStore">
<view class="row-center">
<cl-icon name="location"></cl-icon>
<text class="mx-6">{{ locationData.store }}</text>
<cl-icon name="arrow-right"></cl-icon>
</view>
<view class="mt-10 text-size-m">
<text class="text-grey mx-6">{{ locationData.distance }}</text>
</view>
</view>
<view v-if="mode == 'mode-3'" @click="moreStore">
<view class="row-center">
<cl-icon name="location"></cl-icon>
<text class="mx-6">{{ locationData.address }}</text>
</view>
<view class="mt-10 text-size-m">
<text class="text-grey"></text>
<text class="text-grey mx-6">{{ locationData.store }}</text>
<text class="text-grey">提供</text>
</view>
</view>
</view>
<view class="is-bg" :style="headerBackground"></view>
</view>
<view class="banner" v-if="banner.open">
<swiper
:class="[{ 'is-float': float.open }]"
:style="{ height: `${props.banner.height}rpx` }"
>
<swiper-item v-for="(item, index) in banner.list" :key="index">
<image
:src="item.pic"
:class="[{ 'is-float': float.open }]"
class="banner-item"
:style="{ height: `${props.banner.height}rpx` }"
/>
</swiper-item>
</swiper>
<view class="float" v-if="float.open">
<view class="left" :style="leftStyle" @click="toPath(float.left.link)">
<template v-if="float.left.mode === 'mode-1'">
<image class="icon" mode="widthFix" :src="float.left.icon"></image>
<view class="mt-20 text">{{ float.left.text }}</view>
</template>
</view>
<view class="right" :style="rightStyle" @click="toPath(float.right.link)">
<template v-if="float.right.mode === 'mode-1'">
<image class="icon" mode="widthFix" :src="float.right.icon"></image>
<view class="mt-20 text">{{ float.right.text }}</view>
</template>
</view>
</view>
</view>
</view>
</fix-base-style>
</template>
<script lang="ts" name="fix-positioning" setup>
import { computed, watch, ref, type PropType } from "vue";
import type { Form } from "../../types/form";
import { baseProps } from "../../hooks";
import { useCool, useStore } from "/@/cool";
const props = defineProps({
mode: {
type: String,
default: "",
},
banner: {
type: Object as PropType<{ open: boolean; height: number; list: Form.Banner[] }>,
default: () => {
return {
open: false,
height: 750,
list: [],
};
},
},
float: {
type: Object,
default: () => {
return {
open: false,
left: {
text: "",
mode: "mode-1",
icon: "",
color: "#000",
backgroundColor: "#FFFFFF",
link: {
name: "",
type: "",
appid: "",
page: "",
},
},
right: {
text: "",
mode: "mode-1",
icon: "",
color: "#000",
backgroundColor: "#FFFFFF",
link: {
name: "",
appid: "",
type: "",
page: "",
},
},
};
},
},
index: {
type: Number,
default: 0,
},
...baseProps,
});
const { service, router } = useCool();
const { user } = useStore();
const emits = defineEmits(["jump"]);
const headerBackground = computed(() => {
return {
opacity: props.styleColor.opacity,
backgroundColor: props.styleColor.backgroundColor,
};
});
const leftStyle = computed(() => {
let url = "";
if (props.float.left.mode === "mode-2") {
url = props.float.left.icon;
}
return {
backgroundColor: props.float.left.backgroundColor,
color: props.float.left.color,
backgroundImage: `url('${url}')`,
};
});
const rightStyle = computed(() => {
let url = "";
if (props.float.right.mode === "mode-2") {
url = props.float.right.icon;
}
return {
backgroundColor: props.float.right.backgroundColor,
color: props.float.right.color,
backgroundImage: `url('${url}')`,
};
});
const locationData = ref({
name: "张大仙",
time: "早上好",
store: "南村番禺店",
distance: "距离你 0.7km",
address: "广州番禺南村镇建奇大厦5号...",
});
watch(
() => props.mode,
async (newValue) => {
locationData.value.time = getTimePeriod();
getStore();
},
{
deep: true,
immediate: true,
},
);
function distanceInMeters(distanceInKilometers: number) {
let dis = "0m";
if (distanceInKilometers < 1) {
// 如果距离小于1公里将其转换为米1公里 = 1000米
dis = Math.floor(distanceInKilometers * 1000) + "m";
} else {
dis = distanceInKilometers + "km";
}
return "距离你 " + dis;
}
function getTimePeriod() {
const now = new Date();
const hours = now.getHours();
if (hours >= 5 && hours < 12) {
return "早上好!"; // 5:00 - 11:59
} else if (hours >= 12 && hours < 14) {
return "中午好!"; // 12:00 - 13:59
} else if (hours >= 14 && hours < 18) {
return "下午好!"; // 14:00 - 17:59
} else if (hours >= 18 && hours < 24) {
return "晚上好!"; // 18:00 - 23:59
} else {
return "深夜好!"; // 00:00 - 4:59
}
}
function getStore() {
uni.getLocation({
type: "wgs84",
success(res) {
service.store.sample
.vicinity({
...res,
size: 1,
page: 1,
})
.then((res: any) => {
if (res.list.length) {
const { intact, sampleName, distance } = res.list[0];
locationData.value.distance = distanceInMeters(distance);
locationData.value.store = sampleName;
locationData.value.address = intact;
locationData.value.name = user.info?.nickName || "游客";
}
});
},
fail(result) {
// 第一次拒绝后,下次点击提示打开设置授权弹窗
uni.showModal({
title: "定位获取失败",
content: "附近门店查找失败,是否去设置授权打开?",
success(modal: any) {
if (modal.confirm) {
uni.openSetting({
success: (res) => {},
});
}
},
});
},
});
}
function moreStore() {
router.push("/pages/partnership/sample/vicinity");
}
function toPath(link: Form.Link) {
emits("jump", link);
}
</script>
<style lang="scss" scoped>
.fix-positioning {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
min-height: 140rpx;
overflow: hidden;
position: relative;
box-sizing: border-box;
.header {
position: absolute;
top: 0;
width: 100%;
padding: 20rpx;
box-sizing: border-box;
min-height: 140rpx;
.is-bg {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 1;
}
.item {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 2;
padding: 20rpx;
}
}
.banner {
width: 100%;
height: 100%;
position: relative;
.banner-item {
width: 750rpx;
max-width: 100%;
min-height: 750rpx;
height: 100%;
}
.float {
display: flex;
justify-content: center;
position: absolute;
bottom: 20rpx;
left: 20rpx;
right: 20rpx;
.left {
margin-right: 30rpx;
}
.right {
margin-left: 30rpx;
}
.left,
.right {
width: 240rpx;
height: 280rpx;
border-radius: 12rpx;
background-size: 100% 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.text {
font-size: 32rpx;
font-family: PingFang SC;
font-weight: bold;
}
.icon {
width: 140rpx;
height: 140rpx;
}
}
}
}
.is-mode-4 {
display: none;
}
.row-center {
display: flex;
align-items: center;
}
.flex-1 {
flex: 1;
}
.is-float {
min-height: 750rpx;
:deep(.uni-swiper-wrapper) {
overflow: inherit !important;
}
}
.mt-20 {
margin-top: 20rpx;
}
.mt-10 {
margin-top: 10rpx;
}
.text-size-m {
font-size: 24rpx;
}
.mx-6 {
margin: 0 6rpx;
}
.text-grey {
color: #9e9e9e;
}
}
</style>