tanxue il y a 17 heures
Parent
commit
82775f214d

+ 35 - 0
pages/chanpinShop/cp4/card.vue

@@ -0,0 +1,35 @@
+<template>
+  <view class="shop-card-box" @click="handleClick">
+      <!-- 封面 -->
+      <image :src="item.cover" class="shop-img"></image>
+      <view class="card-right-box">
+        <!-- 名称 -->
+        <view class="card-title">{{item.name}}</view>
+        <!-- 简介 -->
+        <view class="card-content">{{item.intro}}</view>
+        <!-- 共计 -->
+        <view class="card-price">¥{{item.price}}</view>
+      </view>
+  </view>
+</template>
+
+<script setup>
+import ezyActiveVue from "@/components/ezyActive/ezyActive.vue";
+const props = defineProps({
+  item: {
+    type: Object
+  }
+})
+
+	// 选择产品等级
+function handleClick() {
+	uni.navigateTo({
+		url: '/pages/chanpinShop/cp4/intro'
+	})
+}
+
+</script>
+
+<style scoped>
+
+</style>

+ 278 - 0
pages/chanpinShop/cp4/dingdan.vue

@@ -0,0 +1,278 @@
+<template>
+	<view class="ezy-qrdd-page">
+		<view class="icon-title-navBar-box">
+			<view class="nav-bar-icon" @click="handleBack"></view>
+			<text class="nav-bar-title">确认订单</text>
+		</view>
+		<view class="qrdd-body-box">
+			<!-- 卡片 -->
+			<view class="dd-item-box">
+				<!-- 封面 -->
+				<image class="item-img-box" :src="data.cover" mode=""></image>
+				<view class="item-content-box">
+					<!-- 名称 -->
+					<view class="item-name">{{data.name}}</view>
+					<!-- 简介 -->
+					<view class="item-intro">{{data.intro}}</view>
+					<!-- 价格 -->
+					<view class="item-xianjia">¥{{xianjia}}</view>
+				</view>
+				<view class="item-play-btn"></view>
+			</view>
+			<!-- 等级 -->
+			<view class="qrdd-border-box">
+				<view class="kcxxdj-title">课程学习等级</view>
+				<view class="kcxxdj-tc-box">
+					<!-- 套餐 -->
+					<ezyActiveVue class="ezy-btn-active tc-item" v-for="item in data.taocanList"
+						@click="handleSelectTaoCan(item)" :class="{active: item.taocanId == activeTaocan.taocanId}">
+						{{item.name}}
+					</ezyActiveVue>
+				</view>
+			</view>
+
+			<!-- 商品总价 -->
+			<view class="qrdd-border-box">
+				<view class="border-row">
+					<view>商品总价</view>
+					<view>¥{{yuanjia}}</view>
+				</view>
+				<view class="border-row">
+					<view>优惠券</view>
+					<view class="jg-text">-¥{{youhui}}</view>
+				</view>
+				<view class="border-row sum-row">
+					<view class="sum-text">合计</view>
+					<view class="jg-text">¥{{xianjia}}</view>
+				</view>
+			</view>
+			<!-- 支付模式 -->
+			<template v-if="currentPlatform != 'ios'">
+				<radio-group @change="radioChange" class="qrdd-border-box">
+					<label class="border-row" v-for="(item, index) in items" :key="item.value">
+						<view class="zzfs-name-box">
+							<icon :class="{
+							  'wechat-icon': item.name === '微信',
+							  'alipay-icon': item.name === '支付宝'
+							}"></icon>
+							<text>{{item.name}}</text>
+						</view>
+						<radio :value="item.value" :checked="index === current" class="qrdd-radio-item"/>
+					</label>
+				</radio-group>
+			</template>
+		</view>
+
+		<!-- 支付区 -->
+		<view class="qrdd-footer-box">
+			<view class="jg-box">
+				<view class="sum-row">
+					<text class="sum-text">合计:</text>
+					<text class="xj-text-text">¥{{xianjia}}</text>
+				</view>
+				<view class="yh-text">共优惠¥{{youhui}}</view>
+			</view>
+			<view @click="handlePay" class="ljzf-btn">立即支付</view>
+		</view>
+		<!-- <view class="shop-mask">遮盖层</view> -->
+	</view>
+	
+	<kaiTongFongShiVue ref="kaiRef" @ykIoszhifu="ykIoszhifu" @success="handlePay"></kaiTongFongShiVue>
+</template>
+
+<script setup>
+	import {
+		reactive,
+		ref,
+		computed,
+	} from "vue";
+	import {
+		onLoad,
+		onShow
+	} from "@dcloudio/uni-app"
+	import * as shopHttp from "@/api/shop.js"
+	import kaiTongFongShiVue from "../components/kaiTongFongShi.vue";
+	import {
+		getAppCp4Buy
+	} from "@/api/shop";
+	import {
+		usePay
+	} from "../usePay.js";
+	import {
+		getUserIsYouke
+	} from "@/utils/common.js"
+	import cacheManager from "@/utils/cacheManager.js";
+	import ezyActiveVue from "@/components/ezyActive/ezyActive.vue";
+	
+	
+	const currentPlatform = ref(null);
+
+	function isIOSorAndroid() {
+		const systemInfo = uni.getSystemInfoSync();
+
+		if (systemInfo.platform == 'ios') {
+			currentPlatform.value = 'ios'
+		} else {
+			currentPlatform.value = 'android'
+		}
+	}
+
+	const data = reactive({
+		chanpinId: null,
+		cover: null,
+		intro: null,
+		name: null,
+		taocanList: []
+	})
+
+	const activeTaocan = ref(null)
+	const kaiRef = ref(null)
+
+	const current = ref(0)
+	const items = ref([{
+		name: '微信',
+		value: '0'
+	}, {
+		name: '支付宝',
+		value: '1'
+	}])
+
+
+
+	const youhui = computed(() => {
+		if (!activeTaocan.value) {
+			return '0.00'
+		} else {
+			return activeTaocan.value.youhui
+		}
+	})
+
+	const xianjia = computed(() => {
+		if (!activeTaocan.value) {
+			return '0.00'
+		} else {
+			return activeTaocan.value.xianjia
+		}
+	})
+
+	const yuanjia = computed(() => {
+		if (!activeTaocan.value) {
+			return '0.00'
+		} else {
+			return activeTaocan.value.yuanjia
+		}
+	})
+
+	const {
+		OrderPay
+	} = usePay({
+		createOrderError: () => {}, // 创建订单失败
+		checkError: () => {}, // 校验失败
+		payError: () => {}, // 支付失败
+		paySuccess: () => {
+			// 支付成功删除contentInfo 缓存
+			cacheManager.remove("contentInfo");
+			// zhifu='success' 用于判断在订单页 游客模式ios支付成功情况,要去弹出弹窗
+			uni.navigateTo({
+				url: "/pages/chanpinMy/order?zhifu=success"
+			})
+			// uni.showLoading({
+			// 	title: '跳转中...',
+			// 	mask: true
+			// });
+			// uni.switchTab({
+			// 	url: "/pages/chanpinMy/my" // 你的F页面实际路径(不变)
+			// });
+			// setTimeout(() => {
+			// 	uni.navigateTo({
+			// 		url: "/pages/chanpinMy/order?zhifu=success", // 你的D页面路径+保留zhifu=success传参
+			// 		success: () => {
+			// 			uni.hideLoading();
+			// 		},
+			// 		fail: () => {
+			// 			uni.hideLoading();
+			// 			toast("跳转失败,请重试");
+			// 		}
+			// 	});
+			// }, 300);
+
+
+
+		}, //支付成功
+		applePayError: () => {}, // 苹果内购失败
+	});
+
+	onLoad(() => {
+		isIOSorAndroid();
+		initPage();
+		if (currentPlatform.value == 'ios') {
+			// ios 无微信与支付宝
+			current.value = -1;
+		}
+	})
+
+	function ykIoszhifu() {
+		console.log('12311');
+		const options = {
+			chanpinId: data.chanpinId,
+			taocanId: activeTaocan.value.taocanId
+		};
+		options.applePid = activeTaocan.value.applePid;
+		console.log('options', options);
+		console.log('activeTaocan.value.applePid', activeTaocan.value.applePid);
+		OrderPay('apple', options)
+	}
+
+
+	function radioChange(d) {
+		current.value = d.detail.value;
+	}
+
+	function handleSelectTaoCan(item) {
+		activeTaocan.value = item;
+	}
+
+	function initPage() {
+		shopHttp.getAppCp4Buy().then(res => {
+			Object.assign(data, res.data)
+
+			activeTaocan.value = res.data.taocanList[0]
+		})
+	}
+
+	function handlePay() {
+		if (getUserIsYouke()) {
+			// 游客
+			kaiRef.value.handleShow();
+		} else {
+			// 非游客
+			const options = {
+				chanpinId: data.chanpinId,
+				taocanId: activeTaocan.value.taocanId
+			};
+
+			if (currentPlatform.value == 'ios') {
+				options.applePid = activeTaocan.value.applePid;
+				console.log('apple支付入参', options)
+				// 苹果
+				OrderPay('apple', options)
+			} else if (currentPlatform.value != 'ios' && current.value == '0') {
+				console.log('wx支付入参', options)
+				// 微信
+				OrderPay('wx', options)
+			} else if (currentPlatform.value != 'ios' && current.value == '1') {
+				console.log('ali支付入参', options)
+				// 支付宝
+				OrderPay('ali', options)
+			}
+		}
+	}
+
+	function handleBack() {
+		uni.navigateBack()
+	}
+</script>
+
+<style>
+
+</style>

+ 80 - 0
pages/chanpinShop/cp4/intro.vue

@@ -0,0 +1,80 @@
+<template>
+	<view class="ezy-shop-info-page">
+		<view class="icon-title-navBar-box">
+			<view class="nav-bar-icon" @click="handleBack"></view>
+			<text class="nav-bar-title">商品详情</text>
+		</view>
+		<view class="shop-info-body">
+			<view class="img-content-box">
+				<img :src="imageUrl" alt="" />
+			</view>
+			<view class="fx-btn-row">
+				<view @click="fenxiang" class="fx-btn">
+					<icon class="fx-icon"></icon>
+					<view>分享</view>
+				</view>
+				<ezyActiveVue @click="handleStudy" class="ezy-btn-active bmxx-btn">立即报名学习</ezyActiveVue>
+			</view>
+		</view>
+		
+
+<!--  分享  -->
+    <SharePopup ref="sharePopup" :type="2" title="商品详情" desc="商品详情"
+                :image="imageUrl" currentPage="tupian"
+                @success="handleShareSuccess" @error="handleShareError" />
+	</view>
+</template>
+
+<script setup>
+	import {
+		reactive,
+		ref
+	} from "vue";
+	import {
+		onLoad,
+		onShow
+	} from "@dcloudio/uni-app"
+	import * as shopHttp from "@/api/shop.js"
+  import {getAppCp1Info} from "@/api/shop";
+  import ezyActiveVue from "@/components/ezyActive/ezyActive.vue";
+  import SharePopup from "@/components/sharePopUp/index.vue"
+  import {toast} from "uview-plus";
+	
+	const imageUrl = ref(null);
+  const sharePopup = ref(null);
+
+	onLoad(() => {
+		initPage()
+	})
+
+	function initPage() {
+		shopHttp.getAppCp4Info().then(res => {
+			imageUrl.value = res.data.image;
+		})
+	}
+
+  function handleShareError() {
+    toast('分享失败')
+  }
+
+  function handleShareSuccess() {
+    toast('分享成功')
+  }
+	
+	function fenxiang() {
+    sharePopup.value.open();
+  }
+	function handleStudy() {
+		uni.navigateTo({
+			url: '/pages/chanpinShop/cp4/dingdan'
+		})
+	}
+	
+	function handleBack() {
+		uni.navigateBack()
+	}
+</script>
+
+<style>
+
+</style>

+ 334 - 0
pages/chanpinneirong/chanpin3.vue

@@ -0,0 +1,334 @@
+<template>
+	<view class="ezy-page-body xuexi-page-body">
+		<!-- 滚动区域 -->
+		<scroll-view v-if="existData" :scroll-with-animation="true" scroll-y :scroll-top="scrollTop"
+			@scroll="handleScroll">
+			<view class="xxjl-card-box-padding">
+				<view class="xxjl-card-box">
+					<!-- 显示内容 -->
+					<view class="card-body-box">
+						<img :src="neirongInfo.cover" />
+						<view class="body-right">
+							<view class="right-name">{{ neirongInfo.chanpinName }}</view>
+							<view class="right-item right-item-mini">等级:{{neirongInfo.dengjiName}}</view>
+							<view class="right-item">版本:{{neirongInfo.name}}</view>
+							<view>课程:{{neirongInfo.curKechengName}}</view>
+						</view>
+					</view>
+					<view class="card-progress-box">
+						<view class="xx-progress-box">
+							<view class="progress-title">学习进度</view>
+							<progress :percent="curProcess" class="xx-progress" stroke-width="20"
+								backgroundColor="#3c7dfd" activeColor="#ffd11c" />
+						</view>
+						<ezyActiveVue class="ezy-btn-active jxxx-btn" @aclick="handlePlay(neirongInfo,'jixu')">
+						</ezyActiveVue>
+					</view>
+				</view>
+			</view>
+
+			<view class="xx-item-list">
+				<view class="xx-item-title">— 以下为当前等级课程目录 —</view>
+
+				<view v-for="(item, index) in jieList" :key="item.jieId">
+					<!-- 节列表 -->
+					<ezyActiveVue class="ezy-list-item-active xx-item-box" :class="item.lock?'xx-disabled-item-box':''"  @aclick="handlePlay(item,'play')">
+						<view class="xx-item-status"
+							:class="item.wanchengFlag == 1 ? 'completed-status' : 'uncompleted-status'"></view>
+						<img :src="item.cover" />
+						<view class="xx-text-box">
+							<view>{{ item.jieName }}</view>
+							<view>{{ item.jieIntro }}</view>
+						</view>
+						<view v-if="item.lock" class="xx-item-lock-btn"></view>
+						<view v-else class="xx-item-btn"></view>
+					</ezyActiveVue>
+				</view>
+
+				<view class="xx-item-title">本级别最后一单元啦~</view>
+				<view class="xx-more-btn" @click="moreBtn"></view>
+			</view>
+		</scroll-view>
+		<!-- 回到顶部 -->
+		<view v-show="showGoTop" class="go-top-btn" @click="goTopBtn"></view>
+
+		<!-- 无数据占位 -->
+		<view v-if="!existData" class="ezy-page-body">
+			<view class="ezy-no-sj">
+				<icon></icon>
+				<text>暂无数据</text>
+			</view>
+		</view>
+		<!-- 弹窗组件 -->
+		<danyuanInfoVue ref="dyRef" v-if="isShow" @close="isShow = false"></danyuanInfoVue>
+		<!-- 购买提示窗 -->
+		<tipSmallDialog ref="gmtRef" content="需要购买当前课程才能学习" @confirm-btn="handleConfirmBtn" qrBtnName="前往购买"></tipSmallDialog>
+	</view>
+</template>
+
+<script>
+	import ezyActiveVue from "@/components/ezyActive/ezyActive.vue";
+	import CustomTabBar from '@/components/custom-tabbar/index.vue';
+	import cacheManager from "@/utils/cacheManager.js";
+	import {
+		yingyuDanciInfo,
+		shuxueSave2
+	} from "@/api/chanpinneirong.js"
+	import {
+		onLoad,
+		onShow,
+		onHide,
+		onUnload
+	} from "@dcloudio/uni-app"
+	import danyuanInfoVue from '@/pages/xinshuxue/components/danyuanInfo.vue';
+	import {
+		toast
+	} from '../../utils/common';
+	import {
+		updateChanpin3Process
+	} from "./useNeirongChanpin3"
+	import tipSmallDialog from "@/components/dialog/tipSmallDialog.vue";
+	// 产品2 计算特训
+	export default {
+		data() {
+			return {
+				canExitApp: false,
+
+				jieList: [],
+				neirongInfo: {},
+				banbenId: '',
+				jieId: '',
+				chanpinId: '',
+				dengjiId: '',
+				curProcess: '',
+				existData: false,
+				isShow: false,
+
+				stickyHeight: 0, // 吸顶栏高度(px)
+				currentStickyTitle: '', // 初始为空,不显示吸顶
+				currentStickyIntro: '',
+				currentDanyuanId: '',
+				currentStickyDengjiId: '',
+				titlePositions: [],
+				scrollTop: 0,
+				showGoTop: false,
+				scrollThreshold: 300,
+			}
+		},
+		components: {
+			CustomTabBar,
+			danyuanInfoVue,
+			ezyActiveVue,
+			tipSmallDialog
+		},
+
+		onHide() {
+			console.log('学习页面隐藏')
+		},
+		onUnload() {
+			// 页面卸载无需特殊处理
+		},
+		methods: {
+			handleConfirmBtn() {
+				// 加锁视频需要购买
+				uni.navigateTo({
+					url: "/pages/chanpinShop/cp2/dingdan"
+				})
+			},
+			initData(banbenId) {
+				console.log('阿斯顿发送到发送到饭撒的');
+				const cacheData = cacheManager.get('contentInfo');
+				if (cacheData) {
+					console.log('使用缓存数据');
+					this.updateFromCache();
+				} else {
+					console.log('重新请求数据');
+					this.initFromOptions(banbenId);
+				}
+			},
+			goTopBtn() {
+				// 替换原来的 uni.pageScrollTo
+				this.scrollTop = Math.random(); // 先设置一个随机值
+				this.$nextTick(() => {
+					this.scrollTop = 0; // 再设置回0
+				});
+
+				this.showGoTop = false;
+			},
+			moreBtn() {
+				uni.switchTab({
+					url: '/pages/chanpinXuanze/index'
+				})
+			},
+
+			initFromOptions(banbenId) {
+
+				this.loadDataFromApi(banbenId);
+			},
+			// 从缓存更新数据方法
+			updateFromCache() {
+				console.log('12311');
+				updateChanpin3Process()
+				const cacheData = cacheManager.get('contentInfo');
+				console.log('cacheData 从缓存更新数据方法', cacheData);
+				if (cacheData) {
+					this.neirongInfo = {
+						...cacheData
+					};
+					this.curProcess = cacheData.curProcess;
+					this.jieList = [...(cacheData.jieList || [])];
+					this.banbenId = cacheData.banbenId
+
+
+					if (this.jieList.length == 0) {
+						this.existData = false
+					} else {
+						this.existData = true
+					}
+					// this.$nextTick(() => {
+					// 	this.updateTitlePositions();
+					// });
+				} else {
+					this.existData = false;
+				}
+			},
+
+			loadDataFromApi(banbenId) {
+				uni.showLoading({
+					title: '加载中'
+				});
+				this.banbenId = banbenId
+				this.neirongInfo = {}
+				this.curProcess = ''
+				this.jieList = []
+				const req = {
+					banbenId: banbenId
+				}
+				yingyuDanciInfo(req).then(res => {
+					if (res.code === 0) {
+						
+						this.neirongInfo = res.data;
+						this.neirongInfo.jieId = res.data.curJieId;
+						this.curProcess = res.data.curProcess * 100;
+						this.jieList = res.data.jieList || [];
+						if (this.jieList.length == 0) {
+							this.existData = false
+						} else {
+							this.existData = true
+						}
+						const cacheData = {
+							...res.data,
+							banbenId: banbenId,
+						};
+						cacheManager.set('contentInfo', cacheData);
+						uni.hideLoading();
+					}
+				}).catch(res => {
+					cacheManager.remove("contentInfo");
+					toast("加载失败,请重试");
+					uni.hideLoading();
+				});
+			},
+
+
+			handleScroll(e) {
+				const scrollTop = e.detail.scrollTop;
+				console.log('scrollTop', scrollTop);
+				this.showGoTop = scrollTop > this.scrollThreshold;
+			},
+
+			getJieAndDanyuan(data, jieId) {
+				for (let jie of data.jieList) {
+						if (jie.jieId == jieId) {
+							return {
+								jie
+							}
+						}
+					
+				}
+				return null;
+			},
+
+			async saveAndNavigate(jieId,  da, code) {
+
+				if (code == 'jixu') {
+					if (!da.jieId) {
+						toast("jieId 丢失")
+						return false
+					}
+				}
+
+				let req = {
+					"dengjiId": da.dengjiId,
+					"jieId": da.jieId
+				}
+				console.log('req', req);
+				const res = await shuxueSave2(req);
+				if (res.code == 0) {
+					let curJieAndDanyuan = this.getJieAndDanyuan(this.neirongInfo, jieId);
+					console.log('curJieAndDanyuan',curJieAndDanyuan);
+					
+					if (!curJieAndDanyuan) {
+						toast("未找到课程信息");
+						return false;
+					}
+
+					const cacheData = cacheManager.get('contentInfo') || {};
+					cacheData.curKechengName = curJieAndDanyuan.jie.jieIntro;
+					cacheData.jieId = curJieAndDanyuan.jie.jieId;
+					cacheData.curJieId = jieId;
+					cacheData.type = curJieAndDanyuan.jie.type;
+					cacheManager.set('contentInfo', cacheData);
+
+					uni.navigateTo({
+						url: `/pages/jisuantexun/lookShipin?jieId=${jieId}`
+					})
+				} else {
+					return false;
+				}
+			},
+			handlePlay(da, code) {
+				console.log('ddd',da)
+				if (da.lock && code == 'play') {
+					
+					this.$refs.gmtRef.handleShow();
+					
+					// 加锁视频需要购买
+					// uni.navigateTo({
+					// 	url: "/pages/chanpinShop/cp1/dingdan"
+					// })
+					return;
+				}
+				let jieId = code === 'jixu' ? da.curJieId : da.jieId;
+				if (!jieId) {
+					toast("无课程ID");
+					return;
+				}
+				this.saveAndNavigate(jieId, da, code);
+			},
+			handleClickDanyuan(jieId) {
+
+				if (!jieId) {
+					toast("jieId丢失")
+					return false
+				}
+				this.isShow = true;
+				setTimeout(() => {
+					// 更新为点击的动态单元Id [临时]
+					this.$refs.dyRef.handleShow(jieId)
+				}, 100)
+			},
+			handleBack() {
+				uni.navigateTo({
+					url: `/pages/chanpinXuanze/banben?dengjiId=` + this.dengjiId
+				})
+			},
+		},
+
+		// 计算吸顶栏下方的偏移(确保内容不被遮挡)
+		computed: {
+
+
+		}
+	}
+</script>

+ 12 - 0
pages/chanpinneirong/useNeirongChanpin3.js

@@ -0,0 +1,12 @@
+import cacheManager from "@/utils/cacheManager.js";
+
+export function updateChanpin3Process() {
+	const cacheData = cacheManager.get('contentInfo');
+	console.log('cacheData333333', cacheData)
+	const list = cacheData.jieList;
+	const defaultCurProcess = cacheData.curProcess;
+
+	const process = list.filter(item => item.wanchengFlag).length/list.length * 100 || 0;
+	cacheData.curProcess = defaultCurProcess > process ? defaultCurProcess: process;
+	cacheManager.set('contentInfo', cacheData);
+}

BIN
static/images/common/xbb-item-jt-white.png