This commit is contained in:
oneao committed 2026-01-29 17:29:08 +08:00
1 parent d33cef825a
commit 295b3306a3
7 files changed
+477 -291

No files matched your search

+139 -135
View File
@@ -1,13 +1,14 @@
import { useEvent } from 'expo'
import ExpoQQ from 'expo-qq'
// import ExpoQQ from 'expo-qq'
import { useRouter } from 'expo-router'
import ExpoWeChat from 'expo-wechat'
// import ExpoWeChat from 'expo-wechat'
import { useEffect, useState } from 'react'
import { Image, Text, View } from 'react-native'
import { AButton, ACheckbox } from '@/components/common/ao'
import CustomHeader from '@/components/custom/Header'
import { IconQq, IconWeixin } from '@/components/iconfont'
import { loginQqApi, loginWxApi } from '@/request/api/auth'
import { useAppStore } from '@/store/app'
import { useUserStore } from '@/store/user'
import { toast } from '@/utils/toast'
@@ -22,161 +23,162 @@ export default function Auth() {
const router = useRouter()
const userStore = useUserStore()
const appStore = useAppStore()
const onLoginFinished = useEvent(ExpoQQ, 'onLoginFinished')
const onGetUserInfo = useEvent(ExpoQQ, 'onGetUserInfo')
const authResult = useEvent(ExpoWeChat, 'onAuthResult')
// const onLoginFinished = useEvent(ExpoQQ, 'onLoginFinished')
// const onGetUserInfo = useEvent(ExpoQQ, 'onGetUserInfo')
// const authResult = useEvent(ExpoWeChat, 'onAuthResult')
async function onQQLogin() {
setLoading(true)
setForm(val => ({
...val,
type: 1,
}))
await ExpoQQ.login(['get_user_info'])
}
// async function onQQLogin() {
// setLoading(true)
// setForm(val => ({
// ...val,
// type: 1,
// }))
// await ExpoQQ.login(['get_user_info'])
// }
async function onWeChatLogin() {
setLoading(true)
// async function onWeChatLogin() {
// setLoading(true)
// 检查微信是否安装
const isInstalled = await ExpoWeChat.isWXAppInstalled()
if (!isInstalled) {
toast.show({
title: onLoginFinished?.errorMessage || '请先安装微信',
})
setLoading(false)
return
}
// // 检查微信是否安装
// const isInstalled = await ExpoWeChat.isWXAppInstalled()
// if (!isInstalled) {
// toast.show({
// title: onLoginFinished?.errorMessage || '请先安装微信',
// })
// setLoading(false)
// return
// }
setForm(val => ({
...val,
type: 0,
}))
// setForm(val => ({
// ...val,
// type: 0,
// }))
ExpoWeChat.sendAuthRequest('snsapi_userinfo', 'state123')
}
// ExpoWeChat.sendAuthRequest('snsapi_userinfo', 'state123')
// }
useEffect(() => {
ExpoQQ.init('102826474', '')
ExpoWeChat.registerApp('wxdab3e21a1f7e392f', '')
}, [])
// useEffect(() => {
// ExpoQQ.init('102826474', '')
// ExpoWeChat.registerApp('wxdab3e21a1f7e392f', '')
// }, [])
useEffect(() => {
if (!onLoginFinished) {
return
}
// useEffect(() => {
// if (!onLoginFinished) {
// return
// }
if (!onLoginFinished.success) {
toast.show({
title: onLoginFinished?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权',
})
setLoading(false)
return
}
// if (!onLoginFinished.success) {
// toast.show({
// title: onLoginFinished?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权',
// })
// setLoading(false)
// return
// }
const fetchUserInfo = async () => {
try {
const tokenInfo = await ExpoQQ.getLoginTokenInfo()
if (!tokenInfo.openId) {
toast.show({
title: tokenInfo?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权',
})
setLoading(false)
return
}
// const fetchUserInfo = async () => {
// try {
// const tokenInfo = await ExpoQQ.getLoginTokenInfo()
// if (!tokenInfo.openId) {
// toast.show({
// title: tokenInfo?.errorMessage || '授权失败,请检查手机是否安装 QQ 或确认授权',
// })
// setLoading(false)
// return
// }
setForm(val => ({
...val,
openid: String(tokenInfo.openId),
}))
// setForm(val => ({
// ...val,
// openid: String(tokenInfo.openId),
// }))
await ExpoQQ.sendGetUserInfoReq()
}
catch (e) {
console.error('QQ 登录未完成', e)
setLoading(false)
}
}
// await ExpoQQ.sendGetUserInfoReq()
// }
// catch (e) {
// console.error('QQ 登录未完成', e)
// setLoading(false)
// }
// }
fetchUserInfo()
}, [onLoginFinished])
// fetchUserInfo()
// }, [onLoginFinished])
// QQ登录
useEffect(() => {
const handleLogin = async () => {
if (!onGetUserInfo)
return
// // QQ登录
// useEffect(() => {
// const handleLogin = async () => {
// if (!onGetUserInfo)
// return
try {
const loginRes = await loginQqApi({
openid: form.openid,
username: onGetUserInfo.nickname || '',
avatar: onGetUserInfo.figureurlQq_2 || onGetUserInfo.figureurl_2,
})
// try {
// const loginRes = await loginQqApi({
// openid: form.openid,
// username: onGetUserInfo.nickname || '',
// avatar: onGetUserInfo.figureurlQq_2 || onGetUserInfo.figureurl_2,
// })
if (loginRes.isSuccess) {
userStore.setUserInfo({
token: loginRes.data.token,
id: loginRes.data.userId,
username: loginRes.data.username,
avatar: loginRes.data.avatar,
})
// if (loginRes.isSuccess) {
// userStore.setUserInfo({
// token: loginRes.data.token,
// id: loginRes.data.userId,
// username: loginRes.data.username,
// avatar: loginRes.data.avatar,
// })
console.log(loginRes.data.token)
// console.log(loginRes.data.token)
router.push('/')
}
}
catch (err) {
console.error('登录接口出错', err)
}
finally {
setLoading(false)
}
}
// router.push('/')
// }
// }
// catch (err) {
// console.error('登录接口出错', err)
// }
// finally {
// setLoading(false)
// }
// }
handleLogin()
}, [onGetUserInfo])
// handleLogin()
// }, [onGetUserInfo])
// 微信登录
useEffect(() => {
if (!authResult)
return
// // 微信登录
// useEffect(() => {
// if (!authResult)
// return
const handleLogin = async () => {
if (authResult.errorCode === 0) {
try {
const loginRes = await loginWxApi({
code: authResult.code,
})
// const handleLogin = async () => {
// if (authResult.errorCode === 0) {
// try {
// const loginRes = await loginWxApi({
// code: authResult.code,
// })
if (loginRes.isSuccess) {
userStore.setUserInfo({
token: loginRes.data.token,
id: loginRes.data.userId,
username: loginRes.data.username,
avatar: loginRes.data.avatar,
})
// if (loginRes.isSuccess) {
// userStore.setUserInfo({
// token: loginRes.data.token,
// id: loginRes.data.userId,
// username: loginRes.data.username,
// avatar: loginRes.data.avatar,
// })
router.push('/')
}
}
catch (err) {
console.error('登录接口出错', err)
}
finally {
setLoading(false)
}
}
else {
console.log('授权失败:', authResult.errorMessage)
setLoading(false)
}
}
// router.push('/')
// }
// }
// catch (err) {
// console.error('登录接口出错', err)
// }
// finally {
// setLoading(false)
// }
// }
// else {
// console.log('授权失败:', authResult.errorMessage)
// setLoading(false)
// }
// }
handleLogin()
}, [authResult])
// handleLogin()
// }, [authResult])
function testLogin() {
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo3NjY3ODU5ODIxNjUwNjEsImlhdCI6MTc2OTM0ODI0Nn0.17ZNaHD3HSLM8dVn_JQK-gvsG9MKj47IRYV9D4xZkzs
@@ -188,6 +190,8 @@ export default function Auth() {
avatar: 'http://thirdqq.qlogo.cn/ek_qqapp/AQHVialeUibE42oV8RvTTVZ4tyRlPYeJrUibWTwtCPfV68E4rSzn9cw00GkXQ3QDTiawwhjoqQb7/100',
})
appStore.init()
router.push('/')
}
@@ -208,7 +212,7 @@ export default function Auth() {
</View>
<View className="flex flex-col gap-4">
<AButton
{/* <AButton
leftIcon={
<IconWeixin color="#fff" />
}
@@ -227,7 +231,7 @@ export default function Auth() {
onPress={onQQLogin}
>
QQ
</AButton>
</AButton> */}
<AButton
variant="outline"
@@ -1,6 +1,8 @@
import type { LegendListRef } from '@legendapp/list'
import type { MoneyCategoryItem } from '@/types/money/category'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { FlatList, Pressable, Text, View } from 'react-native'
import { LegendList } from '@legendapp/list'
import { useEffect, useRef, useState } from 'react'
import { Pressable, Text, View } from 'react-native'
import { AButton, ADrawer, AInput } from '@/components/common/ao'
import MoneyCategoryIcon from '@/components/common/MoneyCategoryIcon'
import { useMoneyCategoryStore } from '@/store/moneyCategory'
@@ -33,11 +35,8 @@ export default function CreateCategory({
const [form, setForm] = useState<EditCategoryForm>({ icon: '', name: '' })
const [confirmDisabled, setConfirmDisabled] = useState(true)
const [confirmLoading, setConfirmLoading] = useState(false)
const flatListData = Object.entries(moneyCategoryStore.ICON_GROUPS)
const flatListData2 = Object.values(moneyCategoryStore.ICON_GROUPS).flat()
const listRef = useRef<LegendListRef>(null)
const flatListRef = useRef<FlatList<any>>(null)
// Drawer 打开/关闭控制
useEffect(() => {
setIsOpen(open)
if (!open)
@@ -47,24 +46,24 @@ export default function CreateCategory({
// 确认按钮状态
useEffect(() => {
setConfirmDisabled(!(form.name && form.name.length <= 5 && form.icon))
const itemIndex = flatListData2.findIndex(item => item === form.icon)
if (itemIndex === -1 || !flatListRef.current)
return
if (form.icon) {
setTimeout(() => {
if (flatListRef.current) {
flatListRef.current.scrollToIndex({
index: Math.floor(itemIndex / 5),
animated: true,
viewPosition: 0.5,
})
}
}, 0)
}
}, [form.name, form.icon])
useEffect(() => {
if (!form.icon || !listRef.current) {
return
}
const index = moneyCategoryStore.findIconGroupsRow(form.icon)
if (index !== -1) {
listRef.current.scrollToIndex({
index,
viewPosition: 0.5,
animated: true,
})
}
}, [form.icon])
// 编辑已有分类时填充数据
useEffect(() => {
if (category)
@@ -77,55 +76,6 @@ export default function CreateCategory({
onClose?.()
}
// 渲染每组 Icon
const renderGroup = useCallback(
({ item }: { item: [string, string[]] }) => {
const [groupName, icons] = item
return (
<View className="mb-4">
<Text className="text-center text-sm mb-3">{groupName}</Text>
<View className="flex flex-row flex-wrap">
{icons.map((icon) => {
const selected = form.icon === icon
return (
<Pressable
key={icon}
className="w-1/5 mb-3 flex items-center"
onPress={() =>
setForm(v => ({
...v,
icon,
}))}
>
<View
style={{
width: 46,
height: 46,
borderRadius: 28,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: selected ? '#333' : '#F3F4F6',
}}
>
<MoneyCategoryIcon
name={icon}
size={32}
color={selected ? '#fff' : '#000'}
/>
</View>
</Pressable>
)
})}
</View>
</View>
)
},
[form.icon],
)
return (
<ADrawer
visible={isOpen}
@@ -161,15 +111,72 @@ export default function CreateCategory({
</View>
)}
>
<FlatList
ref={flatListRef}
data={flatListData}
keyExtractor={([groupName]) => groupName}
renderItem={renderGroup}
getItemLayout={(data, index) => {
return { length: 80, offset: 80 * index, index }
}}
/>
<View className="flex-1">
<AInput
className="mx-4 mb-4"
placeholder="分类名称"
value={form.name}
onChangeText={text => setForm(prevForm => ({ ...prevForm, name: text }))}
/>
<LegendList
ref={listRef}
data={moneyCategoryStore.IconGroups}
extraData={form.icon}
keyExtractor={item => String(item.index)}
recycleItems
initialContainerPoolRatio={20}
style={{ flex: 1 }}
initialScrollIndex={moneyCategoryStore.findIconGroupsRow(category?.icon || '')}
renderItem={({ item }) => (
<View className="mb-1" key={item.index}>
{
item.type === 'title'
? (
<Text className="text-center text-sm mb-3">{item.value}</Text>
)
: (
<View className="flex flex-row flex-wrap">
{item.value.map((icon) => {
const selected = form.icon === icon
return (
<Pressable
key={icon}
className="w-1/5 mb-3 flex items-center"
onPress={() => {
setForm(prevForm => ({
...prevForm,
icon,
}))
}}
>
<View
style={{
width: 46,
height: 46,
borderRadius: 28,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: selected ? '#333' : '#F3F4F6',
}}
>
<MoneyCategoryIcon
name={icon}
size={32}
color={selected ? '#fff' : '#000'}
/>
</View>
</Pressable>
)
})}
</View>
)
}
</View>
)}
/>
</View>
</ADrawer>
)
}