初始版本

This commit is contained in:
贾祥聪
2025-08-19 14:16:51 +08:00
commit f937a1f9b9
4373 changed files with 359728 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
<template>
<view
class="banner translate-y-0"
:class="{ 'px-[20rpx]': !isLargeScreen }"
v-if="content.data.length && content.enabled"
>
<LSwiper
:content="content"
:height="isLargeScreen ? '1100' : '321'"
:circular="true"
:effect3d="false"
:border-radius="isLargeScreen ? '0' : '14'"
interval="7000"
bgColor="transparent"
@change="handleChange"
></LSwiper>
</view>
</template>
<script setup lang="ts">
import LSwiper from '@/components/l-swiper/l-swiper.vue'
import {useAppStore} from "@/stores/app";
const emit = defineEmits(['change'])
const props = defineProps({
content: {
type: Object,
default: () => ({})
},
styles: {
type: Object,
default: () => ({})
},
isLargeScreen: {
type: Boolean
}
})
const {getImageUrl} = useAppStore();
const handleChange = (index: number) => {
emit('change', getImageUrl(props['content'].data[index].bg))
}
</script>

View File

@@ -0,0 +1,65 @@
<template>
<view class="bg-white p-[30rpx] flex text-[#101010] font-medium text-lg">
联系我们
</view>
<view
class="customer-service bg-white flex flex-col justify-center items-center mx-[36rpx] mt-[30rpx] rounded-[20rpx] px-[20rpx] pb-[100rpx]"
>
<view
class="w-full border-solid border-0 border-b border-[#f5f5f5] p-[30rpx] text-center text-[#101010] text-base font-medium">
{{ content.title }}
</view>
<view class="mt-[60rpx]">
<!-- 这样渲染是为了能在小程序中长按识别二维码 -->
<u-parse :html="richTxt"></u-parse>
<!-- <u-image width="200" height="200" border-radius="10rpx" :src="getImageUrl(content.qrcode)"/>-->
</view>
<view v-if="content.remark" class="text-sm mt-[40rpx] font-medium">{{ content.remark }}</view>
<view v-if="content.mobile" class="text-sm mt-[24rpx] flex flex-wrap">
<!-- #ifdef H5 -->
<a class="ml-[10rpx] phone text-primary underline" :href="'tel:' + content.mobile">
{{ content.mobile }}
</a>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="ml-[10rpx] phone text-primary underline" @click="handleCall">
{{ content.mobile }}
</view>
<!-- #endif -->
</view>
<view v-if="content.time" class="text-muted text-sm mt-[30rpx]">
服务时间{{ content.time }}
</view>
</view>
</template>
<script lang="ts" setup>
import {useAppStore} from '@/stores/app'
import { computed } from 'vue'
const props = defineProps({
content: {
type: Object,
default: () => ({})
},
styles: {
type: Object,
default: () => ({})
}
})
const {getImageUrl} = useAppStore()
const richTxt = computed(() => {
const src = getImageUrl(props.content.qrcode)
return `<img src="${src}" style="width: 100px;height: 100px; border-radius: 8px" />`
})
const handleCall = () => {
uni.makePhoneCall({
phoneNumber: String(props.content.mobile)
})
}
</script>
<style lang="scss"></style>

View File

@@ -0,0 +1,54 @@
<template>
<view
class="banner h-[200rpx] mx-[20rpx] mt-[20rpx] translate-y-0"
v-if="showList.length && content.enabled"
>
<swiper
class="swiper h-full"
:indicator-dots="showList.length > 1"
indicator-active-color="#4173ff"
:autoplay="true"
>
<swiper-item
v-for="(item, index) in showList"
:key="index"
@click="handleClick(item.link)"
>
<u-image
mode="widthFix"
width="100%"
height="100%"
:src="getImageUrl(item.image)"
:border-radius="14"
/>
</swiper-item>
</swiper>
</view>
</template>
<script setup lang="ts">
import { useAppStore } from '@/stores/app'
import { navigateTo } from '@/utils/util'
import { computed } from 'vue'
const props = defineProps({
content: {
type: Object,
default: () => ({})
},
styles: {
type: Object,
default: () => ({})
}
})
const handleClick = (link: any) => {
navigateTo(link)
}
const { getImageUrl } = useAppStore()
const showList = computed(() => {
return props.content.data?.filter((item: any) => item.is_show == '1') || []
})
</script>
<style></style>

View File

@@ -0,0 +1,75 @@
<template>
<div class="relative mx-[20rpx] mt-[20rpx]">
<swiper
class="py-[20rpx] bg-white rounded-lg"
:style="{
height: navList[0].length > content.per_line ? '288rpx' : '132rpx'
}"
:autoplay="false"
:indicator-dots="false"
@change="swiperChange"
>
<swiper-item v-for="(sItem, sIndex) in navList" :key="sIndex">
<view class="nav" v-if="navList.length && content.enabled">
<view
class="grid grid-rows-auto gap-y-3 w-full"
:style="{ 'grid-template-columns': `repeat(${content.per_line}, 1fr)` }"
>
<view
v-for="(item, index) in sItem"
:key="index"
class="flex flex-col items-center"
@click="handleClick(item.link)"
>
<u-image width="82" height="82" :src="getImageUrl(item.image)" alt=""/>
<view class="mt-[14rpx] text-xs">{{ item.name }}</view>
</view>
</view>
</view>
</swiper-item>
</swiper>
</div>
</template>
<script setup lang="ts">
import {ref, watch, computed} from 'vue'
import {useAppStore} from '@/stores/app'
import {navigateTo, sliceArray} from '@/utils/util'
const props = defineProps({
content: {
type: Object,
default: () => ({})
},
styles: {
type: Object,
default: () => ({})
}
})
const {getImageUrl} = useAppStore()
const swiperCurrent = ref<number>(0)
const navList = ref<Record<string, any>>([])
const pagesNum = computed<number>(() => {
return props.content.per_line * props.content.show_line
})
watch(
() => props.content.data,
(val) => {
const num = props.content.style === 1 ? val.length : pagesNum.value
navList.value = sliceArray(val, num)
console.log(navList.value)
},
{deep: true, immediate: true}
)
const handleClick = (link: any) => {
navigateTo(link)
}
const swiperChange = (e: any) => {
swiperCurrent.value = e.detail.current
}
</script>

View File

@@ -0,0 +1,93 @@
<template>
<!-- #ifndef H5 -->
<u-sticky h5-nav-height="0" bg-color="transparent">
<u-navbar
:class="{ 'fixed top-0 z-10': isLargeScreen }"
:is-back="false"
:is-fixed="true"
:title="metaData.title"
:custom-title="metaData.title_type == 2"
:border-bottom="false"
:title-bold="true"
:background="{ background: 'rgba(256,256, 256, 0)' }"
:title-color="percent > 0.5 ? '#000' : metaData.text_color == 1 ? '#fff' : '#000'"
>
<template #default>
<view class="px-[24px] py-[30px] flex items-center">
<u-image src="" height="50" width="50" border-radius="999"></u-image>
<text class="ml-1 text-white">肩颈管家·精油按摩(雅乐店)</text>
</view>
<!-- <navigator
url="/pages/search/search"
class="mini-search"
hover-class="none"
:style="{ opacity: isLargeScreen ? 1 : percent }"
>
<u-icon name="search"></u-icon>
</navigator> -->
</template>
<!-- <template #title>
<image class="!h-[54rpx]" :src="metaData.title_img" mode="widthFix"></image>
</template> -->
</u-navbar>
</u-sticky>
<!-- #endif -->
<!-- <navigator
v-if="!isLargeScreen"
url="/pages/search/search"
class="px-[24rpx] mt-[24rpx] mb-[30rpx]"
:style="{ opacity: 1 - percent }"
hover-class="none"
>
<u-search
placeholder="请输入关键词搜索"
:height="72"
:disabled="true"
:show-action="false"
bgColor="#ffffff"
></u-search>
</navigator> -->
</template>
<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps({
pageMeta: {
type: Object,
default: () => []
},
content: {
type: Object,
default: () => ({})
},
styles: {
type: Object,
default: () => ({})
},
isLargeScreen: {
type: Boolean
},
percent: {
type: Number
}
})
const metaData: any = computed(() => {
return props.pageMeta[0].content
})
</script>
<style scoped>
.mini-search {
display: flex;
align-items: center;
justify-content: center;
width: 60rpx;
height: 60rpx;
margin-left: 20rpx;
background-color: #ffffff;
border-radius: 50%;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.2);
}
</style>

View File

@@ -0,0 +1,49 @@
<template>
<view
class="banner h-[200rpx] mx-[20rpx] mt-[20rpx] translate-y-0"
v-if="content.data.length && content.enabled"
>
<swiper
class="swiper h-full"
:indicator-dots="content.data.length > 1"
indicator-active-color="#4173ff"
:autoplay="true"
>
<swiper-item
v-for="(item, index) in content.data"
:key="index"
@click="handleClick(item.limk)"
>
<u-image
mode="aspectFit"
width="100%"
height="100%"
:src="getImageUrl(item.image)"
:border-radius="14"
/>
</swiper-item>
</swiper>
</view>
</template>
<script setup lang="ts">
import { useAppStore } from '@/stores/app'
import { navigateTo } from '@/utils/util'
const props = defineProps({
content: {
type: Object,
default: () => ({})
},
styles: {
type: Object,
default: () => ({})
}
})
const handleClick = (link: any) => {
navigateTo(link)
}
const { getImageUrl } = useAppStore()
</script>
<style></style>

View File

@@ -0,0 +1,170 @@
<template>
<view class="user-info" v-if="content.enabled">
<view class="flex items-center justify-between px-[30rpx] pb-[30rpx] pt-[20rpx]">
<view
v-if="isLogin"
class="flex items-center w-full"
@click="router.navigate('/pages/user_set/user_set')"
>
<u-avatar :src="userInfo.logo" :size="108"></u-avatar>
<view class="ml-[28rpx] text-black">
<view class="text-xl text-main font-medium">{{ userInfo.name }}</view>
<view
v-if="content.user_info == 2"
class="text-base mt-1 text-content"
@click.stop="copy(userInfo.mobile)"
>
手机号{{ userInfo.mobile || '-' }}
</view>
<view
v-else
class="text-base mt-1 text-content"
@click.stop="copy(userInfo.sn)"
>
工号: {{ userInfo.sn || '-' }}
</view>
</view>
</view>
<navigator
v-else
class="flex items-center text-black"
hover-class="none"
url="/pages/login/login"
>
<u-avatar src="/static/images/user/default_avatar.png" :size="108"></u-avatar>
<view class="ml-[28rpx] text-black">
<view class="text-xl text-main font-bold">立即登录/注册</view>
<view class="text-base text-content mt-1">
登录后查看更多
</view>
</view>
</navigator>
<navigator v-if="isLogin" hover-class="none" url="/pages/user_set/user_set">
<u-icon name="arrow-right" color="#999" :size="28"></u-icon>
</navigator>
<navigator v-else hover-class="none" url="/pages/login/login">
<u-icon name="arrow-right" color="#999" :size="28"></u-icon>
</navigator>
</view>
<view class="bg-white mt-4 rounded-xl p-[10px]">
<view class="flex justify-around py-2">
<view
class="text-center"
v-if="content.content?.includes('value1')"
@click="router.navigateTo('/packages/pages/my_master/my_master')"
>
<view class="text-[20px] font-bold">
{{ userInfo?.coach_count || 0 }}</view>
<view class="text-muted">我的技师</view>
</view>
<view
class="text-center"
v-if="content.content?.includes('value2')"
@click="router.navigateTo('/packages/pages/platform_project/platform_project')"
>
<view class="text-[20px] font-bold">
{{ userInfo?.goods_count || 0 }}
</view>
<view class="text-muted">平台项目</view>
</view>
<view
class="text-center"
v-if="content.content?.includes('value3')"
@click="router.navigateTo('/packages/pages/my_project/my_project')"
>
<view class="text-[20px] font-bold">{{ userInfo?.shop_goods_count || 0 }}</view>
<view class="text-muted">店铺项目</view>
</view>
</view>
<view class="flex gap-x-[10px] mt-2">
<view
class="comment flex flex-1 text-[#4A65A3]"
@click="router.navigateTo('/packages/pages/bond/bond')"
>
<view class="w-full">
<view class="text-xl font-medium">
{{ userInfo?.deposit || 0 }}
</view>
<view class="mt-1 flex items-center">
<view class="text-xs mr-[4rpx]">
我的保证金
</view>
<u-icon name="arrow-right" color="#4A65A3" :size="20">
</u-icon>
</view>
</view>
</view>
<view
class="wallet flex flex-1 text-[#2DA9BC]"
@click="router.navigateTo('/packages/pages/balance/balance')"
>
<view class="w-full">
<view class="text-xl font-medium">
{{ userInfo?.money || 0 }}
</view>
<view class="mt-1 flex items-center">
<view class="text-xs mr-[4rpx]">
我的账户余额
</view>
<u-icon name="arrow-right" color="#2DA9BC" :size="20">
</u-icon>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { useCopy } from '@/hooks/useCopy'
import { useRouter } from 'uniapp-router-next'
const { copy } = useCopy()
const router = useRouter()
const props = defineProps({
content: {
type: Object,
default: () => ({})
},
styles: {
type: Object,
default: () => ({})
},
userInfo: {
type: Object,
default: () => ({})
},
isLogin: {
type: Boolean
}
})
const navigateTo = (url: string) => {
uni.navigateTo({
url
})
}
</script>
<style lang="scss" scoped>
.user-info {
padding: 24px 12px 0 12px;
.comment {
background-color: #e0ebfd;
background-image: url('@/static/images/user/bg_wdbzj.png');
background-size: 100% auto;
border-radius: 10px;
padding: 10px;
}
.wallet {
background-color: #c7effb;
background-image: url('@/static/images/user/bg_wdzhye.png');
background-size: 100% auto;
border-radius: 10px;
padding: 10px;
}
}
</style>

View File

@@ -0,0 +1,63 @@
<template>
<div
class="user-service bg-white mx-[30rpx] mt-[30rpx] rounded-lg p-[30rpx]"
v-if="content.enabled"
>
<div
v-if="content.title"
class="title text-content text-base"
>
<div>{{ content.title }}</div>
</div>
<!-- 横排 -->
<div v-if="content.style == 1" class="grid grid-cols-4 gap-x-6">
<div
v-for="(item, index) in content.data"
:key="index"
class="flex flex-col items-center pt-[40rpx]"
@click="handleClick(item.link)"
v-show="Number(item.is_show)"
>
<u-image width="68" height="68" :src="getImageUrl(item.image)" alt="" />
<div class="mt-2 text-xs">{{ item.name }}</div>
</div>
</div>
<!-- 竖排 -->
<div v-if="content.style == 2">
<div
v-for="(item, index) in content.data"
:key="index"
class="flex items-center h-[100rpx] px-[24rpx]"
@click="handleClick(item.link)"
v-show="Number(item.is_show)"
>
<u-image width="52" height="52" :src="getImageUrl(item.image)" alt="" />
<div class="ml-[20rpx] flex-1">{{ item.name }}</div>
<div class="text-muted">
<u-icon name="arrow-right" />
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { useAppStore } from '@/stores/app'
import { navigateTo } from '@/utils/util'
const props = defineProps({
content: {
type: Object,
default: () => ({})
},
styles: {
type: Object,
default: () => ({})
}
})
const { getImageUrl } = useAppStore()
const handleClick = (link: any) => {
navigateTo(link)
}
</script>
<style lang="scss"></style>