feat: auth

This commit is contained in:
2025-09-07 13:32:25 +08:00
parent 1d5f227a72
commit 5a7a40bd41
13 changed files with 144 additions and 99 deletions

View File

@@ -1,11 +1,8 @@
import { Component, ReactNode } from 'react' import { Component, ReactNode } from 'react'
import Taro from '@tarojs/taro';
import './nutui-theme.scss' import './nutui-theme.scss'
import './app.scss' import './app.scss'
import { useDictionaryStore } from './store/dictionaryStore' import { useDictionaryStore } from './store/dictionaryStore'
import { useGlobalStore } from './store/global' import { useGlobalStore } from './store/global'
import { check_login_status } from './services/loginService';
// import { getNavbarHeight } from "@/utils/getNavbarHeight"; // import { getNavbarHeight } from "@/utils/getNavbarHeight";
@@ -18,13 +15,6 @@ class App extends Component<AppProps> {
onLaunch() { onLaunch() {
console.log('小程序启动,初始化逻辑写这里') console.log('小程序启动,初始化逻辑写这里')
// 已经登录过就跳转到 列表页
let is_login = check_login_status()
if (is_login) {
Taro.redirectTo({
url: '/pages/list/index'
})
}
} }
componentDidMount() { componentDidMount() {

View File

@@ -0,0 +1,51 @@
import React, { useEffect, useState } from 'react'
import Taro, { useDidShow } from '@tarojs/taro'
import { View } from '@tarojs/components'
import { check_login_status } from '@/services/loginService'
export function getCurrentFullPath(): string {
const pages = Taro.getCurrentPages()
const currentPage = pages.at(-1)
if (currentPage) {
const route = currentPage.route
const options = currentPage.options || {}
const query = Object.keys(options)
.map(key => `${key}=${options[key]}`)
.join('&')
return query ? `/${route}?${query}` : `/${route}`
}
return ''
}
export default function withAuth<P extends object>(WrappedComponent: React.ComponentType<P>) {
const ComponentWithAuth: React.FC<P> = (props: P) => {
const [authed, setAuthed] = useState(false)
useEffect(() => {
const is_login = check_login_status()
setAuthed(is_login)
if (!is_login) {
const currentPage = getCurrentFullPath()
Taro.redirectTo({
url: `/pages/login/index/index${
currentPage ? `?redirect=${currentPage}` : ''
}`,
})
}
}, [])
if (!authed) {
return <View /> // 空壳,避免 children 渲染出错
}
return <WrappedComponent {...props} />
}
return ComponentWithAuth
}

View File

@@ -15,15 +15,16 @@ import CommonDialog from './CommonDialog'
import PublishMenu from './PublishMenu/PublishMenu' import PublishMenu from './PublishMenu/PublishMenu'
import UploadCover from './UploadCover' import UploadCover from './UploadCover'
import EditModal from './EditModal/index' import EditModal from './EditModal/index'
import withAuth from './Auth'
export { export {
ActivityTypeSwitch, ActivityTypeSwitch,
TextareaTag, TextareaTag,
FormSwitch, FormSwitch,
ImageUpload, ImageUpload,
Range, Range,
NumberInterval, NumberInterval,
TimeSelector, TimeSelector,
TitleTextarea, TitleTextarea,
CommonPopup, CommonPopup,
DateTimePicker, DateTimePicker,
@@ -33,6 +34,7 @@ import EditModal from './EditModal/index'
CommonDialog, CommonDialog,
PublishMenu, PublishMenu,
UploadCover, UploadCover,
EditModal EditModal,
withAuth,
} }

View File

@@ -1,30 +1,24 @@
import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react' import React, { useState, useRef, useImperativeHandle, forwardRef } from 'react'
import { View, Text, Button, Swiper, SwiperItem, Image, Map, ScrollView } from '@tarojs/components' import { View, Text, Image, Map, ScrollView } from '@tarojs/components'
import { Cell, Avatar, Progress, Popover } from '@nutui/nutui-react-taro' import { Avatar, Popover } from '@nutui/nutui-react-taro'
import Taro, { useRouter, useShareAppMessage, useShareTimeline, useDidShow } from '@tarojs/taro' import Taro, { useRouter, useShareAppMessage, useShareTimeline, useDidShow } from '@tarojs/taro'
import dayjs, { locale } from 'dayjs' import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn' import 'dayjs/locale/zh-cn'
// 导入API服务 // 导入API服务
import DetailService, { MATCH_STATUS} from '../../services/detailService' import { CommonPopup, withAuth } from '@/components'
import { updateUserProfile, get_user_info } from '../../services/loginService' import DetailService, { MATCH_STATUS} from '@/services/detailService'
import { getCurrentLocation, calculateDistance } from '../../utils/locationUtils' import { getCurrentLocation, calculateDistance } from '@/utils/locationUtils'
import { import {
useUserInfo, useUserInfo,
useUserActions, useUserActions,
} from '../../store/userStore' } from '@/store/userStore'
import img from '../../config/images' import img from '@/config/images'
import { getTextColorOnImage } from '../../utils' // import { getTextColorOnImage } from '../../utils'
import './index.scss' import './index.scss'
import { CommonPopup } from '@/components'
dayjs.locale('zh-cn') dayjs.locale('zh-cn')
const images = [ // 将·作为连接符插入到标签文本之间
'http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/1a35ebbf-2361-44da-b338-7608561d0b31.png',
'http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/cf5a82ba-90af-4138-a1b3-9119adcde9e0.png',
'http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/49d7cdf0-b03c-4a0f-91c6-e7778080cfcd.png'
]
function insertDotInTags(tags: string[]) { function insertDotInTags(tags: string[]) {
return tags.join('-·-').split('-') return tags.join('-·-').split('-')
} }
@@ -39,35 +33,35 @@ const SharePopup = forwardRef(({ id, from }: { id: string, from: string }, ref)
} }
})) }))
function handleShareToWechat() { // function handleShareToWechat() {
useShareAppMessage(() => { // useShareAppMessage(() => {
return { // return {
title: '分享', // title: '分享',
path: `/pages/detail/index?id=${id}&from=${from}`, // path: `/pages/detail/index?id=${id}&from=share`,
} // }
}) // })
} // }
function handleShareToWechatMoments() { // function handleShareToWechatMoments() {
useShareTimeline(() => { // useShareTimeline(() => {
return { // return {
title: '分享', // title: '分享',
path: `/pages/detail/index?id=${id}&from=${from}`, // path: `/pages/detail/index?id=${id}&from=share`,
} // }
}) // })
} // }
function handleSaveToLocal() { // function handleSaveToLocal() {
Taro.saveImageToPhotosAlbum({ // Taro.saveImageToPhotosAlbum({
filePath: images[0], // filePath: images[0],
success: () => { // success: () => {
Taro.showToast({ title: '保存成功', icon: 'success' }) // Taro.showToast({ title: '保存成功', icon: 'success' })
}, // },
fail: () => { // fail: () => {
Taro.showToast({ title: '保存失败', icon: 'none' }) // Taro.showToast({ title: '保存失败', icon: 'none' })
}, // },
}) // })
} // }
return ( return (
<CommonPopup <CommonPopup
@@ -78,18 +72,7 @@ const SharePopup = forwardRef(({ id, from }: { id: string, from: string }, ref)
style={{ minHeight: '100px' }} style={{ minHeight: '100px' }}
> >
<View catchMove className='share-popup-content'> <View catchMove className='share-popup-content'>
<View onClick={handleShareToWechat}>
<Image src={img.ICON_DETAIL_SHARE} />
<Text></Text>
</View>
<View onClick={handleShareToWechatMoments}>
<Image src={img.ICON_DETAIL_SHARE} />
<Text></Text>
</View>
<View onClick={handleSaveToLocal}>
<Image src={img.ICON_DETAIL_SHARE} />
<Text></Text>
</View>
</View> </View>
</CommonPopup> </CommonPopup>
) )
@@ -398,7 +381,7 @@ function Index() {
</View> </View>
</View> </View>
</view> </view>
<View className='detail-page-bg' style={{ backgroundImage: `url(${images[0]})` }} /> <View className='detail-page-bg' style={detail?.image_list?.[0] ? { backgroundImage: `url(${detail?.image_list?.[0]})` } : {}} />
<View className='detail-page-bg-text' /> <View className='detail-page-bg-text' />
{/* swiper */} {/* swiper */}
<View className="detail-swiper-container"> <View className="detail-swiper-container">
@@ -649,4 +632,4 @@ function Index() {
) )
} }
export default Index export default withAuth(Index)

View File

@@ -13,6 +13,7 @@ import InputCustomerBar from "@/container/inputCustomerNavbar";
import GuideBar from "@/components/GuideBar"; import GuideBar from "@/components/GuideBar";
import ListContainer from "@/container/listContainer"; import ListContainer from "@/container/listContainer";
import DistanceQuickFilter from "@/components/DistanceQuickFilter"; import DistanceQuickFilter from "@/components/DistanceQuickFilter";
import { withAuth } from "@/components";
import img from "@/config/images"; import img from "@/config/images";
const ListPage = () => { const ListPage = () => {
@@ -193,4 +194,4 @@ const ListPage = () => {
); );
}; };
export default ListPage; export default withAuth(ListPage);

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { View, Text, Button, Image } from '@tarojs/components'; import { View, Text, Button, Image } from '@tarojs/components';
import Taro from '@tarojs/taro'; import Taro, { useRouter } from '@tarojs/taro';
import { wechat_auth_login, save_login_state, check_login_status } from '../../../services/loginService'; import { wechat_auth_login, save_login_state, check_login_status } from '../../../services/loginService';
import './index.scss'; import './index.scss';
@@ -8,9 +8,11 @@ const LoginPage: React.FC = () => {
const [is_loading, set_is_loading] = useState(false); const [is_loading, set_is_loading] = useState(false);
const [agree_terms, set_agree_terms] = useState(false); const [agree_terms, set_agree_terms] = useState(false);
const [show_terms_layer, set_show_terms_layer] = useState(false); const [show_terms_layer, set_show_terms_layer] = useState(false);
const { params: { redirect } } = useRouter();
// 微信授权登录 // 微信授权登录
const handle_wechat_login = async (e: any) => { const handle_wechat_login = async (e: any) => {
@@ -42,7 +44,11 @@ const LoginPage: React.FC = () => {
save_login_state(response.token!, response.user_info!); save_login_state(response.token!, response.user_info!);
setTimeout(() => { setTimeout(() => {
Taro.redirectTo({ url: '/pages/list/index' }); if (redirect) {
Taro.redirectTo({ url: decodeURIComponent(redirect) });
} else {
Taro.redirectTo({ url: '/pages/list/index' });
}
}, 200); }, 200);
} else { } else {
Taro.showToast({ Taro.showToast({
@@ -76,7 +82,7 @@ const LoginPage: React.FC = () => {
// 跳转到验证码页面 // 跳转到验证码页面
Taro.navigateTo({ Taro.navigateTo({
url: '/pages/login/verification/index' url: `/pages/login/verification/index?redirect=${redirect}`
}); });
}; };

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, Input, Button, Image } from '@tarojs/components'; import { View, Text, Input, Button, Image } from '@tarojs/components';
import Taro from '@tarojs/taro'; import Taro, { useRouter } from '@tarojs/taro';
import { phone_auth_login, send_sms_code } from '../../../services/loginService'; import { phone_auth_login, send_sms_code } from '../../../services/loginService';
import './index.scss'; import './index.scss';
@@ -12,6 +12,8 @@ const VerificationPage: React.FC = () => {
const [is_loading, setIsLoading] = useState(false); const [is_loading, setIsLoading] = useState(false);
const [code_input_focus, setCodeInputFocus] = useState(false); const [code_input_focus, setCodeInputFocus] = useState(false);
const { params: { redirect } } = useRouter();
// 计算登录按钮是否应该启用 // 计算登录按钮是否应该启用
const can_login = phone.length === 11 && verification_code.length === 6 && !is_loading; const can_login = phone.length === 11 && verification_code.length === 6 && !is_loading;
@@ -123,9 +125,13 @@ const VerificationPage: React.FC = () => {
if (result.success) { if (result.success) {
setTimeout(() => { setTimeout(() => {
Taro.redirectTo({ if (redirect) {
url: '/pages/list/index' Taro.redirectTo({ url: decodeURIComponent(redirect) });
}); } else {
Taro.redirectTo({
url: '/pages/list/index'
});
}
}, 200); }, 200);
} else { } else {
Taro.showToast({ Taro.showToast({

View File

@@ -3,10 +3,11 @@ import { View, Text, ScrollView } from '@tarojs/components'
import { Avatar } from '@nutui/nutui-react-taro' import { Avatar } from '@nutui/nutui-react-taro'
import Taro from '@tarojs/taro' import Taro from '@tarojs/taro'
import GuideBar from '@/components/GuideBar' import GuideBar from '@/components/GuideBar'
import { withAuth } from '@/components'
// import img from '@/config/images' // import img from '@/config/images'
import './index.scss' import './index.scss'
const Personal = () => { const Message = () => {
const messageList = Array(10).fill(0).map((_, index) => ({ const messageList = Array(10).fill(0).map((_, index) => ({
id: index + 1, id: index + 1,
title: `消息${index + 1}消息${index + 1}消息${index + 1}消息${index + 1}`, title: `消息${index + 1}消息${index + 1}消息${index + 1}消息${index + 1}`,
@@ -40,4 +41,4 @@ const Personal = () => {
) )
} }
export default Personal export default withAuth(Message)

View File

@@ -4,6 +4,7 @@ import Taro, { useDidShow, useRouter } from '@tarojs/taro'
import { delay } from '@/utils' import { delay } from '@/utils'
import orderService from '@/services/orderService' import orderService from '@/services/orderService'
import detailService, { GameDetail } from '@/services/detailService' import detailService, { GameDetail } from '@/services/detailService'
import { withAuth } from '@/components'
const OrderCheck = () => { const OrderCheck = () => {
const { params } = useRouter() const { params } = useRouter()
@@ -67,4 +68,4 @@ const OrderCheck = () => {
) )
} }
export default OrderCheck export default withAuth(OrderCheck)

View File

@@ -4,6 +4,7 @@ import { Checkbox } from '@nutui/nutui-react-taro'
import Taro from '@tarojs/taro' import Taro from '@tarojs/taro'
import { type ActivityType } from '../../components/ActivityTypeSwitch' import { type ActivityType } from '../../components/ActivityTypeSwitch'
import CommonDialog from '../../components/CommonDialog' import CommonDialog from '../../components/CommonDialog'
import { withAuth } from '@/components'
import PublishForm from './publishForm' import PublishForm from './publishForm'
import { FormFieldConfig, publishBallFormSchema } from '../../config/formSchema/publishBallFormSchema'; import { FormFieldConfig, publishBallFormSchema } from '../../config/formSchema/publishBallFormSchema';
import { PublishBallFormData } from '../../../types/publishBall'; import { PublishBallFormData } from '../../../types/publishBall';
@@ -87,13 +88,13 @@ const PublishBall: React.FC = () => {
// 检查相邻两组数据是否相同 // 检查相邻两组数据是否相同
const checkAdjacentDataSame = (formDataArray: PublishBallFormData[]) => { const checkAdjacentDataSame = (formDataArray: PublishBallFormData[]) => {
if (formDataArray.length < 2) return false if (formDataArray.length < 2) return false
const lastIndex = formDataArray.length - 1 const lastIndex = formDataArray.length - 1
const secondLastIndex = formDataArray.length - 2 const secondLastIndex = formDataArray.length - 2
const lastData = formDataArray[lastIndex] const lastData = formDataArray[lastIndex]
const secondLastData = formDataArray[secondLastIndex] const secondLastData = formDataArray[secondLastIndex]
// 比较关键字段是否相同 // 比较关键字段是否相同
return (JSON.stringify(lastData) === JSON.stringify(secondLastData)) return (JSON.stringify(lastData) === JSON.stringify(secondLastData))
} }
@@ -117,7 +118,7 @@ const PublishBall: React.FC = () => {
} }
}]) }])
} }
// 复制上一场数据 // 复制上一场数据
const handleCopyPrevious = (index: number) => { const handleCopyPrevious = (index: number) => {
@@ -372,7 +373,7 @@ const PublishBall: React.FC = () => {
<View className={styles['publish-ball']}> <View className={styles['publish-ball']}>
{/* 活动类型切换 */} {/* 活动类型切换 */}
<View className={styles['activity-type-switch']}> <View className={styles['activity-type-switch']}>
{/* <ActivityTypeSwitch {/* <ActivityTypeSwitch
value={activityType} value={activityType}
onChange={handleActivityTypeChange} onChange={handleActivityTypeChange}
/> */} /> */}
@@ -452,7 +453,7 @@ const PublishBall: React.FC = () => {
{ {
activityType === 'group' && ( activityType === 'group' && (
<View className={styles['submit-tip']}> <View className={styles['submit-tip']}>
<Checkbox <Checkbox
className={styles['submit-checkbox']} className={styles['submit-checkbox']}
checked={checked} checked={checked}
onChange={onCheckedChange} onChange={onCheckedChange}
@@ -466,4 +467,4 @@ const PublishBall: React.FC = () => {
) )
} }
export default PublishBall export default withAuth(PublishBall)

View File

@@ -4,6 +4,7 @@ import { Input } from "@nutui/nutui-react-taro";
import { useEffect, useMemo, useRef } from "react"; import { useEffect, useMemo, useRef } from "react";
import { useListState } from "@/store/listStore"; import { useListState } from "@/store/listStore";
import img from "@/config/images"; import img from "@/config/images";
import { withAuth } from "@/components";
import "./index.scss"; import "./index.scss";
import Taro from "@tarojs/taro"; import Taro from "@tarojs/taro";
@@ -197,4 +198,4 @@ const ListSearch = () => {
</> </>
); );
}; };
export default ListSearch; export default withAuth(ListSearch);

View File

@@ -5,6 +5,7 @@ import ListContainer from "@/container/listContainer";
import "./index.scss"; import "./index.scss";
import DistanceQuickFilter from "@/components/DistanceQuickFilter"; import DistanceQuickFilter from "@/components/DistanceQuickFilter";
import { withAuth } from "@/components";
import { useEffect } from "react"; import { useEffect } from "react";
const SearchResult = () => { const SearchResult = () => {
@@ -68,4 +69,4 @@ const SearchResult = () => {
); );
}; };
export default SearchResult; export default withAuth(SearchResult);

View File

@@ -7,6 +7,7 @@ import { UserInfoCard, UserInfo } from '@/components/UserInfo/index'
import { UserService } from '@/services/userService' import { UserService } from '@/services/userService'
import ListContainer from '@/container/listContainer' import ListContainer from '@/container/listContainer'
import { TennisMatch } from '../../../../types/list/types' import { TennisMatch } from '../../../../types/list/types'
import { withAuth } from '@/components';
const MyselfPage: React.FC = () => { const MyselfPage: React.FC = () => {
// 获取页面参数 // 获取页面参数
@@ -157,7 +158,7 @@ const MyselfPage: React.FC = () => {
is_current_user={is_current_user} is_current_user={is_current_user}
is_following={is_following} is_following={is_following}
on_follow={handle_follow} on_follow={handle_follow}
/> />
)} )}
{/* 球局订单和收藏功能 */} {/* 球局订单和收藏功能 */}
@@ -212,4 +213,4 @@ const MyselfPage: React.FC = () => {
); );
}; };
export default MyselfPage; export default withAuth(MyselfPage);