Commit 3d83a00b authored by zhangchenchen's avatar zhangchenchen

Merge branch 'dev' into feature/20251104-feature

parents 9c3b2110 7f2fbf2e
No preview for this file type
...@@ -14,4 +14,6 @@ export const fetchHomeInfo = () => api.get('/c/user/index'); ...@@ -14,4 +14,6 @@ export const fetchHomeInfo = () => api.get('/c/user/index');
export const fetchCanEatIndex = () => api.get('/c/eat/index'); export const fetchCanEatIndex = () => api.get('/c/eat/index');
export const fetchCanEatJoin = (data) => api.post('/c/eat/join', data); export const fetchCanEatJoin = (data) => api.post('/c/eat/join', data);
export const fetchHomeJSON = () => api.get('/c/front/content',{type:'home_V1'}); export const fetchHomeJSON = () => api.get('/c/front/content', { type: 'home_V1' });
export const fetchGameActConfigJSON = () => api.get('/c/front/content', { type: 'gameActConfig' });
...@@ -15,12 +15,12 @@ const { ...@@ -15,12 +15,12 @@ const {
// request.js // request.js
// 通常可以吧 baseUrl 单独放在一个 js 文件了 // 通常可以吧 baseUrl 单独放在一个 js 文件了
// const baseUrl = "http://172.16.230.108:7777/pmall"; // export const baseUrl = "http://172.16.230.108:7777/pmall";
// const baseUrl = "https://momclub-uat.feihe.com/pmall";//测试环境 // export const baseUrl = "https://momclub-uat.feihe.com/pmall";//测试环境
// const baseUrl = "https://momclub-test.feihe.com/pmall"; export const baseUrl = "https://momclub-test.feihe.com/pmall";
let baseUrl = "https://momclub.feihe.com/pmall";//生产环境 // export const baseUrl = "https://momclub.feihe.com/pmall";//生产环境
// const baseUrl = "https://docs.dui88.com/mock/1956/api";//mock // export const baseUrl = "https://docs.dui88.com/mock/1956/api";//mock
// const baseUrl = "https://feihe.m.duibatest.com.cn/pmall" // export const baseUrl = "https://feihe.m.duibatest.com.cn/pmall"
const request = (options = {}) => { const request = (options = {}) => {
// 在这里可以对请求头进行一些设置 // 在这里可以对请求头进行一些设置
......
...@@ -73,4 +73,11 @@ export const getExchangeList = (params = {}) => api.get('/c/user/exchange/list', ...@@ -73,4 +73,11 @@ export const getExchangeList = (params = {}) => api.get('/c/user/exchange/list',
* @param {orderNo} data * @param {orderNo} data
* @returns * @returns
*/ */
export const getOrderDetail = (data) => api.get('/c/order/detail', data); export const getOrderDetail = (data) => api.get('/c/order/detail', data);
\ No newline at end of file
/**
* 保存宝宝额外信息
* @param {Object} data - 宝宝额外信息
* @returns {Promise} 接口响应
*/
export const saveBabyExtra = (data) => api.post('/c/user/saveBabyExtra', data);
\ No newline at end of file
...@@ -9,10 +9,11 @@ ...@@ -9,10 +9,11 @@
<!-- 结果标题和图标 --> <!-- 结果标题和图标 -->
<view class="result-header"> <view class="result-header">
<text class="result-title">{{ isCorrect ? '你太棒了,回答正确!' : '快来补课吧,回答错误哦!' }}</text> <text class="result-title">{{ isCorrect ? '你太棒了,回答正确!' : '快来补课吧回答错误哦!' }}</text>
<view class="result-icon"> <view class="result-icon">
<image v-if="isCorrect" :src="`${$baseUrl}homepage/Q3Res/eat_goodIcon.png`" mode="aspectFit"></image> <image class="correct" v-if="isCorrect" :src="`${$baseUrl}homepage/Q3Res/eat_goodIcon.png`"
<image v-else :src="`${$baseUrl}homepage/Q3Res/eat_cryIcon.png`" mode="aspectFit"></image> mode="aspectFit"></image>
<image class="incorrect" v-else :src="`${$baseUrl}homepage/Q3Res/eat_cryIcon.png`" mode="aspectFit"></image>
</view> </view>
</view> </view>
...@@ -164,9 +165,9 @@ export default { ...@@ -164,9 +165,9 @@ export default {
// 添加曝光埋点 // 添加曝光埋点
this.$nextTick(() => { this.$nextTick(() => {
md.sensorPopLogTake({ md.sensorPopLogTake({
xcxPopExposure: "true", xcxPopExposure: "true",
toolName: "能不能吃", toolName: "能不能吃",
popName: "解析弹窗" popName: "解析弹窗"
}); });
}); });
}, },
...@@ -191,9 +192,9 @@ export default { ...@@ -191,9 +192,9 @@ export default {
<style scoped> <style scoped>
.answer-popup-container { .answer-popup-container {
width: 750rpx; width: 750rpx;
height: 986rpx;
position: relative; position: relative;
margin: 0 auto; margin: 0 auto;
bottom: -80rpx;
overflow: visible; overflow: visible;
} }
...@@ -244,7 +245,20 @@ export default { ...@@ -244,7 +245,20 @@ export default {
line-height: 1.4; line-height: 1.4;
} }
.result-icon {
.result-icon .correct {
width: 164rpx;
height: 164rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
top: -20rpx;
left: -170rpx;
}
.result-icon .incorrect {
width: 164rpx; width: 164rpx;
height: 164rpx; height: 164rpx;
display: flex; display: flex;
...@@ -252,7 +266,7 @@ export default { ...@@ -252,7 +266,7 @@ export default {
justify-content: center; justify-content: center;
position: relative; position: relative;
top: 0rpx; top: 0rpx;
left: -140rpx; left: -120rpx;
} }
.result-icon image { .result-icon image {
...@@ -356,7 +370,7 @@ export default { ...@@ -356,7 +370,7 @@ export default {
.analysis-section { .analysis-section {
background: #FFFFFF; background: #FFFFFF;
height: 446rpx; max-height: 446rpx;
padding: 40rpx; padding: 40rpx;
border-radius: 36rpx; border-radius: 36rpx;
margin-bottom: 40rpx; margin-bottom: 40rpx;
......
...@@ -331,10 +331,18 @@ ...@@ -331,10 +331,18 @@
width: 220rpx; // 固定宽度220rpx width: 220rpx; // 固定宽度220rpx
height: 380rpx; // 固定高度380rpx height: 380rpx; // 固定高度380rpx
border-radius: 16rpx; border-radius: 16rpx;
padding: 15rpx 15rpx 39rpx 15rpx; padding: 15rpx 0 39rpx 0rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
&:first-child {
margin-left: 24rpx;
}
&:last-child {
margin-right: 24rpx;
}
.good_info_container { .good_info_container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
......
...@@ -769,171 +769,155 @@ const generateTestSeckillData = () => { ...@@ -769,171 +769,155 @@ const generateTestSeckillData = () => {
"sessionKey": "session_1_ongoing", "sessionKey": "session_1_ongoing",
"start": session1Start "start": session1Start
}, },
// { {
// "end": session2End, "end": session2End,
// "goods": [ "goods": [
// { {
// "button": {"key": 1, "text": "立即抢购"}, "button": {"key": 1, "text": "立即抢购"},
// "credits": 200, "credits": 200,
// "creditsType": "CREDITS", "creditsType": "CREDITS",
// "creditsTypeName": "积分", "creditsTypeName": "积分",
// "goods": { "goods": {
// "id": 201, "id": 201,
// "goodsName": "限时秒杀商品A - 正在进行中", "goodsName": "限时秒杀商品A - 正在进行中",
// "goodsImage": ["https://via.placeholder.com/150/FF6B35/FFFFFF?text=SeckillA"], "goodsImage": ["https://via.placeholder.com/150/FF6B35/FFFFFF?text=SeckillA"],
// "credits": "200", "credits": "200",
// "priceSale": "400.00", "priceSale": "400.00",
// "stock": 15 "stock": 15
// }, },
// "priceSale": "400.00", "priceSale": "400.00",
// "stock": 15 "stock": 15
// }, },
// { {
// "button": {"key": 1, "text": "立即抢购"}, "button": {"key": 1, "text": "立即抢购"},
// "credits": 300, "credits": 300,
// "creditsType": "CREDITS", "creditsType": "CREDITS",
// "creditsTypeName": "积分", "creditsTypeName": "积分",
// "goods": { "goods": {
// "id": 202, "id": 202,
// "goodsName": "限时秒杀商品B - 正在进行中", "goodsName": "限时秒杀商品B - 正在进行中",
// "goodsImage": ["https://via.placeholder.com/150/4CAF50/FFFFFF?text=SeckillB"], "goodsImage": ["https://via.placeholder.com/150/4CAF50/FFFFFF?text=SeckillB"],
// "credits": "300", "credits": "300",
// "priceSale": "600.00", "priceSale": "600.00",
// "stock": 8 "stock": 8
// }, },
// "priceSale": "600.00", "priceSale": "600.00",
// "stock": 8 "stock": 8
// }, },
// { ],
// "button": {"key": 1, "text": "立即抢购"}, "sessionKey": "session_2_ongoing",
// "credits": 150, "start": session2Start
// "creditsType": "CREDITS", },
// "creditsTypeName": "积分", {
// "goods": { "end": session3End,
// "id": 203, "goods": [
// "goodsName": "限时秒杀商品C - 正在进行中", {
// "goodsImage": ["https://via.placeholder.com/150/9C27B0/FFFFFF?text=SeckillC"], "button": {"key": 2, "text": "即将开始"},
// "credits": "150", "credits": 300,
// "priceSale": "300.00", "creditsType": "CREDITS",
// "stock": 12 "creditsTypeName": "积分",
// }, "goods": {
// "priceSale": "300.00", "id": 301,
// "stock": 12 "goodsName": "测试商品D - 即将开始",
// } "goodsImage": ["https://via.placeholder.com/150/9C27B0/FFFFFF?text=GoodD"],
// ], "credits": "300",
// "sessionKey": "session_2_ongoing", "priceSale": "600.00",
// "start": session2Start "stock": 3
// }, },
// { "priceSale": "600.00",
// "end": session3End, "stock": 3
// "goods": [ },
// { {
// "button": {"key": 2, "text": "即将开始"}, "button": {"key": 2, "text": "即将开始"},
// "credits": 300, "credits": 250,
// "creditsType": "CREDITS", "creditsType": "CREDITS",
// "creditsTypeName": "积分", "creditsTypeName": "积分",
// "goods": { "goods": {
// "id": 301, "id": 302,
// "goodsName": "测试商品D - 即将开始", "goodsName": "测试商品E - 即将开始",
// "goodsImage": ["https://via.placeholder.com/150/9C27B0/FFFFFF?text=GoodD"], "goodsImage": ["https://via.placeholder.com/150/FF9800/FFFFFF?text=GoodE"],
// "credits": "300", "credits": "250",
// "priceSale": "600.00", "priceSale": "500.00",
// "stock": 3 "stock": 6
// }, },
// "priceSale": "600.00", "priceSale": "500.00",
// "stock": 3 "stock": 6
// }, },
// { {
// "button": {"key": 2, "text": "即将开始"}, "button": {"key": 2, "text": "即将开始"},
// "credits": 250, "credits": 180,
// "creditsType": "CREDITS", "creditsType": "CREDITS",
// "creditsTypeName": "积分", "creditsTypeName": "积分",
// "goods": { "goods": {
// "id": 302, "id": 303,
// "goodsName": "测试商品E - 即将开始", "goodsName": "测试商品F - 即将开始",
// "goodsImage": ["https://via.placeholder.com/150/FF9800/FFFFFF?text=GoodE"], "goodsImage": ["https://via.placeholder.com/150/795548/FFFFFF?text=GoodF"],
// "credits": "250", "credits": "180",
// "priceSale": "500.00", "priceSale": "360.00",
// "stock": 6 "stock": 12
// }, },
// "priceSale": "500.00", "priceSale": "360.00",
// "stock": 6 "stock": 12
// }, }
// { ],
// "button": {"key": 2, "text": "即将开始"}, "sessionKey": "session_3_upcoming",
// "credits": 180, "start": session3Start
// "creditsType": "CREDITS", },
// "creditsTypeName": "积分", {
// "goods": { "end": session4End,
// "id": 303, "goods": [
// "goodsName": "测试商品F - 即将开始", {
// "goodsImage": ["https://via.placeholder.com/150/795548/FFFFFF?text=GoodF"], "button": {"key": 2, "text": "即将开始"},
// "credits": "180", "credits": 300,
// "priceSale": "360.00", "creditsType": "CREDITS",
// "stock": 12 "creditsTypeName": "积分",
// }, "goods": {
// "priceSale": "360.00", "id": 301,
// "stock": 12 "goodsName": "测试商品D - 即将开始",
// } "goodsImage": ["https://via.placeholder.com/150/9C27B0/FFFFFF?text=GoodD"],
// ], "credits": "300",
// "sessionKey": "session_3_upcoming", "priceSale": "600.00",
// "start": session3Start "stock": 3
// }, },
// { "priceSale": "600.00",
// "end": session4End, "stock": 3
// "goods": [ },
// { {
// "button": {"key": 2, "text": "即将开始"}, "button": {"key": 2, "text": "即将开始"},
// "credits": 300, "credits": 250,
// "creditsType": "CREDITS", "creditsType": "CREDITS",
// "creditsTypeName": "积分", "creditsTypeName": "积分",
// "goods": { "goods": {
// "id": 301, "id": 302,
// "goodsName": "测试商品D - 即将开始", "goodsName": "测试商品E - 即将开始",
// "goodsImage": ["https://via.placeholder.com/150/9C27B0/FFFFFF?text=GoodD"], "goodsImage": ["https://via.placeholder.com/150/FF9800/FFFFFF?text=GoodE"],
// "credits": "300", "credits": "250",
// "priceSale": "600.00", "priceSale": "500.00",
// "stock": 3 "stock": 6
// }, },
// "priceSale": "600.00", "priceSale": "500.00",
// "stock": 3 "stock": 6
// }, },
// { {
// "button": {"key": 2, "text": "即将开始"}, "button": {"key": 2, "text": "即将开始"},
// "credits": 250, "credits": 180,
// "creditsType": "CREDITS", "creditsType": "CREDITS",
// "creditsTypeName": "积分", "creditsTypeName": "积分",
// "goods": { "goods": {
// "id": 302, "id": 303,
// "goodsName": "测试商品E - 即将开始", "goodsName": "测试商品F - 即将开始",
// "goodsImage": ["https://via.placeholder.com/150/FF9800/FFFFFF?text=GoodE"], "goodsImage": ["https://via.placeholder.com/150/795548/FFFFFF?text=GoodF"],
// "credits": "250", "credits": "180",
// "priceSale": "500.00", "priceSale": "360.00",
// "stock": 6 "stock": 12
// }, },
// "priceSale": "500.00", "priceSale": "360.00",
// "stock": 6 "stock": 12
// }, }
// { ],
// "button": {"key": 2, "text": "即将开始"}, "sessionKey": "session_3_upcoming",
// "credits": 180, "start": session4Start
// "creditsType": "CREDITS", }
// "creditsTypeName": "积分",
// "goods": {
// "id": 303,
// "goodsName": "测试商品F - 即将开始",
// "goodsImage": ["https://via.placeholder.com/150/795548/FFFFFF?text=GoodF"],
// "credits": "180",
// "priceSale": "360.00",
// "stock": 12
// },
// "priceSale": "360.00",
// "stock": 12
// }
// ],
// "sessionKey": "session_3_upcoming",
// "start": session4Start
// }
], ],
"id": 1141, "id": 1141,
"name": "测试秒杀", "name": "测试秒杀",
...@@ -957,7 +941,7 @@ const loadSeckillData = async () => { ...@@ -957,7 +941,7 @@ const loadSeckillData = async () => {
const seckillData = await integralStore.getSeckillData(props.isdebug); const seckillData = await integralStore.getSeckillData(props.isdebug);
if (seckillData) { if (seckillData) {
mapSeckillDataToCreditsSale(seckillData); mapSeckillDataToCreditsSale(seckillData);
初始化倒计时 //初始化倒计时
initCountdowns(); initCountdowns();
} }
} catch (error) { } catch (error) {
......
...@@ -99,6 +99,10 @@ ...@@ -99,6 +99,10 @@
} }
} }
} }
.invite_button::after {
border: none !important;
outline: none !important;
}
} }
.record_button { .record_button {
......
...@@ -48,10 +48,11 @@ ...@@ -48,10 +48,11 @@
margin-bottom: 20rpx; margin-bottom: 20rpx;
text-align: center; text-align: center;
display: block; display: block;
overflow: hidden; // overflow: hidden;
text-overflow: ellipsis; // text-overflow: ellipsis;
white-space: nowrap; // white-space: nowrap;
max-width: 560rpx; max-width: 560rpx;
max-height: 200rpx;
} }
.points_text { .points_text {
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
<!-- 弹窗内容 --> <!-- 弹窗内容 -->
<view class="task_complete_tips_container"> <view class="task_complete_tips_container">
<!-- 第一行:标题文字 --> <!-- 第一行:标题文字 -->
<text class="tips_title">完成{{ taskTitle }}任务</text> <text class="tips_title">{{ displayTitle }}</text>
<!-- <text class="tips_title">完成任务完成任务完成任务任务任务</text> -->
<!-- 第二行:积分文字 --> <!-- 第二行:积分文字 -->
<text class="points_text">获得{{ points }}积分</text> <text class="points_text">获得{{ points }}积分</text>
...@@ -30,7 +31,7 @@ ...@@ -30,7 +31,7 @@
</template> </template>
<script setup> <script setup>
import { defineProps, defineEmits, ref, watch } from 'vue'; import { defineProps, defineEmits, ref, watch,computed } from 'vue';
import md from '../../md'; import md from '../../md';
// Props 定义 // Props 定义
...@@ -49,6 +50,17 @@ const props = defineProps({ ...@@ -49,6 +50,17 @@ const props = defineProps({
} }
}); });
// 处理标题文本,超过14个字显示省略号
const displayTitle = computed(() => {
const title = `完成${props.taskTitle}任务`;
// const title = '完成任务完成任务完成任务任务啊啊啊';//`完成${props.taskTitle}任务`;
if (title.length > 16) {
return title.substring(0, 15) + '...';
}
console.log('title:', title);
return title;
});
// Emits 定义 // Emits 定义
const emit = defineEmits(['close', 'accept']); const emit = defineEmits(['close', 'accept']);
...@@ -103,7 +115,7 @@ const handleAccept = () => { ...@@ -103,7 +115,7 @@ const handleAccept = () => {
setTimeout(() => { setTimeout(() => {
isAnimating.value = false; isAnimating.value = false;
emit('close'); emit('close');
}, 1500); }, 950);
}; };
</script> </script>
......
# H5分享方法调用文档
## 概述
本文档说明H5页面如何通过微信小程序的消息机制调用小程序的分享功能,实现自定义分享内容。
## 适用场景
当H5页面需要在小程序中自定义分享内容(标题、图片、路径)时,可以通过 `postMessage` API向小程序发送分享数据。
## 前置条件
1. H5页面必须在微信小程序的 `<web-view>` 组件中加载
2. 小程序页面路径:`/pages/gameWebview/webview`
3. 需要在微信小程序环境中运行(微信开发者工具或真实微信环境)
## 调用方法
### 基本语法
```javascript
wx.miniProgram.postMessage({
data: {
// 分享数据对象
shareUrl: '/pages/index/index?param=value',
shareTitle: '分享标题',
shareImageUrl: 'https://example.com/share-image.jpg'
}
})
```
### 完整示例
```javascript
// H5页面代码
function shareToWechat() {
// 检查是否在微信小程序环境中
if (typeof wx !== 'undefined' && wx.miniProgram) {
wx.miniProgram.postMessage({
data: [{
shareUrl: '/pages/index/index?activityId=123&type=game',
shareTitle: '快来参与游戏,赢取丰厚奖品!',
shareImageUrl: 'https://example.com/images/share.jpg'
}]
})
// 触发分享(需要用户手动触发,如点击按钮)
wx.miniProgram.navigateBack()
} else {
console.warn('当前不在微信小程序环境中')
}
}
```
## 分享数据格式
### 数据结构
分享数据必须是一个**数组**,数组中的每个元素是一个对象,包含以下字段:
```javascript
[
{
shareUrl: string, // 分享路径(小程序页面路径)
shareTitle: string, // 分享标题
shareImageUrl: string // 分享图片URL(可选)
},
// ... 可以包含多个分享数据对象
]
```
**重要**:小程序会使用数组的**最后一个元素**作为分享数据。
### 字段说明
| 字段名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| `shareUrl` | String | 是 | 分享后跳转的小程序页面路径(支持参数) | `/pages/index/index?activityId=123` |
| `shareTitle` | String | 是 | 分享卡片显示的标题 | `快来参与活动!` |
| `shareImageUrl` | String | 否 | 分享卡片显示的图片URL(网络图片) | `https://example.com/share.jpg` |
### 字段详细说明
#### shareUrl
- **格式**:小程序页面路径,以 `/` 开头
- **支持参数**:可以在路径后添加查询参数
- **默认值**:如果未提供或为空,使用 `/pages/index/index`
- **示例**
- `/pages/index/index`
- `/pages/index/index?pageType=home`
- `/pages/gameWebview/webview?url=https://example.com/h5/page&activityId=123`
#### shareTitle
- **格式**:纯文本字符串
- **长度限制**:建议不超过20个字符(微信分享卡片显示限制)
- **示例**`快来参与活动,赢取丰厚奖品!`
#### shareImageUrl
- **格式**:完整的网络图片URL(必须以 `http://``https://` 开头)
- **尺寸要求**:建议 500x500 像素或更高(微信会自动压缩)
- **格式要求**:支持 JPG、PNG 格式
- **大小限制**:建议不超过 200KB
- **默认值**:如果未提供或为空,使用小程序默认分享图
## 调用时机
### 推荐调用时机
1. **用户点击分享按钮时**
```javascript
document.getElementById('share-btn').addEventListener('click', function() {
wx.miniProgram.postMessage({
data: [{
shareUrl: '/pages/index/index?activityId=123',
shareTitle: '分享标题',
shareImageUrl: 'https://example.com/share.jpg'
}]
})
})
```
2. **页面加载完成后**
```javascript
window.addEventListener('load', function() {
// 设置默认分享数据
wx.miniProgram.postMessage({
data: [{
shareUrl: window.location.href,
shareTitle: document.title,
shareImageUrl: 'https://example.com/default-share.jpg'
}]
})
})
```
3. **动态更新分享内容**
```javascript
function updateShareContent(activityId, activityName) {
wx.miniProgram.postMessage({
data: [{
shareUrl: `/pages/index/index?activityId=${activityId}`,
shareTitle: `快来参与${activityName}!`,
shareImageUrl: `https://example.com/activity/${activityId}/share.jpg`
}]
})
}
```
## 完整示例代码
### 示例1:基础分享功能
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>H5分享示例</title>
</head>
<body>
<button id="shareBtn">分享给好友</button>
<script>
// 检查是否在微信小程序环境中
function isInMiniProgram() {
return typeof wx !== 'undefined' && wx.miniProgram
}
// 设置分享内容
function setShareContent() {
if (!isInMiniProgram()) {
console.warn('当前不在微信小程序环境中')
return
}
wx.miniProgram.postMessage({
data: [{
shareUrl: '/pages/index/index?source=h5&activityId=123',
shareTitle: '快来参与活动,赢取丰厚奖品!',
shareImageUrl: 'https://example.com/images/share-activity.jpg'
}]
})
console.log('分享内容已设置')
}
// 页面加载时设置默认分享内容
window.addEventListener('load', function() {
setShareContent()
})
// 点击分享按钮
document.getElementById('shareBtn').addEventListener('click', function() {
setShareContent()
alert('分享内容已更新,请点击右上角分享按钮')
})
</script>
</body>
</html>
```
### 示例2:动态更新分享内容
```javascript
// 根据活动状态动态更新分享内容
function updateShareByActivity(activity) {
if (!isInMiniProgram()) {
return
}
const shareData = {
shareUrl: `/pages/index/index?activityId=${activity.id}&type=${activity.type}`,
shareTitle: activity.shareTitle || `快来参与${activity.name}!`,
shareImageUrl: activity.shareImage || 'https://example.com/default-share.jpg'
}
wx.miniProgram.postMessage({
data: [shareData]
})
}
// 获取活动信息后更新分享
fetch('/api/activity/123')
.then(res => res.json())
.then(activity => {
updateShareByActivity(activity)
})
```
### 示例3:多个分享数据(使用最后一个)
```javascript
// 小程序会使用数组最后一个元素
wx.miniProgram.postMessage({
data: [
{
shareUrl: '/pages/index/index',
shareTitle: '第一个分享(不会被使用)',
shareImageUrl: 'https://example.com/image1.jpg'
},
{
shareUrl: '/pages/index/index?activityId=123',
shareTitle: '第二个分享(会被使用)',
shareImageUrl: 'https://example.com/image2.jpg'
}
]
})
```
## 小程序端处理
小程序端会自动接收H5页面发送的分享数据,并在用户触发分享时使用。
### 分享类型
小程序支持两种分享方式:
1. **分享给好友**(`onShareAppMessage`)
2. **分享到朋友圈**(`onShareTimeline`)
两种分享方式都会使用相同的分享数据。
## 注意事项
### 1. 数据格式要求
- 分享数据必须是**数组格式**
- 数组最后一个元素会被使用
- 如果数组为空或格式错误,会使用默认分享内容
### 2. 调用时机限制
- `postMessage` 必须在用户交互(如点击)后调用才能生效
- 不能在页面加载时立即调用(可能被微信拦截)
### 3. 环境检测
建议在调用前检测是否在微信小程序环境中:
```javascript
function isInMiniProgram() {
return typeof wx !== 'undefined' && wx.miniProgram
}
if (isInMiniProgram()) {
// 调用 postMessage
} else {
console.warn('当前不在微信小程序环境中')
}
```
### 4. 分享图片要求
- 必须是网络图片(不能是本地路径)
- 建议尺寸:500x500 像素或更高
- 建议格式:JPG、PNG
- 建议大小:不超过 200KB
### 5. 分享路径
- 必须以 `/` 开头
- 可以是小程序内任意页面路径
- 支持查询参数
- 路径必须在 `pages.json` 中配置
### 6. 调试方法
在微信开发者工具中:
1. 打开调试器
2. 查看 Console 输出
3. 检查 `postMessage` 是否成功调用
4. 点击右上角分享按钮测试分享功能
## 常见问题
### Q1: 分享数据发送后没有生效?
A: 检查以下几点:
- 数据格式是否正确(必须是数组)
- 是否在用户交互后调用(不能直接调用)
- 是否在微信小程序环境中
- 分享数据字段是否完整
### Q2: 如何动态更新分享内容?
A: 可以在需要的时候多次调用 `postMessage`,每次调用都会更新分享内容。
### Q3: 分享图片显示不出来?
A: 检查:
- 图片URL是否可访问(必须是网络图片)
- 图片格式是否正确(JPG、PNG)
- 图片大小是否合适(建议不超过200KB)
### Q4: 可以同时设置多个分享数据吗?
A: 可以,但小程序只会使用数组的最后一个元素。
### Q5: 分享路径可以跳转到其他小程序吗?
A: 不可以,`shareUrl` 只能是小程序内的页面路径,不能跳转到其他小程序或H5页面。
## 最佳实践
1. **及时更新分享内容**:根据页面状态动态更新分享内容
2. **提供默认分享**:页面加载时设置默认分享内容
3. **优化分享图片**:使用高质量、合适尺寸的分享图片
4. **测试分享功能**:在不同场景下测试分享功能是否正常
5. **错误处理**:添加环境检测和错误处理逻辑
## 更新日志
- 2025-01-XX: 初始版本,支持基础分享功能
- 2025-01-XX: 添加分享到朋友圈支持
# H5投放参数使用文档
## 概述
本文档说明如何在小程序中跳转到H5页面(webview),以及如何传递参数给H5页面。
## 页面路径
小程序webview页面路径:`/pages/gameWebview/webview`
## URL参数说明
### 基础参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| `url` | String | 否 | H5页面URL(完整URL或相对路径) | `https://example.com/h5/page` |
| `baseUrl` | String | 否 | 同 `url`,用于指定H5页面URL | `https://example.com/h5/page` |
| `scene` | String | 否 | 二维码场景值(会自动双重解码) | `?type=activity&id=123` |
| `needLogin` | String | 否 | 是否需要登录(`'true'``'false'`) | `'true'` |
**注意**
- `url``baseUrl` 参数互斥,两者功能相同,优先使用 `url`
- 如果 `url``baseUrl` 不包含协议(`http://``https://`),会自动添加 `https://`
- 如果未指定 `url``baseUrl`,默认使用:`https://momclub-test.feihe.com/h5/game/index.html`
### 自定义参数
除了上述基础参数外,其他所有参数都会原样传递给H5页面。
**示例**
```javascript
uni.navigateTo({
url: '/pages/gameWebview/webview?url=https://example.com/h5/page&activityId=123&type=game&source=wechat'
})
```
H5页面接收到的URL为:
```
https://example.com/h5/page?activityId=123&type=game&source=wechat&cuk=xxx&openId=xxx&...
```
## 自动添加的参数
小程序会自动在H5 URL中添加以下参数(无需手动传递):
### 用户身份参数
| 参数名 | 说明 | 示例值 | 备注 |
|--------|------|--------|------|
| `cuk` | 用户登录凭证 | `abc123def456` | 自动添加(如果已登录) |
| `miniopenid` | 用户OpenID | `oXXX...` | 自动添加 |
| `unionId` | 用户UnionID | `uXXX...` | 自动添加(如果存在) |
| `wxNickName` | 微信昵称 | `张三` | 自动添加(如果存在) |
### 会员信息参数(仅已登录用户)
| 参数名 | 说明 | 示例值 | 备注 |
|--------|------|--------|------|
| `memberid` | 会员ID | `CRM000000000188501075` | 自动添加(已登录时) |
| `crmId` | 会员ID(同memberid) | `CRM000000000188501075` | 自动添加(已登录时) |
| `programLogin` | 是否登录 | `'1'``'0'` | `'1'`=已登录,`'0'`=未登录 |
| `memberType` | 会员等级名称 | `V1黄金会员` | 从 `gradeList` 中根据 `grade` 匹配获取 |
**会员等级说明**
- `memberType` 的值来自接口返回的 `gradeList` 数组
- 根据当前用户的 `grade` 值,在 `gradeList` 中查找对应的 `gradeName`
- 如果找不到,则使用 `gradeName` 字段
- 如果都没有,则使用 `grade` 的字符串值
**示例数据**
```json
{
"grade": "0",
"gradeList": [
{"grade": "0", "gradeName": "V1黄金会员"},
{"grade": "1", "gradeName": "V2铂金会员"},
{"grade": "2", "gradeName": "V3钻石会员"}
]
}
```
如果用户的 `grade``"0"`,则 `memberType` 参数值为 `"V1黄金会员"`
## 完整示例
### 示例1:基础跳转
```javascript
// 小程序代码
uni.navigateTo({
url: '/pages/gameWebview/webview?url=https://example.com/h5/game'
})
```
**实际传递到H5的URL**
```
```
### 示例2:带自定义参数和场景值
```javascript
// 小程序代码
uni.navigateTo({
url: '/pages/gameWebview/webview?url=https://example.com/h5/activity&activityId=123&type=game&scene=' + encodeURIComponent(encodeURIComponent('?campaign=summer&source=qr'))
})
```
**说明**
- `scene` 参数会被双重解码,所以需要双重编码
- 其他参数会原样传递
### 示例3:需要登录的页面
```javascript
// 小程序代码
uni.navigateTo({
url: '/pages/gameWebview/webview?url=https://example.com/h5/member&needLogin=true'
})
```
**说明**
- 如果 `needLogin=true` 且用户未登录,会自动跳转到注册页
- 注册成功后返回webview页面
### 示例4:使用相对路径
```javascript
// 小程序代码
uni.navigateTo({
url: '/pages/gameWebview/webview?url=momclub-test.feihe.com/h5/game'
})
```
**说明**
- 如果URL不包含协议,会自动添加 `https://`
- 实际URL:`https://momclub-test.feihe.com/h5/game`
## 参数编码说明
### 自动编码
所有参数值都会自动进行 `encodeURIComponent` 编码,无需手动编码。
### Scene参数特殊处理
`scene` 参数会被双重解码,所以如果需要传递 `scene` 参数,需要双重编码:
```javascript
const scene = '?campaign=summer&source=qr'
const encodedScene = encodeURIComponent(encodeURIComponent(scene))
uni.navigateTo({
url: `/pages/gameWebview/webview?url=https://example.com/h5/page&scene=${encodedScene}`
})
```
## 在H5页面中获取参数
H5页面可以通过以下方式获取参数:
```javascript
// 方式1:使用 URLSearchParams
const urlParams = new URLSearchParams(window.location.search)
const activityId = urlParams.get('activityId')
const memberId = urlParams.get('memberId')
const programLogin = urlParams.get('programLogin')
const memberType = urlParams.get('memberType')
// 方式2:手动解析
function getQueryParam(name) {
const urlParams = new URLSearchParams(window.location.search)
return urlParams.get(name)
}
const memberId = getQueryParam('memberId')
```
## 注意事项
1. **参数长度限制**:URL总长度有限制,建议不要传递过多参数
2. **参数编码**:参数值会自动编码,无需手动处理
3. **登录状态**`programLogin` 参数会自动根据用户登录状态设置
4. **会员信息**:会员相关参数(`memberId``memberType`)仅在用户已登录时添加
5. **Scene参数**`scene` 参数会被特殊处理(双重解码),主要用于二维码场景
6. **默认URL**:如果未指定 `url``baseUrl`,会使用默认的测试环境URL
## 常见问题
### Q1: 如何判断用户是否登录?
A: 检查 `programLogin` 参数,值为 `'1'` 表示已登录,`'0'` 表示未登录。
### Q2: 如何获取会员等级?
A: 使用 `memberType` 参数,值为会员等级名称(如 `"V1黄金会员"`)。
### Q3: 如何传递复杂数据结构?
A: 建议将复杂数据序列化为JSON字符串传递,或通过接口获取。
### Q4: Scene参数如何使用?
A: `scene` 参数主要用于二维码场景,会自动双重解码,可以包含查询字符串格式的参数。
## 更新日志
- 2025-01-XX: 添加 `memberId``programLogin``memberType` 参数自动传递
- 2025-01-XX: `memberType` 改为从 `gradeList` 中获取 `gradeName`
{
"code": "aliqua dolor",
"message": "ullamco veniam sunt nostrud aute",
"ok": true,
"success": false,
"data": "dolor ipsum elit"
}
...@@ -3,11 +3,12 @@ ...@@ -3,11 +3,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {ref, watch, nextTick} from "vue"; import {ref, watch, nextTick, computed} from "vue";
import {onLoad, onShow, onShareAppMessage, onShareTimeline} from "@dcloudio/uni-app"; import {onLoad, onShow, onShareAppMessage, onShareTimeline} from "@dcloudio/uni-app";
import {useGlobalStore} from "../../stores/global"; import {useGlobalStore} from "@/stores/global";
import {useUserStore} from "../../stores/user"; import {useUserStore} from "@/stores/user";
import {jump, JumpType} from "../../utils"; import {jump, JumpType} from "@/utils";
import {baseUrl as requestBaseUrl} from "@/api/request";
const userStore = useUserStore(); const userStore = useUserStore();
const globalStore = useGlobalStore() const globalStore = useGlobalStore()
...@@ -21,14 +22,15 @@ const src = ref("") ...@@ -21,14 +22,15 @@ const src = ref("")
const registered = ref(undefined) const registered = ref(undefined)
const urlMap = { const urlMap = {
//'main': 'http://192.168.0.5:8001/#/page', 'main': '/h5/#/page',
'main': 'https://momclub.feihe.com/h5/#/page',
//'main': 'https://momclub-test.feihe.com/h5/#/page',
//'main': 'https://momclub-uat.feihe.com/h5/#/page',
}; };
const shareData = ref(null) const shareData = ref(null)
const baseUrl = computed(() => {
return requestBaseUrl.substring(0, requestBaseUrl.indexOf('/', 'http'.length + 4))
})
const handleBack = () => { const handleBack = () => {
try { try {
uni.navigateBack({ uni.navigateBack({
...@@ -51,7 +53,7 @@ const handleBack = () => { ...@@ -51,7 +53,7 @@ const handleBack = () => {
async function ensureAutoLogin() { async function ensureAutoLogin() {
//debugger //debugger
//if (!globalStore.cuk) { //if (!globalStore.cuk) {
await userStore.normalAutoLogin() await userStore.normalAutoLogin()
//} //}
} }
...@@ -108,7 +110,7 @@ function initOk() { ...@@ -108,7 +110,7 @@ function initOk() {
if (options.type) { if (options.type) {
const type = options.type; const type = options.type;
url = urlMap[type]; url = baseUrl.value + urlMap[type];
} else if (options.url) { } else if (options.url) {
url = decodeURIComponent(options.url) url = decodeURIComponent(options.url)
} }
......
<template> <template>
<view class="webview-container"> <view class="webview-container">
<!-- Webview内容 --> <!-- Webview内容 -->
<web-view :src="webviewUrl" @message="getMessage" class="webview-content"></web-view> <web-view :src="webviewUrl" :key="webviewUrl" @message="getMessage" class="webview-content"></web-view>
</view> </view>
</template> </template>
...@@ -10,6 +10,7 @@ import { ref, watch, nextTick } from 'vue' ...@@ -10,6 +10,7 @@ import { ref, watch, nextTick } from 'vue'
import { useUserStore } from '@/stores/user.js' import { useUserStore } from '@/stores/user.js'
import { useGlobalStore } from '../../stores/global' import { useGlobalStore } from '../../stores/global'
import { fetchSyWebviewJSON } from '../../api/sywebview' import { fetchSyWebviewJSON } from '../../api/sywebview'
import { fetchGameActConfigJSON } from '../../api/home'
import { onLoad, onShow, onShareAppMessage, onShareTimeline, onPageScroll } from "@dcloudio/uni-app"; import { onLoad, onShow, onShareAppMessage, onShareTimeline, onPageScroll } from "@dcloudio/uni-app";
import { jump, JumpType } from '../../utils' import { jump, JumpType } from '../../utils'
import md from '../../md'; import md from '../../md';
...@@ -17,7 +18,7 @@ import md from '../../md'; ...@@ -17,7 +18,7 @@ import md from '../../md';
// 响应式数据 // 响应式数据
const statusBarHeight = ref(0) const statusBarHeight = ref(0)
const webviewUrl = ref('https://momclub-test.feihe.com/h5/game/index.html') const webviewUrl = ref('')
const share = ref(null) // 分享数据 const share = ref(null) // 分享数据
const pageOptions = ref({}) const pageOptions = ref({})
const registered = ref(undefined) const registered = ref(undefined)
...@@ -79,17 +80,36 @@ const getMessage = (e) => { ...@@ -79,17 +80,36 @@ const getMessage = (e) => {
share.value = messageData[messageData.length - 1] share.value = messageData[messageData.length - 1]
} }
} }
let baseUrl = '' // 默认URL
// 初始化 webview URL // 初始化 webview URL
const initWebviewUrl = async () => { const initWebviewUrl = async () => {
// 使用固定的基础URL,从 options 中获取或使用默认值
const options = pageOptions.value const options = pageOptions.value
let baseUrl = options.url || options.baseUrl || 'https://momclub-test.feihe.com/h5/game/index.html'
if (!baseUrl) {
// 从接口获取游戏配置
const configRes = await fetchGameActConfigJSON()
console.log('游戏配置接口返回:', configRes)
if (configRes && configRes.data) {
const gameType = 'lianliankan'
if (configRes.data[gameType] && configRes.data[gameType].url) {
baseUrl = configRes.data[gameType].url
}
}
}
if (!baseUrl) {
uni.redirectTo({
url: '/pages/index/index'
})
return
}
// 如果 baseUrl 已经包含协议,直接使用;否则添加协议 // 如果 baseUrl 已经包含协议,直接使用;否则添加协议
if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) { if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {
baseUrl = 'https://' + baseUrl baseUrl = 'https://' + baseUrl
...@@ -113,17 +133,25 @@ const initWebviewUrl = async () => { ...@@ -113,17 +133,25 @@ const initWebviewUrl = async () => {
const params = { ...cleanOptions } const params = { ...cleanOptions }
if (cuk && !params.cuk) params.cuk = cuk if (cuk && !params.cuk) params.cuk = cuk
// 添加用户信息参数 // 添加用户信息参数
if (openId && !params.openId) params.openId = openId if (openId && !params.miniopenid) params.miniopenid = openId
if (unionId && !params.unionId) params.unionId = unionId if (unionId && !params.unionId) params.unionId = unionId
// 获取会员信息(优先从 memberInfo 获取,如果没有则从 userInfo 获取) // 获取会员信息(优先从 memberInfo 获取,如果没有则从 userInfo 获取)
const memberInfo = userStore.memberInfo || userStore.userInfo const memberInfo = userStore.memberInfo || userStore.userInfo
const babyInfo = userStore.babyInfo
// 添加微信昵称(优先使用 babyInfo.babyName,没有则使用默认值)
if (babyInfo?.babyName) {
params.wxNickName = babyInfo.babyName
} else {
params.wxNickName = '暂无昵称'
}
// 添加 memberId(如果已注册) // 添加 memberId(如果已注册)
if (memberInfo?.memberId && memberInfo.memberId !== "not_login") { if (memberInfo?.memberId && memberInfo.memberId !== "not_login") {
params.crmId = memberInfo.memberId params.crmId = memberInfo.memberId
// 添加会员ID // 添加会员ID
params.memberId = memberInfo.memberId params.memberid = memberInfo.memberId
// 添加是否登录(1表示已登录,0表示未登录) // 添加是否登录(1表示已登录,0表示未登录)
params.programLogin = '1' params.programLogin = '1'
// 添加会员等级(从 gradeList 中根据 grade 获取 gradeName) // 添加会员等级(从 gradeList 中根据 grade 获取 gradeName)
...@@ -196,8 +224,7 @@ const initWebviewUrl = async () => { ...@@ -196,8 +224,7 @@ const initWebviewUrl = async () => {
// 监听注册状态变化,初始化 webview URL // 监听注册状态变化,初始化 webview URL
watch(() => registered.value, (newVal, oldVal) => { watch(() => registered.value, (newVal, oldVal) => {
if (!pageOptions.value.needLogin || newVal) { if (newVal && newVal !== oldVal) {
webviewUrl.value = ''
nextTick(() => { nextTick(() => {
initWebviewUrl() initWebviewUrl()
}) })
...@@ -217,17 +244,10 @@ onShow(async () => { ...@@ -217,17 +244,10 @@ onShow(async () => {
if (oldVal === undefined) { if (oldVal === undefined) {
// 首次加载 // 首次加载
if (pageOptions.value.needLogin && !registered.value) {
// 需要登录但未注册,跳转到注册页 // 不需要登录,直接初始化 URL
jump({ if (!webviewUrl.value) {
type: JumpType.INNER, await initWebviewUrl()
url: '/pages/activity/register',
})
} else if (!pageOptions.value.needLogin) {
// 不需要登录,直接初始化 URL
if (!webviewUrl.value) {
await initWebviewUrl()
}
} }
} else { } else {
// 授权状态变化:如果从已注册变为未注册(授权失败),显示提示并返回 // 授权状态变化:如果从已注册变为未注册(授权失败),显示提示并返回
...@@ -315,7 +335,7 @@ onShareTimeline((options) => { ...@@ -315,7 +335,7 @@ onShareTimeline((options) => {
return { return {
title: title || '分享', title: title || '分享',
path: shareurl || '/pages/index/index', path: shareurl || '/pages/gameWebview/webview',
imageUrl: imageUrl || '', imageUrl: imageUrl || '',
success: function (res) { success: function (res) {
//星妈会埋点方法,用户分享成功后触发事件 //星妈会埋点方法,用户分享成功后触发事件
......
...@@ -248,7 +248,7 @@ export const useUserStore = defineStore("userInfo", { ...@@ -248,7 +248,7 @@ export const useUserStore = defineStore("userInfo", {
console.log("fetchMemberInfo=", data); console.log("fetchMemberInfo=", data);
this.setMemberInfo(data); this.setMemberInfo(data);
if (data?.memberId !== "not_login") { if (data?.memberId !== "not_login") {
uni.setStorageSync('memberId', data?.memberId) uni.setStorageSync('memberId', data?.memberId)
} }
...@@ -393,16 +393,16 @@ export const useUserStore = defineStore("userInfo", { ...@@ -393,16 +393,16 @@ export const useUserStore = defineStore("userInfo", {
/** /**
* 清除用户信息(注销时使用) * 清除用户信息(注销时使用)
*/ */
// clearUserData() { clearUserData() {
// this.userInfo = null; this.userInfo = null;
// this.babyInfo = null; this.babyInfo = null;
// this.memberInfo = null; this.memberInfo = null;
// this.babyNickCache = []; this.babyNickCache = [];
// this.cepingjieguoInfo = null; this.cepingjieguoInfo = null;
// // 清除本地存储 // 清除本地存储
// uni.removeStorageSync('memberId'); uni.removeStorageSync('memberId');
// uni.removeStorageSync('loginStatus'); uni.removeStorageSync('loginStatus');
// }, },
}, },
}); });
\ No newline at end of file
...@@ -809,7 +809,7 @@ export default { ...@@ -809,7 +809,7 @@ export default {
md.sensorComponentLogTake({ md.sensorComponentLogTake({
xcxComponentClick: "true", xcxComponentClick: "true",
pageName: "商品详情页", pageName: "商品详情页",
componentName: "立即兑换", componentName: "商品详情",
componentContent: "立即兑换" componentContent: "立即兑换"
}); });
console.log('handleExchange 被调用'); console.log('handleExchange 被调用');
......
...@@ -88,11 +88,11 @@ export default { ...@@ -88,11 +88,11 @@ export default {
uni.hideLoading(); uni.hideLoading();
if (res.ok) { if (res.ok) {
// 清除本地缓存的用户信息 // 清除本地缓存的用户信息
// const userStore = useUserStore(); const userStore = useUserStore();
// const globalStore = useGlobalStore(); // const globalStore = useGlobalStore();
// const homeStore = useHomeStore(); // const homeStore = useHomeStore();
// userStore.clearUserData(); userStore.clearUserData();
// globalStore.clearAuthData(); // globalStore.clearAuthData();
// homeStore.clearHomeData(); // homeStore.clearHomeData();
...@@ -100,7 +100,7 @@ export default { ...@@ -100,7 +100,7 @@ export default {
// 跳转到首页 // 跳转到首页
uni.reLaunch({ uni.reLaunch({
url: '/pages/index/index' url: '/pages/index/index?pageType=home'
}); });
} else { } else {
uni.showToast({ uni.showToast({
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<text class="product-name">{{ order.productName }}</text> <text class="product-name">{{ order.productName }}</text>
<text class="product-points">{{ order.points }}{{ order.creditsTypeName }}</text> <text class="product-points">{{ order.points }}{{ order.creditsTypeName }}</text>
</view> </view>
<text class="product-description">{{ order.description }}</text> <!-- <text class="product-description">{{ order.description }}</text> -->
<!-- 卡券有效期 --> <!-- 卡券有效期 -->
<text v-if="order.productType === 'coupon' && order.validUntil" class="validity-period"> <text v-if="order.productType === 'coupon' && order.validUntil" class="validity-period">
...@@ -115,8 +115,8 @@ export default { ...@@ -115,8 +115,8 @@ export default {
// 遍历订单列表,为显示"查看详情"按钮的订单添加曝光埋点 // 遍历订单列表,为显示"查看详情"按钮的订单添加曝光埋点
this.orderList.forEach((order) => { this.orderList.forEach((order) => {
// 只有当订单状态不是 pending_payment、pending_use、pending_take 时才显示"查看详情"按钮 // 只有当订单状态不是 pending_payment、pending_use、pending_take 时才显示"查看详情"按钮
if (order.status !== 'pending_payment' && if (order.status !== 'pending_payment' &&
order.status !== 'pending_use' && order.status !== 'pending_use' &&
order.status !== 'pending_take') { order.status !== 'pending_take') {
md.sensorComponentLogTake({ md.sensorComponentLogTake({
xcxComponentExposure: "true", xcxComponentExposure: "true",
...@@ -548,6 +548,7 @@ export default { ...@@ -548,6 +548,7 @@ export default {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between;
} }
.product-name-row { .product-name-row {
...@@ -558,11 +559,15 @@ export default { ...@@ -558,11 +559,15 @@ export default {
} }
.product-name { .product-name {
width: 350rpx;
font-size: 30rpx; font-size: 30rpx;
color: #333333; color: #333333;
font-weight: 600; font-weight: 600;
flex: 1; flex: 1;
margin-right: 20rpx; margin-right: 20rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
.product-points { .product-points {
......
...@@ -364,11 +364,12 @@ ...@@ -364,11 +364,12 @@
<!-- 答案解析弹窗 --> <!-- 答案解析弹窗 -->
<CanEatAnswerPopup :visible="showAnswerPopup" :isCorrect="isAnswerCorrect" :rewardInfo="rewardInfo" <CanEatAnswerPopup :visible="showAnswerPopup" :isCorrect="isAnswerCorrect" :rewardInfo="rewardInfo"
:question="currentQuestion" :correctAnswer="correctAnswer" :analysis="answerAnalysis" :question="currentQuestion" :correctAnswer="correctAnswer" :analysis="answerAnalysis"
:optionDistribution="optionDistribution" :allResult="canEatData?.analysis?.allResult" :allResult="canEatData?.analysis?.allResult" @close="showAnswerPopup = false" />
@close="showAnswerPopup = false" />
<!-- 金币动画模块 --> <!-- 金币动画模块 -->
<view class="gold-coin-animation" v-if="showGoldCoinAnimation" @tap="hideGoldCoinAnimation"> <view class="gold-coin-animation" v-if="showGoldCoinAnimation" @tap="hideGoldCoinAnimation">
<!-- 背景底 -->
<view class="gold-coin-background"></view>
<view class="gold-coin-content" @tap.stop> <view class="gold-coin-content" @tap.stop>
<view class="gold-coin-title">{{ goldCoinConfig.title }}</view> <view class="gold-coin-title">{{ goldCoinConfig.title }}</view>
<view class="gold-coin-description">{{ goldCoinConfig.description }}</view> <view class="gold-coin-description">{{ goldCoinConfig.description }}</view>
...@@ -2655,17 +2656,24 @@ export default { ...@@ -2655,17 +2656,24 @@ export default {
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
z-index: 9999; z-index: 9999;
animation: fadeIn 0.3s ease-out; animation: fadeIn 0.3s ease-out;
}
/* 背景底 */
.gold-coin-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
} }
.gold-coin-animation::after { .gold-coin-background::after {
content: ''; content: '';
position: absolute; position: absolute;
bottom: 42rpx; bottom: 42rpx;
...@@ -2682,6 +2690,7 @@ export default { ...@@ -2682,6 +2690,7 @@ export default {
.gold-coin-content { .gold-coin-content {
text-align: center; text-align: center;
padding: 60rpx 40rpx; padding: 60rpx 40rpx;
z-index: 1;
} }
.gold-coin-title { .gold-coin-title {
......
...@@ -741,8 +741,7 @@ ...@@ -741,8 +741,7 @@
.task_button { .task_button {
width: 384rpx; width: 384rpx;
height: 86rpx; height: 86rpx;
background: rgba(255, 255, 255, 0); border: none;
border: 2px solid #e6a23c;
border-radius: 60rpx; border-radius: 60rpx;
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -753,58 +752,12 @@ ...@@ -753,58 +752,12 @@
.task_button_text { .task_button_text {
font-size: 32rpx; font-size: 32rpx;
color: #e6a23c;
font-weight: bold; font-weight: bold;
} }
&:active { &:active {
transform: scale(0.95); transform: scale(0.95);
} }
// itemIndex = 0
&.item-0 {
border-color: #503404;
.task_button_text.item-0 {
color: #503404;
}
}
// itemIndex = 1
&.item-1 {
border-color: #284A6C;
.task_button_text.item-1 {
color: #284A6C;
}
}
// itemIndex = 2
&.item-2 {
border-color: #322D6F;
.task_button_text.item-2 {
color: #322D6F;
}
}
// itemIndex = 3
&.item-3 {
border-color: #513403;
.task_button_text.item-3 {
color: #513403;
}
}
// itemIndex = 4
&.item-4 {
border-color: #F7D1A0;
.task_button_text.item-4 {
color: #F7D1A0;
}
}
} }
} }
...@@ -850,6 +803,14 @@ ...@@ -850,6 +803,14 @@
height: auto; height: auto;
margin-top: 22rpx; margin-top: 22rpx;
.exchange-title {
margin-top: 50rpx;
font-size: 30rpx;
color: #000000;
// margin-bottom: 20rpx;
font-weight: bold;
display: block;
}
.custom-tabs { .custom-tabs {
display: flex; display: flex;
......
...@@ -267,8 +267,8 @@ ...@@ -267,8 +267,8 @@
<text class="signin_button_text">立即签到</text> <text class="signin_button_text">立即签到</text>
</view> </view>
<!-- 已签到状态 --> <!-- 已签到状态 -->
<view v-else class="task_button" :class="`item-${itemIndex}`" @click="handleTaskButtonClick"> <view v-else class="task_button" :class="`item-${itemIndex}`" :style="getTaskButtonBgStyle" @click="handleTaskButtonClick">
<text class="task_button_text" :class="`item-${itemIndex}`">赚更多积分</text> <text class="task_button_text" :class="`item-${itemIndex}`" :style="{ color: getTaskButtonTextColor }">赚更多积分</text>
</view> </view>
</view> </view>
<!-- 积分限时购 --> <!-- 积分限时购 -->
...@@ -303,7 +303,7 @@ ...@@ -303,7 +303,7 @@
<view class="yiyequan_card" :class="`item-${itemIndex}`"> <view class="yiyequan_card" :class="`item-${itemIndex}`">
<!-- 卡片头部 --> <!-- 卡片头部 -->
<view class="yiyequan_card_header"> <view class="yiyequan_card_header">
<text class="card_title" :class="`item-${itemIndex}`">积分兑换惊喜福利</text> <text class="card_title" :class="`item-${itemIndex}`">积分权益兑换</text>
<text class="card_count" :class="`item-${itemIndex}`">您有{{ availableBenefits }}个权益可兑换</text> <text class="card_count" :class="`item-${itemIndex}`">您有{{ availableBenefits }}个权益可兑换</text>
</view> </view>
...@@ -365,6 +365,9 @@ ...@@ -365,6 +365,9 @@
<!-- 商品展示容器 --> <!-- 商品展示容器 -->
<view class="goods-container" v-if="goodsDataArr?.length > 0"> <view class="goods-container" v-if="goodsDataArr?.length > 0">
<!-- 积分兑换标题 -->
<text class="exchange-title" :style="{ color: itemIndex === 4 ? '#FFF0DF' : '#000000' }">积分兑换</text>
<!-- <view class="goods-container"> --> <!-- <view class="goods-container"> -->
<!-- 页签栏 --> <!-- 页签栏 -->
<view class="custom-tabs" :class="{ <view class="custom-tabs" :class="{
...@@ -1685,6 +1688,26 @@ const getWeekdayLabel = (day) => { ...@@ -1685,6 +1688,26 @@ const getWeekdayLabel = (day) => {
const weekdays = ['', '周一', '周二', '周三', '周四', '周五', '周六', '周日']; const weekdays = ['', '周一', '周二', '周三', '周四', '周五', '周六', '周日'];
return weekdays[day] || `第${day}天`; return weekdays[day] || `第${day}天`;
} }
// 获取任务按钮背景渐变样式
const getTaskButtonBgStyle = computed(() => {
const gradients = {
0: { from: '#D1AF82', to: '#E6C7A3' },
1: { from: '#8DBAE6', to: '#A0C9F1' },
2: { from: '#9980C2', to: '#BEA8E2' },
3: { from: '#CDA36B', to: '#E0B97D' },
4: { from: '#E7CA9F', to: '#EBD9C9' }
};
const gradient = gradients[itemIndex.value] || gradients[0];
return {
background: `linear-gradient(to right, ${gradient.from}, ${gradient.to})`
};
});
// 获取任务按钮文字颜色
const getTaskButtonTextColor = computed(() => {
return itemIndex.value === 4 ? '#030200' : '#ffffff';
});
const getColor = (type) => { const getColor = (type) => {
let colors = ''; let colors = '';
switch (type) { switch (type) {
...@@ -1993,7 +2016,7 @@ onMounted(async () => { ...@@ -1993,7 +2016,7 @@ onMounted(async () => {
quanyitiaozhuanInfo.value = integralData.value?.quanyitiaozhuanInfo; quanyitiaozhuanInfo.value = integralData.value?.quanyitiaozhuanInfo;
quanyiListIcon.value = []; quanyiListIcon.value = [];
imgInfos.value.forEach((element, index) => { imgInfos.value?.forEach((element, index) => {
quanyiListIcon.value.push(element.img); quanyiListIcon.value.push(element.img);
privilegeSizes.value.push({ width: element.width, height: element.height, name: element.name }); privilegeSizes.value.push({ width: element.width, height: element.height, name: element.name });
}); });
...@@ -2070,7 +2093,7 @@ onMounted(async () => { ...@@ -2070,7 +2093,7 @@ onMounted(async () => {
}); });
const initExposure = () => { const initExposure = () => {
imgInfos.value.forEach((item, index) => { imgInfos.value?.forEach((item, index) => {
md.sensorComponentLogTake({ md.sensorComponentLogTake({
xcxComponentExposure: "true", xcxComponentExposure: "true",
pageName: "积分服务页", pageName: "积分服务页",
......
This diff is collapsed.
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