feat(login): 添加H5登录弹窗支持并集成jweixin-module

- 新增H5环境下的登录弹窗组件及逻辑
- 添加jweixin-module依赖用于微信相关功能
- 修改baseUrl配置为本地开发环境
- 优化登录组件代码结构和样式
This commit is contained in:
zzp 2025-09-09 15:46:49 +08:00
parent c6d8278f7d
commit cf3cd6e263
6 changed files with 69 additions and 138 deletions

7
package-lock.json generated
View File

@ -28,6 +28,7 @@
"echarts": "^5.6.0",
"js-cookie": "^3.0.5",
"js-md5": "^0.8.3",
"jweixin-module": "^1.6.0",
"pinia": "^2.0.36",
"qs": "^6.11.2",
"vue": "^3.2.45",
@ -9510,6 +9511,12 @@
"graceful-fs": "^4.1.6"
}
},
"node_modules/jweixin-module": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/jweixin-module/-/jweixin-module-1.6.0.tgz",
"integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w==",
"license": "ISC"
},
"node_modules/kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/kleur/-/kleur-3.0.3.tgz",

View File

@ -59,6 +59,7 @@
"echarts": "^5.6.0",
"js-cookie": "^3.0.5",
"js-md5": "^0.8.3",
"jweixin-module": "^1.6.0",
"pinia": "^2.0.36",
"qs": "^6.11.2",
"vue": "^3.2.45",

View File

@ -1,34 +1,17 @@
<template>
<view class="news-rank-list">
<u-skeleton
rows="5"
title
loading
style="margin-bottom: 30rpx"
v-if="loading"
></u-skeleton>
<u-skeleton rows="5" title loading style="margin-bottom: 30rpx" v-if="loading"></u-skeleton>
<view class="list" v-else>
<view
v-for="(item, index) in rankListLocal"
:key="index"
class="news-item"
@click="goDetail(item, 0)"
>
<view v-for="(item, index) in rankListLocal" :key="index" class="news-item" @click="goDetail(item, 0)">
<view class="rank-tag">
<view v-if="index == 0" class="rank-text-top3">
<image
src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/icon_top_1.png"
/>
<image src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/icon_top_1.png" />
</view>
<view v-else-if="index == 1" class="rank-text-top3">
<image
src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/icon_top_2.png"
/>
<image src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/icon_top_2.png" />
</view>
<view v-else-if="index == 2" class="rank-text-top3">
<image
src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/icon_top_3.png"
/>
<image src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/icon_top_3.png" />
</view>
<text class="rank-text" v-else>{{ index + 1 }}</text>
</view>
@ -37,56 +20,32 @@
<view class="news-content">
<text style="">
<text class="news-title">{{ item.title.slice(0, 3) }}</text>
<text :class="['news-title', isLogin ? '' : 'mohu']">{{
item.title.slice(3, item.title.length)
}}</text>
<text :class="['news-title', isLogin ? '' : 'mohu']">{{ item.title.slice(3, item.title.length) }}</text>
</text>
<text :class="['news-desc', isLogin ? '' : 'mohu']">{{
item.summary
}}</text>
<text :class="['news-desc', isLogin ? '' : 'mohu']">{{ item.summary }}</text>
<view :class="['news-meta', isLogin ? '' : 'mohu']">
<view
style="display: flex; justify-content: space-between; width: 100%"
>
<view style="display: flex; justify-content: space-between; width: 100%">
<view style="display: flex">
<text class="source">{{ item.source }}</text>
<text class="time">{{
dayjs(item.publish_time).format("YYYY-MM-DD HH:MM:ss")
}}</text>
<text class="time">{{ dayjs(item.publish_time).format("YYYY-MM-DD HH:MM:ss") }}</text>
</view>
<view class="r_option">
<image
class="option_icon"
src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/eye_icon%402x.png"
></image>
<image class="option_icon" src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/eye_icon%402x.png"></image>
<text class="option_text">{{ item.viewCount }}</text>
<image
class="option_icon"
src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/like_icon%402x.png"
></image>
<image class="option_icon" src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/like_icon%402x.png"></image>
<text class="option_text">{{ item.likeCount }}</text>
<image
class="option_icon"
src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/share_icon%402x.png"
></image>
<image class="option_icon" src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/share_icon%402x.png"></image>
<text class="option_text">{{ item.shareCount }}</text>
</view>
</view>
</view>
<view class="lock_view" v-if="!isLogin">
<image
class="lock_icon"
src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/lock_icon%402x.png"
>
</image>
<text class="lock_text"
>海外独家资讯内容<text style="color: #d13e3c">登录</text
>后可查阅全文</text
>
<image class="lock_icon" src="https://cankao.obs.cn-east-3.myhuaweicloud.com/mini/newmini/lock_icon%402x.png"> </image>
<text class="lock_text">海外独家资讯内容<text style="color: #d13e3c">登录</text>后可查阅全文</text>
</view>
</view>
</view>
@ -104,6 +63,7 @@ const isExp = ref(true);
const rankListLocal = ref([]);
const loading = ref(true);
const isLogin = ref(uni.getStorageSync("token"));
console.log(`🚀 ~ uni.getStorageSync("token"):`, uni.getStorageSync("token"));
watch(
() => isExp.value,
@ -139,28 +99,16 @@ watch(
let viewCount = 0;
let favCount = 0;
if (item.likeCount) {
likeCount =
item.likeCount > 10000
? Number(item.likeCount / 10000).toFixed(1) + "万"
: item.likeCount;
likeCount = item.likeCount > 10000 ? Number(item.likeCount / 10000).toFixed(1) + "万" : item.likeCount;
}
if (item.shareCount) {
shareCount =
item.shareCount > 10000
? Number(item.shareCount / 10000).toFixed(1) + "万"
: item.shareCount;
shareCount = item.shareCount > 10000 ? Number(item.shareCount / 10000).toFixed(1) + "万" : item.shareCount;
}
if (item.viewCount) {
viewCount =
item.viewCount > 10000
? Number(item.viewCount / 10000).toFixed(1) + "万"
: item.viewCount;
viewCount = item.viewCount > 10000 ? Number(item.viewCount / 10000).toFixed(1) + "万" : item.viewCount;
}
if (item.favCount) {
favCount =
item.favCount > 10000
? Number(item.favCount / 10000).toFixed(1) + "万"
: item.viewCount;
favCount = item.favCount > 10000 ? Number(item.favCount / 10000).toFixed(1) + "万" : item.viewCount;
}
rankListLocal.value.push({

View File

@ -1,56 +1,24 @@
<template>
<!-- <view class="loginPopup"> -->
<u-popup
class="loginPopup"
:show="props.show"
closeable
:mode="props.mode"
round="12"
:closeOnClickOverlay="false"
@close="handlePopupClose"
>
<u-popup class="loginPopup" :show="props.show" closeable :mode="props.mode" round="12" :closeOnClickOverlay="false" @close="handlePopupClose">
<view class="loginPopupContent">
<view class="loginTitle">登录后掌握更多优质财经内容</view>
<!-- 登录表单 -->
<view class="loginForm">
<u--form :model="state.loginForm" ref="uForm">
<u-form-item
style="padding: 0"
class="loginFormItem"
prop="userInfo.name"
borderBottom
ref="item1"
>
<u--input
class="loginFormInput"
placeholder="请输入您的手机号"
v-model="state.loginForm.phone"
border="none"
></u--input>
<u-form-item style="padding: 0" class="loginFormItem" prop="userInfo.name" borderBottom ref="item1">
<u--input class="loginFormInput" placeholder="请输入您的手机号" v-model="state.loginForm.phone" border="none"></u--input>
</u-form-item>
<u-form-item
class="loginFormItem"
prop="userInfo.name"
borderBottom
ref="item1"
>
<u--input
class="loginFormInput"
placeholder="请输入短信验证码"
v-model="state.loginForm.code"
border="none"
></u--input>
<u-form-item class="loginFormItem" prop="userInfo.name" borderBottom ref="item1">
<u--input class="loginFormInput" placeholder="请输入短信验证码" v-model="state.loginForm.code" border="none"></u--input>
<view class="getCode" @click="captcha">{{ codeText }}</view>
</u-form-item>
</u--form>
<u-button class="loginFormBtn" text="登录" @click="Login"></u-button>
</view>
<!-- 用户协议 -->
<view class="tips"
>登录即代表已经阅读并同意
<view class="userAgreement">用户协议</view></view
>
<view class="tips">登录即代表已经阅读并同意 <view class="userAgreement">用户协议</view></view>
</view>
</u-popup>
<!-- </view> -->
@ -61,11 +29,7 @@ import { reactive, ref } from "vue";
import { getCaptcha, login } from "@/api";
import { validatePhoneNumber } from "@/utils/util";
import { Session } from "@/utils/storage";
const emit = defineEmits([
"handlePopupClose",
"handlePopupSuccessCallback",
"handlePopupErrorCallback",
]);
const emit = defineEmits(["handlePopupClose", "handlePopupSuccessCallback", "handlePopupErrorCallback"]);
const props = defineProps({
//
@ -158,6 +122,10 @@ const Login = async () => {
uni.hideLoading();
Session.set("token", data.token);
Session.set("userPhone", data.phone);
uni.setStorageSync("token", data.token);
console.log(`🚀 ~ Login ~ uni.setStorageSync("token", data.token):`, uni.getStorageSync("token"));
uni.setStorageSync("userPhone", data.phone);
uni.showToast({
title: "登录成功",
icon: "success",

View File

@ -1,7 +1,7 @@
// const baseUrl = "http://192.168.31.25:8060/api";
// export const baseUrl = "http://127.0.0.1:8040/apih5";
export const baseUrl = "http://127.0.0.1:8040/apih5";
// export const baseUrl = "http://192.168.3.38:8040/apih5";
export const baseUrl = "https://cankao.cs.com.cn/mini";
// export const baseUrl = "https://cankao.cs.com.cn/mini";
export const baseUrlDataV = "https://cankao.cs.com.cn/zzck_datav";
// export const baseUrlDataV = "http://123.60.153.169:9995/zzck_datav";

View File

@ -9,12 +9,7 @@
<!-- 用户协议 -->
<view class="tips" @click="doChangeCheck">
<u-checkbox-group
v-model="checked"
placement="column"
activeColor="#e7303f"
@change="checkboxChange"
>
<u-checkbox-group v-model="checked" placement="column" activeColor="#e7303f" @change="checkboxChange">
<u-checkbox class="checkbox" shape="circle"></u-checkbox>
</u-checkbox-group>
@ -25,36 +20,35 @@
>
</view>
<button
v-if="checked && checked?.length > 0"
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
class="bottom_btn"
>
<!-- #ifdef MP-WEIXIN -->
<button v-if="checked && checked?.length > 0" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber" class="bottom_btn">
<view>
<text>立即进入</text>
</view>
</button>
<button v-else class="bottom_btn" @click="needCheck">
<view>
<text>立即进入</text>
</view>
</button>
<!-- #endif -->
<!-- #ifdef H5 -->
<button class="bottom_btn" @click="LoginShow = true">
<view>
<text>立即进入</text>
</view>
</button>
<!-- #endif -->
<LoginPopup :show="LoginShow" @handlePopupClose="handlePopupClose" @handlePopupSuccessCallback="handlePopupSuccessCallback" />
</view>
</template>
<script setup lang="ts">
import { onMounted, ref, reactive, watch, nextTick, onActivated } from "vue";
import {
onLaunch,
onShow,
onLoad,
onShareAppMessage,
onShareTimeline,
onUnload,
} from "@dcloudio/uni-app";
import { onLaunch, onShow, onLoad, onShareAppMessage, onShareTimeline, onUnload } from "@dcloudio/uni-app";
import { doWxAuth } from "@/api/index";
import LoginPopup from "@/components/loginPopup/index.vue";
import { onPullDownRefresh, onReachBottom } from "@dcloudio/uni-app";
import { useShareStore } from "@/stores/shareStore";
@ -174,6 +168,19 @@ function goUserAgreement() {
});
}
// login
const LoginShow = ref(false);
//
const handlePopupClose = () => {
LoginShow.value = false;
};
//
const handlePopupSuccessCallback = () => {
LoginShow.value = false;
// emit("onChange");
uni.navigateBack({});
};
//
onUnload(() => {
clearTimeout(timer.value);