automated_uniapp/uni_modules/cool-fixtures/components/fix-positioning/fix-positioning.vue
2025-01-09 16:40:44 +08:00

379 lines
8.3 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>
<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>