feat(minihome): 实现首页tab切换功能并添加我的页面

- 在Tabbar组件中添加tabChange事件发射
- 修改minihome页面支持tab切换显示不同内容
- 新增mineMini组件作为我的页面
- 调整pages.json路由顺序
- 修复utils中header拼写错误
This commit is contained in:
34701892@qq.com 2025-08-13 13:21:40 +08:00
parent 557aa97a99
commit 761758accf
7 changed files with 411 additions and 41 deletions

View File

@ -2,7 +2,7 @@
<view class="mine"> <view class="mine">
<!-- 用户信息 --> <!-- 用户信息 -->
<view class="userContainer"> <view class="userContainer">
<u-avatar :src="avatarImg" size="60"></u-avatar> <u-avatar src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/avatar.png" size="60"></u-avatar>
<view class="userData"> <view class="userData">
<text class="phone">{{ <text class="phone">{{
!isLoginStatus !isLoginStatus
@ -33,26 +33,27 @@
<!-- 其他功能区 --> <!-- 其他功能区 -->
<view class="otherContainer" v-if="isLoginStatus"> <view class="otherContainer" v-if="isLoginStatus">
<u-cell-group :border="false"> <u-cell-group :border="false">
<u-cell title="已订阅栏目" :icon="vip" isLink :iconStyle="{ width: '46rpx', height: '32rpx', marginRight: '14rpx' }" <u-cell title="已订阅栏目" icon="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/vip.png" isLink
:titleStyle="{ :iconStyle="{ width: '46rpx', height: '32rpx', marginRight: '14rpx' }" :titleStyle="{
fontSize: '32rpx', fontSize: '32rpx',
color: '#333333', color: '#333333',
}" @click="handleClick(-1)"> }" @click="handleClick(-1)">
</u-cell> </u-cell>
<u-cell title="我的收藏" :icon="star" isLink :iconStyle="{ width: '40rpx', height: '40rpx', marginRight: '20rpx' }" <u-cell title="我的收藏" icon="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/star.png" isLink
:titleStyle="{ :iconStyle="{ width: '40rpx', height: '40rpx', marginRight: '20rpx' }" :titleStyle="{
fontSize: '32rpx', fontSize: '32rpx',
color: '#333333', color: '#333333',
}" @click="handleClick(0)"> }" @click="handleClick(0)">
</u-cell> </u-cell>
<u-cell title="我喜欢的" :icon="like" isLink :iconStyle="{ width: '40rpx', height: '40rpx', marginRight: '20rpx' }" <u-cell title="我喜欢的" icon="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/like.png" isLink
:titleStyle="{ :iconStyle="{ width: '40rpx', height: '40rpx', marginRight: '20rpx' }" :titleStyle="{
fontSize: '32rpx', fontSize: '32rpx',
color: '#333333', color: '#333333',
}" @click="handleClick(1)"> }" @click="handleClick(1)">
</u-cell> </u-cell>
<!-- title="浏览记录" :icon="time" :border="false" --> <!-- title="浏览记录" :icon="time" :border="false" -->
<u-cell :icon="time" isLink :iconStyle="{ width: '40rpx', height: '40rpx', marginRight: '20rpx' }" :titleStyle="{ <u-cell icon="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/time.png" isLink
:iconStyle="{ width: '40rpx', height: '40rpx', marginRight: '20rpx' }" :titleStyle="{
fontSize: '32rpx', fontSize: '32rpx',
color: '#333333', color: '#333333',
}" @click="handleClick(2)"> }" @click="handleClick(2)">
@ -90,14 +91,6 @@ import { onMounted, ref } from "vue";
import { onPullDownRefresh, onShow } from "@dcloudio/uni-app"; import { onPullDownRefresh, onShow } from "@dcloudio/uni-app";
import { Session } from "@/utils/storage"; import { Session } from "@/utils/storage";
import LoginPopup from "@/components/loginPopup/index.vue"; import LoginPopup from "@/components/loginPopup/index.vue";
import avatarImg from "https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/avatar.png";
import column from "https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/column.png";
import article from "https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/article.png";
import balance from "https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/balance.png";
import star from "https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/star.png";
import like from "https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/like.png";
import time from "https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/time.png";
import vip from "https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/vip.png";
import { useShareStore } from "@/stores/shareStore"; import { useShareStore } from "@/stores/shareStore";
const stores = useShareStore(); const stores = useShareStore();
const curPages = getCurrentPages(); const curPages = getCurrentPages();

371
src/components/mineMini.vue Normal file
View File

@ -0,0 +1,371 @@
<template>
<view class="mine">
<!-- 用户信息 -->
<view class="userContainer">
<u-avatar src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/avatar.png" size="60"></u-avatar>
<view class="userData">
<text class="phone">{{
!isLoginStatus
? "未登录用户"
: maskPhoneNumber()
}}</text>
<!-- <view class="setUserData">
编辑我的个人资料
<u-icon size="12" name="arrow-right"></u-icon>
</view> -->
</view>
</view>
<!-- 订阅模块 旧UI版本 -->
<!-- <view class="subscribeContainer">
<view class="subTitle">我的订阅</view>
<u-grid :border="false" col="5">
<u-grid-item v-for="(listItem, listIndex) in state.list" :key="listIndex">
<view class="gridImg">
<image :src="listItem.imgurl" class="img"></image>
</view>
<text class="gridText">{{ listItem.title }}</text>
</u-grid-item>
</u-grid>
</view> -->
<!-- 其他功能区 -->
<view class="otherContainer" v-if="isLoginStatus">
<u-cell-group :border="false">
<u-cell title="已订阅栏目" icon="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/vip.png" isLink
:iconStyle="{ width: '46rpx', height: '32rpx', marginRight: '14rpx' }" :titleStyle="{
fontSize: '32rpx',
color: '#333333',
}" @click="handleClick(-1)">
</u-cell>
<u-cell title="我的收藏" icon="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/star.png" isLink
:iconStyle="{ width: '40rpx', height: '40rpx', marginRight: '20rpx' }" :titleStyle="{
fontSize: '32rpx',
color: '#333333',
}" @click="handleClick(0)">
</u-cell>
<u-cell title="我喜欢的" icon="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/like.png" isLink
:iconStyle="{ width: '40rpx', height: '40rpx', marginRight: '20rpx' }" :titleStyle="{
fontSize: '32rpx',
color: '#333333',
}" @click="handleClick(1)">
</u-cell>
<!-- title="浏览记录" :icon="time" :border="false" -->
<u-cell icon="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/time.png" isLink
:iconStyle="{ width: '40rpx', height: '40rpx', marginRight: '20rpx' }" :titleStyle="{
fontSize: '32rpx',
color: '#333333',
}" @click="handleClick(2)">
<template #title>
<view class="recordText">
<text style="font-size: 32rpx">浏览记录</text>
<view class="tips">保存近3个月的浏览记录</view>
</view>
</template>
</u-cell>
</u-cell-group>
</view>
<!-- 未登录的状态 -->
<view v-else class="notLogin">
<view class="notLoginImg"></view>
<view class="notLoginText">登录后查看内容哦~</view>
</view>
<!-- 退出登录的按钮 -->
<view class="loginOut" :class="!isLoginStatus && 'loginBtn'">
<u-button type="danger" size="large" @click="loginBtnStatus">{{
!isLoginStatus ? "点击登录" : "退出登录"
}}</u-button>
</view>
<!-- 登录弹框 -->
<LoginPopup :show="LoginShow" @handlePopupClose="handlePopupClose"
@handlePopupSuccessCallback="handlePopupSuccessCallback" @handlePopupErrorCallback="handlePopupErrorCallback" />
</view>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { onPullDownRefresh, onShow } from "@dcloudio/uni-app";
import { Session } from "@/utils/storage";
import LoginPopup from "@/components/loginPopup/index.vue";
import { useShareStore } from "@/stores/shareStore";
const stores = useShareStore();
const curPages = getCurrentPages();
const isLoginStatus = ref(false);
// login
const LoginShow = ref(false);
onMounted(() => {
console.log("🚀 ~ uni.getStorageSync('token'):", uni.getStorageSync('token'))
if (uni.getStorageSync('token')) {
isLoginStatus.value = true;
}
});
// *
const maskPhoneNumber = (phoneNumber: string) => {
if (!phoneNumber && uni.getStorageSync('userPhone')) {
phoneNumber = uni.getStorageSync('userPhone')
}
if (phoneNumber) {
return phoneNumber.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
} else {
return "未登录用户";
}
};
//
const handlePopupClose = () => {
LoginShow.value = false;
};
//
const handlePopupSuccessCallback = () => {
isLoginStatus.value = true;
};
//
const handlePopupErrorCallback = () => {
console.log("登录失败");
};
//
const loginBtnStatus = () => {
if (isLoginStatus.value) {
// 退
loginOut();
} else {
LoginShow.value = true;
}
};
// 退
const loginOut = () => {
uni.showToast({
title: "退出登录",
icon: "none",
duration: 1500,
});
// cookie
Session.clear();
uni.removeStorageSync("subStatus");
uni.removeStorageSync("tabValue");
uni.reLaunch({
url: "/pages/login/index",
});
};
const handleClick = (val: number) => {
if (val === -1) {
uni.navigateTo({
url: "/pages/subscribed/index",
});
} else {
uni.navigateTo({
url: `/pages/bookmark/index?tabs=${val}`,
});
}
};
const wxShare = () => {
let link = stores.redirectUrl;
let path = curPages[curPages.length - 1].route;
let query = encodeURIComponent(
JSON.stringify({
tabIndex: 2,
})
);
link += `?path=${path}`;
const shareData = {
title: `中证参考`,
desc: "天下事 秒知道",
link: link,
imgUrl: "https://cankao.cs.com.cn/static/share-default.jpg",
};
console.log("output >>>>> shareData", shareData);
stores.initWxConfig(shareData);
};
onShow(() => {
wxShare();
});
onPullDownRefresh(() => {
uni.stopPullDownRefresh();
});
</script>
<style lang="scss" scoped>
.mine {
min-height: calc(100vh - 130rpx);
background-color: #f5f5f5;
// position: relative;
position: relative;
font-family: "SourceHanSansCN-Medium";
//
.userContainer {
background-color: #fff;
box-sizing: border-box;
padding: 90rpx 45rpx 45rpx 45rpx;
display: flex;
.userData {
display: flex;
align-items: center;
flex-wrap: wrap;
width: 216rpx;
margin-left: 40rpx;
.phone {
// font-size: 32rpx;
font-size: var(--h1-font-size);
}
.setUserData {
display: flex;
align-items: center;
// font-size: 24rpx;
font-size: var(--h4-font-size);
color: rgba(51, 51, 51, 0.6);
}
}
}
//
.subscribeContainer {
background-color: #fff;
margin: 30rpx 20rpx;
padding: 21rpx 36rpx;
box-sizing: border-box;
border-radius: 8rpx;
.subTitle {
// font-size: 32rpx;
font-size: var(--h1-font-size);
color: #333;
margin-bottom: 30rpx;
font-weight: bold;
}
::v-deep {
.u-grid-item {
margin-right: 30rpx;
}
}
.gridImg {
width: 96rpx;
height: 96rpx;
border-radius: 16rpx;
background-color: #fff0d5;
margin-bottom: 15rpx;
display: flex;
align-items: center;
justify-content: center;
.img {
width: 64rpx;
height: 64rpx;
}
}
.gridText {
// font-size: 24rpx;
font-size: var(--h4-font-size);
color: #333;
}
}
//
.otherContainer {
background-color: #fff;
margin: 30rpx 20rpx;
box-sizing: border-box;
border-radius: 8rpx;
.recordText {
display: flex;
align-items: center;
.tips {
// font-size: 24rpx;
font-size: var(--h4-font-size);
color: rgba(51, 51, 51, 0.6);
padding-left: 21rpx;
font-family: "SourceHanSansCN-Regular";
}
}
}
.notLogin {
margin: 120rpx auto 21rpx auto;
box-sizing: border-box;
// background-color: red;
display: flex;
flex-wrap: wrap;
justify-content: center;
font-family: "SourceHanSansCN-Regular";
position: absolute;
bottom: 500rpx;
left: 50%;
transform: translateX(-50%);
.notLoginImg {
width: 278rpx;
height: 220rpx;
// border: 1px solid;
background-image: url(https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/images/notLogin.png);
background-size: cover;
}
.notLoginText {
width: 100%;
text-align: center;
// font-size: 32rpx;
font-size: var(--h1-font-size);
color: #afafaf;
margin-top: 21rpx;
}
}
// 退
.loginOut {
width: 600rpx;
height: 100rpx;
background-color: #fff;
box-sizing: border-box;
border-radius: 20rpx;
border: 4rpx solid #e7303f;
// font-size: 32rpx;
font-size: var(--h1-font-size);
color: #e7303f;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: 240rpx;
left: 50%;
transform: translateX(-50%);
font-family: "SourceHanSansCN-Regular";
&.loginBtn {
width: 256rpx;
height: 100rpx;
border-radius: 70rpx;
color: #fff;
background-color: #e7303f;
bottom: 390rpx;
}
}
}
</style>

View File

@ -23,10 +23,13 @@
<script setup> <script setup>
import { ref, onMounted, onUnmounted, reactive } from "vue"; import { ref, onMounted, onUnmounted, reactive } from "vue";
const emit = defineEmits(["tabChange"]);
const tabIndex = ref(0); const tabIndex = ref(0);
function tabChange(index) { function tabChange(index) {
tabIndex.value = index; tabIndex.value = index;
emit("tabChange", index);
} }
onMounted(async () => { }); onMounted(async () => { });

View File

@ -12,6 +12,9 @@
{ {
"path": "pages/realtimeInfo/index" "path": "pages/realtimeInfo/index"
}, },
{
"path": "pages/bookmark/index"
},
{ {
"path": "pages/login/index" "path": "pages/login/index"
}, },
@ -22,6 +25,9 @@
"bounce": "none" "bounce": "none"
} }
}, },
{
"path": "pages/subscribed/index"
},
{ {
"path": "pages/mine/index" "path": "pages/mine/index"
}, },
@ -46,12 +52,6 @@
{ {
"path": "pages/worldlyAffairs/index" "path": "pages/worldlyAffairs/index"
}, },
{
"path": "pages/subscribed/index"
},
{
"path": "pages/bookmark/index"
},
{ {
"path": "pages/realtimeInfo/rankDetail" "path": "pages/realtimeInfo/rankDetail"
}, },

View File

@ -3,26 +3,23 @@
<view class="all"> <view class="all">
<Navbar title="中证参考" :hasBack="false"></Navbar> <Navbar title="中证参考" :hasBack="false"></Navbar>
<RankListMini v-if="tabIndex == 0" :newsList="newsList"></RankListMini>
<RankListMini :newsList="newsList"></RankListMini> <MineMini v-if="tabIndex == 1"></MineMini>
<Tabbar @tabChange="tabChange"></Tabbar>
<tabbar></tabbar>
</view> </view>
</template> </template>
<script setup> <script setup>
import { ref, onMounted, onUnmounted, reactive } from "vue"; import { ref, onMounted, defineAsyncComponent, reactive } from "vue";
import tabbar from "@/components/mini/Tabbar.vue"; import Tabbar from "@/components/mini/Tabbar.vue";
import Navbar from '@/components/mini/Navbar.vue' import Navbar from '@/components/mini/Navbar.vue'
import RankListMini from "@/components/RankListMini.vue"; import RankListMini from "@/components/RankListMini.vue";
// const Mine = defineAsyncComponent(() => import("@/components/mine.vue"));
import MineMini from "@/components/mineMini.vue";
import { import {
getindustryCount,
getConceptCount,
getTopNews, getTopNews,
getTopIndustry_d,
getTopConcept_d,
getNews_cnt_d,
newsInfoScore,
} from "@/api/newsInfo"; } from "@/api/newsInfo";
const newsList = ref([]); const newsList = ref([]);
@ -34,6 +31,12 @@ async function getNewsList() {
const tabIndex = ref(0); const tabIndex = ref(0);
function tabChange(index) { function tabChange(index) {
tabIndex.value = index; tabIndex.value = index;
switch (index) {
case 0:
getNewsList()
break;
}
} }
onMounted(async () => { onMounted(async () => {

View File

@ -47,8 +47,8 @@ Request.setConfig((config: any) => {
// config.baseURL = "http://127.0.0.1:8082"; // config.baseURL = "http://127.0.0.1:8082";
if (uni.getStorageSync("token")) { if (uni.getStorageSync("token")) {
// config.header["Authorization"] = "Bearer " + uni.getStorageSync("token"); // config.header["Authorization"] = "Bearer " + uni.getStorageSync("token");
config.headers!["auth-token"] = uni.getStorageSync("token"); config.header!["auth-token"] = uni.getStorageSync("token");
config.headers!["phone"] = uni.getStorageSync("token"); config.header!["phone"] = uni.getStorageSync("token");
} }
return config; return config;

View File

@ -47,8 +47,8 @@ Request.setConfig((config: any) => {
// config.baseURL = "http://127.0.0.1:8082"; // config.baseURL = "http://127.0.0.1:8082";
if (uni.getStorageSync("token")) { if (uni.getStorageSync("token")) {
// config.header["Authorization"] = "Bearer " + uni.getStorageSync("token"); // config.header["Authorization"] = "Bearer " + uni.getStorageSync("token");
config.headers!["auth-token"] = uni.getStorageSync("token"); config.header!["auth-token"] = uni.getStorageSync("token");
config.headers!["phone"] = uni.getStorageSync("token"); config.header!["phone"] = uni.getStorageSync("token");
} }
return config; return config;