更新:游客模式、我的湖分、我的证书

This commit is contained in:
2025-12-09 14:28:02 +08:00
parent 79aa8e3fe6
commit 66b004d6bf
18 changed files with 702 additions and 60 deletions

58
App.vue
View File

@@ -1,29 +1,55 @@
<script>
// #ifdef APP-PLUS
import update from "@/uni_modules/uni-upgrade-center-app/utils/check-update";
// #endif
export default {
onLaunch: function() {
console.log('App Launch')
import { useUserStore } from '@/stores/user'
export default {
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
update();
// #endif
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
},
onTabItemTap: function() {
console.log('点击了');
}
}
</script>
<style lang="scss">
@import "@/style/tailwind.css";
@import "@/style/ui.scss";
@import "@/style/tailwind.css";
@import "@/style/ui.scss";
.container {
padding: 15px;
}
.container {
padding: 15px;
}
</style>

View File

@@ -7,8 +7,8 @@ export const ENV = process.env.NODE_ENV || 'development';
*/
const BASE_URL_MAP = {
development: {
// MAIN: 'http://192.168.110.100:9300/pb/', // 张川川
MAIN: 'https://global.nuttyreading.com/', // 线上
MAIN: 'http://192.168.110.100:9300/pb/', // 张川川
//MAIN: 'https://global.nuttyreading.com/', // 线上
// PAYMENT: 'https://dev-pay.example.com', // 暂时用不到
// CDN: 'https://cdn-dev.example.com', // 暂时用不到
},

View File

@@ -2,6 +2,9 @@
import { mainClient } from '@/api/clients/main'
import type { IApiResponse } from '@/api/types'
import type { IAgreement } from '@/types/user'
import { useUserStore } from '@/stores/user'
export const commonApi = {
/**
@@ -36,8 +39,9 @@ export const commonApi = {
* @returns 消息列表
*/
getMessageList(isBook: number, isMedical: number, isSociology: number) {
const userStore = useUserStore()
return mainClient.request<IMessageListResponse>({
url: 'common/message/listByPage',
url: userStore.token ? 'common/message/listByPage' : '/visitor/listByPage',
method: 'POST',
data: { isBook, isMedical, isSociology }
})

View File

@@ -14,6 +14,9 @@ import type {
} from '@/types/course'
import type { ISearchRequest, ISearchResponse } from '@/types/search'
import type { ICommentListResponse, IAddCommentResponse, IComment } from '@/types/comment'
import { useUserStore } from '@/stores/user'
const client = createRequestClient({ baseURL: SERVICE_MAP.MAIN })
@@ -57,8 +60,9 @@ export const courseApi = {
page: number,
limit: number
}) {
const userStore = useUserStore()
return client.request<IMarketCourseListResponse>({
url: 'medical/home/getMarketCourseList',
url: userStore.token ? 'medical/home/getMarketCourseList' : 'visitor/getMarketCourseList',
method: 'POST',
data
})

View File

@@ -7,6 +7,8 @@ import type {
IMarketCourseListResponse,
ICourseMedicalLabelsResponse
} from '@/types/course'
import { useUserStore } from '@/stores/user'
const client = createRequestClient({ baseURL: SERVICE_MAP.MAIN })
@@ -20,8 +22,9 @@ export const courseSubjectClassificationApi = {
* @returns 分类数据
*/
getCourseMedicalTree() {
const userStore = useUserStore()
return client.request<ICourseCategoryResponse>({
url: 'medical/home/getCourseMedicalTree',
url: userStore.token ? 'medical/home/getCourseMedicalTree' : '/visitor/getCourseMedicalTree',
method: 'POST',
data: {}
})

View File

@@ -314,3 +314,31 @@ export async function migrateUserData(data: { tel: string, code: string }) {
})
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
}

View File

@@ -227,7 +227,11 @@
"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.",
"instruction4": "If you encounter any issues, please contact customer service for assistance.",
"closeWindow": "Close the payment pop-up window"
"closeWindow": "Close the payment pop-up window",
"certificate": "My certificate",
"iHufen": "My lake",
"hufenRecord": "Lake division record",
"hufen": "Hufen"
},
"book": {
"title": "My Books",

View File

@@ -228,7 +228,11 @@
"instruction2": "数据迁移完成后旧账号数据将被清空已购买的天医币、积分、课程、电子书、VIP、证书、湖分将转移到当前账号。",
"instruction3": "迁移过程可能需要几分钟时间,请耐心等待。",
"instruction4": "如遇到问题,请联系客服获取帮助。",
"closeWindow": "关闭支付弹窗"
"closeWindow": "关闭支付弹窗",
"certificate": "我的证书",
"iHufen": "我的湖分",
"hufenRecord": "湖分记录",
"hufen": "湖分"
},
"book": {
"title": "我的书单",

View File

@@ -67,6 +67,24 @@
"navigationBarTitleText": "%user.feedback%",
"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",
"style": {
@@ -219,6 +237,11 @@
"animationDuration": 200
}
}
}, {
"path": "pages/visitor/index",
"style": {
"navigationStyle": "custom"
}
}
],
"tabBar": {

View File

@@ -211,7 +211,9 @@ import { commonApi } from '@/api/modules/common'
import { getNotchHeight } from '@/utils/system'
// import { onPageJump } from '@/utils'
import type { IMedicalTag, ICourse, INews } from '@/types/course'
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
const { t } = useI18n()
// 系统信息
@@ -239,18 +241,21 @@ const selectedFirstLevel = ref<number>('医学') // 当前选中的一级分类
* 学科点击处理
*/
const handleFirstLevelClick = (item: string) => {
selectedFirstLevel.value = item
switch (item) {
case '医学':
getMedicalTags()
break
case '心理学':
getSoulCateList()
break
case '国学':
getSociologyCateList()
break
}
getPrompt()
if(!userStore.token) return
selectedFirstLevel.value = item
switch (item) {
case '医学':
getMedicalTags()
break
case '心理学':
getSoulCateList()
break
case '国学':
getSociologyCateList()
break
}
}
/**
* 医学
@@ -326,15 +331,19 @@ const getSociologyCateList = async () => {
* 终极分类点击处理
*/
const curseClickJump = (item: IMedicalTag) => {
uni.navigateTo({
url: `/pages/course/list/category?id=${item.id}&title=${item.title}&pid=${item.pid}&subject=${selectedFirstLevel.value}`
})
getPrompt()
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) => {
getPrompt()
if(!userStore.token) return
let targetUrl = url
if (id !== undefined) {
targetUrl += `?id=${id}`
@@ -381,9 +390,12 @@ const getNewsList = async () => {
* 新闻点击处理
*/
const newsClick = (item: INews) => {
uni.navigateTo({
url: `/pages/news/details?newsId=${item.id}&url=${item.url}&type=${item.type}`
})
getPrompt()
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 () => {
getLearnCourse()
getMedicalTags()
getTryListenList()
getNewsList()
if(userStore.token){
getLearnCourse()
}
getMedicalTags()
getTryListenList()
getNewsList()
}
/**
* 页面挂载
*/
onMounted(() => {
if(!userStore.token) {
uni.navigateTo({
url: '/pages/login/login'
});
}
// 重置分类索引
currentIndex.value = 0
// 请求所有数据
requestAll()
console.log('进来了2');
})
/**
* 页面显示
*/
onShow(() => {
console.log('进来了1');
// 检查是否有固定的分类选择状态
const fixed = uni.getStorageSync('fixed')
if (fixed && currentItem.value) {

View File

@@ -115,11 +115,11 @@
</view>
<!-- 游客体验 -->
<!-- <view class="youke-l">
<view @click="onPageJump('/pages/visitor/visitor')">
<view class="youke-l">
<view @click="onPageJump('/pages/course/index')">
{{ $t('login.noLogin') }}
</view>
</view> -->
</view>
</view>
<!-- 用户协议弹窗 -->
@@ -399,7 +399,7 @@ const yszc = () => {
* 页面跳转
*/
const onPageJump = (url: string) => {
uni.navigateTo({
uni.switchTab({
url: url,
})
}

View 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>

View 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>

View 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>

View File

@@ -1,5 +1,5 @@
<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">
<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-content">
<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>
<wd-button v-if="vipInfo?.length > 0" plain type="primary" size="small" @click="goCourseVipSub">{{ $t('vip.renewal') }}</wd-button>
<wd-button v-else plain type="primary" size="small" @click="goCourseVipSub">{{ $t('vip.openVip') }}</wd-button>
<wd-button v-if="vipInfo?.length > 0" plain type="primary" size="small"
@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 class="vip-card-content">
<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>
<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>
@@ -65,22 +70,28 @@
<!-- 功能菜单列表 -->
<view class="menu-section">
<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>
</view>
</view>
<visitor v-else></visitor>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useUserStore } from '@/stores/user'
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 { getNotchHeight } from '@/utils/system'
import { parseTime } from '@/utils/index'
import { t } from '@/utils/i18n'
import { onShow } from '@dcloudio/uni-app'
import visitor from '@/pages/visitor/index.vue';
const userStore = useUserStore()
const sysStore = useSysStore()
@@ -140,7 +151,22 @@
// desc: t('user.migrateSubtitle'),
// 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(() => {
getData()
console.log(userInfo, 'userInfo');
if (userStore.token) {
getData()
}
})
onMounted(() => {
getPlatform()
console.log(userInfo, 'userInfo');
if (userStore.token) {
getPlatform()
getHufen()
}
})
</script>
@@ -394,6 +436,16 @@
border-radius: 15rpx;
overflow: hidden;
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 {

138
pages/visitor/index.vue Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/moments.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB