From 03dfc75c3a0ae3c88525cfe13793414824e66276 Mon Sep 17 00:00:00 2001 From: oneao Date: Wed, 21 Jan 2026 22:28:54 +0800 Subject: [PATCH] u --- .../biz/handler/money/money_record_service.go | 1 - code/allapp/allapp-rn/app.json | 13 +- code/allapp/allapp-rn/package.json | 2 +- code/allapp/allapp-rn/pnpm-lock.yaml | 39 ++- code/allapp/allapp-rn/src/app/auth/index.tsx | 37 ++- .../setting/components/EditCategory.tsx | 10 +- .../src/components/common/ao/Drawer.tsx | 261 ++++++++++++++++++ .../src/components/common/ao/index.ts | 3 + code/allapp/allapp-rn/src/request/index.ts | 4 +- 9 files changed, 332 insertions(+), 38 deletions(-) create mode 100644 code/allapp/allapp-rn/src/components/common/ao/Drawer.tsx diff --git a/code/allapp/allapp-go/biz/handler/money/money_record_service.go b/code/allapp/allapp-go/biz/handler/money/money_record_service.go index f06b12f5..bc49a198 100644 --- a/code/allapp/allapp-go/biz/handler/money/money_record_service.go +++ b/code/allapp/allapp-go/biz/handler/money/money_record_service.go @@ -151,7 +151,6 @@ func InsertMoneyRecord(ctx context.Context, c *app.RequestContext) { resp.RecordTime = pgtypex.DateToString(record.RecordTime) resp.CreateTime = pgtypex.TimestampToDateTimeString(record.CreateTime) resp.UpdateTime = pgtypex.TimestampToDateTimeString(record.UpdateTime) - response.Success(c).Data(resp).Message("新增成功").Send() } diff --git a/code/allapp/allapp-rn/app.json b/code/allapp/allapp-rn/app.json index 0516d357..7f3ac6cb 100644 --- a/code/allapp/allapp-rn/app.json +++ b/code/allapp/allapp-rn/app.json @@ -7,7 +7,10 @@ "icon": "./assets/icon.png", "userInterfaceStyle": "light", "newArchEnabled": true, - "scheme": "allapp", + "scheme": [ + "allapp", + "tencent102826474" + ], "splash": { "image": "./assets/splash-icon.png", "resizeMode": "contain", @@ -30,7 +33,13 @@ }, "plugins": [ "expo-router", - "expo-font" + "expo-font", + [ + "expo-qq", + { + "appId": "102826474" + } + ] ] } } diff --git a/code/allapp/allapp-rn/package.json b/code/allapp/allapp-rn/package.json index d7736a5e..a9a9fde4 100644 --- a/code/allapp/allapp-rn/package.json +++ b/code/allapp/allapp-rn/package.json @@ -32,6 +32,7 @@ "expo-font": "~14.0.9", "expo-linear-gradient": "~15.0.7", "expo-linking": "~8.0.8", + "expo-qq": "^0.1.5", "expo-router": "~6.0.17", "expo-splash-screen": "~31.0.10", "expo-status-bar": "~3.0.8", @@ -47,7 +48,6 @@ "react-native-keyboard-controller": "1.18.5", "react-native-pager-view": "6.9.1", "react-native-popup-menu": "^0.18.0", - "react-native-qq-lib": "git+https://github.com/haxibiao/react-native-qq-lib.git", "react-native-qrcode-svg": "^6.3.20", "react-native-reanimated": "~4.1.1", "react-native-safe-area-context": "~5.6.1", diff --git a/code/allapp/allapp-rn/pnpm-lock.yaml b/code/allapp/allapp-rn/pnpm-lock.yaml index 5015a112..f559fdea 100644 --- a/code/allapp/allapp-rn/pnpm-lock.yaml +++ b/code/allapp/allapp-rn/pnpm-lock.yaml @@ -74,6 +74,9 @@ importers: expo-linking: specifier: ~8.0.8 version: 8.0.8(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) + expo-qq: + specifier: ^0.1.5 + version: 0.1.5(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) expo-router: specifier: ~6.0.17 version: 6.0.17(349aaac499003fc399e184fbbadde92f) @@ -119,9 +122,6 @@ importers: react-native-popup-menu: specifier: ^0.18.0 version: 0.18.0 - react-native-qq-lib: - specifier: git+https://github.com/haxibiao/react-native-qq-lib.git - version: git+https://github.com/haxibiao/react-native-qq-lib.git#da1a25d40a31a18b85ce35c55737a5d7af40a2c9(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) react-native-qrcode-svg: specifier: ^6.3.20 version: 6.3.20(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) @@ -3329,6 +3329,13 @@ packages: react: '*' react-native: '*' + expo-qq@0.1.5: + resolution: {integrity: sha512-wEL+QOJpjSIJ0QdHcl726elSnIZryt/0QpVuZhcY5h9Iaq5iGMssdgRQtk2aCyvMhFnUpGxP9ckVSJsqcUvwgg==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + expo-router@6.0.17: resolution: {integrity: sha512-2n0lTidH2H+dOjk/Lu+krKIgK7b1qQ3O/9RWmf9P5IEuFiu7BSUgSDc+g69bUEElTnca8FR+zPTyk15kMXHrXg==} peerDependencies: @@ -3967,56 +3974,48 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-gnu@1.30.2: resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.27.0: resolution: {integrity: sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.27.0: resolution: {integrity: sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.27.0: resolution: {integrity: sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-arm64-msvc@1.27.0: resolution: {integrity: sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ==} @@ -4958,13 +4957,6 @@ packages: react-native-popup-menu@0.18.0: resolution: {integrity: sha512-XD3gyp/hwL5YWw2J034DerfvbJ6S2YHqAzvqAFRU+UGnFD4JyTqggfm4UyynBD26O1PDoRb45Loil+NZCGfCnA==} - react-native-qq-lib@git+https://github.com/haxibiao/react-native-qq-lib.git#da1a25d40a31a18b85ce35c55737a5d7af40a2c9: - resolution: {commit: da1a25d40a31a18b85ce35c55737a5d7af40a2c9, repo: https://github.com/haxibiao/react-native-qq-lib.git, type: git} - version: 3.1.0 - peerDependencies: - react: ^16.8.1 - react-native: '>=0.60.0-rc.0 <1.0.x' - react-native-qrcode-svg@6.3.20: resolution: {integrity: sha512-GDP7T3DDEHUo53xmDyWWXXm3MhWRp0YayqVMum98JYfm0DW2rEbz1GIj+XLaA0QX443G0nURyzPnuQJeHjuvjA==} peerDependencies: @@ -9972,6 +9964,12 @@ snapshots: react: 19.1.0 react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0) + expo-qq@0.1.5(expo@54.0.23)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0): + dependencies: + expo: 54.0.23(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.17)(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) + react: 19.1.0 + react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0) + expo-router@6.0.17(349aaac499003fc399e184fbbadde92f): dependencies: '@expo/metro-runtime': 6.1.2(expo@54.0.23)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) @@ -12012,11 +12010,6 @@ snapshots: react-native-popup-menu@0.18.0: {} - react-native-qq-lib@git+https://github.com/haxibiao/react-native-qq-lib.git#da1a25d40a31a18b85ce35c55737a5d7af40a2c9(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0): - dependencies: - react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0) - react-native-qrcode-svg@6.3.20(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0): dependencies: prop-types: 15.8.1 diff --git a/code/allapp/allapp-rn/src/app/auth/index.tsx b/code/allapp/allapp-rn/src/app/auth/index.tsx index 0832300a..b5da07b1 100644 --- a/code/allapp/allapp-rn/src/app/auth/index.tsx +++ b/code/allapp/allapp-rn/src/app/auth/index.tsx @@ -1,3 +1,5 @@ +import { useEvent } from 'expo' +import ExpoQQ from 'expo-qq' import { useRouter } from 'expo-router' import { useEffect } from 'react' import { Image, Text, View } from 'react-native' @@ -11,6 +13,39 @@ export default function AuthIndex() { router.push(url) } + /// 监听登录结果,你也可以使用ExpoQQ.addListener('onLoginFinished', callback)来实现,但请不要忘记移除监听 + const onLoginFinished = useEvent(ExpoQQ, 'onLoginFinished') + + /// 国内应用需要在用户接受隐私协议后再初始化 + useEffect(() => { + const init = async () => { + await ExpoQQ.init('102826474', 'universal link') + } + + init() + }, []) + + useEffect(() => { + const run = async () => { + if (!onLoginFinished) + return + + console.log('onLoginFinished', onLoginFinished) + const tokenInfoRes = await ExpoQQ.getLoginTokenInfo() + console.log(tokenInfoRes) + const userInfoRes = await ExpoQQ.sendGetUserInfoReq() + console.log(userInfoRes) + } + + run() + }, [onLoginFinished]) + + /// 调用qq登陆 + const loginByQQ = async () => { + const res = await ExpoQQ.login(['get_user_info']) + console.log(res) + } + return ( - diff --git a/code/allapp/allapp-rn/src/app/money/category/setting/components/EditCategory.tsx b/code/allapp/allapp-rn/src/app/money/category/setting/components/EditCategory.tsx index 43479494..40a95ce1 100644 --- a/code/allapp/allapp-rn/src/app/money/category/setting/components/EditCategory.tsx +++ b/code/allapp/allapp-rn/src/app/money/category/setting/components/EditCategory.tsx @@ -1,8 +1,7 @@ import type { MoneyCategoryEnum, MoneyCategoryItem } from '@/types/money/category' import { useEffect, useRef, useState } from 'react' import { Pressable, Text, View } from 'react-native' -import { Drawer } from 'react-native-drawer-layout' -import { AButton, AInput } from '@/components/common/ao' +import { AButton, ADrawer, AInput } from '@/components/common/ao' import MoneyCategoryIcon from '@/components/common/MoneyCategoryIcon' import { useMoneyCategoryStore } from '@/store/moneyCategory' @@ -62,12 +61,7 @@ export default function CreateCategory({ } return ( - - + ) } diff --git a/code/allapp/allapp-rn/src/components/common/ao/Drawer.tsx b/code/allapp/allapp-rn/src/components/common/ao/Drawer.tsx new file mode 100644 index 00000000..c14b6456 --- /dev/null +++ b/code/allapp/allapp-rn/src/components/common/ao/Drawer.tsx @@ -0,0 +1,261 @@ +import type { ReactNode } from 'react' +import type { DimensionValue, ViewStyle } from 'react-native' +import React, { useCallback, useEffect, useRef, useState } from 'react' +import { + Animated, + Dimensions, + Modal, + Platform, + StyleSheet, + Text, + TouchableWithoutFeedback, + View, +} from 'react-native' +import LucideIcon from './LucideIcon' + +const WINDOW = Dimensions.get('window') + +interface DrawerMenuProps { + visible: boolean + duration?: number + menuPosition?: 'left' | 'right' | 'top' | 'bottom' + Height?: DimensionValue + hideModal: () => void + children?: ReactNode + isCircle?: boolean + CircleNum?: number + isShadowHideModal?: boolean + title?: string +} + +export default function Drawer({ + visible, + Height, + hideModal, + duration = 300, + isCircle, + menuPosition = 'bottom', + children, + CircleNum, + isShadowHideModal = true, + title, +}: DrawerMenuProps) { + const [menuPositionStyle, setMenuPositionStyle] = useState() + const [drawerMenuBox, setDrawerMenuBox] = useState() + const [innerVisible, setInnerVisible] = useState(false) + + const anim = useRef(new Animated.Value(0)).current + + /* ================== 同步外部 visible ================== */ + useEffect(() => { + if (visible) { + setInnerVisible(true) + open() + } + else { + close() + } + }, [visible]) + + /* ================== 布局样式 ================== */ + useEffect(() => { + switch (menuPosition) { + case 'left': + setMenuPositionStyle({ + flex: 1, + backgroundColor: '#fff', + borderTopRightRadius: isCircle ? CircleNum : 0, + borderBottomRightRadius: isCircle ? CircleNum : 0, + }) + setDrawerMenuBox({ + width: Height, + height: WINDOW.height, + position: 'absolute', + left: 0, + top: 0, + }) + break + + case 'right': + setMenuPositionStyle({ + flex: 1, + backgroundColor: '#fff', + borderTopLeftRadius: isCircle ? CircleNum : 0, + borderBottomLeftRadius: isCircle ? CircleNum : 0, + }) + setDrawerMenuBox({ + width: Height, + height: WINDOW.height, + position: 'absolute', + right: 0, + top: 0, + }) + break + + case 'top': + setMenuPositionStyle({ + flex: 1, + backgroundColor: '#fff', + borderBottomLeftRadius: isCircle ? CircleNum : 0, + borderBottomRightRadius: isCircle ? CircleNum : 0, + }) + setDrawerMenuBox({ + width: WINDOW.width, + height: Height, + position: 'absolute', + top: 0, + right: 0, + }) + break + + case 'bottom': + default: + setMenuPositionStyle({ + flex: 1, + backgroundColor: '#fff', + borderTopLeftRadius: isCircle ? CircleNum : 0, + borderTopRightRadius: isCircle ? CircleNum : 0, + }) + setDrawerMenuBox({ + width: WINDOW.width, + height: Height, + position: 'absolute', + bottom: 0, + right: 0, + }) + break + } + }, [menuPosition, Height, isCircle, CircleNum]) + + /* ================== 动画 ================== */ + const open = () => { + Animated.timing(anim, { + toValue: 1, + duration, + useNativeDriver: true, + }).start() + } + + const close = () => { + Animated.timing(anim, { + toValue: 0, + duration, + useNativeDriver: true, + }).start(({ finished }) => { + if (finished) { + setInnerVisible(false) + hideModal() + } + }) + } + + /* ================== 位移 ================== */ + const getTransform = useCallback(() => { + switch (menuPosition) { + case 'left': + return { + translateX: anim.interpolate({ + inputRange: [0, 1], + outputRange: [-WINDOW.width, 0], + }), + } + case 'right': + return { + translateX: anim.interpolate({ + inputRange: [0, 1], + outputRange: [WINDOW.width, 0], + }), + } + case 'top': + return { + translateY: anim.interpolate({ + inputRange: [0, 1], + outputRange: [-WINDOW.height, 0], + }), + } + case 'bottom': + default: + return { + translateY: anim.interpolate({ + inputRange: [0, 1], + outputRange: [WINDOW.height, 0], + }), + } + } + }, [menuPosition]) + + if (!innerVisible) + return null + + return ( + + {/* 遮罩 */} + isShadowHideModal && close()}> + + + + {/* Drawer */} + + + + {menuPosition !== 'bottom' && ( + + )} + + + {title} + + + + {children} + + + + + ) +} + +const styles = StyleSheet.create({ + mask: { + ...StyleSheet.absoluteFillObject, + backgroundColor: '#000', + }, + container: { + height: '100%', + width: '100%', + position: 'absolute', + }, + headTitle: { + height: 40, + width: '100%', + padding: 10, + justifyContent: 'center', + alignItems: 'center', + }, + title: { + fontSize: 18, + }, +}) diff --git a/code/allapp/allapp-rn/src/components/common/ao/index.ts b/code/allapp/allapp-rn/src/components/common/ao/index.ts index 53627787..6f173337 100644 --- a/code/allapp/allapp-rn/src/components/common/ao/index.ts +++ b/code/allapp/allapp-rn/src/components/common/ao/index.ts @@ -3,6 +3,8 @@ import { Cell, CellGroup } from './Cell' import Checkbox from './Checkbox' import DatePicker from './DatePicker' import Divider from './Divider' + +import Drawer from './Drawer' import Form, { FormRef } from './Form' import FormItem from './FormItem' import Input from './Input' @@ -19,6 +21,7 @@ export { Checkbox as ACheckbox, DatePicker as ADatePicker, Divider as ADivider, + Drawer as ADrawer, Form as AForm, FormItem as AFormItem, FormRef as AFormRef, diff --git a/code/allapp/allapp-rn/src/request/index.ts b/code/allapp/allapp-rn/src/request/index.ts index 476eb11d..de7e4c95 100644 --- a/code/allapp/allapp-rn/src/request/index.ts +++ b/code/allapp/allapp-rn/src/request/index.ts @@ -32,8 +32,8 @@ function isWhiteListed(url: string) { } const alovaInstance = createAlova({ - // baseURL: 'http://192.168.5.6:8086/app', - baseURL: 'http://192.168.1.137:8086/app', + baseURL: 'http://192.168.5.6:8086/app', + // baseURL: 'http://192.168.1.137:8086/app', requestAdapter: axiosRequestAdapter(), timeout: 5000, cacheFor: null,