基础插件修改
This commit is contained in:
		
							parent
							
								
									d2f735d2f6
								
							
						
					
					
						commit
						28e34c191d
					
				@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style :styleSpacing="styleSpacing" :styleColor="styleColor" :index="index">
 | 
				
			||||||
 | 
							<view class="banner">
 | 
				
			||||||
 | 
								<cl-banner
 | 
				
			||||||
 | 
									:indicatorDots="indicatorDots"
 | 
				
			||||||
 | 
									:list="list"
 | 
				
			||||||
 | 
									:type="mode"
 | 
				
			||||||
 | 
									:height="height"
 | 
				
			||||||
 | 
									:autoplay="autoplay"
 | 
				
			||||||
 | 
									@select="toPath"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<template #item="{ item }">
 | 
				
			||||||
 | 
										<cl-skeleton height="100%" :loading="!item.pic" :loading-style="style">
 | 
				
			||||||
 | 
											<image :style="style" mode="fill" :src="item.pic" />
 | 
				
			||||||
 | 
										</cl-skeleton>
 | 
				
			||||||
 | 
									</template>
 | 
				
			||||||
 | 
								</cl-banner>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup name="fix-banner">
 | 
				
			||||||
 | 
					import { computed, type PropType } from "vue";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					import type { Form } from "../../types/form";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const emits = defineEmits(["jump"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						mode: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						height: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 300,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						autoplay: {
 | 
				
			||||||
 | 
							type: Boolean,
 | 
				
			||||||
 | 
							default: true,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						indicatorDots: Boolean,
 | 
				
			||||||
 | 
						list: {
 | 
				
			||||||
 | 
							type: Array as PropType<Form.Banner[]>,
 | 
				
			||||||
 | 
							default: function () {
 | 
				
			||||||
 | 
								return [];
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toPath(index: number) {
 | 
				
			||||||
 | 
						const link = props.list[index].link;
 | 
				
			||||||
 | 
						emits("jump", link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const style = computed(() => {
 | 
				
			||||||
 | 
						const { borderTopLR, borderBottomLR } = props.styleSpacing;
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							borderRadius: `${borderTopLR}rpx ${borderTopLR}rpx ${borderBottomLR}rpx ${borderBottomLR}rpx`,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.banner {
 | 
				
			||||||
 | 
						margin: 0 auto;
 | 
				
			||||||
 | 
						width: 100%;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						image {
 | 
				
			||||||
 | 
							height: 100%;
 | 
				
			||||||
 | 
							width: 100%;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,135 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view
 | 
				
			||||||
 | 
							:style="{
 | 
				
			||||||
 | 
								paddingTop: seatHeight + 'px',
 | 
				
			||||||
 | 
							}"
 | 
				
			||||||
 | 
							class="layer"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<view
 | 
				
			||||||
 | 
								:style="{
 | 
				
			||||||
 | 
									...basePosition,
 | 
				
			||||||
 | 
									width: '100%',
 | 
				
			||||||
 | 
								}"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<view :style="{ position: 'absolute', ...baseBackground }"></view>
 | 
				
			||||||
 | 
								<view class="fix-base-style" :style="baseStyle" :class="[`fix-base-style-${index}`]">
 | 
				
			||||||
 | 
									<slot></slot>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup name="fix-base-style">
 | 
				
			||||||
 | 
					import { computed, watch, ref, nextTick, getCurrentInstance } from "vue";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { proxy }: any = getCurrentInstance();
 | 
				
			||||||
 | 
					const { statusBarHeight = 0 } = uni.getSystemInfoSync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 定义属性,简化默认对象的写法
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
						// 背景跟随子元素的间距圆角
 | 
				
			||||||
 | 
						flowInner: {
 | 
				
			||||||
 | 
							type: Boolean,
 | 
				
			||||||
 | 
							default: true,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						statusBar: {
 | 
				
			||||||
 | 
							type: Boolean,
 | 
				
			||||||
 | 
							default: false,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 计算 baseStyle,使用解构优化
 | 
				
			||||||
 | 
					const baseStyle = computed(() => {
 | 
				
			||||||
 | 
						const { marginTop, marginBottom, marginLR, padding, borderTopLR, borderBottomLR } =
 | 
				
			||||||
 | 
							props.styleSpacing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const { color } = props.styleColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							margin: `${marginTop}rpx ${marginLR}rpx ${marginBottom}rpx ${marginLR}rpx`,
 | 
				
			||||||
 | 
							color: color,
 | 
				
			||||||
 | 
							padding: `${padding}rpx`,
 | 
				
			||||||
 | 
							borderRadius: `${borderTopLR}rpx ${borderTopLR}rpx ${borderBottomLR}rpx ${borderBottomLR}rpx`,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const baseBackground = computed(() => {
 | 
				
			||||||
 | 
						const { backgroundColor, opacity } = props.styleColor;
 | 
				
			||||||
 | 
						const { marginTop, marginBottom, marginLR, borderTopLR, borderBottomLR } = props.styleSpacing;
 | 
				
			||||||
 | 
						let flow: any = {
 | 
				
			||||||
 | 
							left: 0,
 | 
				
			||||||
 | 
							top: 0,
 | 
				
			||||||
 | 
							right: 0,
 | 
				
			||||||
 | 
							bottom: 0,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						if (props.flowInner) {
 | 
				
			||||||
 | 
							flow = {
 | 
				
			||||||
 | 
								left: `${marginLR}rpx`,
 | 
				
			||||||
 | 
								top: `${marginTop}rpx`,
 | 
				
			||||||
 | 
								right: `${marginLR}rpx`,
 | 
				
			||||||
 | 
								bottom: `${marginBottom}rpx`,
 | 
				
			||||||
 | 
								borderRadius: `${borderTopLR}rpx ${borderTopLR}rpx ${borderBottomLR}rpx ${borderBottomLR}rpx`,
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							backgroundColor: backgroundColor,
 | 
				
			||||||
 | 
							opacity: opacity,
 | 
				
			||||||
 | 
							zIndex: -1,
 | 
				
			||||||
 | 
							...flow,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const basePosition = computed(() => {
 | 
				
			||||||
 | 
						const { top, mode, zIndex } = props.position;
 | 
				
			||||||
 | 
						let topPos = top;
 | 
				
			||||||
 | 
						if (props.statusBar) topPos = topPos + statusBarHeight;
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							top: `${topPos}px`,
 | 
				
			||||||
 | 
							position: mode,
 | 
				
			||||||
 | 
							zIndex: zIndex,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const seatHeight = ref(0);
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
						() => props.position,
 | 
				
			||||||
 | 
						async (position) => {
 | 
				
			||||||
 | 
							if (position.isSeat && position.mode === "fixed") {
 | 
				
			||||||
 | 
								refreshSeat();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							deep: true,
 | 
				
			||||||
 | 
							immediate: true,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function refreshSeat() {
 | 
				
			||||||
 | 
						nextTick(() => {
 | 
				
			||||||
 | 
							uni.createSelectorQuery()
 | 
				
			||||||
 | 
								// #ifndef MP-ALIPAY
 | 
				
			||||||
 | 
								.in(proxy)
 | 
				
			||||||
 | 
								// #endif
 | 
				
			||||||
 | 
								.select(`.fix-base-style-${props.index}`)
 | 
				
			||||||
 | 
								.boundingClientRect((res: any) => {
 | 
				
			||||||
 | 
									seatHeight.value = res.height;
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.exec();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.layer {
 | 
				
			||||||
 | 
						width: 100%;
 | 
				
			||||||
 | 
						position: relative;
 | 
				
			||||||
 | 
						.fix-base-style {
 | 
				
			||||||
 | 
							height: auto;
 | 
				
			||||||
 | 
							box-sizing: border-box;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										221
									
								
								uni_modules/cool-fixtures/components/fix-coupon/fix-coupon.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								uni_modules/cool-fixtures/components/fix-coupon/fix-coupon.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,221 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style
 | 
				
			||||||
 | 
							:styleSpacing="styleSpacing"
 | 
				
			||||||
 | 
							:styleColor="styleColor"
 | 
				
			||||||
 | 
							:position="position"
 | 
				
			||||||
 | 
							:index="index"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<div class="fix-coupon" v-if="item.id" :style="couponStyle">
 | 
				
			||||||
 | 
								<div class="coupon-activity" @tap="toGet">
 | 
				
			||||||
 | 
									<div class="a">
 | 
				
			||||||
 | 
										<div class="text">
 | 
				
			||||||
 | 
											<span class="name">{{ item?.title }}</span>
 | 
				
			||||||
 | 
											<span class="desc">{{ item?.description }}</span>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<span class="tag" v-if="item">点击领券</span>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									<div class="b">
 | 
				
			||||||
 | 
										<template v-if="item">
 | 
				
			||||||
 | 
											<span class="amount">{{ item?.amount || 0 }}</span>
 | 
				
			||||||
 | 
											<span class="doc">
 | 
				
			||||||
 | 
												{{ doc }}
 | 
				
			||||||
 | 
											</span>
 | 
				
			||||||
 | 
										</template>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									<div class="c"></div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-coupon" setup>
 | 
				
			||||||
 | 
					import { computed, type PropType } from "vue";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					import { useCool } from "/@/cool";
 | 
				
			||||||
 | 
					import { useUi } from "/$/cool-ui";
 | 
				
			||||||
 | 
					const { service } = useCool();
 | 
				
			||||||
 | 
					const ui = useUi();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						item: {
 | 
				
			||||||
 | 
							type: Object as PropType<Eps.MarketCouponInfoEntity>,
 | 
				
			||||||
 | 
							default: () => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									id: 0,
 | 
				
			||||||
 | 
									title: "",
 | 
				
			||||||
 | 
									description: "",
 | 
				
			||||||
 | 
									amount: 0,
 | 
				
			||||||
 | 
									type: 0,
 | 
				
			||||||
 | 
									condition: "",
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						color: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "#2b2e3d",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 领取
 | 
				
			||||||
 | 
					function toGet() {
 | 
				
			||||||
 | 
						service.market.coupon.user
 | 
				
			||||||
 | 
							.receive({
 | 
				
			||||||
 | 
								couponId: props.item?.id,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							.then(() => {
 | 
				
			||||||
 | 
								ui.showToast("领取成功");
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							.catch((err) => {
 | 
				
			||||||
 | 
								ui.showToast(err.message);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 将十六进制颜色转换为 RGB
 | 
				
			||||||
 | 
					 * @param  hex - 十六进制颜色代码 (例如: #2b2e3d)
 | 
				
			||||||
 | 
					 * @returns - RGB 颜色字符串 (例如: 43, 46, 61)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function hexToRgb(hex: string) {
 | 
				
			||||||
 | 
						// 移除前导 #
 | 
				
			||||||
 | 
						hex = hex.replace(/^#/, "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 处理 3 位和 6 位十六进制颜色
 | 
				
			||||||
 | 
						if (hex.length === 4) {
 | 
				
			||||||
 | 
							hex = hex
 | 
				
			||||||
 | 
								.split("")
 | 
				
			||||||
 | 
								.map((char: any, index: number) => (index > 0 ? char + char : char))
 | 
				
			||||||
 | 
								.join("");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const bigint = parseInt(hex, 16);
 | 
				
			||||||
 | 
						return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255].join(", ");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 使用说明
 | 
				
			||||||
 | 
					const doc = computed(() => {
 | 
				
			||||||
 | 
						const { type, condition } = props.item;
 | 
				
			||||||
 | 
						switch (type) {
 | 
				
			||||||
 | 
							case 0:
 | 
				
			||||||
 | 
								return `满${condition?.fullAmount}可用`;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const couponStyle = computed(() => {
 | 
				
			||||||
 | 
						const { color } = props;
 | 
				
			||||||
 | 
						const rgbaColor = hexToRgb(color);
 | 
				
			||||||
 | 
						// 返回样式对象
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							"--coupon-color": rgbaColor,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-coupon {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.coupon-activity {
 | 
				
			||||||
 | 
						display: flex;
 | 
				
			||||||
 | 
						position: relative;
 | 
				
			||||||
 | 
						height: 160rpx;
 | 
				
			||||||
 | 
						letter-spacing: 1rpx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.a {
 | 
				
			||||||
 | 
							background: linear-gradient(
 | 
				
			||||||
 | 
								140deg,
 | 
				
			||||||
 | 
								rgba(var(--coupon-color), 0.75),
 | 
				
			||||||
 | 
								rgba(var(--coupon-color), 1)
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
							height: 140rpx;
 | 
				
			||||||
 | 
							width: calc(100% - 250rpx);
 | 
				
			||||||
 | 
							border-radius: 12rpx;
 | 
				
			||||||
 | 
							position: absolute;
 | 
				
			||||||
 | 
							left: 24rpx;
 | 
				
			||||||
 | 
							bottom: 1rpx;
 | 
				
			||||||
 | 
							z-index: 2;
 | 
				
			||||||
 | 
							color: #fff;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							justify-content: space-between;
 | 
				
			||||||
 | 
							padding: 0 24rpx;
 | 
				
			||||||
 | 
							box-sizing: border-box;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.name {
 | 
				
			||||||
 | 
								display: block;
 | 
				
			||||||
 | 
								font-size: 28rpx;
 | 
				
			||||||
 | 
								font-weight: 500;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.desc {
 | 
				
			||||||
 | 
								font-size: 20rpx;
 | 
				
			||||||
 | 
								color: #ccc;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.tag {
 | 
				
			||||||
 | 
								padding: 2rpx 10rpx;
 | 
				
			||||||
 | 
								border-radius: 4rpx;
 | 
				
			||||||
 | 
								background-color: #eb10ab;
 | 
				
			||||||
 | 
								color: #fff;
 | 
				
			||||||
 | 
								font-size: 20rpx;
 | 
				
			||||||
 | 
								margin-right: 16rpx;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.b {
 | 
				
			||||||
 | 
							height: 160rpx;
 | 
				
			||||||
 | 
							width: 220rpx;
 | 
				
			||||||
 | 
							background-color: #e2e2e2;
 | 
				
			||||||
 | 
							box-sizing: border-box;
 | 
				
			||||||
 | 
							position: absolute;
 | 
				
			||||||
 | 
							right: 24rpx;
 | 
				
			||||||
 | 
							bottom: 0;
 | 
				
			||||||
 | 
							border-radius: 12rpx;
 | 
				
			||||||
 | 
							z-index: 3;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							flex-direction: column;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.amount {
 | 
				
			||||||
 | 
								font-size: 60rpx;
 | 
				
			||||||
 | 
								font-weight: bold;
 | 
				
			||||||
 | 
								line-height: 1;
 | 
				
			||||||
 | 
								color: rgba(var(--coupon-color), 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&::after {
 | 
				
			||||||
 | 
									content: "元";
 | 
				
			||||||
 | 
									font-size: 48rpx;
 | 
				
			||||||
 | 
									position: relative;
 | 
				
			||||||
 | 
									top: -4rpx;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.doc {
 | 
				
			||||||
 | 
								font-size: 22rpx;
 | 
				
			||||||
 | 
								color: #666;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.c {
 | 
				
			||||||
 | 
							content: "";
 | 
				
			||||||
 | 
							display: block;
 | 
				
			||||||
 | 
							height: 40rpx;
 | 
				
			||||||
 | 
							width: 40rpx;
 | 
				
			||||||
 | 
							background-color: #868686;
 | 
				
			||||||
 | 
							border-radius: 40rpx;
 | 
				
			||||||
 | 
							z-index: 1;
 | 
				
			||||||
 | 
							position: absolute;
 | 
				
			||||||
 | 
							right: 216rpx;
 | 
				
			||||||
 | 
							top: 2rpx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										31
									
								
								uni_modules/cool-fixtures/components/fix-empty/fix-empty.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								uni_modules/cool-fixtures/components/fix-empty/fix-empty.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style
 | 
				
			||||||
 | 
							:styleSpacing="styleSpacing"
 | 
				
			||||||
 | 
							:styleColor="styleColor"
 | 
				
			||||||
 | 
							:position="position"
 | 
				
			||||||
 | 
							:index="index"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<view class="fix-empty" :style="{ height: height + 'rpx' }"></view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-empty" setup>
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						height: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 20,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-empty {
 | 
				
			||||||
 | 
						width: 750rpx;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,236 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style :styleSpacing="styleSpacing" :styleColor="styleColor" :position="position" :index="index">
 | 
				
			||||||
 | 
							<view class="fix-goods-list">
 | 
				
			||||||
 | 
								<template v-if="list.length">
 | 
				
			||||||
 | 
									<view class="inner" :class="[`is-${data.mode}`, data.isShadow ? 'is-shadow-pb' : '']">
 | 
				
			||||||
 | 
										<view class="grid-item" v-for="(item, index) in list" :key="index" :class="[data.isShadow ? 'is-shadow' : '']"
 | 
				
			||||||
 | 
											@click="toDetail(item)">
 | 
				
			||||||
 | 
											<image mode="widthFix" class="icon" :src="item.mainPic" />
 | 
				
			||||||
 | 
											<view class="content">
 | 
				
			||||||
 | 
												<view class="title">{{ item.title }}</view>
 | 
				
			||||||
 | 
												<view class="price-sold">
 | 
				
			||||||
 | 
													<cl-text type="price" :color="styleColor.color" :size="34" :value="item.price" bold />
 | 
				
			||||||
 | 
													<cl-text color="info" :size="22" :value="`${item.sold || 0}件已售`" />
 | 
				
			||||||
 | 
												</view>
 | 
				
			||||||
 | 
											</view>
 | 
				
			||||||
 | 
										</view>
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
								</template>
 | 
				
			||||||
 | 
								<template v-else>
 | 
				
			||||||
 | 
									<cl-empty :fixed="false" text="暂无商品~~"></cl-empty>
 | 
				
			||||||
 | 
								</template>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-goods-list" setup>
 | 
				
			||||||
 | 
						import { ref, watch, computed, type PropType } from "vue";
 | 
				
			||||||
 | 
						import type { Form } from "../../types/form";
 | 
				
			||||||
 | 
						import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
						import { useCool, useStore } from "/@/cool";
 | 
				
			||||||
 | 
						const { service, router } = useCool();
 | 
				
			||||||
 | 
						const { user } = useStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const props = defineProps({
 | 
				
			||||||
 | 
							data: {
 | 
				
			||||||
 | 
								type: Object as PropType<Form.Goods>,
 | 
				
			||||||
 | 
								default: () => {
 | 
				
			||||||
 | 
									({
 | 
				
			||||||
 | 
										mode: "mode-1",
 | 
				
			||||||
 | 
										source: "source-1",
 | 
				
			||||||
 | 
										attribute: 0,
 | 
				
			||||||
 | 
										num: 99,
 | 
				
			||||||
 | 
										gap: 0,
 | 
				
			||||||
 | 
										isShadow: false,
 | 
				
			||||||
 | 
										isVoucher: false,
 | 
				
			||||||
 | 
										type: [],
 | 
				
			||||||
 | 
										list: [],
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							index: {
 | 
				
			||||||
 | 
								type: Number,
 | 
				
			||||||
 | 
								default: 0,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							...baseProps,
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const list = ref<Array<Eps.GoodsInfoEntity>>([]);
 | 
				
			||||||
 | 
						// 创建计算属性来返回我们关心的特定属性
 | 
				
			||||||
 | 
						const watchedData = computed(() => ({
 | 
				
			||||||
 | 
							source: props.data.source,
 | 
				
			||||||
 | 
							attribute: props.data.attribute,
 | 
				
			||||||
 | 
							num: props.data.num,
 | 
				
			||||||
 | 
							ids: props.data.list.map((e) => e.id),
 | 
				
			||||||
 | 
							typeIds: props.data.type.map((e) => e.id),
 | 
				
			||||||
 | 
						}));
 | 
				
			||||||
 | 
						watch(
 | 
				
			||||||
 | 
							() => watchedData.value,
 | 
				
			||||||
 | 
							async (newValue) => {
 | 
				
			||||||
 | 
								let goods = [];
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									goods = await service.goods.info.getGoodsFromFixture({
 | 
				
			||||||
 | 
										source: newValue.source,
 | 
				
			||||||
 | 
										attribute: newValue.attribute,
 | 
				
			||||||
 | 
										num: newValue.num,
 | 
				
			||||||
 | 
										ids: newValue.ids,
 | 
				
			||||||
 | 
										typeIds: newValue.typeIds,
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								} catch (error) {
 | 
				
			||||||
 | 
									console.log(error);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								list.value = goods;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								deep: true,
 | 
				
			||||||
 | 
								immediate: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						async function toDetail(item : Eps.GoodsInfoEntity) {
 | 
				
			||||||
 | 
							if (item.openJump && item.jumpInfo.AppID) {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									// @ts-ignore
 | 
				
			||||||
 | 
									await wx.openEmbeddedMiniProgram({
 | 
				
			||||||
 | 
										appId: item.jumpInfo.AppID,
 | 
				
			||||||
 | 
										path: item.jumpInfo.page,
 | 
				
			||||||
 | 
										allowFullScreen: true,
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								} catch {
 | 
				
			||||||
 | 
									// @ts-ignore
 | 
				
			||||||
 | 
									await wx.navigateToMiniProgram({
 | 
				
			||||||
 | 
										appId: item.jumpInfo.AppID,
 | 
				
			||||||
 | 
										path: item.jumpInfo.page,
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								router.push({
 | 
				
			||||||
 | 
									path: "/pages/goods/detail",
 | 
				
			||||||
 | 
									query: {
 | 
				
			||||||
 | 
										id: item.id,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-goods-list {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.is-shadow-pb {
 | 
				
			||||||
 | 
							padding-bottom: 20rpx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.inner {
 | 
				
			||||||
 | 
							.grid-item {
 | 
				
			||||||
 | 
								background-color: #fff;
 | 
				
			||||||
 | 
								border-radius: 12rpx;
 | 
				
			||||||
 | 
								box-sizing: border-box;
 | 
				
			||||||
 | 
								overflow: hidden;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.is-shadow {
 | 
				
			||||||
 | 
								box-shadow:
 | 
				
			||||||
 | 
									0 3px 5px rgba(0, 0, 0, 0.2),
 | 
				
			||||||
 | 
									0 6px 10px rgba(0, 0, 0, 0.1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.icon {
 | 
				
			||||||
 | 
								width: 100%;
 | 
				
			||||||
 | 
								max-width: 100%;
 | 
				
			||||||
 | 
								vertical-align: middle;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.content {
 | 
				
			||||||
 | 
								max-width: 100%;
 | 
				
			||||||
 | 
								padding: 20rpx;
 | 
				
			||||||
 | 
								box-sizing: border-box;
 | 
				
			||||||
 | 
								overflow: hidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								.title {
 | 
				
			||||||
 | 
									box-sizing: border-box;
 | 
				
			||||||
 | 
									white-space: nowrap;
 | 
				
			||||||
 | 
									/* 禁止换行 */
 | 
				
			||||||
 | 
									overflow: hidden;
 | 
				
			||||||
 | 
									/* 隐藏溢出的内容 */
 | 
				
			||||||
 | 
									text-overflow: ellipsis;
 | 
				
			||||||
 | 
									/* 超出部分显示省略号 */
 | 
				
			||||||
 | 
									max-width: 100%;
 | 
				
			||||||
 | 
									/* 确保元素最大宽度不超过容器 */
 | 
				
			||||||
 | 
									font-size: 28rpx;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								.price-sold {
 | 
				
			||||||
 | 
									margin-top: 16rpx;
 | 
				
			||||||
 | 
									font-size: 28rpx;
 | 
				
			||||||
 | 
									display: flex;
 | 
				
			||||||
 | 
									justify-content: space-between;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								.voucher {
 | 
				
			||||||
 | 
									font-size: 28rpx;
 | 
				
			||||||
 | 
									margin-top: 16rpx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									.tips {
 | 
				
			||||||
 | 
										color: #e6a23c;
 | 
				
			||||||
 | 
										font-size: 24rpx;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									.di {
 | 
				
			||||||
 | 
										margin-left: 20rpx;
 | 
				
			||||||
 | 
										color: #e6a23c;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.is-mode-1 {
 | 
				
			||||||
 | 
							display: grid;
 | 
				
			||||||
 | 
							grid-template-columns: 1fr 1fr;
 | 
				
			||||||
 | 
							gap: 20rpx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.is-mode-2 {
 | 
				
			||||||
 | 
							display: grid;
 | 
				
			||||||
 | 
							grid-template-columns: 1fr 1fr 1fr;
 | 
				
			||||||
 | 
							gap: 20rpx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.is-mode-3 {
 | 
				
			||||||
 | 
							display: grid;
 | 
				
			||||||
 | 
							grid-template-columns: 1fr;
 | 
				
			||||||
 | 
							gap: 20rpx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.grid-item {
 | 
				
			||||||
 | 
								background-color: #fff;
 | 
				
			||||||
 | 
								border-top-right-radius: 12rpx;
 | 
				
			||||||
 | 
								border-top-left-radius: 12rpx;
 | 
				
			||||||
 | 
								border-bottom-right-radius: 12rpx;
 | 
				
			||||||
 | 
								border-bottom-left-radius: 12rpx;
 | 
				
			||||||
 | 
								overflow: hidden;
 | 
				
			||||||
 | 
								display: grid;
 | 
				
			||||||
 | 
								grid-template-columns: 200rpx 1fr;
 | 
				
			||||||
 | 
								gap: 40rpx;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.is-mode-4 {
 | 
				
			||||||
 | 
							display: grid;
 | 
				
			||||||
 | 
							grid-template-columns: 1fr;
 | 
				
			||||||
 | 
							gap: 20rpx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.grid-item {
 | 
				
			||||||
 | 
								display: flex;
 | 
				
			||||||
 | 
								flex-direction: column;
 | 
				
			||||||
 | 
								background-color: #fff;
 | 
				
			||||||
 | 
								border-top-right-radius: 12rpx;
 | 
				
			||||||
 | 
								border-top-left-radius: 12rpx;
 | 
				
			||||||
 | 
								border-bottom-right-radius: 12rpx;
 | 
				
			||||||
 | 
								border-bottom-left-radius: 12rpx;
 | 
				
			||||||
 | 
								overflow: hidden;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style :styleSpacing="styleSpacing" :styleColor="styleColor" :position="position">
 | 
				
			||||||
 | 
							<view class="fix-hot-image" :class="[`fix-hot-image-${index}`]">
 | 
				
			||||||
 | 
								<image
 | 
				
			||||||
 | 
									v-if="data.pic"
 | 
				
			||||||
 | 
									mode="widthFix"
 | 
				
			||||||
 | 
									:src="data.pic"
 | 
				
			||||||
 | 
									class="img hot-image"
 | 
				
			||||||
 | 
									@load="loadImage"
 | 
				
			||||||
 | 
									@click="toPath"
 | 
				
			||||||
 | 
								/>
 | 
				
			||||||
 | 
								<view
 | 
				
			||||||
 | 
									v-for="(item, index) in hot"
 | 
				
			||||||
 | 
									:key="index"
 | 
				
			||||||
 | 
									class="hot-item"
 | 
				
			||||||
 | 
									:style="{
 | 
				
			||||||
 | 
										width: `${item.relativeW}px`,
 | 
				
			||||||
 | 
										height: `${item.relativeH}px`,
 | 
				
			||||||
 | 
										top: `${item.relativeY}px`,
 | 
				
			||||||
 | 
										left: `${item.relativeX}px`,
 | 
				
			||||||
 | 
										zIndex: item.index,
 | 
				
			||||||
 | 
									}"
 | 
				
			||||||
 | 
									@click="hotJump(item)"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-hot-image" setup>
 | 
				
			||||||
 | 
					import { type PropType, ref, nextTick, getCurrentInstance } from "vue";
 | 
				
			||||||
 | 
					import type { Form } from "../../types/form";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					const { proxy }: any = getCurrentInstance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						data: {
 | 
				
			||||||
 | 
							type: Object as PropType<Form.HotImage>,
 | 
				
			||||||
 | 
							default: () => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									pic: "",
 | 
				
			||||||
 | 
									link: {},
 | 
				
			||||||
 | 
									width: 0,
 | 
				
			||||||
 | 
									height: 0,
 | 
				
			||||||
 | 
									attr: [],
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const emits = defineEmits(["jump"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const hot = ref<Form.Hot[]>(props.data.attr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function refreshHot() {
 | 
				
			||||||
 | 
						nextTick(() => {
 | 
				
			||||||
 | 
							uni.createSelectorQuery()
 | 
				
			||||||
 | 
								// #ifndef MP-ALIPAY
 | 
				
			||||||
 | 
								.in(proxy)
 | 
				
			||||||
 | 
								// #endif
 | 
				
			||||||
 | 
								.select(`.fix-hot-image-${props.index}`)
 | 
				
			||||||
 | 
								.boundingClientRect((res: any) => {
 | 
				
			||||||
 | 
									const { width, height } = res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// 调整等比例缩放位置 大小
 | 
				
			||||||
 | 
									const scaleX = width / props.data.width;
 | 
				
			||||||
 | 
									const scaleY = height / props.data.height;
 | 
				
			||||||
 | 
									// 调整子元素属性
 | 
				
			||||||
 | 
									hot.value = props.data.attr.map((element) => {
 | 
				
			||||||
 | 
										element.relativeX = Math.floor(element.x * scaleX);
 | 
				
			||||||
 | 
										element.relativeY = Math.floor(element.y * scaleY);
 | 
				
			||||||
 | 
										element.relativeW = Math.floor(element.w * scaleX);
 | 
				
			||||||
 | 
										element.relativeH = Math.floor(element.h * scaleY);
 | 
				
			||||||
 | 
										return element;
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.exec();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function loadImage(event: any) {
 | 
				
			||||||
 | 
						refreshHot();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function hotJump(item: Form.Hot) {
 | 
				
			||||||
 | 
						emits("jump", item.link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					function toPath() {
 | 
				
			||||||
 | 
						const link = props.data.link;
 | 
				
			||||||
 | 
						emits("jump", link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-hot-image {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
						position: relative;
 | 
				
			||||||
 | 
						.img {
 | 
				
			||||||
 | 
							width: 100%;
 | 
				
			||||||
 | 
							max-width: 100%;
 | 
				
			||||||
 | 
							vertical-align: middle;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						.hot-item {
 | 
				
			||||||
 | 
							position: absolute;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										175
									
								
								uni_modules/cool-fixtures/components/fix-index/fix-index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								uni_modules/cool-fixtures/components/fix-index/fix-index.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,175 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view class="parent">
 | 
				
			||||||
 | 
							<view class="item" v-for="(item, index) in list" :key="index">
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-top-bar'">
 | 
				
			||||||
 | 
									<fix-top-bar
 | 
				
			||||||
 | 
										v-bind="item.component.props"
 | 
				
			||||||
 | 
										:statusBar="statusBar"
 | 
				
			||||||
 | 
										@jump="jump"
 | 
				
			||||||
 | 
									></fix-top-bar>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-positioning'">
 | 
				
			||||||
 | 
									<fix-positioning
 | 
				
			||||||
 | 
										v-bind="item.component.props"
 | 
				
			||||||
 | 
										:index="index"
 | 
				
			||||||
 | 
										@jump="jump"
 | 
				
			||||||
 | 
									></fix-positioning>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-search'">
 | 
				
			||||||
 | 
									<fix-search
 | 
				
			||||||
 | 
										v-bind="item.component.props"
 | 
				
			||||||
 | 
										:statusBar="statusBar"
 | 
				
			||||||
 | 
										:index="index"
 | 
				
			||||||
 | 
										@jump="jump"
 | 
				
			||||||
 | 
									></fix-search>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-banner'">
 | 
				
			||||||
 | 
									<fix-banner v-bind="item.component.props" :index="index" @jump="jump"></fix-banner>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-menus'">
 | 
				
			||||||
 | 
									<fix-menus v-bind="item.component.props" :index="index" @jump="jump"></fix-menus>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-goods-list'">
 | 
				
			||||||
 | 
									<fix-goods-list v-bind="item.component.props" :index="index"></fix-goods-list>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-picture'">
 | 
				
			||||||
 | 
									<fix-picture
 | 
				
			||||||
 | 
										v-bind="item.component.props"
 | 
				
			||||||
 | 
										:index="index"
 | 
				
			||||||
 | 
										@jump="jump"
 | 
				
			||||||
 | 
									></fix-picture>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-hot-image'">
 | 
				
			||||||
 | 
									<fix-hot-image
 | 
				
			||||||
 | 
										v-bind="item.component.props"
 | 
				
			||||||
 | 
										:index="index"
 | 
				
			||||||
 | 
										@jump="jump"
 | 
				
			||||||
 | 
									></fix-hot-image>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-coupon'">
 | 
				
			||||||
 | 
									<fix-coupon v-bind="item.component.props" :index="index"></fix-coupon>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-title'">
 | 
				
			||||||
 | 
									<fix-title v-bind="item.component.props" :index="index" @jump="jump"></fix-title>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-empty'">
 | 
				
			||||||
 | 
									<fix-empty v-bind="item.component.props" :index="index"></fix-empty>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-line'">
 | 
				
			||||||
 | 
									<fix-line v-bind="item.component.props" :index="index"></fix-line>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-rich-text'">
 | 
				
			||||||
 | 
									<fix-rich-text v-bind="item.component.props" :index="index"></fix-rich-text>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-list-menu'">
 | 
				
			||||||
 | 
									<fix-list-menu
 | 
				
			||||||
 | 
										v-bind="item.component.props"
 | 
				
			||||||
 | 
										:index="index"
 | 
				
			||||||
 | 
										@jump="jump"
 | 
				
			||||||
 | 
									></fix-list-menu>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-rubik-cube'">
 | 
				
			||||||
 | 
									<fix-rubik-cube
 | 
				
			||||||
 | 
										v-bind="item.component.props"
 | 
				
			||||||
 | 
										:index="index"
 | 
				
			||||||
 | 
										@jump="jump"
 | 
				
			||||||
 | 
									></fix-rubik-cube>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-video'">
 | 
				
			||||||
 | 
									<fix-video v-bind="item.component.props" :index="index"></fix-video>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-suspension'">
 | 
				
			||||||
 | 
									<fix-suspension v-bind="item.component.props" @jump="jump"></fix-suspension>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
								<block v-if="item.component.name == 'fix-wechat'">
 | 
				
			||||||
 | 
									<fix-wechat v-bind="item.component.props"></fix-wechat>
 | 
				
			||||||
 | 
								</block>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup name="fix-index">
 | 
				
			||||||
 | 
					import { type PropType } from "vue";
 | 
				
			||||||
 | 
					import { useCool } from "/@/cool";
 | 
				
			||||||
 | 
					const { router } = useCool();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						list: {
 | 
				
			||||||
 | 
							type: Array as PropType<{ component: { name: string; props: Record<string, any> } }[]>,
 | 
				
			||||||
 | 
							default: () => [],
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						statusBar: Boolean,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 将字符串 id=1&t=2 转成对象
 | 
				
			||||||
 | 
					function strToObj(str: string): Record<string, string> {
 | 
				
			||||||
 | 
						if (!str) return {};
 | 
				
			||||||
 | 
						return str.split("&").reduce((acc: { [key: string]: string }, pair) => {
 | 
				
			||||||
 | 
							const [key, value] = pair.split("=");
 | 
				
			||||||
 | 
							acc[key] = value;
 | 
				
			||||||
 | 
							return acc;
 | 
				
			||||||
 | 
						}, {});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 统一的跳转函数
 | 
				
			||||||
 | 
					function jump(link: { name: string; page: string; type: string; appid: string }) {
 | 
				
			||||||
 | 
						let [path, param = ""] = link.page.split("?");
 | 
				
			||||||
 | 
						const query = strToObj(param);
 | 
				
			||||||
 | 
						switch (link.type) {
 | 
				
			||||||
 | 
							case "goodsType":
 | 
				
			||||||
 | 
								// 分类
 | 
				
			||||||
 | 
								router.push({
 | 
				
			||||||
 | 
									path,
 | 
				
			||||||
 | 
									query,
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case "goodsDetails":
 | 
				
			||||||
 | 
								// 商品
 | 
				
			||||||
 | 
								router.push({
 | 
				
			||||||
 | 
									path,
 | 
				
			||||||
 | 
									query,
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case "index":
 | 
				
			||||||
 | 
								// 平台
 | 
				
			||||||
 | 
								router.push(path);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case "web":
 | 
				
			||||||
 | 
								// 网页
 | 
				
			||||||
 | 
								router.push({
 | 
				
			||||||
 | 
									path: "/pages/index/web",
 | 
				
			||||||
 | 
									query: {
 | 
				
			||||||
 | 
										url: link.page,
 | 
				
			||||||
 | 
										title: link.name,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case "applet":
 | 
				
			||||||
 | 
								// 小程序
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									// @ts-ignore
 | 
				
			||||||
 | 
									wx.openEmbeddedMiniProgram({
 | 
				
			||||||
 | 
										appId: link.appid,
 | 
				
			||||||
 | 
										path: link.page,
 | 
				
			||||||
 | 
										allowFullScreen: true,
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								} catch {
 | 
				
			||||||
 | 
									// @ts-ignore
 | 
				
			||||||
 | 
									wx.navigateToMiniProgram({
 | 
				
			||||||
 | 
										appId: link.appid,
 | 
				
			||||||
 | 
										path: link.page,
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case "fixtures":
 | 
				
			||||||
 | 
								// 自定义
 | 
				
			||||||
 | 
								router.push({
 | 
				
			||||||
 | 
									path,
 | 
				
			||||||
 | 
									query,
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
							
								
								
									
										44
									
								
								uni_modules/cool-fixtures/components/fix-line/fix-line.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								uni_modules/cool-fixtures/components/fix-line/fix-line.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style :styleSpacing="styleSpacing" :styleColor="styleColor" :index="index">
 | 
				
			||||||
 | 
							<view class="fix-line">
 | 
				
			||||||
 | 
								<view class="inner" :style="innerStyle"></view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-line" setup>
 | 
				
			||||||
 | 
					import { computed } from "vue";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						mode: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "solid",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						color: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "#f5f6fa",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						height: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 4,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const innerStyle = computed(() => {
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							borderBottom: `${props.height}rpx ${props.mode} ${props.color}`,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-line {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,133 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style
 | 
				
			||||||
 | 
							:styleSpacing="styleSpacing"
 | 
				
			||||||
 | 
							:styleColor="styleColor"
 | 
				
			||||||
 | 
							:position="position"
 | 
				
			||||||
 | 
							:index="index"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<view class="fix-list-menu">
 | 
				
			||||||
 | 
								<view class="inner" v-if="list.length">
 | 
				
			||||||
 | 
									<view
 | 
				
			||||||
 | 
										class="item"
 | 
				
			||||||
 | 
										:class="[`${isBorder ? 'is-border' : ''}`]"
 | 
				
			||||||
 | 
										v-for="(item, index) in list"
 | 
				
			||||||
 | 
										:key="index"
 | 
				
			||||||
 | 
										@click="toPath(item.link)"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<view class="left">
 | 
				
			||||||
 | 
											<image v-if="item.icon" :src="item.icon" class="icon" />
 | 
				
			||||||
 | 
											<view class="text" :style="{ color: item.color }">
 | 
				
			||||||
 | 
												{{ item.text }}
 | 
				
			||||||
 | 
											</view>
 | 
				
			||||||
 | 
										</view>
 | 
				
			||||||
 | 
										<view class="right">
 | 
				
			||||||
 | 
											<text class="text">{{ item.text2 }}</text>
 | 
				
			||||||
 | 
											<cl-icon color="#a8abb2" name="arrow-right"></cl-icon>
 | 
				
			||||||
 | 
										</view>
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-list-menu" setup>
 | 
				
			||||||
 | 
					import { type PropType } from "vue";
 | 
				
			||||||
 | 
					import type { Form } from "../../types/form";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						list: {
 | 
				
			||||||
 | 
							type: Array as PropType<Form.Title[]>,
 | 
				
			||||||
 | 
							default: () => {
 | 
				
			||||||
 | 
								return [
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										text: "",
 | 
				
			||||||
 | 
										text2: "",
 | 
				
			||||||
 | 
										color: "",
 | 
				
			||||||
 | 
										icon: "",
 | 
				
			||||||
 | 
										link: {
 | 
				
			||||||
 | 
											name: "",
 | 
				
			||||||
 | 
											type: "",
 | 
				
			||||||
 | 
											appid: "",
 | 
				
			||||||
 | 
											page: "",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						isBorder: {
 | 
				
			||||||
 | 
							type: Boolean,
 | 
				
			||||||
 | 
							default: false,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const emits = defineEmits(["jump"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toPath(link: Form.Link) {
 | 
				
			||||||
 | 
						emits("jump", link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-list-menu {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
						.inner {
 | 
				
			||||||
 | 
							.is-border {
 | 
				
			||||||
 | 
								border-bottom: 1px solid #e4e7ed;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							.is-border:last-child {
 | 
				
			||||||
 | 
								border-bottom: none;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							.item {
 | 
				
			||||||
 | 
								height: 80rpx;
 | 
				
			||||||
 | 
								padding: 12rpx;
 | 
				
			||||||
 | 
								box-sizing: border-box;
 | 
				
			||||||
 | 
								display: flex;
 | 
				
			||||||
 | 
								justify-content: space-between;
 | 
				
			||||||
 | 
								align-items: center;
 | 
				
			||||||
 | 
								.left {
 | 
				
			||||||
 | 
									flex: 1;
 | 
				
			||||||
 | 
									height: 100%;
 | 
				
			||||||
 | 
									display: flex;
 | 
				
			||||||
 | 
									justify-content: flex-start;
 | 
				
			||||||
 | 
									align-items: center;
 | 
				
			||||||
 | 
									margin-right: 40rpx;
 | 
				
			||||||
 | 
									.icon {
 | 
				
			||||||
 | 
										margin-right: 12rpx;
 | 
				
			||||||
 | 
										width: 50rpx;
 | 
				
			||||||
 | 
										height: 50rpx;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									.text {
 | 
				
			||||||
 | 
										width: 440rpx;
 | 
				
			||||||
 | 
										height: 60rpx;
 | 
				
			||||||
 | 
										line-height: 60rpx;
 | 
				
			||||||
 | 
										font-size: 32rpx;
 | 
				
			||||||
 | 
										text-overflow: ellipsis;
 | 
				
			||||||
 | 
										white-space: nowrap;
 | 
				
			||||||
 | 
										overflow: hidden;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								.right {
 | 
				
			||||||
 | 
									width: 160rpx;
 | 
				
			||||||
 | 
									height: 100%;
 | 
				
			||||||
 | 
									display: flex;
 | 
				
			||||||
 | 
									justify-content: flex-end;
 | 
				
			||||||
 | 
									align-items: center;
 | 
				
			||||||
 | 
									.text {
 | 
				
			||||||
 | 
										color: #a8abb2;
 | 
				
			||||||
 | 
										font-size: 24rpx;
 | 
				
			||||||
 | 
										margin-right: 8rpx;
 | 
				
			||||||
 | 
										text-overflow: ellipsis;
 | 
				
			||||||
 | 
										white-space: nowrap;
 | 
				
			||||||
 | 
										overflow: hidden;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										208
									
								
								uni_modules/cool-fixtures/components/fix-menus/fix-menus.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								uni_modules/cool-fixtures/components/fix-menus/fix-menus.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,208 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style
 | 
				
			||||||
 | 
							:styleSpacing="styleSpacing"
 | 
				
			||||||
 | 
							:styleColor="styleColor"
 | 
				
			||||||
 | 
							:position="position"
 | 
				
			||||||
 | 
							:index="index"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<view class="fix-menus">
 | 
				
			||||||
 | 
								<swiper
 | 
				
			||||||
 | 
									class="inner"
 | 
				
			||||||
 | 
									:style="{
 | 
				
			||||||
 | 
										height: height,
 | 
				
			||||||
 | 
									}"
 | 
				
			||||||
 | 
									:circular="false"
 | 
				
			||||||
 | 
									:indicator-dots="false"
 | 
				
			||||||
 | 
									@change="changeCurrent"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<swiper-item v-for="(item, index) in tabs" :key="index">
 | 
				
			||||||
 | 
										<view
 | 
				
			||||||
 | 
											class="row"
 | 
				
			||||||
 | 
											:class="[`is-${style.rowNum}`]"
 | 
				
			||||||
 | 
											v-for="(row, r) in item"
 | 
				
			||||||
 | 
											:key="r"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											<view
 | 
				
			||||||
 | 
												class="item"
 | 
				
			||||||
 | 
												v-for="(col, c) in row"
 | 
				
			||||||
 | 
												:key="c"
 | 
				
			||||||
 | 
												@click="toPath(col.link)"
 | 
				
			||||||
 | 
											>
 | 
				
			||||||
 | 
												<view
 | 
				
			||||||
 | 
													:class="[`is-${style.shape}`, `is-${col.mode}`]"
 | 
				
			||||||
 | 
													:style="{ backgroundColor: col.backgroundColor }"
 | 
				
			||||||
 | 
													class="icon-box"
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													<cl-image :src="col.icon" mode="aspectFill" class="icon">
 | 
				
			||||||
 | 
													</cl-image>
 | 
				
			||||||
 | 
												</view>
 | 
				
			||||||
 | 
												<span
 | 
				
			||||||
 | 
													v-if="col.mode == 'mode-1'"
 | 
				
			||||||
 | 
													class="text"
 | 
				
			||||||
 | 
													:style="{ color: col.color }"
 | 
				
			||||||
 | 
													>{{ col.text }}</span
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
											</view>
 | 
				
			||||||
 | 
										</view>
 | 
				
			||||||
 | 
									</swiper-item>
 | 
				
			||||||
 | 
								</swiper>
 | 
				
			||||||
 | 
								<!-- 自定义指示器 -->
 | 
				
			||||||
 | 
								<view class="custom-indicator">
 | 
				
			||||||
 | 
									<view
 | 
				
			||||||
 | 
										v-for="(item, index) in tabs"
 | 
				
			||||||
 | 
										:key="index"
 | 
				
			||||||
 | 
										class="custom-indicator-dot"
 | 
				
			||||||
 | 
										:class="{ active: current === index }"
 | 
				
			||||||
 | 
									></view>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup name="fix-menus">
 | 
				
			||||||
 | 
					import { computed, ref, type PropType } from "vue";
 | 
				
			||||||
 | 
					import type { Form } from "../../types/form";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const emits = defineEmits(["jump"]);
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						style: {
 | 
				
			||||||
 | 
							type: Object,
 | 
				
			||||||
 | 
							default: () => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									shape: "round",
 | 
				
			||||||
 | 
									pageNum: 1,
 | 
				
			||||||
 | 
									rowNum: 3,
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						list: {
 | 
				
			||||||
 | 
							type: Array as PropType<Form.Menu[]>,
 | 
				
			||||||
 | 
							default: () => [],
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const current = ref(0);
 | 
				
			||||||
 | 
					function changeCurrent(event: any) {
 | 
				
			||||||
 | 
						current.value = event.detail.current;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const height = computed(() => {
 | 
				
			||||||
 | 
						return 180 * props.style.pageNum + "rpx";
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const tabs = computed(() => {
 | 
				
			||||||
 | 
						return paginateArray(props.list, props.style.pageNum, props.style.rowNum);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 解决 每页1行 每行3个 的问题
 | 
				
			||||||
 | 
					function paginateArray(data: Form.Menu[], pageNum: number, rowNum: number) {
 | 
				
			||||||
 | 
						const result: any[] = [];
 | 
				
			||||||
 | 
						const totalItems = data.length;
 | 
				
			||||||
 | 
						let pageIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (pageIndex < totalItems) {
 | 
				
			||||||
 | 
							const page: any[] = [];
 | 
				
			||||||
 | 
							for (let i = 0; i < pageNum && pageIndex < totalItems; i++) {
 | 
				
			||||||
 | 
								const row: any[] = [];
 | 
				
			||||||
 | 
								for (let j = 0; j < rowNum && pageIndex < totalItems; j++) {
 | 
				
			||||||
 | 
									row.push(data[pageIndex]);
 | 
				
			||||||
 | 
									pageIndex++;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								page.push(row);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							result.push(page);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toPath(link: Form.Link) {
 | 
				
			||||||
 | 
						emits("jump", link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-menus {
 | 
				
			||||||
 | 
						width: 100%;
 | 
				
			||||||
 | 
						padding-bottom: 20rpx;
 | 
				
			||||||
 | 
						.inner {
 | 
				
			||||||
 | 
							height: 100%;
 | 
				
			||||||
 | 
							padding: 10rpx;
 | 
				
			||||||
 | 
							box-sizing: border-box;
 | 
				
			||||||
 | 
							.row {
 | 
				
			||||||
 | 
								margin-bottom: 20rpx;
 | 
				
			||||||
 | 
								.item {
 | 
				
			||||||
 | 
									display: flex;
 | 
				
			||||||
 | 
									flex-direction: column;
 | 
				
			||||||
 | 
									justify-content: center;
 | 
				
			||||||
 | 
									align-items: center;
 | 
				
			||||||
 | 
									height: 160rpx;
 | 
				
			||||||
 | 
									box-sizing: border-box;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									.is-round {
 | 
				
			||||||
 | 
										border-radius: 40rpx;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									.is-mode-2 {
 | 
				
			||||||
 | 
										width: 120rpx !important;
 | 
				
			||||||
 | 
										height: 120rpx !important;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									.icon-box {
 | 
				
			||||||
 | 
										width: 80rpx;
 | 
				
			||||||
 | 
										height: 80rpx;
 | 
				
			||||||
 | 
										overflow: hidden;
 | 
				
			||||||
 | 
										.icon {
 | 
				
			||||||
 | 
											width: 100%;
 | 
				
			||||||
 | 
											height: 100%;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									.text {
 | 
				
			||||||
 | 
										font-size: 26rpx;
 | 
				
			||||||
 | 
										margin-top: 12rpx;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							.row:last-child {
 | 
				
			||||||
 | 
								margin-bottom: 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							.is-3 {
 | 
				
			||||||
 | 
								display: grid;
 | 
				
			||||||
 | 
								grid-template-columns: repeat(3, 1fr); /* 每行3列,每列宽度相等 */
 | 
				
			||||||
 | 
								gap: 20rpx; /* 间距 */
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							.is-4 {
 | 
				
			||||||
 | 
								display: grid;
 | 
				
			||||||
 | 
								grid-template-columns: repeat(4, 1fr); /* 每行3列,每列宽度相等 */
 | 
				
			||||||
 | 
								gap: 20rpx; /* 间距 */
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							.is-5 {
 | 
				
			||||||
 | 
								display: grid;
 | 
				
			||||||
 | 
								grid-template-columns: repeat(5, 1fr); /* 每行3列,每列宽度相等 */
 | 
				
			||||||
 | 
								gap: 20rpx; /* 间距 */
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.custom-indicator {
 | 
				
			||||||
 | 
						display: flex;
 | 
				
			||||||
 | 
						justify-content: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.custom-indicator-dot {
 | 
				
			||||||
 | 
						width: 12rpx;
 | 
				
			||||||
 | 
						height: 12rpx;
 | 
				
			||||||
 | 
						background-color: #686580;
 | 
				
			||||||
 | 
						border-radius: 50%; /* 默认圆形 */
 | 
				
			||||||
 | 
						margin: 0 10rpx;
 | 
				
			||||||
 | 
						transition: all 0.3s ease; /* 过渡效果 */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.custom-indicator-dot.active {
 | 
				
			||||||
 | 
						width: 40rpx; /* 激活状态变成长方形 */
 | 
				
			||||||
 | 
						height: 12rpx;
 | 
				
			||||||
 | 
						background: var(--btn-color) !important;
 | 
				
			||||||
 | 
						border-radius: 20rpx; /* 调整边角的圆度 */
 | 
				
			||||||
 | 
						transition: all 0.5s ease; /* 激活状态有更慢的动画过渡 */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style
 | 
				
			||||||
 | 
							:styleSpacing="styleSpacing"
 | 
				
			||||||
 | 
							:styleColor="styleColor"
 | 
				
			||||||
 | 
							:position="position"
 | 
				
			||||||
 | 
							:index="index"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<view class="fix-picture">
 | 
				
			||||||
 | 
								<view class="inner" @click="toPath">
 | 
				
			||||||
 | 
									<template v-if="data.pic">
 | 
				
			||||||
 | 
										<image mode="widthFix" :src="data.pic" class="img" />
 | 
				
			||||||
 | 
									</template>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-picture" setup>
 | 
				
			||||||
 | 
					import { type PropType } from "vue";
 | 
				
			||||||
 | 
					import type { Form } from "../../types/form";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						data: {
 | 
				
			||||||
 | 
							type: Object as PropType<Form.Picture>,
 | 
				
			||||||
 | 
							default: () => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									pic: "",
 | 
				
			||||||
 | 
									link: {},
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const emits = defineEmits(["jump"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toPath() {
 | 
				
			||||||
 | 
						const link = props.data.link;
 | 
				
			||||||
 | 
						emits("jump", link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-picture {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.inner {
 | 
				
			||||||
 | 
							height: 100%;
 | 
				
			||||||
 | 
							flex: 1;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
							.img {
 | 
				
			||||||
 | 
								width: 100%;
 | 
				
			||||||
 | 
								max-width: 100%;
 | 
				
			||||||
 | 
								vertical-align: middle;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,378 @@
 | 
				
			|||||||
 | 
					<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>
 | 
				
			||||||
@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style :styleSpacing="styleSpacing" :styleColor="styleColor" :index="index">
 | 
				
			||||||
 | 
							<view class="fix-rich-text">
 | 
				
			||||||
 | 
								<mp-html :content="data"></mp-html>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-rich-text" setup>
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						data: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-rich-text {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
						:deep(img) {
 | 
				
			||||||
 | 
							width: 100%;
 | 
				
			||||||
 | 
							max-width: 100%;
 | 
				
			||||||
 | 
							height: auto; /* 保持图像的原始纵横比 */
 | 
				
			||||||
 | 
							display: block; /* 消除图像下方的默认间隙(如果是内联元素的话)*/
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,147 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style
 | 
				
			||||||
 | 
							:styleSpacing="styleSpacing"
 | 
				
			||||||
 | 
							:styleColor="styleColor"
 | 
				
			||||||
 | 
							:position="position"
 | 
				
			||||||
 | 
							:index="index"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<div class="fix-rubik-cube">
 | 
				
			||||||
 | 
								<div
 | 
				
			||||||
 | 
									class="box"
 | 
				
			||||||
 | 
									:class="[`is-${data.mode}`]"
 | 
				
			||||||
 | 
									:style="{
 | 
				
			||||||
 | 
										gap: `${data.gap}rpx`,
 | 
				
			||||||
 | 
										'--gap': `${data.gap}rpx`,
 | 
				
			||||||
 | 
									}"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										class="item"
 | 
				
			||||||
 | 
										v-for="(item, index) in data.list"
 | 
				
			||||||
 | 
										:key="index"
 | 
				
			||||||
 | 
										:class="[`is-${data.mode}-item-${index}`]"
 | 
				
			||||||
 | 
										@click="toPath(item.link)"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										<image class="icon" :src="item.icon" mode="widthFix"></image>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-rubik-cube" setup>
 | 
				
			||||||
 | 
					import { type PropType } from "vue";
 | 
				
			||||||
 | 
					import type { Form } from "../../types/form";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						data: {
 | 
				
			||||||
 | 
							type: Object as PropType<Form.RubikCube>,
 | 
				
			||||||
 | 
							default: () => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									mode: "mode-1",
 | 
				
			||||||
 | 
									gap: 0,
 | 
				
			||||||
 | 
									list: [
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											icon: "",
 | 
				
			||||||
 | 
											tips: "宽度375px",
 | 
				
			||||||
 | 
											link: {
 | 
				
			||||||
 | 
												name: "",
 | 
				
			||||||
 | 
												type: "",
 | 
				
			||||||
 | 
												appid: "",
 | 
				
			||||||
 | 
												page: "",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											icon: "",
 | 
				
			||||||
 | 
											tips: "宽度375px",
 | 
				
			||||||
 | 
											link: {
 | 
				
			||||||
 | 
												name: "",
 | 
				
			||||||
 | 
												type: "",
 | 
				
			||||||
 | 
												appid: "",
 | 
				
			||||||
 | 
												page: "",
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									],
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const emits = defineEmits(["jump"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toPath(link: Form.Link) {
 | 
				
			||||||
 | 
						emits("jump", link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.box {
 | 
				
			||||||
 | 
						display: flex;
 | 
				
			||||||
 | 
						.item {
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
							box-sizing: border-box;
 | 
				
			||||||
 | 
							.icon {
 | 
				
			||||||
 | 
								width: 100%;
 | 
				
			||||||
 | 
								max-width: 100%;
 | 
				
			||||||
 | 
								border: 0;
 | 
				
			||||||
 | 
								vertical-align: middle;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.is-mode-1 {
 | 
				
			||||||
 | 
						display: grid;
 | 
				
			||||||
 | 
						grid-template-columns: repeat(2, 1fr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.is-mode-2 {
 | 
				
			||||||
 | 
						display: grid;
 | 
				
			||||||
 | 
						grid-template-columns: repeat(3, 1fr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.is-mode-3 {
 | 
				
			||||||
 | 
						display: grid;
 | 
				
			||||||
 | 
						grid-template-columns: 1fr 1fr;
 | 
				
			||||||
 | 
						grid-template-rows: 1fr 1fr;
 | 
				
			||||||
 | 
						.item {
 | 
				
			||||||
 | 
							&.is-mode-3-item-0 {
 | 
				
			||||||
 | 
								grid-column: 1 / 2;
 | 
				
			||||||
 | 
								grid-row: 1 / 3;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							&.is-mode-3-item-1 {
 | 
				
			||||||
 | 
								grid-column: 2 / 3;
 | 
				
			||||||
 | 
								grid-row: 1 / 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							&.is-mode-3-item-2 {
 | 
				
			||||||
 | 
								grid-column: 2 / 3;
 | 
				
			||||||
 | 
								grid-row: 2 / 3;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.is-mode-4 {
 | 
				
			||||||
 | 
						display: grid;
 | 
				
			||||||
 | 
						grid-template-columns: 1fr 1fr;
 | 
				
			||||||
 | 
						grid-template-rows: auto auto;
 | 
				
			||||||
 | 
						.item {
 | 
				
			||||||
 | 
							&.is-mode-4-item-0 {
 | 
				
			||||||
 | 
								grid-column: 1 / 3;
 | 
				
			||||||
 | 
								grid-row: 1 / 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							&.is-mode-4-item-1 {
 | 
				
			||||||
 | 
								grid-column: 1 / 2;
 | 
				
			||||||
 | 
								grid-row: 2 / 3;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							&.is-mode-4-item-2 {
 | 
				
			||||||
 | 
								grid-column: 2 / 3;
 | 
				
			||||||
 | 
								grid-row: 2 / 3;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style
 | 
				
			||||||
 | 
							:styleSpacing="styleSpacing"
 | 
				
			||||||
 | 
							:styleColor="styleColor"
 | 
				
			||||||
 | 
							:position="position"
 | 
				
			||||||
 | 
							:statusBar="statusBar"
 | 
				
			||||||
 | 
							:flowInner="false"
 | 
				
			||||||
 | 
							:index="index"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<view class="search-bar" @tap="toSearch">
 | 
				
			||||||
 | 
								<view class="search-bar__inner" :style="style" :class="[`is-${mode}`]">
 | 
				
			||||||
 | 
									<cl-icon name="search" :margin="[0, 12, 0, 0]"> </cl-icon>
 | 
				
			||||||
 | 
									<cl-text :value="placeholder" :color="styleColor.color"></cl-text>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup name="fix-search">
 | 
				
			||||||
 | 
					import { computed } from "vue";
 | 
				
			||||||
 | 
					import { useCool } from "/@/cool";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					const { router } = useCool();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						mode: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "mode-1",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						backgroundColor: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "#f6f7fa",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						placeholder: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "请输入关键字进行搜索",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
						statusBar: Boolean,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toSearch() {
 | 
				
			||||||
 | 
						router.push("/pages/goods/search");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const style = computed(() => {
 | 
				
			||||||
 | 
						const { borderTopLR, borderBottomLR } = props.styleSpacing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const { color } = props.styleColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							color: color,
 | 
				
			||||||
 | 
							backgroundColor: props.backgroundColor,
 | 
				
			||||||
 | 
							borderRadius: `${borderTopLR}rpx ${borderTopLR}rpx ${borderBottomLR}rpx ${borderBottomLR}rpx`,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.search-bar {
 | 
				
			||||||
 | 
						width: 100%;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&__inner {
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							height: 70rpx;
 | 
				
			||||||
 | 
							width: 100%;
 | 
				
			||||||
 | 
							background-color: #f7f7f7;
 | 
				
			||||||
 | 
							box-sizing: border-box;
 | 
				
			||||||
 | 
							padding: 0 24rpx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						.is-mode-1 {
 | 
				
			||||||
 | 
							justify-content: flex-start;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						.is-mode-2 {
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						.is-mode-3 {
 | 
				
			||||||
 | 
							justify-content: flex-end;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view class="fix-suspension" :style="baseStyle">
 | 
				
			||||||
 | 
							<view class="menu" :style="innerStyle" @click="toggleMenu">
 | 
				
			||||||
 | 
								<image class="icon" :src="list[0].icon"></image>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
							<view class="menu-slide">
 | 
				
			||||||
 | 
								<view
 | 
				
			||||||
 | 
									v-for="(item, index) in visibleItems"
 | 
				
			||||||
 | 
									:key="index"
 | 
				
			||||||
 | 
									class="sub-menu"
 | 
				
			||||||
 | 
									:style="subMenuStyle(index)"
 | 
				
			||||||
 | 
									@click="toPath(item.link)"
 | 
				
			||||||
 | 
								>
 | 
				
			||||||
 | 
									<image class="icon" :src="item.icon"></image>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-suspension" setup>
 | 
				
			||||||
 | 
					import { computed, ref, type PropType } from "vue";
 | 
				
			||||||
 | 
					import type { Form } from "../../types/form";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						mode: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "left",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						backgroundColor: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "rgba(0, 0, 0, 0.8)",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						offsetBottom: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 50,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						shadow: {
 | 
				
			||||||
 | 
							type: Boolean,
 | 
				
			||||||
 | 
							default: false,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						list: {
 | 
				
			||||||
 | 
							type: Array as PropType<Form.Suspension[]>,
 | 
				
			||||||
 | 
							default: () => [
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									icon: "https://tsb-yx.oss-cn-guangzhou.aliyuncs.com/app/mini/float-menu.png",
 | 
				
			||||||
 | 
									tips: "宽高128px",
 | 
				
			||||||
 | 
									link: {
 | 
				
			||||||
 | 
										name: "",
 | 
				
			||||||
 | 
										type: "",
 | 
				
			||||||
 | 
										appid: "",
 | 
				
			||||||
 | 
										page: "",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const emits = defineEmits(["jump"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const baseStyle = computed(() => {
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							bottom: `${props.offsetBottom}rpx`,
 | 
				
			||||||
 | 
							[props.mode]: "10px",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const innerStyle = computed(() => {
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							background: props.backgroundColor,
 | 
				
			||||||
 | 
							boxShadow: props.shadow ? "0 4px 10px rgba(0, 0, 0, 0.3)" : undefined,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const isMenuOpen = ref(false);
 | 
				
			||||||
 | 
					const toggleMenu = () => {
 | 
				
			||||||
 | 
						if (props.list.length > 1) {
 | 
				
			||||||
 | 
							isMenuOpen.value = !isMenuOpen.value;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							toPath(props.list[0].link);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 控制显示的子按钮
 | 
				
			||||||
 | 
					const visibleItems = computed(() => {
 | 
				
			||||||
 | 
						return isMenuOpen.value ? props.list.slice(1) : [];
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 子菜单项的样式和动画效果
 | 
				
			||||||
 | 
					const subMenuStyle = (index: number) => {
 | 
				
			||||||
 | 
						const offset = 90; // 每个子菜单项的高度
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							transition: `transform 0.3s ease, opacity 0.3s ease`,
 | 
				
			||||||
 | 
							transform: isMenuOpen.value ? `translateY(-${(index + 1) * offset}rpx)` : "translateY(0)",
 | 
				
			||||||
 | 
							opacity: isMenuOpen.value ? 1 : 0,
 | 
				
			||||||
 | 
							background: props.backgroundColor,
 | 
				
			||||||
 | 
							boxShadow: props.shadow ? "0 4px 10px rgba(0, 0, 0, 0.3)" : undefined,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toPath(link: Form.Link) {
 | 
				
			||||||
 | 
						emits("jump", link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-suspension {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						position: fixed;
 | 
				
			||||||
 | 
						z-index: 400;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.menu {
 | 
				
			||||||
 | 
							width: 80rpx;
 | 
				
			||||||
 | 
							height: 80rpx;
 | 
				
			||||||
 | 
							border-radius: 50%;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							cursor: pointer;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.icon {
 | 
				
			||||||
 | 
							width: 50rpx;
 | 
				
			||||||
 | 
							height: 50rpx;
 | 
				
			||||||
 | 
							user-select: none;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.menu-slide {
 | 
				
			||||||
 | 
							position: absolute; /* 依赖于父元素定位 */
 | 
				
			||||||
 | 
							bottom: 80rpx; /* 让子菜单从主菜单上方展开 */
 | 
				
			||||||
 | 
							left: 0; /* 根据需要调整位置 */
 | 
				
			||||||
 | 
							width: 80rpx; /* 确保子菜单能够展示 */
 | 
				
			||||||
 | 
							transition: all 0.3s ease;
 | 
				
			||||||
 | 
							overflow: visible; /* 确保子菜单不被裁剪 */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.sub-menu {
 | 
				
			||||||
 | 
							position: absolute;
 | 
				
			||||||
 | 
							width: 80rpx;
 | 
				
			||||||
 | 
							height: 80rpx;
 | 
				
			||||||
 | 
							border-radius: 50%;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							cursor: pointer;
 | 
				
			||||||
 | 
							z-index: 100;
 | 
				
			||||||
 | 
							opacity: 0;
 | 
				
			||||||
 | 
							transition:
 | 
				
			||||||
 | 
								transform 0.3s ease,
 | 
				
			||||||
 | 
								opacity 0.3s ease;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										129
									
								
								uni_modules/cool-fixtures/components/fix-title/fix-title.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								uni_modules/cool-fixtures/components/fix-title/fix-title.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style
 | 
				
			||||||
 | 
							:styleSpacing="styleSpacing"
 | 
				
			||||||
 | 
							:styleColor="styleColor"
 | 
				
			||||||
 | 
							:position="position"
 | 
				
			||||||
 | 
							:index="index"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<view class="fix-title">
 | 
				
			||||||
 | 
								<view class="inner">
 | 
				
			||||||
 | 
									<view class="left" @click="toPath(left.link)">
 | 
				
			||||||
 | 
										<image v-if="left.icon" :src="left.icon" class="icon" />
 | 
				
			||||||
 | 
										<view class="text" :style="{ color: left.color }" :class="[`is-${mode}`]">
 | 
				
			||||||
 | 
											{{ left.text }}
 | 
				
			||||||
 | 
										</view>
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
									<view class="right" @click="toPath(right.link)">
 | 
				
			||||||
 | 
										<text class="text" :style="{ color: right.color }">{{ right.text }}</text>
 | 
				
			||||||
 | 
										<image v-if="right.icon" :src="right.icon" class="icon" />
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-title" setup>
 | 
				
			||||||
 | 
					import { type PropType } from "vue";
 | 
				
			||||||
 | 
					import type { Form } from "../../types/form";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						mode: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "left",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						left: {
 | 
				
			||||||
 | 
							type: Object as PropType<Form.Title>,
 | 
				
			||||||
 | 
							default: () => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									text: "标题内容",
 | 
				
			||||||
 | 
									color: "#000",
 | 
				
			||||||
 | 
									icon: "",
 | 
				
			||||||
 | 
									link: {
 | 
				
			||||||
 | 
										name: "",
 | 
				
			||||||
 | 
										type: "",
 | 
				
			||||||
 | 
										appid: "",
 | 
				
			||||||
 | 
										page: "",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						right: {
 | 
				
			||||||
 | 
							type: Object as PropType<Form.Title>,
 | 
				
			||||||
 | 
							default: () => {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									text: "查看",
 | 
				
			||||||
 | 
									color: "#a8abb2",
 | 
				
			||||||
 | 
									icon: "",
 | 
				
			||||||
 | 
									link: {
 | 
				
			||||||
 | 
										name: "",
 | 
				
			||||||
 | 
										type: "",
 | 
				
			||||||
 | 
										appid: "",
 | 
				
			||||||
 | 
										page: "",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const emits = defineEmits(["jump"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toPath(link: Form.Link) {
 | 
				
			||||||
 | 
						emits("jump", link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-title {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.inner {
 | 
				
			||||||
 | 
							height: 80rpx;
 | 
				
			||||||
 | 
							flex: 1;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							justify-content: space-around;
 | 
				
			||||||
 | 
							padding: 20rpx;
 | 
				
			||||||
 | 
							.left {
 | 
				
			||||||
 | 
								display: flex;
 | 
				
			||||||
 | 
								align-items: center;
 | 
				
			||||||
 | 
								flex: 1;
 | 
				
			||||||
 | 
								.icon {
 | 
				
			||||||
 | 
									margin-right: 20rpx;
 | 
				
			||||||
 | 
									width: 60rpx;
 | 
				
			||||||
 | 
									height: 60rpx;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								.text {
 | 
				
			||||||
 | 
									flex: 1;
 | 
				
			||||||
 | 
									font-size: 32rpx;
 | 
				
			||||||
 | 
									font-weight: bold;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								.is-left {
 | 
				
			||||||
 | 
									text-align: left;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								.is-center {
 | 
				
			||||||
 | 
									text-align: center;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							.right {
 | 
				
			||||||
 | 
								display: flex;
 | 
				
			||||||
 | 
								justify-content: flex-end;
 | 
				
			||||||
 | 
								align-items: center;
 | 
				
			||||||
 | 
								.icon {
 | 
				
			||||||
 | 
									margin-left: 20rpx;
 | 
				
			||||||
 | 
									width: 40rpx;
 | 
				
			||||||
 | 
									height: 40rpx;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								.text {
 | 
				
			||||||
 | 
									font-size: 24rpx;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view class="fix-top-bar" v-if="isShow">
 | 
				
			||||||
 | 
						<view
 | 
				
			||||||
 | 
								v-if="fixed"
 | 
				
			||||||
 | 
								:style="{
 | 
				
			||||||
 | 
									paddingTop: `${(statusBar ? 0 : statusBarHeight) + 44}px`,
 | 
				
			||||||
 | 
								}"
 | 
				
			||||||
 | 
							></view>
 | 
				
			||||||
 | 
							<cl-topbar
 | 
				
			||||||
 | 
								:title="title"
 | 
				
			||||||
 | 
								:color="color"
 | 
				
			||||||
 | 
								:border="border"
 | 
				
			||||||
 | 
								:fixed="fixed"
 | 
				
			||||||
 | 
								:showBack="showBack"
 | 
				
			||||||
 | 
								:withMp="true"
 | 
				
			||||||
 | 
								:background-color="backgroundColor"
 | 
				
			||||||
 | 
							></cl-topbar>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup name="fix-top-bar">
 | 
				
			||||||
 | 
					const { statusBarHeight = 0 } = uni.getSystemInfoSync();
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						backgroundColor: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "#fff",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						color: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "black",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						title: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						isShow: Boolean,
 | 
				
			||||||
 | 
						showBack: Boolean,
 | 
				
			||||||
 | 
						border: Boolean,
 | 
				
			||||||
 | 
						fixed: Boolean,
 | 
				
			||||||
 | 
						statusBar: Boolean,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped></style>
 | 
				
			||||||
							
								
								
									
										65
									
								
								uni_modules/cool-fixtures/components/fix-video/fix-video.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								uni_modules/cool-fixtures/components/fix-video/fix-video.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style :styleSpacing="styleSpacing" :styleColor="styleColor" :index="index">
 | 
				
			||||||
 | 
							<div class="fix-video">
 | 
				
			||||||
 | 
								<div class="inner" v-if="video">
 | 
				
			||||||
 | 
									<video
 | 
				
			||||||
 | 
										:src="video"
 | 
				
			||||||
 | 
										:poster="cover"
 | 
				
			||||||
 | 
										class="vertical"
 | 
				
			||||||
 | 
										controls
 | 
				
			||||||
 | 
										:class="[mode == 'horizontal' ? 'horizontal' : 'vertical']"
 | 
				
			||||||
 | 
									></video>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-video" setup>
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						mode: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "horizontal",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						video: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						cover: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						type: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							default: "local",
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						index: {
 | 
				
			||||||
 | 
							type: Number,
 | 
				
			||||||
 | 
							default: 0,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						...baseProps,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-video {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
						video {
 | 
				
			||||||
 | 
							margin: 0;
 | 
				
			||||||
 | 
							padding: 0;
 | 
				
			||||||
 | 
							display: block; /* 避免 inline 元素造成的间隙 */
 | 
				
			||||||
 | 
							object-fit: cover;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						.vertical {
 | 
				
			||||||
 | 
							width: 750rpx;
 | 
				
			||||||
 | 
							height: 1334rpx; /* 高度根据宽高比自动调整 */
 | 
				
			||||||
 | 
							object-fit: contain; /* 保持视频的宽高比,不会拉伸 */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						.horizontal {
 | 
				
			||||||
 | 
							width: 750rpx; /* 屏幕宽度适配 */
 | 
				
			||||||
 | 
							height: calc(750rpx * 9 / 16); /* 适用于 16:9 的宽高比 */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<fix-base-style :styleSpacing="styleSpacing">
 | 
				
			||||||
 | 
							<view class="fix-wechat" v-show="is_show">
 | 
				
			||||||
 | 
								<!-- #ifdef MP-WEIXIN -->
 | 
				
			||||||
 | 
								<official-account @bindload="load" @binderror="error"></official-account>
 | 
				
			||||||
 | 
								<!-- #endif -->
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</fix-base-style>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" name="fix-wechat" setup>
 | 
				
			||||||
 | 
					import { ref } from "vue";
 | 
				
			||||||
 | 
					import { baseProps } from "../../hooks";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					defineProps({ ...baseProps });
 | 
				
			||||||
 | 
					const is_show = ref(false);
 | 
				
			||||||
 | 
					function load() {
 | 
				
			||||||
 | 
						is_show.value = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					function error() {
 | 
				
			||||||
 | 
						is_show.value = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss" scoped>
 | 
				
			||||||
 | 
					.fix-wechat {
 | 
				
			||||||
 | 
						box-sizing: border-box;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										8
									
								
								uni_modules/cool-fixtures/config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								uni_modules/cool-fixtures/config.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					import type { ModuleConfig } from "/@/cool";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default (): ModuleConfig => {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        // 描述
 | 
				
			||||||
 | 
					        description: "在coo-uni基础上开发的自定义页面,修改或新增组件非常简单!",
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										36
									
								
								uni_modules/cool-fixtures/hooks/base-props.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								uni_modules/cool-fixtures/hooks/base-props.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					export const baseProps = {
 | 
				
			||||||
 | 
					    styleSpacing: {
 | 
				
			||||||
 | 
					        type: Object,
 | 
				
			||||||
 | 
					        default: () => {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                marginTop: 0,
 | 
				
			||||||
 | 
					                marginBottom: 0,
 | 
				
			||||||
 | 
					                marginLR: 0,
 | 
				
			||||||
 | 
					                padding: 0,
 | 
				
			||||||
 | 
					                borderTopLR: 0,
 | 
				
			||||||
 | 
					                borderBottomLR: 0,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    styleColor: {
 | 
				
			||||||
 | 
					        type: Object,
 | 
				
			||||||
 | 
					        default: () => {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                color: "#000",
 | 
				
			||||||
 | 
					                backgroundColor: "#FFFFFF",
 | 
				
			||||||
 | 
					                opacity: 1,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    position: {
 | 
				
			||||||
 | 
					        type: Object,
 | 
				
			||||||
 | 
					        default: () => {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                mode: "static",
 | 
				
			||||||
 | 
					                top: 0,
 | 
				
			||||||
 | 
					                zIndex: 1,
 | 
				
			||||||
 | 
					                isSeat: true,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								uni_modules/cool-fixtures/hooks/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								uni_modules/cool-fixtures/hooks/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					export * from "./base-props";
 | 
				
			||||||
							
								
								
									
										54
									
								
								uni_modules/cool-fixtures/pages/detail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								uni_modules/cool-fixtures/pages/detail.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<cl-page :backgroundColor="data.background" :backgroundImage="data.backgroundImage" :statusBar="!!data.statusBar"
 | 
				
			||||||
 | 
							:statusBarBackground="data.statusBarColor">
 | 
				
			||||||
 | 
							<fix-index :list="data.data" :statusBar="!!data.statusBar"></fix-index>
 | 
				
			||||||
 | 
						</cl-page>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
						import { ref, nextTick } from "vue";
 | 
				
			||||||
 | 
						import { useCool } from "/@/cool";
 | 
				
			||||||
 | 
						import { onReady, onPageScroll, onLoad } from "@dcloudio/uni-app";
 | 
				
			||||||
 | 
						import { useUi } from "/$/cool-ui";
 | 
				
			||||||
 | 
						defineProps({ id: String });
 | 
				
			||||||
 | 
						const { service } = useCool();
 | 
				
			||||||
 | 
						const ui = useUi();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const data = ref({
 | 
				
			||||||
 | 
							background: "#f5f6fa",
 | 
				
			||||||
 | 
							backgroundImage: "",
 | 
				
			||||||
 | 
							statusBarColor: "",
 | 
				
			||||||
 | 
							statusBar: 1,
 | 
				
			||||||
 | 
							name: "",
 | 
				
			||||||
 | 
							data: [],
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function getPage(id : string) {
 | 
				
			||||||
 | 
							service.fixtures.mould
 | 
				
			||||||
 | 
								.getPage({ id })
 | 
				
			||||||
 | 
								.then((res : any) => {
 | 
				
			||||||
 | 
									data.value = res;
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.catch((e) => {
 | 
				
			||||||
 | 
									ui.showToast(e.message);
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.finally(() => {
 | 
				
			||||||
 | 
									nextTick().then(() => {
 | 
				
			||||||
 | 
										uni.hideLoading();
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// 加载数据
 | 
				
			||||||
 | 
						function loadSuccess(query : any) {
 | 
				
			||||||
 | 
							getPage(query.id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						onReady(() => { });
 | 
				
			||||||
 | 
						onLoad((query : any) => {
 | 
				
			||||||
 | 
							uni.showLoading({
 | 
				
			||||||
 | 
								title: "加载中...",
 | 
				
			||||||
 | 
								mask: true,
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							loadSuccess(query)
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						onPageScroll(() => { });
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
							
								
								
									
										54
									
								
								uni_modules/cool-fixtures/pages/preview.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								uni_modules/cool-fixtures/pages/preview.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<cl-page :backgroundColor="data.background" :backgroundImage="data.backgroundImage" :statusBar="!!data.statusBar"
 | 
				
			||||||
 | 
							:statusBarBackground="data.statusBarColor">
 | 
				
			||||||
 | 
							<fix-index :list="data.form" :statusBar="!!data.statusBar"></fix-index>
 | 
				
			||||||
 | 
						</cl-page>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
						import { ref, nextTick } from "vue";
 | 
				
			||||||
 | 
						import { useCool } from "/@/cool";
 | 
				
			||||||
 | 
						import { onReady, onPageScroll, onLoad } from "@dcloudio/uni-app";
 | 
				
			||||||
 | 
						import { useUi } from "/$/cool-ui";
 | 
				
			||||||
 | 
						defineProps({ id: String });
 | 
				
			||||||
 | 
						const { service } = useCool();
 | 
				
			||||||
 | 
						const ui = useUi();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const data = ref({
 | 
				
			||||||
 | 
							background: "#f5f6fa",
 | 
				
			||||||
 | 
							backgroundImage: "",
 | 
				
			||||||
 | 
							statusBarColor: "",
 | 
				
			||||||
 | 
							statusBar: 1,
 | 
				
			||||||
 | 
							name: "",
 | 
				
			||||||
 | 
							form: [],
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function getPage(id : string) {
 | 
				
			||||||
 | 
							service.fixtures.mould
 | 
				
			||||||
 | 
								.getPage({ id })
 | 
				
			||||||
 | 
								.then((res : any) => {
 | 
				
			||||||
 | 
									data.value = res;
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.catch((e) => {
 | 
				
			||||||
 | 
									ui.showToast(e.message);
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								.finally(() => {
 | 
				
			||||||
 | 
									nextTick().then(() => {
 | 
				
			||||||
 | 
										uni.hideLoading();
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// 加载数据
 | 
				
			||||||
 | 
						function loadSuccess(query : any) {
 | 
				
			||||||
 | 
							getPage(query.id);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						onReady(() => { });
 | 
				
			||||||
 | 
						onLoad((query : any) => {
 | 
				
			||||||
 | 
							uni.showLoading({
 | 
				
			||||||
 | 
								title: "加载中...",
 | 
				
			||||||
 | 
								mask: true,
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							loadSuccess(query)
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						onPageScroll(() => { });
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
							
								
								
									
										23
									
								
								uni_modules/cool-fixtures/pages_init.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								uni_modules/cool-fixtures/pages_init.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "subPackages": [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "root": "uni_modules/cool-fixtures/pages",
 | 
				
			||||||
 | 
					        "pages": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "path": "detail",
 | 
				
			||||||
 | 
					                "style": {
 | 
				
			||||||
 | 
					                   "navigationStyle": "custom",
 | 
				
			||||||
 | 
					                  "navigationBarTitleText": "自定义页面"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "path": "preview",
 | 
				
			||||||
 | 
					            "style": {
 | 
				
			||||||
 | 
					              "navigationStyle": "custom",
 | 
				
			||||||
 | 
					              "navigationBarTitleText": "页面预览"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										109
									
								
								uni_modules/cool-fixtures/types/form.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								uni_modules/cool-fixtures/types/form.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					export declare namespace Form {
 | 
				
			||||||
 | 
					    interface Menu {
 | 
				
			||||||
 | 
					        text: string,
 | 
				
			||||||
 | 
					        useText: boolean,
 | 
				
			||||||
 | 
					        mode: string,
 | 
				
			||||||
 | 
					        link: Link,
 | 
				
			||||||
 | 
					        icon: string,
 | 
				
			||||||
 | 
					        color: string,
 | 
				
			||||||
 | 
					        backgroundColor: string
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    interface Link {
 | 
				
			||||||
 | 
					        page: string,
 | 
				
			||||||
 | 
					        appid: string,
 | 
				
			||||||
 | 
					        type: string,
 | 
				
			||||||
 | 
					        name: string
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    interface Banner {
 | 
				
			||||||
 | 
					        pic: string,
 | 
				
			||||||
 | 
					        link: Link
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    interface Spacing {
 | 
				
			||||||
 | 
					        marginTop: number,
 | 
				
			||||||
 | 
					        marginBottom: number,
 | 
				
			||||||
 | 
					        marginLR: number,
 | 
				
			||||||
 | 
					        padding: number,
 | 
				
			||||||
 | 
					        borderTopLR: number,
 | 
				
			||||||
 | 
					        borderBottomLR: number
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    interface Color {
 | 
				
			||||||
 | 
					        color: string,
 | 
				
			||||||
 | 
					        backgroundColor: string,
 | 
				
			||||||
 | 
					        opacity: number
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    interface Picture {
 | 
				
			||||||
 | 
					        pic: string,
 | 
				
			||||||
 | 
					        link: Link
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    interface Title {
 | 
				
			||||||
 | 
					        text: string,
 | 
				
			||||||
 | 
					        text2?: string,
 | 
				
			||||||
 | 
					        color: string,
 | 
				
			||||||
 | 
					        icon: string,
 | 
				
			||||||
 | 
					        link: Link
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    interface Hot {
 | 
				
			||||||
 | 
					        x: number,
 | 
				
			||||||
 | 
					        y: number,
 | 
				
			||||||
 | 
					        w: number,
 | 
				
			||||||
 | 
					        h: number,
 | 
				
			||||||
 | 
					        relativeX: number,
 | 
				
			||||||
 | 
					        relativeY: number,
 | 
				
			||||||
 | 
					        relativeW: number,
 | 
				
			||||||
 | 
					        relativeH: number,
 | 
				
			||||||
 | 
					        index: number,
 | 
				
			||||||
 | 
					        link: Link
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    interface HotImage {
 | 
				
			||||||
 | 
					        pic: string,
 | 
				
			||||||
 | 
					        link: Link,
 | 
				
			||||||
 | 
					        width: number,
 | 
				
			||||||
 | 
					        height: number,
 | 
				
			||||||
 | 
					        attr: Hot[]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    interface RubikCubeMode {
 | 
				
			||||||
 | 
					        type: string,
 | 
				
			||||||
 | 
					        label: string,
 | 
				
			||||||
 | 
					        list: {
 | 
				
			||||||
 | 
					            icon: string,
 | 
				
			||||||
 | 
					            tips: string,
 | 
				
			||||||
 | 
					            link: Link
 | 
				
			||||||
 | 
					        }[]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    interface RubikCube {
 | 
				
			||||||
 | 
					        mode: string,
 | 
				
			||||||
 | 
					        gap: number,
 | 
				
			||||||
 | 
					        list: {
 | 
				
			||||||
 | 
					            icon: string,
 | 
				
			||||||
 | 
					            tips: string,
 | 
				
			||||||
 | 
					            link: Link
 | 
				
			||||||
 | 
					        }[]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    interface Goods {
 | 
				
			||||||
 | 
					        mode: string,
 | 
				
			||||||
 | 
					        source: string,
 | 
				
			||||||
 | 
					        gap: number,
 | 
				
			||||||
 | 
					        num: number,
 | 
				
			||||||
 | 
					        attribute: number,
 | 
				
			||||||
 | 
					        isVoucher: boolean,
 | 
				
			||||||
 | 
					        isShadow: boolean,
 | 
				
			||||||
 | 
					        type: { name: string, pic?: string, id: number }[],
 | 
				
			||||||
 | 
					        list: {
 | 
				
			||||||
 | 
					            mainPic: string,
 | 
				
			||||||
 | 
					            title: string,
 | 
				
			||||||
 | 
					            price: number,
 | 
				
			||||||
 | 
					            sold: number,
 | 
				
			||||||
 | 
					            attribute?: number,
 | 
				
			||||||
 | 
					            id: number,
 | 
				
			||||||
 | 
					        }[]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    interface Suspension {
 | 
				
			||||||
 | 
					        icon: string;
 | 
				
			||||||
 | 
					        tips: string,
 | 
				
			||||||
 | 
					        link: Link
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -5,11 +5,12 @@
 | 
				
			|||||||
			`theme-${app.theme.name}`,
 | 
								`theme-${app.theme.name}`,
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				'is-fullscreen': fullscreen,
 | 
									'is-fullscreen': fullscreen,
 | 
				
			||||||
 | 
									'is-safe-area-bottom': fullscreen,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		]"
 | 
							]"
 | 
				
			||||||
		:style="{
 | 
							:style="{
 | 
				
			||||||
			padding: parseRpx(padding),
 | 
								padding: parseRpx(padding),
 | 
				
			||||||
			height,
 | 
								height
 | 
				
			||||||
		}"
 | 
							}"
 | 
				
			||||||
	>
 | 
						>
 | 
				
			||||||
		<!-- 加载框 -->
 | 
							<!-- 加载框 -->
 | 
				
			||||||
@ -42,14 +43,16 @@
 | 
				
			|||||||
	<view
 | 
						<view
 | 
				
			||||||
		class="cl-page__bg"
 | 
							class="cl-page__bg"
 | 
				
			||||||
		:style="{
 | 
							:style="{
 | 
				
			||||||
			background,
 | 
								backgroundColor: background,
 | 
				
			||||||
 | 
								backgroundImage: 'url(' + backgroundImage + ')',
 | 
				
			||||||
		}"
 | 
							}"
 | 
				
			||||||
	></view>
 | 
						></view>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
import { computed, defineComponent, reactive, getCurrentInstance, onMounted } from "vue";
 | 
					import { onPageScroll } from "@dcloudio/uni-app";
 | 
				
			||||||
import { useApp, useCool } from "/@/cool";
 | 
					import { computed, defineComponent, ref, reactive, getCurrentInstance, onMounted } from "vue";
 | 
				
			||||||
 | 
					import { useApp, useCool} from "/@/cool";
 | 
				
			||||||
import { parseRpx } from "/@/cool/utils";
 | 
					import { parseRpx } from "/@/cool/utils";
 | 
				
			||||||
import { isString } from "lodash-es";
 | 
					import { isString } from "lodash-es";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -73,6 +76,11 @@ export default defineComponent({
 | 
				
			|||||||
		statusBarBackground: String,
 | 
							statusBarBackground: String,
 | 
				
			||||||
		// 页面背景色
 | 
							// 页面背景色
 | 
				
			||||||
		backgroundColor: String,
 | 
							backgroundColor: String,
 | 
				
			||||||
 | 
							// 背景图片
 | 
				
			||||||
 | 
							backgroundImage: {
 | 
				
			||||||
 | 
								type: String,
 | 
				
			||||||
 | 
								default: "",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setup(props) {
 | 
						setup(props) {
 | 
				
			||||||
@ -89,8 +97,9 @@ export default defineComponent({
 | 
				
			|||||||
		const { proxy }: any = getCurrentInstance();
 | 
							const { proxy }: any = getCurrentInstance();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// 是否显示导航栏
 | 
							// 是否显示导航栏
 | 
				
			||||||
		const statusBar = info?.isCustomNavbar ? props.statusBar : false;
 | 
							const statusBar = computed(() => {
 | 
				
			||||||
 | 
								return info?.isCustomNavbar ? props.statusBar : false;
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
		// 背景色
 | 
							// 背景色
 | 
				
			||||||
		const background = computed(() => {
 | 
							const background = computed(() => {
 | 
				
			||||||
			return (
 | 
								return (
 | 
				
			||||||
@ -112,14 +121,15 @@ export default defineComponent({
 | 
				
			|||||||
			// #ifdef H5
 | 
								// #ifdef H5
 | 
				
			||||||
			h = windowHeight;
 | 
								h = windowHeight;
 | 
				
			||||||
			// #endif
 | 
								// #endif
 | 
				
			||||||
 | 
					 | 
				
			||||||
			// #ifndef H5
 | 
								// #ifndef H5
 | 
				
			||||||
			h = screenHeight - statusBarHeight;
 | 
								h = screenHeight - (statusBar ? statusBarHeight : 0);
 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (!info?.isCustomNavbar) {
 | 
								if (!info?.isCustomNavbar) {
 | 
				
			||||||
				h -= 44;
 | 
									h -= 44;
 | 
				
			||||||
 | 
									h -= statusBarHeight;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// #endif
 | 
								// #endif
 | 
				
			||||||
 | 
								if (props.fullscreen) return h + "px";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return h - (safeAreaInsets?.bottom || 0) + "px";
 | 
								return h - (safeAreaInsets?.bottom || 0) + "px";
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
@ -199,11 +209,11 @@ export default defineComponent({
 | 
				
			|||||||
			uni.createSelectorQuery()
 | 
								uni.createSelectorQuery()
 | 
				
			||||||
				.in(proxy)
 | 
									.in(proxy)
 | 
				
			||||||
				.select(".cl-page")
 | 
									.select(".cl-page")
 | 
				
			||||||
				.boundingClientRect((a) => {
 | 
									.boundingClientRect((a: any) => {
 | 
				
			||||||
					uni.createSelectorQuery()
 | 
										uni.createSelectorQuery()
 | 
				
			||||||
						.in(proxy)
 | 
											.in(proxy)
 | 
				
			||||||
						.select(".safe-area-bottom")
 | 
											.select(".safe-area-bottom")
 | 
				
			||||||
						.boundingClientRect((b) => {
 | 
											.boundingClientRect((b: any) => {
 | 
				
			||||||
							const scrollTop = top + (a?.height || 0) - (b?.bottom || 0);
 | 
												const scrollTop = top + (a?.height || 0) - (b?.bottom || 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							uni.pageScrollTo({
 | 
												uni.pageScrollTo({
 | 
				
			||||||
@ -215,13 +225,18 @@ export default defineComponent({
 | 
				
			|||||||
				})
 | 
									})
 | 
				
			||||||
				.exec();
 | 
									.exec();
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
							const scrollTop = ref(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							onPageScroll((e: any) => {
 | 
				
			||||||
 | 
								scrollTop.value = e.scrollTop;
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
		return {
 | 
							return {
 | 
				
			||||||
			app,
 | 
								app,
 | 
				
			||||||
			background,
 | 
								background,
 | 
				
			||||||
			height,
 | 
								height,
 | 
				
			||||||
			refs,
 | 
								refs,
 | 
				
			||||||
			setRefs,
 | 
								setRefs,
 | 
				
			||||||
 | 
								scrollTop,
 | 
				
			||||||
			loader,
 | 
								loader,
 | 
				
			||||||
			parseRpx,
 | 
								parseRpx,
 | 
				
			||||||
			statusBar,
 | 
								statusBar,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user