This commit is contained in:
2025-12-03 14:14:45 +08:00
19 changed files with 172 additions and 163 deletions

View File

@@ -419,7 +419,7 @@ const createOrder = async (): Promise<string | null> => {
<style lang="scss" scoped> <style lang="scss" scoped>
.confirm-order-page { .confirm-order-page {
min-height: 100vh; min-height: calc(100vh - 60px - 40rpx);
background-color: #f5f5f5; background-color: #f5f5f5;
padding: 20rpx; padding: 20rpx;
padding-bottom: 60px; padding-bottom: 60px;

View File

@@ -25,7 +25,9 @@ export function useVideoProgress() {
const localPosition = videoStorage.getVideoPosition(videoInfo.id) || 0 const localPosition = videoStorage.getVideoPosition(videoInfo.id) || 0
// 返回较大的值 // 返回较大的值
let position = Math.max(serverPosition, localPosition) // let position = Math.max(serverPosition, localPosition)
// 采用服务器记录的播放位置
let position = serverPosition
// 如果播放位置接近视频结尾最后5秒内则从头开始 // 如果播放位置接近视频结尾最后5秒内则从头开始
const videoDuration = videoInfo.duration || 0 const videoDuration = videoInfo.duration || 0
@@ -99,12 +101,12 @@ export function useVideoProgress() {
*/ */
const saveNow = async (videoInfo: IVideoInfo) => { const saveNow = async (videoInfo: IVideoInfo) => {
if (currentTime.value > 0) { if (currentTime.value > 0) {
// 保存到本地 // 保存到本地 注释掉: 不再保存到本地
videoStorage.saveVideoPosition( // videoStorage.saveVideoPosition(
videoInfo.id, // videoInfo.id,
Math.floor(currentTime.value), // Math.floor(currentTime.value),
videoInfo // videoInfo
) // )
// 保存到服务器 // 保存到服务器
await saveToServer(videoInfo.id, Math.floor(currentTime.value)) await saveToServer(videoInfo.id, Math.floor(currentTime.value))

View File

@@ -134,7 +134,7 @@ onMounted(async () => {
} }
// 开始保存进度 // 开始保存进度
player.videoProgress.startSaving(videoInfo) // player.videoProgress.startSaving(videoInfo) // 注释掉 不再保存到本地
} }
}) })
@@ -142,12 +142,12 @@ onMounted(async () => {
onHide(() => { onHide(() => {
console.log('Page hidden, saving progress...') console.log('Page hidden, saving progress...')
if (player.currentVideoData.value && player.videoProgress.currentTime.value > 0) { if (player.currentVideoData.value && player.videoProgress.currentTime.value > 0) {
// 立即保存到本地 // 立即保存到本地 注释掉: 不再保存到本地
videoStorage.saveVideoPosition( // videoStorage.saveVideoPosition(
player.currentVideoData.value.id, // player.currentVideoData.value.id,
Math.floor(player.videoProgress.currentTime.value), // Math.floor(player.videoProgress.currentTime.value),
player.currentVideoData.value // player.currentVideoData.value
) // )
// 保存到服务器 // 保存到服务器
player.videoProgress.saveToServer( player.videoProgress.saveToServer(
player.currentVideoData.value.id, player.currentVideoData.value.id,
@@ -164,12 +164,12 @@ onUnmounted(() => {
// 立即保存当前播放进度(同步保存到本地,异步保存到服务器) // 立即保存当前播放进度(同步保存到本地,异步保存到服务器)
if (player.currentVideoData.value && player.videoProgress.currentTime.value > 0) { if (player.currentVideoData.value && player.videoProgress.currentTime.value > 0) {
// 立即保存到本地 // 立即保存到本地 注释掉: 不再保存到本地
videoStorage.saveVideoPosition( // videoStorage.saveVideoPosition(
player.currentVideoData.value.id, // player.currentVideoData.value.id,
Math.floor(player.videoProgress.currentTime.value), // Math.floor(player.videoProgress.currentTime.value),
player.currentVideoData.value // player.currentVideoData.value
) // )
// 保存到服务器(不等待完成) // 保存到服务器(不等待完成)
player.videoProgress.saveToServer( player.videoProgress.saveToServer(
player.currentVideoData.value.id, player.currentVideoData.value.id,
@@ -214,11 +214,13 @@ const pause = () => {
// 暂停时保存进度 // 暂停时保存进度
if (player.currentVideoData.value && player.videoProgress.currentTime.value > 0) { if (player.currentVideoData.value && player.videoProgress.currentTime.value > 0) {
videoStorage.saveVideoPosition( // 保存进度到本地 注释掉: 不再保存到本地
player.currentVideoData.value.id, // videoStorage.saveVideoPosition(
Math.floor(player.videoProgress.currentTime.value), // player.currentVideoData.value.id,
player.currentVideoData.value // Math.floor(player.videoProgress.currentTime.value),
) // player.currentVideoData.value
// )
// 保存进度到服务器
player.videoProgress.saveToServer( player.videoProgress.saveToServer(
player.currentVideoData.value.id, player.currentVideoData.value.id,
Math.floor(player.videoProgress.currentTime.value) Math.floor(player.videoProgress.currentTime.value)
@@ -342,7 +344,7 @@ const playNext = async () => {
// 获取新视频的初始播放位置 // 获取新视频的初始播放位置
if (player.currentVideoData.value) { if (player.currentVideoData.value) {
initialTime.value = player.videoProgress.getInitialPosition(player.currentVideoData.value) initialTime.value = player.videoProgress.getInitialPosition(player.currentVideoData.value)
player.videoProgress.startSaving(player.currentVideoData.value) // player.videoProgress.startSaving(player.currentVideoData.value) // 注释掉 不再保存到本地
} }
} }
} }

View File

@@ -224,7 +224,7 @@
"migrateWarning": "Migration is irreversible, please proceed with caution!", "migrateWarning": "Migration is irreversible, please proceed with caution!",
"migrateInstructions": "Migration Instructions", "migrateInstructions": "Migration Instructions",
"instruction1": "Please obtain the migration code from your chinese account, get it by going to 【我的】-【数据迁移】-【获取迁移验证码】.", "instruction1": "Please obtain the migration code from your chinese account, get it by going to 【我的】-【数据迁移】-【获取迁移验证码】.",
"instruction2": "After data migration is complete, the chinese account data will be cleared, and all purchased Tianyi coins, points, courses, VIP and other data will be transferred to the current account", "instruction2": "After data migration is complete, the chinese account data will be cleared, and all purchased Tianyi Coins, points, courses, E-book, VIP, certificate, and User Contribution will be transferred to the current account",
"instruction3": "The migration process may take a few minutes, please be patient.", "instruction3": "The migration process may take a few minutes, please be patient.",
"instruction4": "If you encounter any issues, please contact customer service for assistance." "instruction4": "If you encounter any issues, please contact customer service for assistance."
@@ -237,7 +237,7 @@
"comment": "Review", "comment": "Review",
"choose": "Browse Books", "choose": "Browse Books",
"nullText": "No books yet, go shopping~", "nullText": "No books yet, go shopping~",
"afterPurchase": "Available after purchase", "afterPurchase": "Purchase to read",
"contents": "Contents", "contents": "Contents",
"zjContents": "Chapter List", "zjContents": "Chapter List",
"set": "Settings", "set": "Settings",

View File

@@ -224,8 +224,8 @@
"migrateCodePlaceholder": "国内版账号获取的迁移验证码", "migrateCodePlaceholder": "国内版账号获取的迁移验证码",
"migrateWarning": "迁移后不可恢复,请谨慎操作!", "migrateWarning": "迁移后不可恢复,请谨慎操作!",
"migrateInstructions": "迁移说明", "migrateInstructions": "迁移说明",
"instruction1": "请在吴门医述APP中获取迁移验证码获取方式【我的】-【数据迁移】-【获取迁移验证码】。", "instruction1": "请在吴门医述、心灵空间、众妙之门、疯子读书任意APP中获取迁移验证码获取方式【我的】-【数据迁移】-【获取迁移验证码】。",
"instruction2": "数据迁移完成后,旧账号数据将被清空,已购买的天医币、积分、课程、VIP等数据将转移到当前账号。", "instruction2": "数据迁移完成后,旧账号数据将被清空,已购买的天医币、积分、课程、电子书、VIP、证书、湖分将转移到当前账号。",
"instruction3": "迁移过程可能需要几分钟时间,请耐心等待。", "instruction3": "迁移过程可能需要几分钟时间,请耐心等待。",
"instruction4": "如遇到问题,请联系客服获取帮助。" "instruction4": "如遇到问题,请联系客服获取帮助。"
}, },
@@ -237,7 +237,7 @@
"comment": "书评", "comment": "书评",
"choose": "去选书", "choose": "去选书",
"nullText": "暂无书籍,快去选购吧~", "nullText": "暂无书籍,快去选购吧~",
"afterPurchase": "购买后即可使用此功能", "afterPurchase": "购买后即可阅读此章节",
"contents": "目录", "contents": "目录",
"zjContents": "章节目录", "zjContents": "章节目录",
"set": "设置", "set": "设置",

View File

@@ -2,8 +2,8 @@
"name" : "吴门国际", "name" : "吴门国际",
"appid" : "__UNI__1250B39", "appid" : "__UNI__1250B39",
"description" : "吴门国际", "description" : "吴门国际",
"versionName" : "0.1.1", "versionName" : "0.1.2",
"versionCode" : 11, "versionCode" : 12,
"transformPx" : false, "transformPx" : false,
/* 5+App */ /* 5+App */
"app-plus" : { "app-plus" : {

View File

@@ -79,15 +79,15 @@
<!-- 底部操作栏 --> <!-- 底部操作栏 -->
<view class="action-bar"> <view class="action-bar">
<template v-if="bookInfo.isBuy"> <template v-if="bookInfo.isBuy || hasVip">
<view class="action-btn read" @click="goToReader"> <view class="action-btn read" @click="goToReader">
<text>{{ $t('bookDetails.startReading') }}</text> <text>{{ $t('bookDetails.startReading') }}</text>
</view> </view>
<view class="action-btn purchased"> <!-- <view class="action-btn purchased">
<wd-button disabled custom-class="purchased-btn"> <wd-button disabled custom-class="purchased-btn">
{{ $t('bookDetails.buttonText2') }} {{ $t('bookDetails.buttonText2') }}
</wd-button> </wd-button>
</view> </view> -->
<view class="action-btn listen" @click="goToListen"> <view class="action-btn listen" @click="goToListen">
<text>{{ $t('bookDetails.startListening') }}</text> <text>{{ $t('bookDetails.startListening') }}</text>
</view> </view>
@@ -120,19 +120,23 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, onMounted } from 'vue' import { ref, computed, onMounted } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app' import { onLoad, onShow } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n' import { t } from '@/utils/i18n'
import { bookApi } from '@/api/modules/book' import { bookApi } from '@/api/modules/book'
import { useUserStore } from '@/stores/user'
import type { IBookDetail, IBook, IComment } from '@/types/book' import type { IBookDetail, IBook, IComment } from '@/types/book'
import type { IGoods } from '@/types/order' import type { IGoods } from '@/types/order'
import GoodsSelector from '@/components/order/GoodsSelector.vue' import GoodsSelector from '@/components/order/GoodsSelector.vue'
import CommentList from '@/components/book/CommentList.vue' import CommentList from '@/components/book/CommentList.vue'
const { t } = useI18n() const userStore = useUserStore()
// 路由参数 // 路由参数
const bookId = ref(0) const bookId = ref(0)
const pageFrom = ref('') const pageFrom = ref('')
// 会员状态
const hasVip = computed(() => userStore.userInfo?.userEbookVip?.length > 0 || false)
// 数据状态 // 数据状态
const bookInfo = ref<IBookDetail>({ const bookInfo = ref<IBookDetail>({
id: 0, id: 0,

View File

@@ -172,10 +172,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue' import { ref, onMounted, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app' import { onShow } from '@dcloudio/uni-app'
import { homeApi } from '@/api/modules/book_home' import { homeApi } from '@/api/modules/book_home'
import { getNotchHeight } from '@/utils/system' import { getNotchHeight } from '@/utils/system'
import { useUserStore } from '@/stores/user'
import BookPrice from '@/components/book/BookPrice.vue' import BookPrice from '@/components/book/BookPrice.vue'
import type { import type {
IBook, IBook,
@@ -184,6 +185,8 @@ import type {
IVipInfo IVipInfo
} from '@/types/book' } from '@/types/book'
const userStore = useUserStore()
// 状态定义 // 状态定义
const showMyBooks = ref(false) const showMyBooks = ref(false)
const showActivity = ref(false) const showActivity = ref(false)
@@ -208,17 +211,7 @@ const currentLevel1Index = ref(0)
const currentLevel2Index = ref(0) const currentLevel2Index = ref(0)
// VIP信息 // VIP信息
const vipInfo = ref<IVipInfo | null>(null) const vipInfo = computed(() => userStore.userInfo?.userEbookVip?.[0] || null)
/**
* 获取VIP信息
*/
const getVipInfo = async () => {
const res = await homeApi.getVipInfo()
if (res.vipInfo) {
vipInfo.value = res.vipInfo
}
}
/** /**
* 获取我的书单 * 获取我的书单
@@ -388,7 +381,6 @@ onMounted(() => {
*/ */
onShow(() => { onShow(() => {
// 刷新数据 // 刷新数据
getVipInfo()
getMyBooks() getMyBooks()
getRecommendBooks() getRecommendBooks()
getActivityLabels() getActivityLabels()

View File

@@ -16,7 +16,7 @@
<text class="author">{{ $t('bookDetails.authorName') }}{{ bookInfo.author?.authorName }}</text> <text class="author">{{ $t('bookDetails.authorName') }}{{ bookInfo.author?.authorName }}</text>
</view> </view>
<wd-button <wd-button
v-if="!bookInfo.isBuy" v-if="!bookInfo.isBuy && !hasVip"
type="primary" type="primary"
size="small" size="small"
@click="purchaseVisible = true" @click="purchaseVisible = true"
@@ -63,18 +63,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app' import { onLoad } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n' import { t } from '@/utils/i18n'
import { bookApi } from '@/api/modules/book' import { bookApi } from '@/api/modules/book'
import { useUserStore } from '@/stores/user'
import type { IBookDetail, IChapter } from '@/types/book' import type { IBookDetail, IChapter } from '@/types/book'
import type { IGoods } from '@/types/order' import type { IGoods } from '@/types/order'
import GoodsSelector from '@/components/order/GoodsSelector.vue' import GoodsSelector from '@/components/order/GoodsSelector.vue'
const { t } = useI18n() const userStore = useUserStore()
// 路由参数 // 路由参数
const bookId = ref(0) const bookId = ref(0)
const fromIndex = ref(-1) const fromIndex = ref(-1)
// 会员状态
const hasVip = computed(() => userStore.userInfo?.userEbookVip?.length > 0 || false)
// 数据状态 // 数据状态
const bookInfo = ref<IBookDetail>({ const bookInfo = ref<IBookDetail>({
id: 0, id: 0,
@@ -163,7 +167,7 @@ async function loadChapterList() {
// 判断章节是否锁定 // 判断章节是否锁定
function isLocked(index: number): boolean { function isLocked(index: number): boolean {
return !bookInfo.value.isBuy && index + 1 > bookInfo.value.freeChapterCount return !bookInfo.value.isBuy && index + 1 > bookInfo.value.freeChapterCount && !hasVip.value
} }
// 播放章节 // 播放章节

View File

@@ -80,7 +80,8 @@
:class="{ 'chapter-item-active': currentChapterIndex === index }" :class="{ 'chapter-item-active': currentChapterIndex === index }"
@click="selectChapter(index)" @click="selectChapter(index)"
> >
<text class="chapter-title">{{ chapter.chapter }}</text> <text class="chapter-title" :class="{ locked: isLocked(index) }">{{ chapter.chapter }}</text>
<wd-icon v-if="isLocked(index)" name="lock-on" size="20px" />
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
@@ -92,10 +93,15 @@
import { ref, computed, onMounted, onUnmounted } from 'vue' import { ref, computed, onMounted, onUnmounted } from 'vue'
import { onLoad, onHide, onUnload } from '@dcloudio/uni-app' import { onLoad, onHide, onUnload } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useUserStore } from '@/stores/user'
import { bookApi } from '@/api/modules/book' import { bookApi } from '@/api/modules/book'
import type { IBookDetail, IChapter } from '@/types/book' import type { IBookDetail, IChapter } from '@/types/book'
const { t } = useI18n() const { t } = useI18n()
const userStore = useUserStore()
// 会员状态
const hasVip = computed(() => userStore.userInfo?.userEbookVip?.length > 0 || false)
// 路由参数 // 路由参数
const bookId = ref(0) const bookId = ref(0)
@@ -284,6 +290,11 @@ async function loadChapterList() {
} }
} }
// 判断章节是否锁定
function isLocked(index: number): boolean {
return !bookInfo.value.isBuy && index + 1 > bookInfo.value.freeChapterCount && !hasVip.value
}
// 加载章节内容(带音频时间点) // 加载章节内容(带音频时间点)
async function loadChapterContent(chapterId: number) { async function loadChapterContent(chapterId: number) {
try { try {
@@ -375,7 +386,7 @@ function togglePlay() {
// 上一章 // 上一章
async function prevChapter() { async function prevChapter() {
if (currentChapterIndex.value > 0) { if (currentChapterIndex.value > 0 && !isLocked(currentChapterIndex.value - 1)) {
currentChapterIndex.value-- currentChapterIndex.value--
await loadChapterContent(chapterList.value[currentChapterIndex.value].id) await loadChapterContent(chapterList.value[currentChapterIndex.value].id)
playChapter(chapterList.value[currentChapterIndex.value]) playChapter(chapterList.value[currentChapterIndex.value])
@@ -390,19 +401,23 @@ async function prevChapter() {
// 下一章 // 下一章
async function nextChapter() { async function nextChapter() {
// 检查是否锁定 // 检查是否锁定
if (isBuy.value === '1' && currentChapterIndex.value + 1 >= count.value) { if (isLocked(currentChapterIndex.value + 1)) {
uni.showModal({ uni.showToast({
title: t('common.limit_title'), title: t('book.afterPurchase'),
content: t('book.afterPurchase'), icon: 'none'
confirmText: t('common.confirm_text'),
success: (res) => {
if (res.confirm) {
uni.navigateTo({
url: `/pages/book/order?id=${bookId.value}`
})
}
}
}) })
// uni.showModal({
// title: t('common.limit_title'),
// content: t('book.afterPurchase'),
// confirmText: t('common.confirm_text'),
// success: (res) => {
// if (res.confirm) {
// uni.navigateTo({
// url: `/pages/book/order?id=${bookId.value}`
// })
// }
// }
// })
return return
} }
@@ -491,7 +506,7 @@ async function selectChapter(index: number) {
} }
// 检查是否锁定 // 检查是否锁定
if (isBuy.value === '1' && index >= count.value) { if (isLocked(index)) {
uni.showToast({ uni.showToast({
title: t('book.afterPurchase'), title: t('book.afterPurchase'),
icon: 'none' icon: 'none'
@@ -698,6 +713,10 @@ function formatTime(seconds: number): string {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
&.locked {
color: #999;
}
} }
.chapter-item-active .chapter-title { .chapter-item-active .chapter-title {

View File

@@ -102,6 +102,7 @@
<text class="popup-title">{{ $t('book.zjContents') }}</text> <text class="popup-title">{{ $t('book.zjContents') }}</text>
<scroll-view scroll-y class="chapter-list"> <scroll-view scroll-y class="chapter-list">
<view <view
v-if="chapterList.length > 0"
v-for="(chapter, index) in chapterList" v-for="(chapter, index) in chapterList"
:key="chapter.id" :key="chapter.id"
class="chapter-item" class="chapter-item"
@@ -111,8 +112,9 @@
<text class="chapter-text" :class="{ locked: isLocked(index) }"> <text class="chapter-text" :class="{ locked: isLocked(index) }">
{{ chapter.chapter }}{{ chapter.content ? ' - ' + chapter.content : '' }} {{ chapter.chapter }}{{ chapter.content ? ' - ' + chapter.content : '' }}
</text> </text>
<wd-icon v-if="isLocked(index)" name="lock-on" size="20px" /> <wd-icon v-if="isLocked(index) && !hasVip" name="lock-on" size="20px" />
</view> </view>
<wd-status-tip v-else image="content" :tip="$t('global.dataNull')" />
</scroll-view> </scroll-view>
</view> </view>
</wd-popup> </wd-popup>
@@ -191,6 +193,7 @@
import { ref, computed, onMounted } from 'vue' import { ref, computed, onMounted } from 'vue'
import { onLoad, onShow, onHide, onBackPress } from '@dcloudio/uni-app' import { onLoad, onShow, onHide, onBackPress } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useUserStore } from '@/stores/user'
import { useBookStore } from '@/stores/book' import { useBookStore } from '@/stores/book'
import { bookApi } from '@/api/modules/book' import { bookApi } from '@/api/modules/book'
import type { IChapter, IChapterContent, IReadProgress } from '@/types/book' import type { IChapter, IChapterContent, IReadProgress } from '@/types/book'
@@ -198,6 +201,10 @@ import { onPageBack } from '@/utils/index'
const { t } = useI18n() const { t } = useI18n()
const bookStore = useBookStore() const bookStore = useBookStore()
const userStore = useUserStore()
// 会员状态
const hasVip = computed(() => userStore.userInfo?.userEbookVip?.length > 0 || false)
// 路由参数 // 路由参数
const bookId = ref(0) const bookId = ref(0)
@@ -430,7 +437,7 @@ async function switchChapter(chapter: IChapter, index: number) {
// 判断章节是否锁定 // 判断章节是否锁定
function isLocked(index: number): boolean { function isLocked(index: number): boolean {
return !isBuy.value && index + 1 > count.value return !isBuy.value && index + 1 > count.value && !hasVip.value
} }
// 判断是否是图片 // 判断是否是图片
@@ -604,10 +611,9 @@ function changeReadMode(mode: 'scroll' | 'page') {
// 语言配置 // 语言配置
const bookLanguages = ref([]) const bookLanguages = ref([])
const currentLanguage = ref('') const currentLanguage = ref('中文')
onMounted(() => { onMounted(() => {
currentLanguage.value = uni.getStorageSync('currentBookLanguage') || '中文' currentLanguage.value = uni.getStorageSync('currentBookLanguage') || '中文'
console.log('currentLanguage', currentLanguage.value)
}) })
const getBookLanguages = async () => { const getBookLanguages = async () => {
const res = await bookApi.getBookLanguages(bookId.value) const res = await bookApi.getBookLanguages(bookId.value)
@@ -658,7 +664,7 @@ async function saveProgress() {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
z-index: 999; z-index: 90;
background: inherit; background: inherit;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -122,14 +122,6 @@ const loadChapterDetail = async () => {
} }
} }
/**
* 选择视频
*/
const selectVideo = async (index: number) => {
if (index === currentVideoIndex.value) return
currentVideoIndex.value = index
}
/** /**
* 预览图片 * 预览图片
*/ */

View File

@@ -122,7 +122,7 @@
</view> </view>
<!-- 锁定图标 --> <!-- 锁定图标 -->
<view v-if="!canAccess(chapter)" class="lock-icon"> <view v-if="!canAccess(chapter) && currentCatalogue.type != 0" class="lock-icon">
<wd-icon name="lock-on" size="24px" color="#258feb" /> <wd-icon name="lock-on" size="24px" color="#258feb" />
</view> </view>
</view> </view>
@@ -252,7 +252,7 @@ const canAccess = (chapter: IChapter): boolean => {
if (chapter.isAudition === 1) return true if (chapter.isAudition === 1) return true
// 免费课程可以访问 // 免费课程可以访问
if (currentCatalogue.value.type === 0) return true // if (currentCatalogue.value.type === 0) return true
return false return false
} }
@@ -261,18 +261,18 @@ const canAccess = (chapter: IChapter): boolean => {
* 点击章节 * 点击章节
*/ */
const handleChapterClick = (chapter: IChapter, catalogue: ICatalogue) => { const handleChapterClick = (chapter: IChapter, catalogue: ICatalogue) => {
if (!isPurchased.value && currentCatalogue.value.type === 0) { if (!canAccess(chapter)) {
if (currentCatalogue.value.type === 0) {
uni.showToast({ uni.showToast({
title: '请先领取课程', title: '请先领取课程',
icon: 'none' icon: 'none'
}) })
return } else {
}
if (!canAccess(chapter)) {
uni.showToast({ uni.showToast({
title: '请先购买课程', title: '请先购买课程',
icon: 'none' icon: 'none'
}) })
}
return return
} }

View File

@@ -3,7 +3,7 @@
<!-- 自定义导航栏 --> <!-- 自定义导航栏 -->
<nav-bar :title="$t('news.newsDetail')" /> <nav-bar :title="$t('news.newsDetail')" />
<web-view v-if="urlVisible" :webview-styles="{ progress: { color: '#55aaff' } }" :src="surl"></web-view> <view v-if="urlVisible" class="web-view-container"><web-view :webview-styles="{ progress: { color: '#55aaff' } }" :src="surl"></web-view></view>
<view v-else class="box"> <view v-else class="box">
<view class="title">{{ news.title }}</view> <view class="title">{{ news.title }}</view>
<view <view
@@ -32,28 +32,27 @@ onLoad((e: any) => {
source.value = e.source || '' source.value = e.source || ''
if(type.value == 1 && surl.value != ''){ if(type.value == 1 && surl.value != ''){
urlVisible.value = true urlVisible.value = true
// APP 设置导航栏按钮
// #ifdef APP-PLUS
const pages = getCurrentPages()
const page = pages[pages.length - 1]
const currentWebview = page.$getAppWebview()
currentWebview.setStyle({
titleNView: {
buttons: [{
float: 'right',
type: 'close',
onclick: () => {
uni.navigateBack({ delta: 1 })
}
}]
}
})
// #endif
} else { } else {
getData() getData()
} }
// APP 设置导航栏按钮
// #ifdef APP-PLUS
// const pages = getCurrentPages()
// const page = pages[pages.length - 1]
// const currentWebview = page.$getAppWebview()
// currentWebview.setStyle({
// titleNView: {
// buttons: [{
// float: 'right',
// type: 'close',
// onclick: () => {
// uni.navigateBack({ delta: 1 })
// }
// }]
// }
// })
// #endif
}) })
// 新闻详情 // 新闻详情
@@ -102,6 +101,9 @@ const formattedContent = computed(() => formatRichText(news.value.content))
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.web-view-container {
padding-top: 60px;
}
.box { .box {
background-color: #fff; background-color: #fff;
padding: 10px; padding: 10px;

View File

@@ -133,13 +133,13 @@
url: '/pages/user/feedback/index', url: '/pages/user/feedback/index',
type: 'pageJump' type: 'pageJump'
}, },
{ // {
id: 6, // id: 6,
name: t('user.dataMigrate'), // name: t('user.dataMigrate'),
url: '/pages/user/migrate/index', // url: '/pages/user/migrate/index',
desc: t('user.migrateSubtitle'), // desc: t('user.migrateSubtitle'),
type: 'pageJump' // type: 'pageJump'
} // }
]) ])
/** /**

View File

@@ -54,6 +54,8 @@
</view> </view>
</view> </view>
</view> </view>
<wd-message-box />
</view> </view>
</template> </template>
@@ -61,6 +63,9 @@
import { ref } from 'vue' import { ref } from 'vue'
import { t } from '@/utils/i18n' import { t } from '@/utils/i18n'
import { migrateUserData } from '@/api/modules/user' import { migrateUserData } from '@/api/modules/user'
import { useMessage } from '@/uni_modules/wot-design-uni'
const message = useMessage()
// 表单引用 // 表单引用
const migrateForm = ref() const migrateForm = ref()
@@ -85,14 +90,20 @@ const rules = ref({
const handleSubmit = async () => { const handleSubmit = async () => {
migrateForm.value.validate().then(({ valid, errors }: any) => { migrateForm.value.validate().then(({ valid, errors }: any) => {
if (valid) { if (valid) {
uni.showModal({ message.confirm({
title: t('global.tips'), title: t('global.tips'),
content: t('user.migrateWarning'), msg: t('user.instruction2'),
success: (res: any) => { }).then(() => {
if (res.confirm) { message.confirm({
title: t('global.tips'),
msg: t('user.migrateWarning'),
}).then(() => {
submitMigrate() submitMigrate()
} }).catch(() => {
} // 取消数据迁移
})
}).catch(() => {
// 取消数据迁移
}) })
} }
}) })

View File

@@ -27,7 +27,7 @@
<ProductInfo v-if="order.orderType === 'vip'" :data="order.vipBuyConfigEntity" :type="order.orderType" /> <ProductInfo v-if="order.orderType === 'vip'" :data="order.vipBuyConfigEntity" :type="order.orderType" />
<ProductInfo v-if="order.orderType === 'abroadVip'" :data="order.ebookvipBuyConfig" :type="order.orderType" /> <ProductInfo v-if="order.orderType === 'abroadVip'" :data="order.ebookvipBuyConfig" :type="order.orderType" />
<!-- 三种订单类型商品信息 end --> <!-- 三种订单类型商品信息 end -->
<view class="order-item-total-price">实付款{{ order.orderMoney }} {{ t('global.coin') }}</view> <view class="order-item-total-price">实付款{{ order.realMoney }} {{ t('global.coin') }}</view>
<template #footer> <template #footer>
<view> <view>

View File

@@ -211,27 +211,15 @@
max-width: 96rem; max-width: 96rem;
} }
} }
.mb-2 {
margin-bottom: calc(var(--spacing) * 2);
}
.mb-2\! { .mb-2\! {
margin-bottom: calc(var(--spacing) * 2) !important; margin-bottom: calc(var(--spacing) * 2) !important;
} }
.mb-\[20rpx\] {
margin-bottom: 20rpx;
}
.mb-\[20rpx\]\! { .mb-\[20rpx\]\! {
margin-bottom: 20rpx !important; margin-bottom: 20rpx !important;
} }
.ml-1 {
margin-left: calc(var(--spacing) * 1);
}
.ml-1\! { .ml-1\! {
margin-left: calc(var(--spacing) * 1) !important; margin-left: calc(var(--spacing) * 1) !important;
} }
.ml-2 {
margin-left: calc(var(--spacing) * 2);
}
.ml-2\.5\! { .ml-2\.5\! {
margin-left: calc(var(--spacing) * 2.5) !important; margin-left: calc(var(--spacing) * 2.5) !important;
} }
@@ -268,9 +256,6 @@
.flex-shrink { .flex-shrink {
flex-shrink: 1; flex-shrink: 1;
} }
.border-collapse {
border-collapse: collapse;
}
.transform { .transform {
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
} }
@@ -284,9 +269,6 @@
border-style: var(--tw-border-style); border-style: var(--tw-border-style);
border-width: 1px; border-width: 1px;
} }
.p-0 {
padding: calc(var(--spacing) * 0);
}
.p-0\! { .p-0\! {
padding: calc(var(--spacing) * 0) !important; padding: calc(var(--spacing) * 0) !important;
} }
@@ -305,12 +287,6 @@
.pt-\[10rpx\] { .pt-\[10rpx\] {
padding-top: 10rpx; padding-top: 10rpx;
} }
.pt-\[20rpx\] {
padding-top: 20rpx;
}
.pb-0 {
padding-bottom: calc(var(--spacing) * 0);
}
.pb-0\! { .pb-0\! {
padding-bottom: calc(var(--spacing) * 0) !important; padding-bottom: calc(var(--spacing) * 0) !important;
} }
@@ -342,9 +318,6 @@
.text-\[\#7dc1f0\] { .text-\[\#7dc1f0\] {
color: #7dc1f0; color: #7dc1f0;
} }
.text-\[14rpx\] {
color: 14rpx;
}
.text-\[cadetblue\] { .text-\[cadetblue\] {
color: cadetblue; color: cadetblue;
} }
@@ -364,9 +337,6 @@
--tw-ordinal: ordinal; --tw-ordinal: ordinal;
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,); font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
} }
.underline {
text-decoration-line: underline;
}
.ring { .ring {
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);

View File

@@ -145,3 +145,8 @@ uni-textarea {
border-radius: 4px !important; border-radius: 4px !important;
padding: 2px 6px !important; padding: 2px 6px !important;
} }
// 缺省
.wd-status-tip__text {
margin: 0px auto 20px !important;
}