新增
This commit is contained in:
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div class="my-service bg-white mx-[20rpx] mt-[20rpx] rounded-lg p-[30rpx]">
|
||||
<div
|
||||
v-if="content.title"
|
||||
class="title font-medium text-lg"
|
||||
>
|
||||
<div>{{ content.title }}</div>
|
||||
</div>
|
||||
<div v-if="content.style == 1" class="grid grid-cols-4 gap-x-9 gap-y-7">
|
||||
<div
|
||||
v-for="(item, index) in showList"
|
||||
:key="index"
|
||||
class="flex flex-col items-center pt-[40rpx]"
|
||||
@click="handleClick(item.link)"
|
||||
>
|
||||
<u-image width="52" height="52" :src="getImageUrl(item.image)" alt="" />
|
||||
<div class="mt-[22rpx] text-sm">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="content.style == 2">
|
||||
<div
|
||||
v-for="(item, index) in showList"
|
||||
:key="index"
|
||||
class="flex items-center border-light border-solid border-0 border-b h-[100rpx] px-[24rpx]"
|
||||
@click="handleClick(item.link)"
|
||||
>
|
||||
<u-image width="48" height="48" :src="getImageUrl(item.image)" alt="" />
|
||||
<div class="ml-[20rpx] flex-1 text-sm">{{ 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'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
content: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
const { getImageUrl } = useAppStore()
|
||||
const handleClick = (link: any) => {
|
||||
navigateTo(link)
|
||||
}
|
||||
|
||||
const showList = computed(() => {
|
||||
return props.content.data?.filter((item: any) => item.is_show == '1') || []
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
<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>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view class="user-info mb-[0rpx]">
|
||||
<!-- #ifndef H5 -->
|
||||
<u-sticky
|
||||
h5-nav-height="0"
|
||||
bg-color="transparent"
|
||||
>
|
||||
<u-navbar
|
||||
:is-back="false"
|
||||
:is-fixed="false"
|
||||
:title="metaData.title"
|
||||
:custom-title="metaData.title_type == 2"
|
||||
:border-bottom="false"
|
||||
:title-bold="true"
|
||||
:background="{ background: 'rgba(256,256, 256, 0)' }"
|
||||
:title-color="$theme.navColor"
|
||||
>
|
||||
<template #title>
|
||||
<image
|
||||
class="!h-[54rpx]"
|
||||
:src="metaData.title_img"
|
||||
mode="widthFix"
|
||||
></image>
|
||||
</template>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
<!-- #endif -->
|
||||
<view class="flex items-center justify-between px-[50rpx] pb-[50rpx] pt-[40rpx]">
|
||||
<view
|
||||
v-if="isLogin"
|
||||
class="flex items-center"
|
||||
@click="navigateTo('/pages/user_data/user_data')"
|
||||
>
|
||||
<u-avatar :src="user.avatar" :size="120"></u-avatar>
|
||||
<view class="text-white ml-[20rpx]">
|
||||
<view class="text-2xl">{{ user.nickname }}</view>
|
||||
<view class="text-xs mt-[18rpx]" @click.stop="copy(user.account)">
|
||||
账号:{{ user.account }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<navigator v-else class="flex items-center" hover-class="none" url="/pages/login/login">
|
||||
<u-avatar src="/static/images/user/default_avatar.png" :size="120"></u-avatar>
|
||||
<view class="text-white text-3xl ml-[20rpx]">未登录</view>
|
||||
</navigator>
|
||||
<navigator v-if="isLogin" hover-class="none" url="/pages/user_set/user_set">
|
||||
<u-icon name="setting" color="#fff" :size="48"></u-icon>
|
||||
</navigator>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { useCopy } from '@/hooks/useCopy'
|
||||
import {computed} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
pageMeta: {
|
||||
type: Object,
|
||||
default: () => []
|
||||
},
|
||||
content: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
user: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
isLogin: {
|
||||
type: Boolean
|
||||
}
|
||||
})
|
||||
const { copy } = useCopy()
|
||||
|
||||
const metaData: any = computed(() => {
|
||||
return props.pageMeta[0].content
|
||||
})
|
||||
|
||||
const navigateTo = (url: string) => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user-info {
|
||||
background: url(../../../static/images/user/my_topbg.png),
|
||||
linear-gradient(90deg, $u-type-primary, $u-minor-color);
|
||||
background-repeat: no-repeat;
|
||||
background-position: bottom;
|
||||
background-size: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user