更新:增加课程“复读”功能
This commit is contained in:
@@ -7,8 +7,8 @@ export const ENV = process.env.NODE_ENV || 'development';
|
|||||||
*/
|
*/
|
||||||
const BASE_URL_MAP = {
|
const BASE_URL_MAP = {
|
||||||
development: {
|
development: {
|
||||||
MAIN: 'http://192.168.110.100:9300/pb/', // 张川川
|
// MAIN: 'http://192.168.110.100:9300/pb/', // 张川川
|
||||||
// MAIN: 'https://global.nuttyreading.com/', // 线上
|
MAIN: 'https://global.nuttyreading.com/', // 线上
|
||||||
// PAYMENT: 'https://dev-pay.example.com', // 暂时用不到
|
// PAYMENT: 'https://dev-pay.example.com', // 暂时用不到
|
||||||
// CDN: 'https://cdn-dev.example.com', // 暂时用不到
|
// CDN: 'https://cdn-dev.example.com', // 暂时用不到
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ export function uploadImage(filePath: string): Promise<string> {
|
|||||||
url: `${SERVICE_MAP.MAIN}oss/fileoss`,
|
url: `${SERVICE_MAP.MAIN}oss/fileoss`,
|
||||||
filePath,
|
filePath,
|
||||||
name: 'file',
|
name: 'file',
|
||||||
success: (res) => {
|
success: (res: any) => {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(res.data)
|
const data = JSON.parse(res.data)
|
||||||
if (data.url) {
|
if (data.url) {
|
||||||
@@ -304,9 +304,10 @@ export async function getPointsData(current : number, limit : number, userId : s
|
|||||||
* 迁移用户数据
|
* 迁移用户数据
|
||||||
* @param tel 旧账号
|
* @param tel 旧账号
|
||||||
* @param code 迁移验证码
|
* @param code 迁移验证码
|
||||||
|
* @param type 未迁移数据类型
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
export async function migrateUserData(data: { tel: string, code: string }) {
|
export async function migrateUserData(data: { tel: string, code: string, type: string }) {
|
||||||
const res = await mainClient.request<IApiResponse>({
|
const res = await mainClient.request<IApiResponse>({
|
||||||
url: 'common/user/migrationWumenData',
|
url: 'common/user/migrationWumenData',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -314,3 +315,18 @@ export async function migrateUserData(data: { tel: string, code: string }) {
|
|||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户迁移信息
|
||||||
|
* @return {
|
||||||
|
* alreadyMigration: 已迁移用户数
|
||||||
|
* notMigration: 未迁移用户数
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export async function getUserMigrateInfo() {
|
||||||
|
const res = await mainClient.request<IApiResponse>({
|
||||||
|
url: 'common/user/getMigrationList',
|
||||||
|
method: 'POST',
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<!-- 商品列表 -->
|
<!-- 商品列表 -->
|
||||||
<view class="selector-header">
|
<view class="selector-header">
|
||||||
<text class="title">{{ isFudu ? t('order.selectFuduScheme') : t('order.selectPurchaseScheme') }}</text>
|
<text class="title">{{ t('order.goodsList') }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="goods-list">
|
<view class="goods-list">
|
||||||
<view
|
<view
|
||||||
@@ -54,7 +54,6 @@ const { t } = useI18n()
|
|||||||
interface Props {
|
interface Props {
|
||||||
show: boolean
|
show: boolean
|
||||||
goods: IGoods[]
|
goods: IGoods[]
|
||||||
isFudu?: boolean // 是否为复读
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|||||||
@@ -438,8 +438,7 @@
|
|||||||
"orderCreateFailed": "Failed to create order"
|
"orderCreateFailed": "Failed to create order"
|
||||||
},
|
},
|
||||||
"order": {
|
"order": {
|
||||||
"selectFuduScheme": "Select Fudu Scheme",
|
"goodsList": "Product List",
|
||||||
"selectPurchaseScheme": "Select Purchase Scheme",
|
|
||||||
"confirmTitle": "Confirm Order",
|
"confirmTitle": "Confirm Order",
|
||||||
"goodsInfo": "Product Information",
|
"goodsInfo": "Product Information",
|
||||||
"priceDetail": "Price Details",
|
"priceDetail": "Price Details",
|
||||||
|
|||||||
@@ -438,8 +438,7 @@
|
|||||||
"orderCreateFailed": "订单创建失败"
|
"orderCreateFailed": "订单创建失败"
|
||||||
},
|
},
|
||||||
"order": {
|
"order": {
|
||||||
"selectFuduScheme": "选择复读方案",
|
"goodsList": "商品列表",
|
||||||
"selectPurchaseScheme": "选择购买方案",
|
|
||||||
"confirmTitle": "确认订单",
|
"confirmTitle": "确认订单",
|
||||||
"goodsInfo": "商品信息",
|
"goodsInfo": "商品信息",
|
||||||
"priceDetail": "价格明细",
|
"priceDetail": "价格明细",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "uni-taimed-international-app",
|
"id": "uni-wumen-international-app",
|
||||||
"name": "TaimedInternationalApp",
|
"name": "wumen-international-app",
|
||||||
"displayName": "太湖国际",
|
"displayName": "太湖国际",
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"description": "太湖国际",
|
"description": "太湖国际",
|
||||||
|
|||||||
@@ -55,12 +55,8 @@
|
|||||||
<wd-button size="small" type="warning" @click="handlePurchase">
|
<wd-button size="small" type="warning" @click="handlePurchase">
|
||||||
{{ $t('courseDetails.purchase') }}
|
{{ $t('courseDetails.purchase') }}
|
||||||
</wd-button>
|
</wd-button>
|
||||||
<wd-button
|
<!-- 如果是复读显示复读按钮 -->
|
||||||
v-if="showRenewBtn"
|
<wd-button v-if="canRenlearn" size="small" type="success" @click="handleRenlearn">
|
||||||
size="small"
|
|
||||||
type="success"
|
|
||||||
@click="handleRenew"
|
|
||||||
>
|
|
||||||
{{ $t('courseDetails.relearn') }}
|
{{ $t('courseDetails.relearn') }}
|
||||||
</wd-button>
|
</wd-button>
|
||||||
<wd-button size="small" type="primary" @click="goToVip">
|
<wd-button size="small" type="primary" @click="goToVip">
|
||||||
@@ -134,28 +130,42 @@
|
|||||||
<text>暂无章节内容</text>
|
<text>暂无章节内容</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 商品选择器 -->
|
||||||
|
<GoodsSelector
|
||||||
|
:show="showGoodsSelector"
|
||||||
|
:goods="goodsList"
|
||||||
|
@select="handleGoodsSelect"
|
||||||
|
@confirm="handleGoodsConfirm"
|
||||||
|
@close="closeGoodsSelector"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 购买协议弹窗 -->
|
||||||
|
<Protocol :visible="showProtocol" @confirmPurchase="confirmPurchase" />
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
import { courseApi } from '@/api/modules/course'
|
import { courseApi } from '@/api/modules/course'
|
||||||
|
import GoodsSelector from '@/components/order/GoodsSelector.vue'
|
||||||
|
import Protocol from './Protocol.vue'
|
||||||
import type { IChapter, ICatalogue, IVipInfo } from '@/types/course'
|
import type { IChapter, ICatalogue, IVipInfo } from '@/types/course'
|
||||||
|
import type { IGoods } from '@/types/order'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
catalogues: ICatalogue[]
|
catalogues: ICatalogue[]
|
||||||
userVip: IVipInfo | null
|
userVip: IVipInfo | null
|
||||||
showRenewBtn?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
click: [chapter: IChapter],
|
click: [chapter: IChapter],
|
||||||
purchase: [catalogue: ICatalogue],
|
change: [index: number],
|
||||||
renew: [catalogue: ICatalogue],
|
toVip: [],
|
||||||
toVip: [catalogue: ICatalogue],
|
toDetail: [chapter: IChapter, catalogue: ICatalogue],
|
||||||
change: [index: number]
|
loadPageData: [],
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
// 当前目录索引
|
// 当前目录索引
|
||||||
@@ -167,14 +177,21 @@ const currentCatalogue = computed(() => {
|
|||||||
// 当前目录的章节
|
// 当前目录的章节
|
||||||
const chapterList = ref<IChapter[]>([])
|
const chapterList = ref<IChapter[]>([])
|
||||||
|
|
||||||
// 显示续费按钮
|
// 当前目录是否是复读
|
||||||
const showRenewBtn = ref<boolean>(false)
|
const isRelearn = ref<boolean>(false)
|
||||||
|
const canRenlearn = ref<boolean>(false)
|
||||||
|
|
||||||
// 判断目录是否已购买
|
// 判断目录是否已购买
|
||||||
const isPurchased = computed(() => {
|
const isPurchased = computed(() => {
|
||||||
return currentCatalogue.value.isBuy === 1
|
return currentCatalogue.value.isBuy === 1
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 商品选择
|
||||||
|
const showGoodsSelector = ref(false)
|
||||||
|
const goodsList = ref<IGoods[]>([])
|
||||||
|
const selectedGoods = ref<IGoods | null>(null)
|
||||||
|
const showProtocol = ref(false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 选择目录
|
* 选择目录
|
||||||
*/
|
*/
|
||||||
@@ -201,9 +218,9 @@ const getChapters = async () => {
|
|||||||
const checkRenewPayment = async () => {
|
const checkRenewPayment = async () => {
|
||||||
if (currentCatalogue.value.isBuy === 0 && !props.userVip) {
|
if (currentCatalogue.value.isBuy === 0 && !props.userVip) {
|
||||||
const renewRes = await courseApi.checkRenewPayment(currentCatalogue.value.id)
|
const renewRes = await courseApi.checkRenewPayment(currentCatalogue.value.id)
|
||||||
showRenewBtn.value = renewRes.canRelearn || false
|
canRenlearn.value = renewRes.canRelearn || false
|
||||||
} else {
|
} else {
|
||||||
showRenewBtn.value = false
|
canRenlearn.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,23 +236,98 @@ watch(() => props.catalogues, (newVal: ICatalogue[]) => {
|
|||||||
}, { immediate: true, deep: true })
|
}, { immediate: true, deep: true })
|
||||||
|
|
||||||
// 购买
|
// 购买
|
||||||
const handlePurchase = () => {
|
const handlePurchase = async () => {
|
||||||
emit('purchase', currentCatalogue.value)
|
if (!currentCatalogue.value) return
|
||||||
|
|
||||||
|
isRelearn.value = false
|
||||||
|
const res = await courseApi.getProductListForCourse(currentCatalogue.value.id)
|
||||||
|
if (res.code === 0 && res.productList.length > 0) {
|
||||||
|
goodsList.value = res.productList
|
||||||
|
showGoodsSelector.value = true
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: '此课程暂无购买方式', icon: 'none' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择商品
|
||||||
|
*/
|
||||||
|
const handleGoodsSelect = (goods: IGoods) => {
|
||||||
|
selectedGoods.value = goods
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认购买
|
||||||
|
*/
|
||||||
|
const handleGoodsConfirm = () => {
|
||||||
|
showGoodsSelector.value = false
|
||||||
|
showProtocol.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭商品选择器
|
||||||
|
*/
|
||||||
|
const closeGoodsSelector = () => {
|
||||||
|
showGoodsSelector.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认购买协议
|
||||||
|
*/
|
||||||
|
const confirmPurchase = () => {
|
||||||
|
showProtocol.value = false
|
||||||
|
if (!selectedGoods.value) return
|
||||||
|
|
||||||
|
showProtocol.value = false
|
||||||
|
|
||||||
|
if (isRelearn.value) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/order/goodsConfirm?isRelearn=1`,
|
||||||
|
success: () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.$emit('selectedGoods', selectedGoods.value)
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 跳转到购买确认订单页
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/order/goodsConfirm?goods=${selectedGoods.value.productId}`
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 去开通vip
|
// 去开通vip
|
||||||
const goToVip = () => {
|
const goToVip = () => {
|
||||||
emit('toVip', currentCatalogue.value)
|
emit('toVip')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 续费/复读
|
// 续费/复读
|
||||||
const handleRenew = () => {
|
const handleRenlearn = async () => {
|
||||||
emit('renew', currentCatalogue.value)
|
if (!currentCatalogue.value) return
|
||||||
|
|
||||||
|
isRelearn.value = true
|
||||||
|
const res = await courseApi.getRenewProductList(currentCatalogue.value.id)
|
||||||
|
if (res.productList.length > 0) {
|
||||||
|
goodsList.value = res.productList
|
||||||
|
showGoodsSelector.value = true
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: '暂无复读方案', icon: 'none' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 领取免费课程
|
// 领取免费课程
|
||||||
const handleGetFreeCourse = async () => {
|
const handleGetFreeCourse = async () => {
|
||||||
emit('getFreeCourse', currentCatalogue.value)
|
if (!currentCatalogue.value) return
|
||||||
|
|
||||||
|
const res = await courseApi.startStudyForMF(currentCatalogue.value.id)
|
||||||
|
if (res.code === 0) {
|
||||||
|
uni.showToast({ title: '领取成功', icon: 'success' })
|
||||||
|
// 刷新页面数据
|
||||||
|
emit('loadPageData')
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: res.msg || '领取失败', icon: 'none' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -260,7 +352,7 @@ const canAccess = (chapter: IChapter): boolean => {
|
|||||||
/**
|
/**
|
||||||
* 点击章节
|
* 点击章节
|
||||||
*/
|
*/
|
||||||
const handleChapterClick = (chapter: IChapter, catalogue: ICatalogue) => {
|
const handleChapterClick = (chapter: IChapter) => {
|
||||||
if (!canAccess(chapter)) {
|
if (!canAccess(chapter)) {
|
||||||
if (currentCatalogue.value.type === 0) {
|
if (currentCatalogue.value.type === 0) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
|
|||||||
91
pages/course/details/components/Protocol.vue
Normal file
91
pages/course/details/components/Protocol.vue
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<wd-popup v-model="showProtocol" position="center">
|
||||||
|
<view class="protocol-popup">
|
||||||
|
<view class="protocol-title">温馨提示</view>
|
||||||
|
<view class="protocol-content">
|
||||||
|
<text>
|
||||||
|
用户您好,本软件对于一个用户名及密码仅允许一部电子设备登陆,多部设备使用同一用户名操作软件的行为属于违规操作,发现违规一次将提出警告,再次违规您的用户名将被封号,无法正常登陆,如因此对您使用带来不便,敬请谅解。
|
||||||
|
</text>
|
||||||
|
<text>
|
||||||
|
课程购买之后一年内不打开,此一年内不会计算有效学习时间,一年后会自动开始计算有效学习时间。
|
||||||
|
</text>
|
||||||
|
<text>
|
||||||
|
本课程一经购买,暂不支持退款,敬请谅解。
|
||||||
|
</text>
|
||||||
|
<view style="color: red; font-weight: bold"> 注: </view>
|
||||||
|
<view>
|
||||||
|
1.手机、pad、电脑均为可登陆电子设备,均有唯一标识码,一个用户名仅允许在一个手机或一个ipad或一个电脑登陆,请根据您的使用习惯自行选择。<br />
|
||||||
|
2.如若申请变更登陆设备请联系客服,<br />
|
||||||
|
客服电话:021-08371305<br />
|
||||||
|
客服微信号:yilujiankangkefu<br />
|
||||||
|
3.如因违反上述使用规定...概不退款,本公司保留追究用户相关法律责任的权利。<br />
|
||||||
|
4.点击“同意”按钮即表示您同意遵守以上条款。
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="protocol-actions">
|
||||||
|
<wd-button type="info" plain @click="showProtocol = false">不同意</wd-button>
|
||||||
|
<wd-button type="primary" @click="confirmPurchase">同意</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
visible: boolean
|
||||||
|
}>()
|
||||||
|
|
||||||
|
console.log(props.visible)
|
||||||
|
|
||||||
|
const showProtocol = computed({
|
||||||
|
get: () => props.visible,
|
||||||
|
set: (val) => emit('update:visible', val)
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:visible': [boolean],
|
||||||
|
confirmPurchase: []
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const confirmPurchase = () => {
|
||||||
|
emit('confirmPurchase')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.protocol-popup {
|
||||||
|
width: 600rpx;
|
||||||
|
padding: 40rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
|
||||||
|
.protocol-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.protocol-content {
|
||||||
|
max-height: 60vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
font-size: 26rpx;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.protocol-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -20,10 +20,8 @@
|
|||||||
v-if="catalogueList.length > 0"
|
v-if="catalogueList.length > 0"
|
||||||
:catalogues="catalogueList"
|
:catalogues="catalogueList"
|
||||||
:userVip="userVip"
|
:userVip="userVip"
|
||||||
@getFreeCourse="handleGetFreeCourse"
|
|
||||||
@purchase="handlePurchase"
|
|
||||||
@toVip="goToVip"
|
@toVip="goToVip"
|
||||||
@renew="handleRenew"
|
@loadPageData="loadPageData"
|
||||||
@toDetail="handleToDetail"
|
@toDetail="handleToDetail"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -89,55 +87,14 @@
|
|||||||
/>
|
/>
|
||||||
</view> -->
|
</view> -->
|
||||||
|
|
||||||
<!-- 商品选择器 -->
|
|
||||||
<GoodsSelector
|
|
||||||
:show="showGoodsSelector"
|
|
||||||
:goods="goodsList"
|
|
||||||
:isFudu="isFudu"
|
|
||||||
@select="handleGoodsSelect"
|
|
||||||
@confirm="handleGoodsConfirm"
|
|
||||||
@close="closeGoodsSelector"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 购买协议弹窗 -->
|
|
||||||
<wd-popup v-model="showProtocol" position="center">
|
|
||||||
<view class="protocol-popup">
|
|
||||||
<view class="protocol-title">温馨提示</view>
|
|
||||||
<view class="protocol-content">
|
|
||||||
<text>
|
|
||||||
用户您好,本软件对于一个用户名及密码仅允许一部电子设备登陆,多部设备使用同一用户名操作软件的行为属于违规操作,发现违规一次将提出警告,再次违规您的用户名将被封号,无法正常登陆,如因此对您使用带来不便,敬请谅解。
|
|
||||||
</text>
|
|
||||||
<text>
|
|
||||||
课程购买之后一年内不打开,此一年内不会计算有效学习时间,一年后会自动开始计算有效学习时间。
|
|
||||||
</text>
|
|
||||||
<text>
|
|
||||||
本课程一经购买,暂不支持退款,敬请谅解。
|
|
||||||
</text>
|
|
||||||
<view style="color: red; font-weight: bold"> 注: </view>
|
|
||||||
<view>
|
|
||||||
1.手机、pad、电脑均为可登陆电子设备,均有唯一标识码,一个用户名仅允许在一个手机或一个ipad或一个电脑登陆,请根据您的使用习惯自行选择。<br />
|
|
||||||
2.如若申请变更登陆设备请联系客服,<br />
|
|
||||||
客服电话:021-08371305<br />
|
|
||||||
客服微信号:yilujiankangkefu<br />
|
|
||||||
3.如因违反上述使用规定...概不退款,本公司保留追究用户相关法律责任的权利。<br />
|
|
||||||
4.点击“同意”按钮即表示您同意遵守以上条款。
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="protocol-actions">
|
|
||||||
<wd-button type="info" plain @click="showProtocol = false">不同意</wd-button>
|
|
||||||
<wd-button type="primary" @click="confirmPurchase">同意</wd-button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</wd-popup>
|
|
||||||
|
|
||||||
<!-- 评论编辑器 -->
|
<!-- 评论编辑器 -->
|
||||||
<CommentEditor
|
<!-- <CommentEditor
|
||||||
:show="showEditor"
|
:show="showEditor"
|
||||||
:parentComment="replyComment"
|
:parentComment="replyComment"
|
||||||
type="course"
|
type="course"
|
||||||
@submit="handleCommentSubmit"
|
@submit="handleCommentSubmit"
|
||||||
@close="closeCommentEditor"
|
@close="closeCommentEditor"
|
||||||
/>
|
/> -->
|
||||||
|
|
||||||
<!-- 返回顶部 -->
|
<!-- 返回顶部 -->
|
||||||
<wd-backtop :scrollTop="scrollTop" custom-class="back-top">
|
<wd-backtop :scrollTop="scrollTop" custom-class="back-top">
|
||||||
@@ -153,7 +110,6 @@ import { useUserStore } from '@/stores/user'
|
|||||||
import { courseApi } from '@/api/modules/course'
|
import { courseApi } from '@/api/modules/course'
|
||||||
import CourseInfo from './components/CourseInfo.vue'
|
import CourseInfo from './components/CourseInfo.vue'
|
||||||
import CatalogueList from './components/CatalogueList.vue'
|
import CatalogueList from './components/CatalogueList.vue'
|
||||||
import GoodsSelector from '@/components/order/GoodsSelector.vue'
|
|
||||||
import CommentList from '@/components/comment/CommentList.vue'
|
import CommentList from '@/components/comment/CommentList.vue'
|
||||||
import CommentEditor from '@/components/comment/CommentEditor.vue'
|
import CommentEditor from '@/components/comment/CommentEditor.vue'
|
||||||
import type { ICourseDetail, ICatalogue, IChapter, IVipInfo } from '@/types/course'
|
import type { ICourseDetail, ICatalogue, IChapter, IVipInfo } from '@/types/course'
|
||||||
@@ -172,14 +128,6 @@ const vipModuleList = ref<string[]>([])
|
|||||||
const learningProgress = ref(0)
|
const learningProgress = ref(0)
|
||||||
const relatedBooks = ref<IGoods[]>([])
|
const relatedBooks = ref<IGoods[]>([])
|
||||||
|
|
||||||
// 商品选择
|
|
||||||
const showGoodsSelector = ref(false)
|
|
||||||
const goodsList = ref<IGoods[]>([])
|
|
||||||
const selectedGoods = ref<IGoods | null>(null)
|
|
||||||
const showProtocol = ref(false)
|
|
||||||
const isFudu = ref(false)
|
|
||||||
const fuduCatalogueId = ref<number>(0)
|
|
||||||
|
|
||||||
// 评论相关
|
// 评论相关
|
||||||
const commentList = ref<IComment[]>([])
|
const commentList = ref<IComment[]>([])
|
||||||
const commentsLoading = ref(false)
|
const commentsLoading = ref(false)
|
||||||
@@ -301,92 +249,6 @@ const goToVip = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 领取免费课程
|
|
||||||
*/
|
|
||||||
const handleGetFreeCourse = async (catalogue: ICatalogue) => {
|
|
||||||
if (!catalogue) return
|
|
||||||
|
|
||||||
const res = await courseApi.startStudyForMF(catalogue.id)
|
|
||||||
if (res.code === 0) {
|
|
||||||
uni.showToast({ title: '领取成功', icon: 'success' })
|
|
||||||
// 刷新页面数据
|
|
||||||
loadPageData()
|
|
||||||
} else {
|
|
||||||
uni.showToast({ title: res.msg || '领取失败', icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 购买课程
|
|
||||||
*/
|
|
||||||
const handlePurchase = async (catalogue: ICatalogue) => {
|
|
||||||
if (!catalogue) return
|
|
||||||
|
|
||||||
isFudu.value = false
|
|
||||||
const res = await courseApi.getProductListForCourse(catalogue.id)
|
|
||||||
if (res.code === 0 && res.productList.length > 0) {
|
|
||||||
goodsList.value = res.productList
|
|
||||||
showGoodsSelector.value = true
|
|
||||||
} else {
|
|
||||||
uni.showToast({ title: '此课程暂无购买方式', icon: 'none' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 续费/复读
|
|
||||||
*/
|
|
||||||
const handleRenew = async () => {
|
|
||||||
// if (!currentCatalogue.value) return
|
|
||||||
|
|
||||||
// isFudu.value = true
|
|
||||||
// fuduCatalogueId.value = currentCatalogue.value.id
|
|
||||||
// const res = await courseApi.getRenewProductList(currentCatalogue.value.id)
|
|
||||||
// if (res.code === 0 && res.productList.length > 0) {
|
|
||||||
// goodsList.value = res.productList
|
|
||||||
// showGoodsSelector.value = true
|
|
||||||
// } else {
|
|
||||||
// uni.showToast({ title: '暂无复读方案', icon: 'none' })
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 选择商品
|
|
||||||
*/
|
|
||||||
const handleGoodsSelect = (goods: IGoods) => {
|
|
||||||
selectedGoods.value = goods
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 确认购买
|
|
||||||
*/
|
|
||||||
const handleGoodsConfirm = () => {
|
|
||||||
showGoodsSelector.value = false
|
|
||||||
showProtocol.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭商品选择器
|
|
||||||
*/
|
|
||||||
const closeGoodsSelector = () => {
|
|
||||||
showGoodsSelector.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 确认购买协议
|
|
||||||
*/
|
|
||||||
const confirmPurchase = () => {
|
|
||||||
showProtocol.value = false
|
|
||||||
if (!selectedGoods.value) return
|
|
||||||
|
|
||||||
showProtocol.value = false
|
|
||||||
|
|
||||||
// 跳转到确认订单页
|
|
||||||
uni.navigateTo({
|
|
||||||
url: `/pages/order/goodsConfirm?goods=${selectedGoods.value.productId}`
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跳转到书籍详情
|
* 跳转到书籍详情
|
||||||
*/
|
*/
|
||||||
@@ -740,40 +602,6 @@ onReachBottom(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.protocol-popup {
|
|
||||||
width: 600rpx;
|
|
||||||
padding: 40rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
|
|
||||||
.protocol-title {
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #333;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 30rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.protocol-content {
|
|
||||||
max-height: 60vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
font-size: 26rpx;
|
|
||||||
line-height: 1.8;
|
|
||||||
color: #666;
|
|
||||||
margin-bottom: 30rpx;
|
|
||||||
|
|
||||||
text {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.protocol-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 20rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.back-top) {
|
:deep(.back-top) {
|
||||||
background-color: #fff !important;
|
background-color: #fff !important;
|
||||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
|||||||
@@ -91,15 +91,23 @@ const orderType = computed(() => {
|
|||||||
* 页面加载
|
* 页面加载
|
||||||
*/
|
*/
|
||||||
onLoad(async (options: any) => {
|
onLoad(async (options: any) => {
|
||||||
if (options.goods) {
|
|
||||||
try {
|
try {
|
||||||
|
if (options.isRelearn == 1) {
|
||||||
|
uni.$on('selectedGoods', async (data: IOrderGoods) => {
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
await getUserInfo()
|
await getUserInfo()
|
||||||
|
|
||||||
|
// 处理商品数据
|
||||||
|
console.log('监听到传入的商品数据:', data)
|
||||||
|
goodsList.value = [ data ]
|
||||||
|
})
|
||||||
|
} else if (options.goods) {
|
||||||
|
// 获取用户信息
|
||||||
|
await getUserInfo()
|
||||||
// 根据商品ID获取商品详细信息
|
// 根据商品ID获取商品详细信息
|
||||||
goodsIds.value = options.goods || ''
|
goodsIds.value = options.goods || ''
|
||||||
isRelearn.value = options.isRelearn == '1'
|
|
||||||
getGoodsList()
|
getGoodsList()
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('解析商品数据失败:', error)
|
console.error('解析商品数据失败:', error)
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@@ -107,7 +115,6 @@ onLoad(async (options: any) => {
|
|||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ const orderType = ref<string>('')
|
|||||||
/**
|
/**
|
||||||
* 页面加载
|
* 页面加载
|
||||||
*/
|
*/
|
||||||
onLoad(async () => {
|
onLoad(() => {
|
||||||
try {
|
try {
|
||||||
// 获取商品列表
|
// 获取商品列表
|
||||||
await uni.$on('selectedGoods', async (data: IOrderGoods) => {
|
uni.$on('selectedGoods', async (data: IOrderGoods) => {
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
await getUserInfo()
|
await getUserInfo()
|
||||||
|
|
||||||
|
|||||||
@@ -116,3 +116,15 @@ export interface IPageData<T> {
|
|||||||
pages: number
|
pages: number
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单接口
|
||||||
|
*/
|
||||||
|
export interface IOrder {
|
||||||
|
id: number
|
||||||
|
orderType: string // 订单类型
|
||||||
|
changeAmount: number
|
||||||
|
remark: string
|
||||||
|
createTime: string
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user