Commit 19bb94f6 authored by spc's avatar spc

Merge branch 'dev' of http://gitlab.dui88.com/fh/20250528_FHQ1 into dev

parents 31e882bc dd0d651a
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.89653 0.709985C10.2855 0.317871 10.9186 0.315289 11.3107 0.704217C11.7028 1.09315 11.7054 1.7263 11.3165 2.11842L2.16168 11.3482C1.77275 11.7403 1.13959 11.7429 0.747476 11.354C0.355362 10.9651 0.352779 10.3319 0.741708 9.93979L9.89653 0.709985Z" fill="#222"/>
<path d="M11.3482 9.89653C11.7403 10.2855 11.7429 10.9186 11.354 11.3107C10.9651 11.7028 10.3319 11.7054 9.93979 11.3165L0.709985 2.16168C0.317871 1.77275 0.315289 1.13959 0.704217 0.747476C1.09315 0.355362 1.7263 0.35278 2.11842 0.741708L11.3482 9.89653Z" fill="#222"/>
</svg>
......@@ -8,6 +8,7 @@
>
<view class="register-baby-info-content">
<view class="register-baby-info-title">选择宝宝的生日和预产期</view>
<image src="@/assets/images/icon-close.svg" class="register-baby-close-btn" mode="aspectFit" @click="handleCancel" />
<view class="register-baby-info-desc">
为了提供更有价值的服务,我们会将宝宝信息关联科学分析,星妈会不会泄漏您的任何个人信息,请放心使用。
</view>
......@@ -335,6 +336,13 @@ function toggleStatus(val) {
margin-bottom: 12rpx;
align-self: flex-start;
}
.register-baby-close-btn {
position: absolute;
top: 60rpx;
right: 40rpx;
width: 40rpx;
height: 40rpx;
}
.register-baby-info-desc {
font-size: 26rpx;
color: #888;
......
......@@ -41,6 +41,12 @@
"navigationStyle": "custom"
}
},
{
"path": "pages/activity/page",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/search/search",
"style": {
......
<script setup lang="ts">
import {onMounted, ref, provide, computed} from 'vue'
import {fetchPageConfig} from './api'
import {PageConfig} from "./types";
import ImageSwiper from "./components/ImageSwiper.vue";
import HotArea from "./components/HotArea.vue";
const props = defineProps<{
id: string
debugMode?: boolean
}>()
const refreshingPageConfig = ref(false)
const pageConfig = ref({} as PageConfig)
const debugMode = computed(() => props.debugMode)
async function refreshPageConfig() {
refreshingPageConfig.value = true
const resp = await fetchPageConfig(props.id)
pageConfig.value = JSON.parse(resp.data.content)
refreshingPageConfig.value = false
console.log(pageConfig.value)
}
onMounted(async () => {
await refreshPageConfig()
})
provide('debugMode', debugMode)
</script>
<template>
<view v-if="!refreshingPageConfig" class="page-render-engine">
<template v-for="(component, index) in pageConfig.components" :key="'comp-' + index">
<HotArea
v-if="component.name === 'HotArea'"
:properties="component.props"
/>
</template>
</view>
<view v-else>
加载中...
</view>
</template>
<style scoped lang="less">
.page-render-engine {
background-repeat: no-repeat;
}
</style>
\ No newline at end of file
import requestModule from '@/api/request.js'
import {CodeResponse, ThematicPageType} from "./types";
const {api} = requestModule
export function fetchPageConfig(id: string) {
return api.get('/c/thematicPage/data', {id}) as Promise<CodeResponse<ThematicPageType>>
}
<script setup lang="ts">
import {computed, inject} from 'vue'
import {jump} from '@/utils'
import {MdConfig} from "../types";
import {useMD} from "../use-md";
const ratio = 2
const props = defineProps<{
properties?: {
area?: { x: number, y: number, width: number, height: number }
link?: { type: number, url: string, extra: any }
mdConfig?: MdConfig
needLogin?: boolean
}
openType?: string
isLogin?: boolean
}>()
const debugMode = inject('debugMode', false)
const style = computed(() => {
const area = props.properties.area
return {
left: area.x * ratio + 'rpx',
top: area.y * ratio + 'rpx',
width: area.width * ratio + 'rpx',
height: area.height * ratio + 'rpx',
}
})
const {logClick} = useMD(props.properties.mdConfig || {})
const emit = defineEmits<{
(e: 'click', e: any): void
(e: 'getphonenumber', e: any): void
}>()
function onClick(e) {
emit('click', e)
if ((!props.properties.needLogin || props.isLogin) && props.properties.link) {
jump(props.properties.link)
}
logClick()
}
</script>
<template>
<button class="click-area" :class="{'debug-mode': debugMode}" :style="style"
:open-type="openType ?? (properties.needLogin && !isLogin ? 'getPhoneNumber' : undefined)"
@click="onClick"
@getphonenumber="(e) => emit('getphonenumber', e)"
/>
</template>
<style scoped lang="less">
.click-area {
position: absolute;
border: none;
border-radius: 0;
background-color: transparent;
&.debug-mode {
background-color: rgba(255, 0, 0, 0.3);
}
&::after {
border: none;
}
}
</style>
\ No newline at end of file
<script setup lang="ts">
import {inject} from 'vue'
import ClickArea from "./ClickArea.vue";
import {JumpType} from "../types";
export interface ClickAreaType {
x: number
y: number
width: number
height: number
link: {
id: string
type: string
url: string
label: string
value: string
}
}
const props = defineProps<{
properties: {
imageUrl: string
list: ClickAreaType[]
}
}>()
const debugMode = inject('debugMode', false)
function transformClickAreaProperties(item: ClickAreaType) {
let link;
if(item.link){
switch (item.link.type) {
case 'MINI_APP_THIRD':
link = {
type: JumpType.MINI,
url: item.link.url,
extra: {
appId: item.link.value,
}
}
break
}
}
return {
area: {
x: item.x,
y: item.y,
width: item.width,
height: item.height,
},
link,
}
}
</script>
<template>
<view class="hot-area">
<image :src="properties.imageUrl" class="hot-area-bg" mode="widthFix"/>
<ClickArea v-for="item in properties.list" :key="item.id"
:properties="transformClickAreaProperties(item)"
/>
</view>
</template>
<style scoped lang="less">
.hot-area {
position: relative;
&-bg {
width: 100%;
display: block;
}
}
</style>
\ No newline at end of file
<script setup lang="ts">
import {onMounted, ref} from 'vue'
import {LinkType, MdConfig} from "../types"
import {useMD} from "../use-md"
import {jump} from '@/utils'
export interface ImageSwiperItem {
image: string
link?: LinkType
}
const props = defineProps<{
properties?: {
autoplay?: boolean
interval?: number
duration?: number
circular?: boolean
indicatorDots?: boolean
items: ImageSwiperItem[]
}
style?: Record<string, any>
}>()
const mds = ref([])
onMounted(() => {
mds.value = props.properties.items.map(item => {
const md = useMD(item.mdConfig || {}, false)
md.logExposure()
return md
})
})
function onClickItem(item: ImageSwiperItem, index: number) {
if (item.link) {
jump(item.link)
}
mds.value[index].logClick()
}
</script>
<template>
<swiper class="comp-swiper"
:style="style"
:indicator-dots="properties.indicatorDots"
:autoplay="properties.autoplay"
:circular="properties.circular"
:interval="properties.interval"
:duration="500">
<swiper-item v-for="(item, index) in properties.items" :key="index" @click="onClickItem(item, index)">
<image class="comp-swiper-item" :src="item.image" mode="aspectFill"></image>
</swiper-item>
</swiper>
</template>
<style scoped lang="less">
.comp-swiper {
&-item {
width: 100%;
height: 100%;
}
}
</style>
\ No newline at end of file
export enum JumpType {
INNER = 1, // 内部小程序页面跳转
MINI = 2, // 其他小程序页面跳转
H5 = 3, // https 网络连接跳转
}
export interface LinkType {
type: JumpType
url: string
extra?: Record<string, any>
}
export interface MdConfig {
pageName: string
componentName: string
componentContent: string
logExposure?: boolean
logClick?: boolean
}
export interface CodeResponse<T> {
code: number
message: string
data: T
success: boolean
ok: boolean
}
export interface ComponentType {
name: string
props: Record<string, any>
styles: Record<string, any>
}
export interface ThematicPageType{
content: string
}
export interface PageConfig {
title: string
shareConfig: {
title: string
imageUrl: string
}
components: ComponentType[]
styles: Record<string, any>
}
import {onMounted} from 'vue'
import md from '@/md.js'
import {MdConfig} from "./types";
export function useMD(mdConfig: MdConfig, autoLogExposure = true) {
function logExposure() {
const {pageName, componentName, componentContent} = mdConfig || {}
if (!pageName || !componentName || !componentContent) {
return
}
md.sensorComponentLogTake({
xcxComponentExposure: "true",
pageName,
componentName,
componentContent,
})
}
function logClick() {
const {pageName, componentName, componentContent} = mdConfig || {}
if (!pageName || !componentName || !componentContent) {
return
}
md.sensorComponentLogTake({
xcxComponentClick: "true",
pageName,
componentName,
componentContent,
})
}
if (autoLogExposure) {
onMounted(() => {
if (mdConfig?.logExposure) {
logExposure()
}
})
}
return {
logClick,
logExposure,
}
}
<script setup lang="ts">
import {ref} from 'vue'
import PageRenderEngine from "./engine/PageRenderEngine.vue";
import {onLoad} from "@dcloudio/uni-app";
const pageOptions = ref({})
const pageId = ref<string>()
const debugMode = ref(false)
function navBack() {
try {
uni.navigateBack({
delta: 1,
success: () => {
console.log('返回成功')
},
fail: () => {
// 如果返回失败,跳转到首页
uni.redirectTo({
url: '/pages/index/index'
})
}
})
} catch (error) {
console.log('返回失败:', error)
uni.redirectTo({
url: '/pages/index/index'
})
}
}
onLoad((options) => {
pageOptions.value = options
pageId.value = options.id
debugMode.value = options.debugMode
})
</script>
<template>
<PageRenderEngine :id="pageId" :debug-mode="debugMode" />
<image class="btn-back" src="@/assets/images/back-btn.png" mode="aspectFit" @click="navBack"/>
</template>
<style scoped lang="less">
.btn-back {
position: fixed;
left: 20rpx;
top: 70rpx;
width: 60rpx;
height: 60rpx;
}
</style>
\ No newline at end of file
......@@ -18,7 +18,19 @@ async function clickBack() {
async function onRegisterConfirm(data) {
console.log('注册确认:', data);
showRegisterLayer.value = false;
await Promise.all([
userStore.loadMemberInfo(),
userStore.loadUserInfo(),
])
uni.navigateBack({
delta: 1
})
}
async function onRegisterCancel() {
console.log('注册取消');
await Promise.all([
userStore.loadMemberInfo(),
......@@ -134,7 +146,7 @@ function testClick() {
</view>
</view>
</div>
<RegisterLayer v-model="showRegisterLayer" @confirm="onRegisterConfirm"/>
<RegisterLayer v-model="showRegisterLayer" @confirm="onRegisterConfirm" @cancel="onRegisterCancel"/>
</div>
</template>
......
This diff is collapsed.
......@@ -9,6 +9,10 @@ const pages = [
{value: '/mini/#/page/home/index?page_source=3', alias: '路演活动'},
]
const singleUrls = [
{value: 'https://testmanage.boysup.cn/smart-age/index.html#/', alias: 'smart-age'},
]
const mpPage = '/pages/activity/index'
function joinUrlAndQs(url, qs) {
......@@ -23,3 +27,8 @@ for (const page of pages) {
console.log(`${page.alias}-${host.alias}: ${url}`)
}
}
for (const item of singleUrls) {
const url = joinUrlAndQs(mpPage, `needLogin=1&url=${encodeURIComponent(item.value)}`)
console.log(`${item.alias}: ${url}`)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment