diff --git a/.env b/.env index fa0c77eeb..228da808c 100644 --- a/.env +++ b/.env @@ -1,4 +1,5 @@ APP_BASE_URL= +APP_WEBSOCKET= APP_COMPANY_ID= APP_PLATFORM= APP_CUSTOM_SERVER= @@ -12,5 +13,4 @@ APP_IMAGE_CDN= APP_DIANWU_URL= APP_MERCHANT_URL= APP_ADAPAY= -APP_I18N_APP_ID= -APP_I18N_APP_KEY= + diff --git a/.gitignore b/.gitignore index d054b3c90..65f30ef9c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ dist/ .cursor/ AGENTS.md openspec/ +scripts/ diff --git a/src/hocs/index.js b/src/hocs/index.js index fda3b4a8a..8d1589293 100644 --- a/src/hocs/index.js +++ b/src/hocs/index.js @@ -7,5 +7,6 @@ export { default as withPager } from './withPager' export { default as withBackToTop } from './withBackToTop' export { default as withPointitem } from './withPointitem' export { default as withLoadMore } from './withLoadMore' +export { default as withPageWrapper } from './withPageWrapper' export default {} diff --git a/src/hocs/withPageWrapper copy.js b/src/hocs/withPageWrapper copy.js deleted file mode 100644 index 9c7b7f4c5..000000000 --- a/src/hocs/withPageWrapper copy.js +++ /dev/null @@ -1,169 +0,0 @@ -/** - * Copyright © ShopeX (http://www.shopex.cn). All rights reserved. - * See LICENSE file for license details. - */ -import { useEffect, useState, useRef } from 'react' -import { useSelector, useDispatch } from 'react-redux' -import Taro from '@tarojs/taro' -import { View } from '@tarojs/components' -import { useEffectAsync, useWhiteShop, useModal } from '@/hooks' -import useModalLogin from '@/hooks/useModalLogin' -import { updateShopInfo } from '@/store/slices/shop' -import { SpPage, SpLogin } from '@/components' -import { SG_CHECK_STORE_RULE } from '@/consts' -import { VERSION_STANDARD } from '@/utils' -import configStore from '@/store' - -const { store } = configStore() - -function withPageWrapper(Component) { - return function EnhancedComponent(props) { - const dispatch = useDispatch() - const { initState, entryDefalutStore, guidderTemplateId } = useSelector((state) => state.sys) - const { shopInfo } = useSelector((state) => state.shop) - const { - checkEnterStoreRule, - checkStoreWhiteList, - checkUserInStoreWhiteList, - getUserWhiteShop - } = useWhiteShop() - const { showModal } = useModal() - const { showLoinModal } = useModalLogin() - const [state, setState] = useState(false) - - useEffectAsync(async () => { - if (initState) { - resolveInStoreRule() - } - }, [initState]) - - useEffect(() => { - if (state) { - setState(false) - - setTimeout(() => { - resolveInStoreRule() - }, 1000) - } - }, [shopInfo]) - - const resolveInStoreRule = async () => { - // 启动时(冷启动+热启动)执行云店进店规则 - if (VERSION_STANDARD && Taro.getStorageSync(SG_CHECK_STORE_RULE) == 0) { - // 云店进店规则 - try { - Taro.setStorageSync(SG_CHECK_STORE_RULE, 1) - await checkEnterStoreRule() - setState(true) - } catch (error) { - // 检查店铺开启了白名单,需要登录授权 - if (error.message == 'AUTH_REQUIRED') { - await handleToLogin() - await handleStoreWhiteList() - setState(true) - } else if (error.message == 'CHECK_WHITE_LIST') { - await handleStoreWhiteList() - setState(true) - } - } - } else { - setState(true) - } - } - - const handleToLogin = async () => { - try { - await showLoinModal() - } catch (error) { - const res = await showModal({ - title: '提示', - content: '你还未登录,请先登录!', - cancelText: '返回', - confirmText: '继续登录', - contentAlign: 'center' - }) - if (res.confirm) { - await handleToLogin() - } else { - // 返回兜底店铺逻辑 - if (entryDefalutStore == '1') { - try { - await checkStoreWhiteList(null, false) - } catch (err) { - await handleToLogin() - } - } else { - Taro.redirectTo({ - url: `/pages/custom/custom-page?id=${guidderTemplateId}&fromConnect=davild` - }) - throw new Error('TO_STORE_GUIDE_PAGE') - } - // Taro.exitMiniProgram() - } - } - } - - const handleStoreWhiteList = async () => { - const status = await checkUserInStoreWhiteList() - if (!status) { - const myShopInfo = await getUserWhiteShop() - if (!myShopInfo) { - const res = await showModal({ - title: '提示', - content: '抱歉,没有可访问的店铺', - showCancel: false, - confirmText: entryDefalutStore == '1' ? '返回首页' : '返回', - contentAlign: 'center' - }) - if (res.confirm) { - if (entryDefalutStore == '1') { - try { - await checkStoreWhiteList(null, false) - } catch (err) { - await handleStoreWhiteList() - } - } else { - Taro.redirectTo({ - url: `/pages/custom/custom-page?id=${guidderTemplateId}&fromConnect=davild` - }) - throw new Error('TO_STORE_GUIDE_PAGE') - } - // Taro.exitMiniProgram() - // throw new Error('EXIT_MINI_PROGRAM') - } - } else { - await handlePhoneCallToStore(myShopInfo) - } - } - } - - const handlePhoneCallToStore = async (myShopInfo) => { - const res = await showModal({ - title: '提示', - content: '抱歉,本店会员才可以访问,如有需要可电话联系店铺!', - cancelText: '回我的店', - confirmText: '联系店铺', - contentAlign: 'center' - }) - if (res.confirm) { - console.log('🚀🚀🚀 ~ handleStoreWhiteList ~ shop:', store.getState().shop.shopInfo) - Taro.makePhoneCall({ - phoneNumber: store.getState().shop.shopInfo.phone, - complete: async () => { - await handlePhoneCallToStore() - } - }) - throw new Error('PHONE_CALL_TO_STORE') - } else { - dispatch(updateShopInfo(myShopInfo)) - } - } - if (state) { - return - } else { - return null - } - } -} - -export default withPageWrapper diff --git a/src/pages/custom/custom-page.js b/src/pages/custom/custom-page.js index de15ac8de..f1ac0dd5d 100644 --- a/src/pages/custom/custom-page.js +++ b/src/pages/custom/custom-page.js @@ -19,7 +19,15 @@ import S from '@/spx' import { View } from '@tarojs/components' import { SpPage, SpSearch, SpSkuSelect, SpTabbar, SpLogin } from '@/components' import { WgtsContext } from '@/pages/home/wgts/wgts-context' -import { getDistributorId, log, entryLaunch, pickBy, showToast, VERSION_STANDARD } from '@/utils' +import { + getDistributorId, + log, + entryLaunch, + pickBy, + showToast, + VERSION_STANDARD, + buildSharePath +} from '@/utils' import { platformTemplateName, transformPlatformUrl } from '@/utils/platform' import { useLogin, useNavigation, useLocation, useModal } from '@/hooks' import { SG_ROUTER_PARAMS } from '@/consts/localstorage' @@ -50,6 +58,7 @@ function CustomPage(props) { useEffect(() => { fetch() + entryLaunch.postGuideUV() entryLaunch.postGuideTask() }, []) @@ -113,8 +122,11 @@ function CustomPage(props) { const getAppShareInfo = async () => { const { id } = await entryLaunch.getRouteParams($instance.router.params) const { userId } = Taro.getStorageSync('userinfo') - const query = userId ? `?uid=${userId}&id=${id}` : `?id=${id}` - let path = `/pages/custom/custom-page${query}` + const params = { id } + if (userId) { + params.uid = userId + } + const path = buildSharePath('poster_custom_page', params) log.debug(`getAppShareInfo: ${path}`) return { diff --git a/src/pages/home/wgts/helper.js b/src/pages/home/wgts/helper.js index 8ae612e06..49dc5044c 100644 --- a/src/pages/home/wgts/helper.js +++ b/src/pages/home/wgts/helper.js @@ -20,7 +20,7 @@ export function linkPage(type, data) { url = '/pages/article/index?id=' + id break case 'planting': - url = '/subpage/pages/recommend/detail?id=' + id + url = '/pages/recommend/detail?id=' + id break case 'custom_page': url = '/pages/custom/custom-page?id=' + id diff --git a/src/pages/index.js b/src/pages/index.js index ecf506704..41069dc42 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -40,7 +40,8 @@ import { pickBy, log, showToast, - entryLaunch + entryLaunch, + buildSharePath } from '@/utils' import { updateShopInfo } from '@/store/slices/shop' import { @@ -150,7 +151,7 @@ function Home() { if (VERSION_STANDARD) { params = Object.assign(params, { dtid: getCurrentShopId() }) } - let path = `/pages/index${isEmpty(params) ? '' : '?' + resolveStringifyParams(params)}` + const path = buildSharePath('poster_home', params) console.log('useShareAppMessage path:', path, params) @@ -276,7 +277,7 @@ function Home() { // renderNavigation={renderNavigation()} pageConfig={pageData?.base || {}} renderFloat={wgts.length > 0 && } - renderFooter={} + renderFooter={} ref={pageRef} navigateMantle={navigateMantle} onReady={({ footerHeight }) => { diff --git a/src/pages/item/espier-detail.js b/src/pages/item/espier-detail.js index 3c02a7cd6..43d60e85a 100644 --- a/src/pages/item/espier-detail.js +++ b/src/pages/item/espier-detail.js @@ -43,7 +43,8 @@ import { isAPP, showToast, getDistributorId, - VERSION_STANDARD + VERSION_STANDARD, + buildSharePath } from '@/utils' import { fetchUserFavs } from '@/store/slices/user' @@ -107,7 +108,8 @@ const initialState = { recommendList: [], isParameter: false, imgHeightList: [], // 用于存储banner高度 - navigateMantle: false + navigateMantle: false, + defaultImageHeight: 520 // 默认图片高度,避免空白 } function EspierDetail(props) { @@ -145,11 +147,13 @@ function EspierDetail(props) { recommendList, isParameter, imgHeightList, - navigateMantle + navigateMantle, + defaultImageHeight } = state useEffect(() => { init() + entryLaunch.postGuideUV() entryLaunch.postGuideTask() }, []) @@ -240,7 +244,7 @@ function EspierDetail(props) { if (userInfo) { query['uid'] = userInfo.user_id } - const path = `/pages/item/espier-detail?${qs.stringify(query)}` + const path = buildSharePath('poster_espier_detail', query) log.debug(`share path: ${path}`) return { title: itemName, @@ -308,17 +312,28 @@ function EspierDetail(props) { } }) } - const banner = await getMultipleImageInfo(data.imgs) setState((draft) => { draft.info = { ...data, subscribe } draft.play = data.video ? true : false // 辉绮需求 - draft.imgHeightList = banner draft.promotionActivity = data.promotionActivity + // 初始化图片高度数组,使用默认高度 + draft.imgHeightList = new Array(data.imgs.length).fill(draft.defaultImageHeight) }) + // 异步计算图片真实高度,不阻塞页面渲染 + getMultipleImageInfo(data.imgs) + .then((heights) => { + setState((draft) => { + draft.imgHeightList = heights + }) + }) + .catch((error) => { + console.log('计算图片高度失败,使用默认高度:', error) + }) + if (isAPP() && userInfo) { try { Taro.SAPPShare.init({ @@ -342,7 +357,7 @@ function EspierDetail(props) { } } const getMultipleImageInfo = async (imageUrls = []) => { - let windowWidth = 375 + let windowWidth = defaultImageHeight try { const sys = Taro.getSystemInfoSync() if (sys && sys.windowWidth) windowWidth = sys.windowWidth @@ -352,9 +367,9 @@ function EspierDetail(props) { const promises = imageUrls.map(async (url) => { try { - const info = await Taro.getImageInfo({ src: url }) - const imgWidth = Number(info?.width) || 0 - const imgHeight = Number(info?.height) || 0 + const imageInfo = await Taro.getImageInfo({ src: url }) + const imgWidth = Number(imageInfo?.width) || 0 + const imgHeight = Number(imageInfo?.height) || 0 if (imgWidth > 0 && imgHeight > 0) { return Math.round((windowWidth * imgHeight) / imgWidth) } @@ -506,7 +521,7 @@ function EspierDetail(props) { className='goods-swiper' // current={curImgIdx} onChange={onChangeSwiper} - style={{ height: imgHeightList[curImgIdx] + 'px' }} + style={{ height: (imgHeightList[curImgIdx] || defaultImageHeight) + 'px' }} > {info.imgs.map((img, idx) => ( @@ -853,7 +868,7 @@ function EspierDetail(props) { {info?.itemParams?.map((item, index) => { return ( - + {item.attribute_name} {item.attribute_value_name} diff --git a/src/pages/recommend/detail.js b/src/pages/recommend/detail.js index bf993bec9..e87e2c308 100644 --- a/src/pages/recommend/detail.js +++ b/src/pages/recommend/detail.js @@ -13,7 +13,8 @@ import { SpPage } from '@/components' import api from '@/api' import doc from '@/doc' import S from '@/spx' -import { pickBy, log, isWeixin, showToast } from '@/utils' +import { pickBy, log, isWeixin, showToast, buildSharePath } from '@/utils' +import { withPageWrapper } from '@/hocs' import { WgtFilm, WgtSlider, WgtWriting, WgtGoods, WgtHeading } from '../home/wgts' import './detail.scss' @@ -55,8 +56,8 @@ function GuideRecommendDetail(props) { gu: `${work_userid}_${shop_code}`, subtask_id } - const sharePath = `/subpage/pages/recommend/detail?${qs.stringify(query)}` - log.debug(`【guide/recommend/detail】onShareAppMessage path: ${sharePath}`) + const sharePath = buildSharePath('poster_recommend_detail', query) + log.debug(`【/pages/recommend/detail】onShareAppMessage path: ${sharePath}`) return { title: title, path: sharePath, @@ -178,4 +179,4 @@ GuideRecommendDetail.options = { addGlobalClass: true } -export default GuideRecommendDetail +export default withPageWrapper(GuideRecommendDetail) diff --git a/src/pages/share-land.js b/src/pages/share-land.js index 3ba25e10c..1ed5cd82b 100644 --- a/src/pages/share-land.js +++ b/src/pages/share-land.js @@ -11,9 +11,13 @@ import qs from 'qs' import { entryLaunch, showToast } from '@/utils' /** - * path 页面路径(必穿参数)(参数格式 path=/pages/indes) - * 其余参数会自动携带到path后面,不用手动处理 - * scene=uid%3D884%26id%3D121%26qr%3DY%26path%3D%2Fsubpages%2Fprescription%2Fprescription-information(页面参数,可供验证) + * 统一分享落地页 + * 参数说明: + * - from_scene: 目标页面类型 (必传, 如: from_scene=xxxx_xxx_xxx) + * - 通过from_scene匹配对应的页面进行跳转 + * + * 兼容旧的场景: + * - t: 特殊场景标识(如处方药) * @returns */ function ShareIand() { @@ -26,50 +30,116 @@ function ShareIand() { const resloveRouterParams = async () => { const routeParams = await entryLaunch.getRouteParams(router) Taro.setStorageSync(SG_ROUTER_PARAMS, routeParams) - if (/^guide_welcome/.test(routeParams?.from_scene)) { - // 欢迎语携带用户编号 + if (routeParams?.gu || routeParams?.gu_user_id) { + // 导购参数处理 Taro.setStorageSync(SG_GUIDE_PARAMS, routeParams) Taro.setStorageSync(SG_GUIDE_PARAMS_UPDATETIME, dayjs().unix()) - - // 导购欢迎语 - if (routeParams.from_scene == 'guide_welcome_home') { - // 导购欢迎语--商城首页 - Taro.redirectTo({ url: '/pages/index' }) - } else if (routeParams.from_scene == 'guide_welcome_category') { - // 导购欢迎语--商城分类页 - Taro.redirectTo({ url: '/pages/category/index' }) - } else if (routeParams.from_scene == 'guide_welcome_couponlist') { - // 导购欢迎语--商城优惠券中心 - Taro.redirectTo({ url: '/subpages/marketing/coupon-center' }) - } else if (routeParams.from_scene == 'guide_welcome_recommend') { - // 导购欢迎语--商城种草 - Taro.redirectTo({ url: '/pages/recommend/list' }) - } else if (routeParams.from_scene == 'guide_welcome_member') { - // 导购欢迎语--商城会员中心 - Taro.redirectTo({ url: '/subpages/member/index' }) - } else if (routeParams.from_scene == 'guide_welcome_itemlist') { - // 导购欢迎语--商城商品列表 - Taro.redirectTo({ url: '/pages/item/list' }) - } else { - showToast('未匹配到参数') - } - if (S.getAuthToken()) { - // entryLaunch.postGuideUV() - entryLaunch.postGuideTask() - } - } else { - // 分享的太阳码场景 - const _tempParams = {} - if (routeParams?.t == 1) { - // 处方药 - _tempParams.order_id = routeParams.oi - _tempParams.prescription_order_random = routeParams.r - Taro.redirectTo({ - url: `/subpages/prescription/prescription-information?${qs.stringify(_tempParams)}` - }) + entryLaunch.postGuideUV() // 导购uv上报 + entryLaunch.postGuideTask() // 导购任务上报 } } + + if (routeParams?.t == 1) { + handlePrescription(routeParams) + } else { + handleShareLand(routeParams) + } + } + + // 处理落地页类型 + const handleShareLand = (routeParams) => { + const { from_scene, ...otherParams } = routeParams + const welcomeRoutes = { + // 导购欢迎语 + 'guide_welcome_home': '/pages/index', // 导购欢迎语--商城首页 + 'guide_welcome_category': '/pages/category/index', // 导购欢迎语--商城分类页 + 'guide_welcome_couponlist': '/subpages/marketing/coupon-center', // 导购欢迎语--商城优惠券中心 + 'guide_welcome_recommend': '/pages/recommend/list', // 导购欢迎语--商城种草 + 'guide_welcome_member': '/subpages/member/index', // 导购欢迎语--商城会员中心 + 'guide_welcome_itemlist': '/pages/item/list', // 导购欢迎语--商城商品列表 + + // 导购任务 + 'guide_task_home': '/pages/index', // 导购任务-管理端-小程序首页 + 'guide_task_gucustom': '/subpages/guide/custom/custom-page', // 导购任务-管理端-导购货架自定义页 + 'guide_task_gucoupon': '/subpages/guide/coupon-home/index', // 导购任务-小程序-优惠券转发 + 'guide_task_gugoods': '/subpages/guide/item/espier-detail', // 导购任务-小程序-商品转发 + 'guide_task_goods': '/pages/item/espier-detail', // 导购任务-小程序-商品海报 + + // 商城小程序 + 'poster_home': '/pages/index', // 小程序-海报分享&页面转发-店务小店 + 'poster_shop_home': '/marketing/pages/distribution/shop-home', // 小程序-海报分享&页面转发-店务小店 + 'poster_espier_detail': '/pages/item/espier-detail', // 小程序-海报分享-商品详情 + 'poster_espier_checkout': '/pages/cart/espier-checkout', // 小程序-海报分享&页面转发-结算页 + 'poster_purchase_auth': '/pages/purchase/auth', // 小程序-海报分享&页面转发-内购邀请 + 'poster_trade_detail': '/subpages/trade/detail', // 小程序-海报分享&页面转发-交易详情 + 'poster_store_index': '/subpages/store/index', // 小程序-海报分享&页面转发-店铺首页 + 'poster_custom_page': '/pages/custom/custom-page', // 小程序-海报分享&页面转发-自定义页 + 'poster_recommend_detail': '/pages/recommend/detail', // 小程序-海报分享&页面转发-种草详情 + 'poster_community_memberdetail': '/subpages/community/group-memberdetail', // 小程序-海报分享&页面转发-社区 + 'poster_coupon_center': '/subpages/marketing/coupon-center', // 小程序-海报分享&页面转发-领券中心 + 'poster_mdugc_detail': '/subpages/mdugc/note-detail', // 小程序-海报分享&页面转发-笔记详情 + 'poster_pointshop_espier_detail': '/subpages/pointshop/espier-detail' // 小程序-海报分享&页面转发-积分商品详情 + } + + // 过滤掉内部使用的参数 + const filteredParams = { ...otherParams } + delete filteredParams.scene + delete filteredParams.$taroTimestamp + const queryString = qs.stringify(filteredParams) + + const targetUrl = queryString + ? `${welcomeRoutes[from_scene]}?${queryString}` + : welcomeRoutes[from_scene] + console.log('导购任务分享跳转:', targetUrl, welcomeRoutes[from_scene]) + + if (welcomeRoutes[from_scene]) { + Taro.redirectTo({ url: targetUrl }) + } else { + showToast('页面跳转失败') + setTimeout(() => { + Taro.redirectTo({ url: '/pages/index' }) + }, 1500) + } + } + + // 处理处方药场景 + const handlePrescription = (routeParams) => { + const params = { + order_id: routeParams.oi, + prescription_order_random: routeParams.r + } + Taro.redirectTo({ + url: `/subpages/prescription/prescription-information?${qs.stringify(params)}` + }) + } + + // 处理通用分享场景 + // 1、海报分享 pages/share-land?scene=share_id%3D68f2037ca18f8 通过shareid获取参数 + // 2、小程序转发 pages/share-land?target_path=pages/item/espier-detail&id=123 + // 3、其他小程序跳转过来 pages/share-land?target_path=pages/item/espier-detail&id=123 + // 4、小程序卡片跳转过来 pages/share-land?target_path=pages/item/espier-detail&id=123 + const handleGeneralShare = (routeParams) => { + // routeParams:pa + const { target_path, ...otherParams } = routeParams + + // 过滤掉内部使用的参数 + const filteredParams = { ...otherParams } + delete filteredParams.scene + delete filteredParams.$taroTimestamp + + // 确保路径以 / 开头 + let normalizedPath = target_path + if (normalizedPath && !normalizedPath.startsWith('/')) { + normalizedPath = '/' + normalizedPath + } + + // 构建目标URL + const queryString = qs.stringify(filteredParams) + const targetUrl = queryString ? `${normalizedPath}?${queryString}` : normalizedPath + + console.log('通用分享跳转:', targetUrl) + Taro.redirectTo({ url: targetUrl }) } return null diff --git a/src/subpage/pages/cashier/comps/we.js b/src/subpage/pages/cashier/comps/we.js index 554f2b9c4..56d3d2c30 100644 --- a/src/subpage/pages/cashier/comps/we.js +++ b/src/subpage/pages/cashier/comps/we.js @@ -2,16 +2,6 @@ * Copyright © ShopeX (http://www.shopex.cn). All rights reserved. * See LICENSE file for license details. */ -/* - * @Author: Arvin - * @GitHub: https://github.com/973749104 - * @Blog: https://liuhgxu.com - * @Description: 说明 - * @FilePath: /unite-vshop/src/subpage/pages/cashier/comps/we.js - * @Date: 2020-11-19 14:22:17 - * @LastEditors: Arvin - * @LastEditTime: 2020-11-19 15:20:48 - */ import React, { Component } from 'react' import Taro, { getCurrentInstance } from '@tarojs/taro' import { View } from '@tarojs/components' diff --git a/src/subpage/pages/recommend/detail.js b/src/subpage/pages/recommend/detail.js index cb39a3650..22108a0bf 100644 --- a/src/subpage/pages/recommend/detail.js +++ b/src/subpage/pages/recommend/detail.js @@ -47,6 +47,7 @@ export default class recommendDetail extends Component { screenWidth: res.screenWidth }) }) + entryLaunch.postGuideUV() entryLaunch.postGuideTask() } diff --git a/src/subpages/community/espier-detail.js b/src/subpages/community/espier-detail.js index 9d1d19d6f..f6ecbd9d1 100644 --- a/src/subpages/community/espier-detail.js +++ b/src/subpages/community/espier-detail.js @@ -39,7 +39,8 @@ import { classNames, navigateTo, VERSION_PLATFORM, - isAPP + isAPP, + buildSharePath } from '@/utils' import doc from '@/doc' @@ -186,7 +187,7 @@ function EspierDetail(props) { if (userInfo) { query['uid'] = userInfo.uid } - const path = `/pages/item/espier-detail?${qs.stringify(query)}` + const path = buildSharePath('poster_espier_detail', query) log.debug(`share path: ${path}`) return { title: itemName, diff --git a/src/subpages/guide/coupon-home/index.js b/src/subpages/guide/coupon-home/index.js index 1a2438e33..f04753914 100644 --- a/src/subpages/guide/coupon-home/index.js +++ b/src/subpages/guide/coupon-home/index.js @@ -16,7 +16,7 @@ import { SpPage, SpScrollView, CouponItem } from '@/components' import api from '@/api' import doc from '@/doc' import qs from 'qs' -import { pickBy, log } from '@/utils' +import { pickBy, log, buildSharePath } from '@/utils' import { useQwLogin } from '@/hooks' import { BaHomeWgts, @@ -76,7 +76,7 @@ function GuideCouponIndex(props) { // subtask_id: subtaskId } - const path = `/subpages/marketing/coupon-center?${qs.stringify(query)}` + const path = buildSharePath('poster_coupon_center', query) log.debug(`getAppShareInfo: ${path}`) return { title: title, diff --git a/src/subpages/guide/item/espier-detail.js b/src/subpages/guide/item/espier-detail.js index 37e115007..2ad2ce813 100644 --- a/src/subpages/guide/item/espier-detail.js +++ b/src/subpages/guide/item/espier-detail.js @@ -39,7 +39,8 @@ import { isWeb, pickBy, classNames, - navigateTo + navigateTo, + buildSharePath } from '@/utils' import doc from '@/doc' @@ -89,7 +90,9 @@ const initialState = { evaluationList: [], evaluationTotal: 0, // 多规格商品选中的规格 - curItem: null + curItem: null, + imgHeightList: [], // 用于存储banner高度 + defaultImageHeight: 520 // 默认图片高度,避免空白 } function EspierDetail(props) { @@ -123,7 +126,9 @@ function EspierDetail(props) { type, dtid, subtaskId, - curItem + curItem, + imgHeightList, // 用于存储banner高度 + defaultImageHeight } = state useEffect(() => { @@ -200,7 +205,7 @@ function EspierDetail(props) { gu: `${work_userid}_${shop_code}`, subtask_id: subtaskId } - const path = `/pages/item/espier-detail?${qs.stringify(query)}` + const path = buildSharePath('poster_espier_detail', query) console.log('gu---------------------', path) log.debug(`share path: ${path}`) return { @@ -264,7 +269,47 @@ function EspierDetail(props) { subscribe } draft.promotionActivity = data.promotionActivity + // 初始化图片高度数组,使用默认高度 + draft.imgHeightList = new Array(data.imgs.length).fill(draft.defaultImageHeight) }) + + // 异步计算图片真实高度,不阻塞页面渲染 + getMultipleImageInfo(data.imgs) + .then((heights) => { + setState((draft) => { + draft.imgHeightList = heights + }) + }) + .catch((error) => { + console.log('计算图片高度失败,使用默认高度:', error) + }) + } + + const getMultipleImageInfo = async (imageUrls = []) => { + let windowWidth = defaultImageHeight + try { + const sys = Taro.getSystemInfoSync() + if (sys && sys.windowWidth) windowWidth = sys.windowWidth + } catch (e) { + console.log('获取系统信息失败,使用默认宽度:', e) + } + + const promises = imageUrls.map(async (url) => { + try { + const imageInfo = await Taro.getImageInfo({ src: url }) + const imgWidth = Number(imageInfo?.width) || 0 + const imgHeight = Number(imageInfo?.height) || 0 + if (imgWidth > 0 && imgHeight > 0) { + return Math.round((windowWidth * imgHeight) / imgWidth) + } + return Math.round(windowWidth) + } catch (error) { + console.log('获取图片信息失败:', url, error) + return Math.round(windowWidth) + } + }) + + return Promise.all(promises) } // 获取包裹 @@ -302,6 +347,17 @@ function EspierDetail(props) { }) } + const setSwiperCss = (item) => { + return { + height: '100%', + width: '100%', + backgroundSize: 'cover', + backgroundImage: `url(${item})`, + backgroundRepeat: 'no-repeat', + backgroundPosition: 'center' + } + } + const onChangeToolBar = (key) => { if (key == 'share') { setState((draft) => { @@ -361,15 +417,13 @@ function EspierDetail(props) { className='goods-swiper' // current={curImgIdx} onChange={onChangeSwiper} + style={{ height: (imgHeightList[curImgIdx] || defaultImageHeight) + 'px' }} > {info.imgs.map((img, idx) => ( - + + + ))} diff --git a/src/subpages/guide/recommend/detail.js b/src/subpages/guide/recommend/detail.js index 660e5220c..02611d04a 100644 --- a/src/subpages/guide/recommend/detail.js +++ b/src/subpages/guide/recommend/detail.js @@ -12,7 +12,7 @@ import { AtButton } from 'taro-ui' import { SpPage } from '@/components' import api from '@/api' import doc from '@/doc' -import { pickBy, log } from '@/utils' +import { pickBy, log, buildSharePath } from '@/utils' import { WgtFilm, WgtSlider, WgtWriting, WgtGoods, WgtHeading } from '../components/wgts' import './detail.scss' @@ -50,7 +50,7 @@ function GuideRecommendDetail(props) { gu: `${work_userid}_${shop_code}`, subtask_id } - const sharePath = `/subpage/pages/recommend/detail?${qs.stringify(query)}` + const sharePath = buildSharePath('poster_recommend_detail', query) log.debug(`【guide/recommend/detail】onShareAppMessage path: ${sharePath}`) return { title: title, diff --git a/src/subpages/i18n/lang/index.json b/src/subpages/i18n/lang/index.json index 4ca8d587b..f6a97b510 100644 --- a/src/subpages/i18n/lang/index.json +++ b/src/subpages/i18n/lang/index.json @@ -12623,5 +12623,15 @@ "zh-cn": "订阅成功", "en": "", "zh-tw": "" + }, + "hp8xmu6": { + "zh-cn": "页面跳转失败", + "en": "Page redirection failed", + "zh-tw": "頁面跳轉失敗" + }, + "er67o3": { + "zh-cn": "总计:", + "en": "Total:", + "zh-tw": "總計:" } } \ No newline at end of file diff --git a/src/subpages/member/index.js b/src/subpages/member/index.js index 8a0b7ce36..a793296cf 100644 --- a/src/subpages/member/index.js +++ b/src/subpages/member/index.js @@ -15,6 +15,7 @@ import { useImmer } from 'use-immer' import S from '@/spx' import qs from 'qs' import req from '@/api/req' +import { buildSharePath } from '@/utils' import { SpLogin, SpImage, SpTabbar, SpPage, SpCell } from '@/components' import api from '@/api' @@ -117,7 +118,7 @@ function MemberIndex(props) { // console.log('===>getCurrentPages==>', getCurrentPages(), getCurrentInstance()) const $instance = getCurrentInstance() const { updateAddress } = useLocation() - const { isLogin, getUserInfo } = useLogin({ + const { isLogin, getUserInfo, isNewUser } = useLogin({ autoLogin: false, // policyUpdateHook: (isUpdate) => { // // isUpdate && setPolicyModal(true) @@ -200,15 +201,15 @@ function MemberIndex(props) { } // 分享 - useShareAppMessage(async (res) => { - const { share_title, share_pic_wechatapp } = await api.member.getMemberShareConfig() + useShareAppMessage(async () => { const { logo } = await api.distribution.getDistributorInfo({ distributor_id: 0 }) + const path = buildSharePath('poster_home', {}) return { - title: state.shareInfo.page_share_title || share_title, - imageUrl: state.shareInfo.page_share_imageUrl || share_pic_wechatapp || logo, - path: '/pages/index' + title: state.shareInfo.page_share_title, + imageUrl: state.shareInfo.page_share_imageUrl || logo, + path: path } }) @@ -345,53 +346,6 @@ function MemberIndex(props) { }) } - const handlePopularChange = async () => { - // 推广跳转 - // 已经是分销员 - if (userInfo.isPromoter) { - Taro.navigateTo({ url: link }) - } else { - const { confirm } = await Taro.showModal({ - title: '邀请推广', - content: '确定申请成为推广员?', - showCancel: true, - cancel: '取消', - confirmText: '确认', - confirmColor: '#0b4137' - }) - if (!confirm) return - const { status } = await api.distribution.become() - if (status) { - Taro.showModal({ - title: '恭喜', - content: '已成为推广员', - showCancel: false, - confirmText: '好' - }) - } - } - } - - const handlePurchaseChange = async () => { - const data = await api.purchase.getUserEnterprises({ - disabled: 0, - distributor_id: getDistributorId() - }) - if (data?.length > 0) { - Taro.navigateTo({ url: '/subpages/purchase/select-identity?is_redirt=1' }) - } else { - Taro.navigateTo({ url: '/pages/purchase/auth' }) - } - dispatch(updatePurchaseShareInfo()) - dispatch(updateInviteCode()) - dispatch(updateCurDistributorId(null)) - } - - const handleClickLink = async (link) => { - // await getUserInfoAuth() - Taro.navigateTo({ url: link }) - } - const handleClickService = async (item) => { const { link, key } = item // 分销推广 @@ -460,13 +414,17 @@ function MemberIndex(props) { Taro.navigateTo({ url: link }) } } + + const onLoginChange = (url) => { + if (!isLogin || !url) return + Taro.navigateTo({ url }) + } + const VipGradeDom = () => { return ( { - Taro.navigateTo({ url: '/subpages/member/member-level' }) - }} + onClick={() => onLoginChange('/subpages/member/member-level')} > { @@ -486,7 +444,7 @@ function MemberIndex(props) { } const memberBckStyle = { - background: `url('${userInfo?.gradeInfo?.grade_background}') no-repeat center center / contain` + background: `url('${userInfo?.gradeInfo?.grade_background}') no-repeat center center / cover` } return ( @@ -508,15 +466,11 @@ function MemberIndex(props) { className='header-block' style={userInfo?.gradeInfo?.grade_background ? memberBckStyle : {}} > - + { - if (isLogin) { - Taro.navigateTo({ url: '/subpages/member/user-info' }) - } - }} + onClick={() => onLoginChange('/subpages/member/user-info')} style={{ width: '72px', height: '72px' }} > Taro.navigateTo({ url: '/subpages/member/user-info' })} + onClick={() => onLoginChange('/subpages/member/user-info')} > {userInfo?.username || userInfo?.mobile} @@ -547,9 +501,7 @@ function MemberIndex(props) { ) : ( - - 点击登录 - + 点击登录 )} @@ -569,47 +521,32 @@ function MemberIndex(props) { className='member-level-bg' /> */} {isLogin && config.menu.member_code && !VERSION_SHUYUN && ( - - - + onLoginChange('/marketing/pages/member/member-code')} + > )} - { - Taro.navigateTo({ url: '/subpages/marketing/coupon' }) - }} + onLoginChange('/subpages/marketing/coupon')} > - } - > - {isLogin ? state.couponCount || 0 : '···'} - 优惠券 - - - { - if (VERSION_SHUYUN) { - handleClickLink('/subpages/member/point-rule') - } else { - handleClickLink('/subpages/member/point-detail') - } - }} + {isLogin ? state.couponCount || 0 : '···'} + 优惠券 + + + onLoginChange('/subpages/member/point-detail')} > - {!VERSION_SHUYUN && ( - - {isLogin ? state.point || 0 : '···'} - {VERSION_SHUYUN ? '积分规则' : pointName} - - )} - + {isLogin ? state.point || 0 : '···'} + 积分 + - + {/* */} diff --git a/src/subpages/pointshop/espier-detail.js b/src/subpages/pointshop/espier-detail.js index 937227fc3..cebd9b5d3 100644 --- a/src/subpages/pointshop/espier-detail.js +++ b/src/subpages/pointshop/espier-detail.js @@ -38,7 +38,8 @@ import { classNames, navigateTo, VERSION_PLATFORM, - isAPP + isAPP, + buildSharePath } from '@/utils' import doc from '@/doc' @@ -170,7 +171,7 @@ function PointShopEspierDetail(props) { if (userInfo) { query['uid'] = userInfo.user_id } - const path = `/subpages/pointshop/espier-detail?${qs.stringify(query)}` + const path = buildSharePath('poster_pointshop_espier_detail', query) log.debug(`share path: ${path}`) return { title: itemName, diff --git a/src/subpages/purchase/index.js b/src/subpages/purchase/index.js index 6beb00004..882dca866 100644 --- a/src/subpages/purchase/index.js +++ b/src/subpages/purchase/index.js @@ -32,7 +32,8 @@ import { classNames, pickBy, showToast, - log + log, + buildSharePath } from '@/utils' import { updatePurchaseShareInfo, @@ -172,11 +173,17 @@ function Home() { const activity_id = router.params?.activity_id || purchase_share_info?.activity_id const enterprise_id = router.params?.enterprise_id || purchase_share_info?.enterprise_id const data = await api.purchase.getEmployeeInviteCode({ enterprise_id, activity_id }) - log.debug(`/pages/purchase/auth?code=${data.invite_code}`) + const params = { + code: data.invite_code, + enterprise_id, + activity_id + } + const path = buildSharePath('poster_purchase_auth', params) + log.debug(path) resolve({ title: activityInfo.name, imageUrl: activityInfo.share_pic, - path: `/pages/purchase/auth?code=${data.invite_code}&enterprise_id=${enterprise_id}&activity_id=${activity_id}` + path }) } }) diff --git a/src/utils/index.js b/src/utils/index.js index de613984f..250a661f1 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -885,6 +885,22 @@ export const pxToUnitRpx = (px) => { return Taro.pxTransform(px * 2) } +/** + * 构建统一分享路径 + * @param {string} from_scene - 目标页面类型 + * @param {object} params - 路径参数 + * @returns {string} 统一的分享落地页路径 + */ +export function buildSharePath(from_scene, params = {}) { + const shareParams = { + from_scene: from_scene, + ...params + } + const queryString = qs.stringify(shareParams) + debugger + return `/pages/share-land${queryString ? '?' + queryString : ''}` +} + export { classNames, log,