Compare commits
4 Commits
v1.0.9-goo
...
b3d9b0c100
| Author | SHA1 | Date | |
|---|---|---|---|
| b3d9b0c100 | |||
| 66b004d6bf | |||
| c3b84946fb | |||
| b671e8d76c |
60
App.vue
60
App.vue
@@ -1,29 +1,55 @@
|
|||||||
<script>
|
<script>
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
import update from "@/uni_modules/uni-upgrade-center-app/utils/check-update";
|
import update from "@/uni_modules/uni-upgrade-center-app/utils/check-update";
|
||||||
|
|
||||||
// #endif
|
// #endif
|
||||||
export default {
|
import { useUserStore } from '@/stores/user'
|
||||||
onLaunch: function() {
|
export default {
|
||||||
console.log('App Launch')
|
onLaunch: function() {
|
||||||
|
const userStore = useUserStore()
|
||||||
|
console.log('App Launch')
|
||||||
|
// 保存原生 switchTab 方法
|
||||||
|
const originalSwitchTab = uni.switchTab;
|
||||||
|
uni.switchTab = (options) => {
|
||||||
|
if (options.url.includes('/pages/book/index') && !userStore.token) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '请先登录后访问该页面',
|
||||||
|
confirmText: '去登录',
|
||||||
|
success: (res) => {
|
||||||
|
console.log(res, 'res');
|
||||||
|
if (res.confirm) uni.navigateTo({
|
||||||
|
url: '/pages/login/login'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return; // 拦截跳转
|
||||||
|
}
|
||||||
|
// 已登录/非拦截页 → 执行原生跳转
|
||||||
|
originalSwitchTab.call(uni, options);
|
||||||
|
}
|
||||||
// 检测自动更新
|
// 检测自动更新
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
update();
|
update();
|
||||||
// #endif
|
// #endif
|
||||||
},
|
},
|
||||||
onShow: function() {
|
onShow: function() {
|
||||||
console.log('App Show')
|
console.log('App Show')
|
||||||
},
|
},
|
||||||
onHide: function() {
|
onHide: function() {
|
||||||
console.log('App Hide')
|
console.log('App Hide')
|
||||||
}
|
},
|
||||||
}
|
onTabItemTap: function() {
|
||||||
|
console.log('点击了');
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import "@/style/tailwind.css";
|
@import "@/style/tailwind.css";
|
||||||
@import "@/style/ui.scss";
|
@import "@/style/ui.scss";
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -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', // 暂时用不到
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
import { mainClient } from '@/api/clients/main'
|
import { mainClient } from '@/api/clients/main'
|
||||||
import type { IApiResponse } from '@/api/types'
|
import type { IApiResponse } from '@/api/types'
|
||||||
import type { IAgreement } from '@/types/user'
|
import type { IAgreement } from '@/types/user'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const commonApi = {
|
export const commonApi = {
|
||||||
/**
|
/**
|
||||||
@@ -36,8 +39,9 @@ export const commonApi = {
|
|||||||
* @returns 消息列表
|
* @returns 消息列表
|
||||||
*/
|
*/
|
||||||
getMessageList(isBook: number, isMedical: number, isSociology: number) {
|
getMessageList(isBook: number, isMedical: number, isSociology: number) {
|
||||||
|
const userStore = useUserStore()
|
||||||
return mainClient.request<IMessageListResponse>({
|
return mainClient.request<IMessageListResponse>({
|
||||||
url: 'common/message/listByPage',
|
url: userStore.token ? 'common/message/listByPage' : '/visitor/listByPage',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: { isBook, isMedical, isSociology }
|
data: { isBook, isMedical, isSociology }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import type {
|
|||||||
} from '@/types/course'
|
} from '@/types/course'
|
||||||
import type { ISearchRequest, ISearchResponse } from '@/types/search'
|
import type { ISearchRequest, ISearchResponse } from '@/types/search'
|
||||||
import type { ICommentListResponse, IAddCommentResponse, IComment } from '@/types/comment'
|
import type { ICommentListResponse, IAddCommentResponse, IComment } from '@/types/comment'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const client = createRequestClient({ baseURL: SERVICE_MAP.MAIN })
|
const client = createRequestClient({ baseURL: SERVICE_MAP.MAIN })
|
||||||
|
|
||||||
@@ -57,8 +60,9 @@ export const courseApi = {
|
|||||||
page: number,
|
page: number,
|
||||||
limit: number
|
limit: number
|
||||||
}) {
|
}) {
|
||||||
|
const userStore = useUserStore()
|
||||||
return client.request<IMarketCourseListResponse>({
|
return client.request<IMarketCourseListResponse>({
|
||||||
url: 'medical/home/getMarketCourseList',
|
url: userStore.token ? 'medical/home/getMarketCourseList' : 'visitor/getMarketCourseList',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import type {
|
|||||||
IMarketCourseListResponse,
|
IMarketCourseListResponse,
|
||||||
ICourseMedicalLabelsResponse
|
ICourseMedicalLabelsResponse
|
||||||
} from '@/types/course'
|
} from '@/types/course'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
|
|
||||||
const client = createRequestClient({ baseURL: SERVICE_MAP.MAIN })
|
const client = createRequestClient({ baseURL: SERVICE_MAP.MAIN })
|
||||||
|
|
||||||
@@ -20,8 +22,9 @@ export const courseSubjectClassificationApi = {
|
|||||||
* @returns 分类数据
|
* @returns 分类数据
|
||||||
*/
|
*/
|
||||||
getCourseMedicalTree() {
|
getCourseMedicalTree() {
|
||||||
|
const userStore = useUserStore()
|
||||||
return client.request<ICourseCategoryResponse>({
|
return client.request<ICourseCategoryResponse>({
|
||||||
url: 'medical/home/getCourseMedicalTree',
|
url: userStore.token ? 'medical/home/getCourseMedicalTree' : '/visitor/getCourseMedicalTree',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: {}
|
data: {}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { paymentClient } from '@/api/clients/payment'
|
|||||||
import type { IApiResponse } from '@/api/types'
|
import type { IApiResponse } from '@/api/types'
|
||||||
import type {
|
import type {
|
||||||
IUserInfo,
|
IUserInfo,
|
||||||
IVipInfo,
|
IVipInfo,
|
||||||
IOrder,
|
IOrder,
|
||||||
IVipPackage,
|
IVipPackage,
|
||||||
ITransaction,
|
ITransaction,
|
||||||
IFeedbackForm,
|
IFeedbackForm,
|
||||||
IPageData
|
IPageData
|
||||||
} from '@/types/user'
|
} from '@/types/user'
|
||||||
@@ -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,13 +304,57 @@ 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',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的湖分
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
export async function getUserContributionData() {
|
||||||
|
const res = await mainClient.request<IApiResponse>({
|
||||||
|
url: 'common/userContribution/getUserContribution',
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 湖分列表
|
||||||
|
* @param current 当前页码
|
||||||
|
* @param limit 每页数量
|
||||||
|
* @param type 湖分类型
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
export async function getUserContributionByTypeList(current : number, limit : number, type : string,) {
|
||||||
|
const res = await mainClient.request<IApiResponse>({
|
||||||
|
url: 'common/userContribution/getUserContributionByType',
|
||||||
|
method: 'POST',
|
||||||
|
data: { current, limit, type, }
|
||||||
|
})
|
||||||
|
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>()
|
||||||
|
|||||||
1012
locale/en.json
1012
locale/en.json
File diff suppressed because it is too large
Load Diff
1014
locale/zh-Hans.json
1014
locale/zh-Hans.json
File diff suppressed because it is too large
Load Diff
@@ -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": "太湖国际",
|
||||||
|
|||||||
23
pages.json
23
pages.json
@@ -67,6 +67,24 @@
|
|||||||
"navigationBarTitleText": "%user.feedback%",
|
"navigationBarTitleText": "%user.feedback%",
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
|
},{
|
||||||
|
"path": "pages/user/certificate/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "%user.certificate%",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
"path": "pages/user/hufen/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "%user.hufen%",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
"path": "pages/user/hufen/forDetails",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "%user.hufen%",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
"path": "pages/user/recharge/index",
|
"path": "pages/user/recharge/index",
|
||||||
"style": {
|
"style": {
|
||||||
@@ -219,6 +237,11 @@
|
|||||||
"animationDuration": 200
|
"animationDuration": 200
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
"path": "pages/visitor/index",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tabBar": {
|
"tabBar": {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -211,7 +211,9 @@ import { commonApi } from '@/api/modules/common'
|
|||||||
import { getNotchHeight } from '@/utils/system'
|
import { getNotchHeight } from '@/utils/system'
|
||||||
// import { onPageJump } from '@/utils'
|
// import { onPageJump } from '@/utils'
|
||||||
import type { IMedicalTag, ICourse, INews } from '@/types/course'
|
import type { IMedicalTag, ICourse, INews } from '@/types/course'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 系统信息
|
// 系统信息
|
||||||
@@ -239,18 +241,21 @@ const selectedFirstLevel = ref<number>('医学') // 当前选中的一级分类
|
|||||||
* 学科点击处理
|
* 学科点击处理
|
||||||
*/
|
*/
|
||||||
const handleFirstLevelClick = (item: string) => {
|
const handleFirstLevelClick = (item: string) => {
|
||||||
selectedFirstLevel.value = item
|
getPrompt()
|
||||||
switch (item) {
|
if(!userStore.token) return
|
||||||
case '医学':
|
selectedFirstLevel.value = item
|
||||||
getMedicalTags()
|
switch (item) {
|
||||||
break
|
case '医学':
|
||||||
case '心理学':
|
getMedicalTags()
|
||||||
getSoulCateList()
|
break
|
||||||
break
|
case '心理学':
|
||||||
case '国学':
|
getSoulCateList()
|
||||||
getSociologyCateList()
|
break
|
||||||
break
|
case '国学':
|
||||||
}
|
getSociologyCateList()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 医学
|
* 医学
|
||||||
@@ -326,15 +331,19 @@ const getSociologyCateList = async () => {
|
|||||||
* 终极分类点击处理
|
* 终极分类点击处理
|
||||||
*/
|
*/
|
||||||
const curseClickJump = (item: IMedicalTag) => {
|
const curseClickJump = (item: IMedicalTag) => {
|
||||||
uni.navigateTo({
|
getPrompt()
|
||||||
url: `/pages/course/list/category?id=${item.id}&title=${item.title}&pid=${item.pid}&subject=${selectedFirstLevel.value}`
|
if(!userStore.token) return
|
||||||
})
|
uni.navigateTo({
|
||||||
|
url: `/pages/course/list/category?id=${item.id}&title=${item.title}&pid=${item.pid}&subject=${selectedFirstLevel.value}`
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页面跳转统一处理
|
* 页面跳转统一处理
|
||||||
*/
|
*/
|
||||||
const onPageJump = (url: string, id?: number, title?: string) => {
|
const onPageJump = (url: string, id?: number, title?: string) => {
|
||||||
|
getPrompt()
|
||||||
|
if(!userStore.token) return
|
||||||
let targetUrl = url
|
let targetUrl = url
|
||||||
if (id !== undefined) {
|
if (id !== undefined) {
|
||||||
targetUrl += `?id=${id}`
|
targetUrl += `?id=${id}`
|
||||||
@@ -381,9 +390,12 @@ const getNewsList = async () => {
|
|||||||
* 新闻点击处理
|
* 新闻点击处理
|
||||||
*/
|
*/
|
||||||
const newsClick = (item: INews) => {
|
const newsClick = (item: INews) => {
|
||||||
uni.navigateTo({
|
getPrompt()
|
||||||
url: `/pages/news/details?newsId=${item.id}&url=${item.url}&type=${item.type}`
|
if(!userStore.token) return
|
||||||
})
|
uni.navigateTo({
|
||||||
|
url: `/pages/news/details?newsId=${item.id}&url=${item.url}&type=${item.type}`
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 精彩试听
|
// 精彩试听
|
||||||
@@ -406,31 +418,59 @@ const getTryListenList = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录提示语
|
||||||
|
*/
|
||||||
|
const getPrompt = () => {
|
||||||
|
if(!userStore.token) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '请先登录后访问该页面',
|
||||||
|
confirmText: '去登录',
|
||||||
|
success: (res) => {
|
||||||
|
console.log(res, 'res');
|
||||||
|
if (res.confirm) uni.navigateTo({
|
||||||
|
url: '/pages/login/login'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一请求所有数据
|
* 统一请求所有数据
|
||||||
*/
|
*/
|
||||||
const requestAll = async () => {
|
const requestAll = async () => {
|
||||||
getLearnCourse()
|
if(userStore.token){
|
||||||
getMedicalTags()
|
getLearnCourse()
|
||||||
getTryListenList()
|
}
|
||||||
getNewsList()
|
getMedicalTags()
|
||||||
|
getTryListenList()
|
||||||
|
getNewsList()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页面挂载
|
* 页面挂载
|
||||||
*/
|
*/
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
if(!userStore.token) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/login/login'
|
||||||
|
});
|
||||||
|
}
|
||||||
// 重置分类索引
|
// 重置分类索引
|
||||||
currentIndex.value = 0
|
currentIndex.value = 0
|
||||||
|
|
||||||
// 请求所有数据
|
// 请求所有数据
|
||||||
requestAll()
|
requestAll()
|
||||||
|
console.log('进来了2');
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页面显示
|
* 页面显示
|
||||||
*/
|
*/
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
console.log('进来了1');
|
||||||
// 检查是否有固定的分类选择状态
|
// 检查是否有固定的分类选择状态
|
||||||
const fixed = uni.getStorageSync('fixed')
|
const fixed = uni.getStorageSync('fixed')
|
||||||
if (fixed && currentItem.value) {
|
if (fixed && currentItem.value) {
|
||||||
|
|||||||
@@ -115,11 +115,11 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 游客体验 -->
|
<!-- 游客体验 -->
|
||||||
<!-- <view class="youke-l">
|
<view class="youke-l">
|
||||||
<view @click="onPageJump('/pages/visitor/visitor')">
|
<view @click="onPageJump('/pages/course/index')">
|
||||||
{{ $t('login.noLogin') }}
|
{{ $t('login.noLogin') }}
|
||||||
</view>
|
</view>
|
||||||
</view> -->
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 用户协议弹窗 -->
|
<!-- 用户协议弹窗 -->
|
||||||
@@ -399,7 +399,7 @@ const yszc = () => {
|
|||||||
* 页面跳转
|
* 页面跳转
|
||||||
*/
|
*/
|
||||||
const onPageJump = (url: string) => {
|
const onPageJump = (url: string) => {
|
||||||
uni.navigateTo({
|
uni.switchTab({
|
||||||
url: url,
|
url: url,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,22 +91,29 @@ 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()
|
||||||
|
|
||||||
|
// 处理商品数据
|
||||||
|
console.log('监听到传入的商品数据:', data)
|
||||||
|
goodsList.value = [ data ]
|
||||||
|
})
|
||||||
|
} else if (options.goods) {
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
await getUserInfo()
|
await getUserInfo()
|
||||||
|
|
||||||
// 根据商品ID获取商品详细信息
|
// 根据商品ID获取商品详细信息
|
||||||
goodsIds.value = options.goods || ''
|
goodsIds.value = options.goods || ''
|
||||||
isRelearn.value = options.isRelearn == '1'
|
|
||||||
getGoodsList()
|
getGoodsList()
|
||||||
} catch (error) {
|
|
||||||
console.error('解析商品数据失败:', error)
|
|
||||||
uni.showToast({
|
|
||||||
title: '商品数据错误',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('解析商品数据失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '商品数据错误',
|
||||||
|
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()
|
||||||
|
|
||||||
|
|||||||
134
pages/user/certificate/index.vue
Normal file
134
pages/user/certificate/index.vue
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
<template>
|
||||||
|
<view class="certificate-page">
|
||||||
|
<nav-bar :title="$t('user.certificate')"></nav-bar>
|
||||||
|
<view v-if="certificateList.length > 0">
|
||||||
|
<view style="margin: 10rpx;" >【共{{certificateList.length}}个证书】</view>
|
||||||
|
<view class="certificate-list" v-for="(item,index) in certificateList" :key="index">
|
||||||
|
<view class="certificate-list-row">
|
||||||
|
<h3>证书编号:{{item.bh}}</h3>
|
||||||
|
<text style="font-size: 26rpx; color: #999;">获得时间:{{item.time}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="certificate-certificate">
|
||||||
|
<view class="img" v-for="(i,index) in item.certificateUrl" :key="index">
|
||||||
|
<image @click="preveImg(i.url)" :src="i.url" mode="heightFix"></image>
|
||||||
|
</view>
|
||||||
|
<view class="certificate-detailed" @click="detailed(item)">详细信息</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-else><wd-divider>您还未获得证书</wd-divider></view>
|
||||||
|
</view>
|
||||||
|
<wd-popup v-model="detailedState" position="bottom" :closeable="true">
|
||||||
|
<view class="detailed">
|
||||||
|
<view class="detailed-text">
|
||||||
|
证书详情
|
||||||
|
</view>
|
||||||
|
<view class="detailed-row">证书类型:<text class="text">{{detailedData.a}}</text></view>
|
||||||
|
<view class="detailed-row">获得时间:<text class="text">{{detailedData.time}}</text></view>
|
||||||
|
<view class="detailed-row">获得途径:<text class="text">{{detailedData.b}}</text></view>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const detailedState = ref(false)
|
||||||
|
const detailedData = ref({})
|
||||||
|
|
||||||
|
// 模拟的 certificateList 数据
|
||||||
|
const certificateList = ref([
|
||||||
|
{ a: 'ZH', b: '吴门', bh: 1, time: '2025-6-20', certificateUrl: "https://ehh-private-01.oss-cn-beijing.aliyuncs.com/certificate/ca2140c3-d212-4d4e-9203-ddc161d50470.jpg,https://ehh-private-01.oss-cn-beijing.aliyuncs.com/certificate/18a7ea22-b75a-4ef6-9109-f448f45e424f.jpg" },
|
||||||
|
{ bh: 2, time: '2025-6-22', certificateUrl: "https://ehh-private-01.oss-cn-beijing.aliyuncs.com/certificate/ca2140c3-d212-4d4e-9203-ddc161d50470.jpg,https://ehh-private-01.oss-cn-beijing.aliyuncs.com/certificate/18a7ea22-b75a-4ef6-9109-f448f45e424f.jpg" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 重新获取数据
|
||||||
|
certificateList.value = certificateList.value.map(item => {
|
||||||
|
return { ...item, certificateUrl: item.certificateUrl.split(',').map(url => ({ url })) };
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看证书详情信息
|
||||||
|
*/
|
||||||
|
const detailed = (item) => {
|
||||||
|
detailedState.value = true
|
||||||
|
detailedData.value = item
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看照片
|
||||||
|
*/
|
||||||
|
const preveImg = (url : any) => {
|
||||||
|
uni.previewImage({
|
||||||
|
urls: [url],
|
||||||
|
current: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.certificate-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f7faf9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-list {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 15rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||||
|
margin: 20rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-list-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-certificate {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding-top: 20rpx;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 36%;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 300rpx;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.certificate-detailed {
|
||||||
|
color: #55aaff;
|
||||||
|
border: #55aaff 1px solid;
|
||||||
|
padding: 10rpx 20rpx;
|
||||||
|
border-radius: 15rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detailed {
|
||||||
|
padding: 20rpx;
|
||||||
|
|
||||||
|
.detailed-text {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detailed-row {
|
||||||
|
color: #999;
|
||||||
|
margin: 20rpx 0;
|
||||||
|
font-size: 26rpx;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
113
pages/user/hufen/forDetails.vue
Normal file
113
pages/user/hufen/forDetails.vue
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<template>
|
||||||
|
<z-paging ref="paging" v-model="bookList" auto-show-back-to-top class="my-book-page" @query="hufenList"
|
||||||
|
:default-page-size="10">
|
||||||
|
<template #top>
|
||||||
|
<!-- 自定义导航栏 -->
|
||||||
|
<nav-bar :title="$t('user.hufenRecord')"></nav-bar>
|
||||||
|
</template>
|
||||||
|
<view class="recharge-record" v-if="(bookList && bookList.length > 0)">
|
||||||
|
<view class="go-gecharge">{{hufenData.nameValue}} {{$t('user.hufenRecord')}}</view>
|
||||||
|
<view class="recharge-record-block" v-for="(item, index) in bookList" :key="index">
|
||||||
|
<view class="recharge-record-block-row">{{item.createTime}}<text class="text">{{item.score}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="time">{{item.detail}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</z-paging>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { getUserContributionByTypeList } from '@/api/modules/user'
|
||||||
|
import { copyToClipboard } from '@/utils/index'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const paging = ref<any>()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
// 数据状态
|
||||||
|
const bookList = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const firstLoad = ref(true)
|
||||||
|
const hufenData = ref('')
|
||||||
|
|
||||||
|
// 湖分记录
|
||||||
|
async function hufenList(pageNo : number, pageSize : number) {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await getUserContributionByTypeList(pageNo, pageSize, hufenData.value.type)
|
||||||
|
console.log(res, 'res');
|
||||||
|
paging.value.complete(res.list.records)
|
||||||
|
} catch (error) {
|
||||||
|
paging.value.complete(false)
|
||||||
|
console.error('Failed to load book list:', error)
|
||||||
|
} finally {
|
||||||
|
firstLoad.value = false
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onLoad((options) => {
|
||||||
|
hufenData.value = options
|
||||||
|
console.log(hufenData);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.my-book-page {
|
||||||
|
background: #f7faf9;
|
||||||
|
min-height: 100vh;
|
||||||
|
|
||||||
|
.recharge-record {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 15rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||||
|
// padding: 20rpx;
|
||||||
|
margin: 20rpx;
|
||||||
|
|
||||||
|
.go-gecharge {
|
||||||
|
text-align: center;
|
||||||
|
background: linear-gradient(to right, #007bff, #17a2b8);
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
padding-left: 20rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
color: #007bff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recharge-record-block {
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
padding: 20rpx;
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-size: 24rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
color: #343434
|
||||||
|
}
|
||||||
|
|
||||||
|
.recharge-record-block-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
// font-weight: 700;
|
||||||
|
color: #909090;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: #007bff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
69
pages/user/hufen/index.vue
Normal file
69
pages/user/hufen/index.vue
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<view class="recharge-page">
|
||||||
|
<nav-bar :title="$t('user.iHufen')"></nav-bar>
|
||||||
|
<view class="menu-section" v-if="hufenList.list.length > 0">
|
||||||
|
<wd-cell-group border class="menu-list">
|
||||||
|
<wd-cell v-for="item in hufenList.list" :key="item.type" :title="item.dict_value" is-link
|
||||||
|
@click="handleMenuClick(item)">
|
||||||
|
<text class="menu-list-hufen">{{item.score}}</text><text class="menu-list-hufen-text">{{$t('user.hufen')}}</text>
|
||||||
|
</wd-cell>
|
||||||
|
</wd-cell-group>
|
||||||
|
</view>
|
||||||
|
<view v-else><wd-divider>您还未获得湖分</wd-divider></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { getUserContributionData } from '@/api/modules/user'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const hufenList = ref([])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户湖分
|
||||||
|
*/
|
||||||
|
const getHufen = async () => {
|
||||||
|
hufenList.value = await getUserContributionData()
|
||||||
|
console.log(hufenList.value.list)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMenuClick = (item) => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/user/hufen/forDetails?type=${item.type}&nameValue=${item.dict_value}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getHufen()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.recharge-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f7faf9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-section {
|
||||||
|
padding: 20rpx 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-list {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 15rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
|
.menu-list-hufen {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #007bff;
|
||||||
|
margin-right: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-list-hufen-text {
|
||||||
|
color: #007bff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="user-page" :style="{ paddingTop: getNotchHeight() + 30 + 'px' }">
|
<view class="user-page" :style="{ paddingTop: getNotchHeight() + 30 + 'px' }" v-if="userStore.token">
|
||||||
<!-- 设置图标 -->
|
<!-- 设置图标 -->
|
||||||
<view class="settings-icon" :style="{ top: getNotchHeight() + 30 + 'px' }" @click="goSettings">
|
<view class="settings-icon" :style="{ top: getNotchHeight() + 30 + 'px' }" @click="goSettings">
|
||||||
<wd-icon name="setting1" size="24px" color="#666" />
|
<wd-icon name="setting1" size="24px" color="#666" />
|
||||||
@@ -23,18 +23,23 @@
|
|||||||
<view class="vip-card-title">{{ $t('user.vip') }}</view>
|
<view class="vip-card-title">{{ $t('user.vip') }}</view>
|
||||||
<view class="vip-card-content">
|
<view class="vip-card-content">
|
||||||
<view class="vip-item-list">
|
<view class="vip-item-list">
|
||||||
<view v-if="vipInfo?.length > 0" v-for="vip in vipInfo">{{ vipTypeDict[vip.type] }}({{ parseTime(vip.endTime, '{y}-{m}-{d}') }} 截止)</view>
|
<view v-if="vipInfo?.length > 0" v-for="vip in vipInfo">
|
||||||
|
{{ vipTypeDict[vip.type] }}({{ parseTime(vip.endTime, '{y}-{m}-{d}') }} 截止)</view>
|
||||||
<view v-else>办理课程VIP,畅享更多权益</view>
|
<view v-else>办理课程VIP,畅享更多权益</view>
|
||||||
</view>
|
</view>
|
||||||
<wd-button v-if="vipInfo?.length > 0" plain type="primary" size="small" @click="goCourseVipSub">{{ $t('vip.renewal') }}</wd-button>
|
<wd-button v-if="vipInfo?.length > 0" plain type="primary" size="small"
|
||||||
<wd-button v-else plain type="primary" size="small" @click="goCourseVipSub">{{ $t('vip.openVip') }}</wd-button>
|
@click="goCourseVipSub">{{ $t('vip.renewal') }}</wd-button>
|
||||||
|
<wd-button v-else plain type="primary" size="small"
|
||||||
|
@click="goCourseVipSub">{{ $t('vip.openVip') }}</wd-button>
|
||||||
</view>
|
</view>
|
||||||
<view class="vip-card-content">
|
<view class="vip-card-content">
|
||||||
<view class="vip-item-list">
|
<view class="vip-item-list">
|
||||||
<view v-if="vipInfoEbook?.length > 0" v-for="vip in vipInfoEbook">电子书VIP{{ vipTypeDict[vip.type] }}({{ parseTime(vip.endTime, '{y}-{m}-{d}') }} 截止)</view>
|
<view v-if="vipInfoEbook?.length > 0" v-for="vip in vipInfoEbook">
|
||||||
|
电子书VIP{{ vipTypeDict[vip.type] }}({{ parseTime(vip.endTime, '{y}-{m}-{d}') }} 截止)</view>
|
||||||
<view v-else>办理电子书VIP,畅享更多权益</view>
|
<view v-else>办理电子书VIP,畅享更多权益</view>
|
||||||
</view>
|
</view>
|
||||||
<wd-button v-if="!vipInfoEbook?.length" plain type="primary" size="small" @click="goSubscribe">{{ $t('vip.openVip') }}</wd-button>
|
<wd-button v-if="!vipInfoEbook?.length" plain type="primary" size="small"
|
||||||
|
@click="goSubscribe">{{ $t('vip.openVip') }}</wd-button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -65,22 +70,28 @@
|
|||||||
<!-- 功能菜单列表 -->
|
<!-- 功能菜单列表 -->
|
||||||
<view class="menu-section">
|
<view class="menu-section">
|
||||||
<wd-cell-group border class="menu-list">
|
<wd-cell-group border class="menu-list">
|
||||||
<wd-cell v-for="item in menuItems" :key="item.id" :title="item.name" :label="item.desc" is-link @click="handleMenuClick(item)" />
|
<wd-cell v-for="item in menuItems" :key="item.id" :title="item.name" :label="item.desc" is-link
|
||||||
|
@click="handleMenuClick(item)">
|
||||||
|
<text v-if="item.hufenState" class="menu-list-hufen">{{hufenData.total ?? 0}}<text
|
||||||
|
style="margin-left: 6rpx;">湖分</text></text>
|
||||||
|
</wd-cell>
|
||||||
</wd-cell-group>
|
</wd-cell-group>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<visitor v-else></visitor>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import { useSysStore } from '@/stores/sys'
|
import { useSysStore } from '@/stores/sys'
|
||||||
import { getUserInfo, getVipInfo } from '@/api/modules/user'
|
import { getUserInfo, getVipInfo, getUserContributionData } from '@/api/modules/user'
|
||||||
import type { IVipInfo } from '@/types/user'
|
import type { IVipInfo } from '@/types/user'
|
||||||
import { getNotchHeight } from '@/utils/system'
|
import { getNotchHeight } from '@/utils/system'
|
||||||
import { parseTime } from '@/utils/index'
|
import { parseTime } from '@/utils/index'
|
||||||
import { t } from '@/utils/i18n'
|
import { t } from '@/utils/i18n'
|
||||||
import { onShow } from '@dcloudio/uni-app'
|
import { onShow } from '@dcloudio/uni-app'
|
||||||
|
import visitor from '@/pages/visitor/index.vue';
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const sysStore = useSysStore()
|
const sysStore = useSysStore()
|
||||||
@@ -140,7 +151,22 @@
|
|||||||
// desc: t('user.migrateSubtitle'),
|
// desc: t('user.migrateSubtitle'),
|
||||||
// type: 'pageJump'
|
// type: 'pageJump'
|
||||||
// }
|
// }
|
||||||
|
// {
|
||||||
|
// id: 7,
|
||||||
|
// name: t('user.certificate'),
|
||||||
|
// url: '/pages/user/certificate/index',
|
||||||
|
// type: 'pageJump'
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: t('user.iHufen'),
|
||||||
|
url: '/pages/user/hufen/index',
|
||||||
|
type: 'pageJump',
|
||||||
|
hufenState: true
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
// 湖分
|
||||||
|
const hufenData = ref('')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取平台信息
|
* 获取平台信息
|
||||||
@@ -161,6 +187,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户湖分
|
||||||
|
*/
|
||||||
|
const getHufen = async () => {
|
||||||
|
hufenData.value = await getUserContributionData()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跳转到设置页面
|
* 跳转到设置页面
|
||||||
*/
|
*/
|
||||||
@@ -243,11 +276,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
getData()
|
console.log(userInfo, 'userInfo');
|
||||||
|
if (userStore.token) {
|
||||||
|
getData()
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getPlatform()
|
console.log(userInfo, 'userInfo');
|
||||||
|
if (userStore.token) {
|
||||||
|
getPlatform()
|
||||||
|
getHufen()
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -255,7 +297,7 @@
|
|||||||
$theme-color: #54a966;
|
$theme-color: #54a966;
|
||||||
|
|
||||||
.user-page {
|
.user-page {
|
||||||
min-height: 100vh;
|
min-height: calc(100vh - 50px);
|
||||||
background-color: #f7faf9;
|
background-color: #f7faf9;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,6 +436,16 @@
|
|||||||
border-radius: 15rpx;
|
border-radius: 15rpx;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
|
.menu-list-hufen {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #007bff;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.chong_btn {
|
.chong_btn {
|
||||||
|
|||||||
@@ -3,10 +3,20 @@
|
|||||||
<!-- 自定义导航栏 -->
|
<!-- 自定义导航栏 -->
|
||||||
<nav-bar :title="$t('user.dataMigrate')"></nav-bar>
|
<nav-bar :title="$t('user.dataMigrate')"></nav-bar>
|
||||||
|
|
||||||
<view class="text-red-500 text-center mb-[20rpx]! font-bold">{{ $t('user.migrateWarning') }}</view>
|
<view v-if="!!migrateInfo.notMigration" class="text-center mb-[20rpx]!">
|
||||||
|
<view v-if="!!migrateInfo.alreadyMigration">{{ $t('user.alreadyMigrated') }}{{ migrateInfo.alreadyMigration }}</view>
|
||||||
|
<view>{{ $t('user.notMigration') }}<text class="font-bold">{{ migrateInfo.notMigration }}</text></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else class="text-center mb-[20rpx]! bg-white p-[20rpx] rounded-[10rpx] shadow-[0_4rpx_12rpx_rgba(0,0,0,0.05)]">
|
||||||
|
<wd-text :text="$t('user.migratedCompleted')" type="warning" />
|
||||||
|
<wd-text :text="migrateInfo.alreadyMigration" type="warning" bold />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="!!migrateInfo.notMigration" class="text-red-500 text-center mb-[20rpx]! font-bold">{{ $t('user.migrateWarning') }}</view>
|
||||||
|
|
||||||
<!-- 主要内容区域 -->
|
<!-- 主要内容区域 -->
|
||||||
<wd-form ref="migrateForm" :model="formData" :rules="rules" :label-width="120" class="migrate-card p-[10rpx]">
|
<wd-form v-if="!!migrateInfo.notMigration" ref="migrateForm" :model="formData" :rules="rules" :label-width="120" class="migrate-card p-[10rpx]">
|
||||||
<wd-cell-group border>
|
<wd-cell-group border>
|
||||||
<wd-input
|
<wd-input
|
||||||
v-model="formData.tel"
|
v-model="formData.tel"
|
||||||
@@ -60,22 +70,40 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { t } from '@/utils/i18n'
|
import { t } from '@/utils/i18n'
|
||||||
import { migrateUserData } from '@/api/modules/user'
|
import { migrateUserData, getUserMigrateInfo } from '@/api/modules/user'
|
||||||
import { useMessage } from '@/uni_modules/wot-design-uni'
|
import { useMessage } from '@/uni_modules/wot-design-uni'
|
||||||
|
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
|
||||||
|
const migrateInfo = ref({
|
||||||
|
alreadyMigration: '',
|
||||||
|
notMigration: ''
|
||||||
|
})
|
||||||
|
|
||||||
// 表单引用
|
// 表单引用
|
||||||
const migrateForm = ref()
|
const migrateForm = ref()
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
tel: '',
|
tel: '',
|
||||||
code: ''
|
code: '',
|
||||||
|
type: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 获取用户迁移信息
|
||||||
|
const getMigrateInfo = async () => {
|
||||||
|
const res = await getUserMigrateInfo()
|
||||||
|
migrateInfo.value.alreadyMigration = res.alreadyMigration
|
||||||
|
// migrateInfo.value.notMigration = res.notMigration
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
getMigrateInfo()
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 表单验证规则
|
// 表单验证规则
|
||||||
const rules = ref({
|
const rules = ref({
|
||||||
tel: [
|
tel: [
|
||||||
@@ -113,6 +141,7 @@ const handleSubmit = async () => {
|
|||||||
}
|
}
|
||||||
// 处理迁移
|
// 处理迁移
|
||||||
const submitMigrate = async () => {
|
const submitMigrate = async () => {
|
||||||
|
formData.value.type = migrateInfo.value.notMigration
|
||||||
await migrateUserData(formData.value)
|
await migrateUserData(formData.value)
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: t('user.migrateSuccess'),
|
title: t('user.migrateSuccess'),
|
||||||
|
|||||||
138
pages/visitor/index.vue
Normal file
138
pages/visitor/index.vue
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
<template>
|
||||||
|
<view class="visitor">
|
||||||
|
<view class="visitor-block">
|
||||||
|
<view style="display: flex;">
|
||||||
|
<image class="visitor_img" src="/static/logo.png" mode="aspectFil">
|
||||||
|
</image>
|
||||||
|
<text class="visitor-text" @click="gologin">立即登录</text>
|
||||||
|
</view>
|
||||||
|
<wd-cell-group border class="visitor-list">
|
||||||
|
<wd-cell v-for="item in menuItems" :title="item.name" is-link @click="handleMenuClick(item)">
|
||||||
|
</wd-cell>
|
||||||
|
</wd-cell-group>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<wd-action-sheet v-model="isShareSheetOpen" title="选择分享渠道" :panels="panels" @select="handleShare" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const menuItems = ref([
|
||||||
|
{
|
||||||
|
name: '分享APP'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '关于我们',
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
const isShareSheetOpen = ref(false)
|
||||||
|
|
||||||
|
const panels = ref([
|
||||||
|
{
|
||||||
|
iconUrl: '/static/contact-person.png',
|
||||||
|
title: '微信消息'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
iconUrl: '/static/moments.png',
|
||||||
|
title: '朋友圈'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// 打开分享菜单
|
||||||
|
const openShareSheet = () => {
|
||||||
|
isShareSheetOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择分享渠道后执行分享逻辑
|
||||||
|
const handleShare = (action) => {
|
||||||
|
console.log(action, 'action');
|
||||||
|
isShareSheetOpen.value = false // 关闭菜单
|
||||||
|
if (action.index == 0) {
|
||||||
|
// 分享到好友
|
||||||
|
uni.share({
|
||||||
|
provider: "weixin",
|
||||||
|
scene: "WXSceneSession",
|
||||||
|
type: 0,
|
||||||
|
href: '',
|
||||||
|
title: "吴门医述",
|
||||||
|
summary: "我正在使用吴门医述提升自己,赶紧跟我一起来体验吧!",
|
||||||
|
imageUrl: "static/icon/home_icon_logo.png",
|
||||||
|
success: function (res) {
|
||||||
|
console.log("success:" + JSON.stringify(res));
|
||||||
|
},
|
||||||
|
fail: function (err) {
|
||||||
|
console.log("fail:" + JSON.stringify(err));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (action.index == 1) {
|
||||||
|
// 分享到朋友圈
|
||||||
|
uni.share({
|
||||||
|
provider: "weixin",
|
||||||
|
scene: "WXSceneTimeline",
|
||||||
|
type: 0,
|
||||||
|
href: '',
|
||||||
|
title: "吴门医述",
|
||||||
|
summary: "我正在使用吴门医述提升自己,赶紧跟我一起来体验吧!",
|
||||||
|
imageUrl: "static/icon/home_icon_logo.png",
|
||||||
|
success: function (res) {
|
||||||
|
console.log("success:" + JSON.stringify(res));
|
||||||
|
},
|
||||||
|
fail: function (err) {
|
||||||
|
console.log("fail:" + JSON.stringify(err));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleMenuClick = (item : { name : string }) => {
|
||||||
|
if (item.name === '关于我们') {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/user/about/index'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
isShareSheetOpen.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const gologin = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/login/login'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.visitor {
|
||||||
|
background: #f4f7ff;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visitor-block {
|
||||||
|
padding: 40rpx 20rpx;
|
||||||
|
|
||||||
|
.visitor_img {
|
||||||
|
width: 150rpx;
|
||||||
|
height: 150rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visitor-text {
|
||||||
|
margin-top: 30rpx;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.visitor-list {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 15rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
BIN
static/contact-person.png
Normal file
BIN
static/contact-person.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/moments.png
Normal file
BIN
static/moments.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
@@ -8,6 +8,7 @@
|
|||||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
||||||
"Courier New", monospace;
|
"Courier New", monospace;
|
||||||
--color-red-500: oklch(63.7% 0.237 25.331);
|
--color-red-500: oklch(63.7% 0.237 25.331);
|
||||||
|
--color-white: #fff;
|
||||||
--spacing: 0.25rem;
|
--spacing: 0.25rem;
|
||||||
--text-xs: 0.75rem;
|
--text-xs: 0.75rem;
|
||||||
--text-xs--line-height: calc(1 / 0.75);
|
--text-xs--line-height: calc(1 / 0.75);
|
||||||
@@ -265,16 +266,25 @@
|
|||||||
.flex-wrap {
|
.flex-wrap {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
.rounded-\[10rpx\] {
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
.border {
|
.border {
|
||||||
border-style: var(--tw-border-style);
|
border-style: var(--tw-border-style);
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
.bg-white {
|
||||||
|
background-color: var(--color-white);
|
||||||
|
}
|
||||||
.p-0\! {
|
.p-0\! {
|
||||||
padding: calc(var(--spacing) * 0) !important;
|
padding: calc(var(--spacing) * 0) !important;
|
||||||
}
|
}
|
||||||
.p-\[10rpx\] {
|
.p-\[10rpx\] {
|
||||||
padding: 10rpx;
|
padding: 10rpx;
|
||||||
}
|
}
|
||||||
|
.p-\[20rpx\] {
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
.p-\[30rpx\] {
|
.p-\[30rpx\] {
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
}
|
}
|
||||||
@@ -337,6 +347,10 @@
|
|||||||
--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,);
|
||||||
}
|
}
|
||||||
|
.shadow-\[0_4rpx_12rpx_rgba\(0\,0\,0\,0\.05\)\] {
|
||||||
|
--tw-shadow: 0 4rpx 12rpx var(--tw-shadow-color, rgba(0,0,0,0.05));
|
||||||
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
}
|
||||||
.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);
|
||||||
|
|||||||
@@ -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