fix ui
This commit is contained in:
34
App.tsx
34
App.tsx
@@ -71,6 +71,16 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
// 先登录获取 userId
|
||||
try {
|
||||
const userId = await Api.instance.login('test123', '123456');
|
||||
console.log('[登录成功] userId:', userId);
|
||||
} catch (error) {
|
||||
console.error('[登录失败]', error);
|
||||
Alert.alert('登录失败', String(error));
|
||||
return;
|
||||
}
|
||||
|
||||
await this.setupPermissions();
|
||||
await this.initProxyClient();
|
||||
this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange);
|
||||
@@ -107,18 +117,20 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
||||
});
|
||||
|
||||
onNotificationMessage((msg: NotificationMessage) => {
|
||||
console.log('[Notification]', msg.packageName, msg.title, msg.text);
|
||||
// console.log('[Notification]', msg.packageName, msg.title, msg.text);
|
||||
});
|
||||
}
|
||||
|
||||
async initProxyClient() {
|
||||
try {
|
||||
this.clientId = DeviceInfo.getUniqueIdSync();
|
||||
console.log('[Proxy] 初始化客户端:', this.clientId);
|
||||
const userId = Api.instance.getUserId();
|
||||
console.log('[Proxy] 初始化客户端:', this.clientId, 'userId:', userId);
|
||||
|
||||
await proxyManager.start({
|
||||
wsUrl: 'ws://192.168.1.117:16001/ws',
|
||||
clientId: this.clientId || '',
|
||||
userId: 1,
|
||||
userId: userId,
|
||||
debug: true,
|
||||
heartbeatInterval: 10000,
|
||||
reconnectInterval: 5000,
|
||||
@@ -130,13 +142,12 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
||||
console.log('[Proxy] 客户端已断开');
|
||||
},
|
||||
onError: (error: string) => {
|
||||
console.error('[Proxy] 错误:', error);
|
||||
console.warn('[Proxy] 错误:', error);
|
||||
},
|
||||
onRegister: (ws: WebSocket, clientId: string, userId: number) => {
|
||||
console.log('[Proxy] 客户端已注册:', clientId, userId);
|
||||
},
|
||||
});
|
||||
console.log('[Proxy] 客户端已连接');
|
||||
} catch (error) {
|
||||
console.error('[Proxy] 初始化失败:', error);
|
||||
}
|
||||
@@ -164,11 +175,13 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
||||
};
|
||||
|
||||
// Paytm Personal
|
||||
handleUploadPaytmPersonal = async (result: PaytmPersonalBindResult) => {
|
||||
handleUploadPaytmPersonalToken = async (result: PaytmPersonalBindResult) => {
|
||||
try {
|
||||
console.log(result);
|
||||
await Api.instance.register(WalletType.PAYTM_PERSONAL, result);
|
||||
this.setState({ showPaytmPersonalBind: false });
|
||||
console.log('绑定成功', 'Paytm Personal Token 绑定成功');
|
||||
Alert.alert('绑定成功', 'Paytm Personal Token 绑定成功');
|
||||
} catch (error) {
|
||||
Alert.alert('绑定失败', (error as Error).message);
|
||||
this.setState({ showPaytmPersonalBind: false });
|
||||
@@ -265,7 +278,7 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
||||
<PaytmPersonalBind
|
||||
processString="Processing..."
|
||||
isDebug={true}
|
||||
onSuccess={this.handleUploadPaytmPersonal}
|
||||
onSuccess={this.handleUploadPaytmPersonalToken}
|
||||
onError={(error: string) => {
|
||||
Alert.alert('绑定失败', error);
|
||||
this.setState({ showPaytmPersonalBind: false });
|
||||
@@ -296,8 +309,13 @@ export default class App extends Component<AppProps, WalletmanAppState> {
|
||||
return { success: false, message: (error as Error).message };
|
||||
}
|
||||
}}
|
||||
onSuccess={this.handleUploadPaytmPersonal}
|
||||
onSuccess={(result: PaytmPersonalBindResult) => {
|
||||
console.log('[PaytmPersonal] OTP 绑定成功:', result);
|
||||
Alert.alert('绑定成功', 'Paytm Personal OTP 绑定成功');
|
||||
this.setState({ showPaytmPersonalBind: false });
|
||||
}}
|
||||
onError={(error: string) => {
|
||||
console.log('[PaytmPersonal] OTP 绑定失败:', error);
|
||||
Alert.alert('绑定失败', error);
|
||||
this.setState({ showPaytmPersonalBind: false });
|
||||
}}
|
||||
|
||||
@@ -60,14 +60,20 @@ export const OTPBindUI: React.FC<OTPBindUIProps> = ({
|
||||
|
||||
{state.step === 'mobile' && (
|
||||
<>
|
||||
{state.errorMessage ? (
|
||||
<Text style={styles.errorText}>{state.errorMessage}</Text>
|
||||
) : null}
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
style={[styles.input, state.errorMessage ? styles.inputError : {}]}
|
||||
placeholder="请输入手机号"
|
||||
placeholderTextColor="#999"
|
||||
keyboardType="phone-pad"
|
||||
maxLength={mobileLength}
|
||||
value={state.mobile}
|
||||
onChangeText={actions.setMobile}
|
||||
onChangeText={(text) => {
|
||||
actions.setMobile(text);
|
||||
if (state.errorMessage) actions.clearError();
|
||||
}}
|
||||
editable={!state.loading}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
@@ -87,14 +93,20 @@ export const OTPBindUI: React.FC<OTPBindUIProps> = ({
|
||||
{state.step === 'otp' && (
|
||||
<>
|
||||
<Text style={styles.hint}>验证码已发送至 {state.mobile}</Text>
|
||||
{state.errorMessage ? (
|
||||
<Text style={styles.errorText}>{state.errorMessage}</Text>
|
||||
) : null}
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
style={[styles.input, state.errorMessage ? styles.inputError : {}]}
|
||||
placeholder={`请输入 ${otpLength} 位验证码`}
|
||||
placeholderTextColor="#999"
|
||||
keyboardType="number-pad"
|
||||
maxLength={otpLength}
|
||||
value={state.otp}
|
||||
onChangeText={actions.setOtp}
|
||||
onChangeText={(text) => {
|
||||
actions.setOtp(text);
|
||||
if (state.errorMessage) actions.clearError();
|
||||
}}
|
||||
editable={!state.loading}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
@@ -149,6 +161,15 @@ const styles = StyleSheet.create({
|
||||
fontSize: 16,
|
||||
marginBottom: 15,
|
||||
},
|
||||
inputError: {
|
||||
borderColor: '#ff3b30',
|
||||
},
|
||||
errorText: {
|
||||
color: '#ff3b30',
|
||||
fontSize: 14,
|
||||
marginBottom: 10,
|
||||
textAlign: 'center',
|
||||
},
|
||||
button: {
|
||||
backgroundColor: '#007AFF',
|
||||
borderRadius: 5,
|
||||
|
||||
@@ -66,7 +66,7 @@ export class PayTmPersonalOTPBind extends Component<{
|
||||
<OTPBindUI
|
||||
walletType={WalletType.PAYTM_PERSONAL}
|
||||
title="Paytm 绑定"
|
||||
otpLength={8}
|
||||
otpLength={6}
|
||||
onRequestOTP={this.props.onRequestOTP}
|
||||
onVerifyOTP={this.props.onVerifyOTP}
|
||||
onSuccess={this.props.onSuccess}
|
||||
|
||||
@@ -15,6 +15,7 @@ export interface OTPBindState {
|
||||
step: 'mobile' | 'otp' | 'processing';
|
||||
loading: boolean;
|
||||
otpData: any;
|
||||
errorMessage: string;
|
||||
}
|
||||
|
||||
export interface OTPBindActions {
|
||||
@@ -23,6 +24,7 @@ export interface OTPBindActions {
|
||||
requestOTP: () => Promise<void>;
|
||||
verifyOTP: () => Promise<void>;
|
||||
resetToMobile: () => void;
|
||||
clearError: () => void;
|
||||
}
|
||||
|
||||
export function useOTPBind(
|
||||
@@ -39,10 +41,13 @@ export function useOTPBind(
|
||||
const [step, setStep] = useState<'mobile' | 'otp' | 'processing'>('mobile');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [otpData, setOtpData] = useState<any>(null);
|
||||
const [errorMessage, setErrorMessage] = useState('');
|
||||
|
||||
const { onRequestOTP, onVerifyOTP, onSuccess, onError, isDebug = false } = callbacks;
|
||||
const { otpLength = 6, mobileLength = 10, additionalParams = {} } = config || {};
|
||||
|
||||
const clearError = () => setErrorMessage('');
|
||||
|
||||
const log = (...args: any[]) => {
|
||||
if (isDebug) console.log(`[${walletType}]`, ...args);
|
||||
};
|
||||
@@ -53,11 +58,14 @@ export function useOTPBind(
|
||||
|
||||
const requestOTP = async () => {
|
||||
if (!mobile || mobile.length !== mobileLength) {
|
||||
onError('Invalid mobile number');
|
||||
const msg = 'Invalid mobile number';
|
||||
setErrorMessage(msg);
|
||||
onError(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
setErrorMessage('');
|
||||
log('Requesting OTP for:', mobile);
|
||||
|
||||
try {
|
||||
@@ -70,13 +78,18 @@ export function useOTPBind(
|
||||
if (response.success) {
|
||||
setOtpData(response.data);
|
||||
setStep('otp');
|
||||
setErrorMessage('');
|
||||
} else {
|
||||
error('OTP request failed:', response.message);
|
||||
onError(response.message || 'Failed to request OTP');
|
||||
const msg = response.message || 'Failed to request OTP';
|
||||
setErrorMessage(msg);
|
||||
onError(msg);
|
||||
}
|
||||
} catch (e) {
|
||||
error('Request OTP error:', e);
|
||||
onError(e instanceof Error ? e.message : 'Failed to request OTP');
|
||||
const msg = e instanceof Error ? e.message : 'Failed to request OTP';
|
||||
setErrorMessage(msg);
|
||||
onError(msg);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -84,11 +97,14 @@ export function useOTPBind(
|
||||
|
||||
const verifyOTP = async () => {
|
||||
if (!otp || otp.length !== otpLength) {
|
||||
onError(`Invalid OTP (expected ${otpLength} digits)`);
|
||||
const msg = `请输入 ${otpLength} 位验证码`;
|
||||
setErrorMessage(msg);
|
||||
onError(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
setErrorMessage('');
|
||||
setStep('processing');
|
||||
log('Verifying OTP:', otp);
|
||||
|
||||
@@ -102,16 +118,21 @@ export function useOTPBind(
|
||||
log('Verify response:', response);
|
||||
|
||||
if (response.success) {
|
||||
setErrorMessage('');
|
||||
onSuccess(response.data);
|
||||
} else {
|
||||
error('Verify failed:', response.message);
|
||||
const msg = response.message || 'Failed to verify OTP';
|
||||
setStep('otp');
|
||||
onError(response.message || 'Failed to verify OTP');
|
||||
setErrorMessage(msg);
|
||||
onError(msg);
|
||||
}
|
||||
} catch (e) {
|
||||
error('Verify OTP error:', e);
|
||||
const msg = e instanceof Error ? e.message : 'Failed to verify OTP';
|
||||
setStep('otp');
|
||||
onError(e instanceof Error ? e.message : 'Failed to verify OTP');
|
||||
setErrorMessage(msg);
|
||||
onError(msg);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -120,10 +141,11 @@ export function useOTPBind(
|
||||
const resetToMobile = () => {
|
||||
setStep('mobile');
|
||||
setOtp('');
|
||||
setErrorMessage('');
|
||||
};
|
||||
|
||||
return [
|
||||
{ mobile, otp, step, loading, otpData },
|
||||
{ setMobile, setOtp, requestOTP, verifyOTP, resetToMobile },
|
||||
{ mobile, otp, step, loading, otpData, errorMessage },
|
||||
{ setMobile, setOtp, requestOTP, verifyOTP, resetToMobile, clearError },
|
||||
];
|
||||
}
|
||||
|
||||
Submodule libs/rnwalletman updated: 51280d4a12...0179dfbc68
@@ -24,7 +24,9 @@ class Api {
|
||||
|
||||
private headers(): Record<string, string> {
|
||||
const h: Record<string, string> = { 'Content-Type': 'application/json' };
|
||||
if (this.userId) h['X-User-ID'] = String(this.userId);
|
||||
if (this.userId > 0) {
|
||||
h['X-User-ID'] = String(this.userId);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,19 +28,18 @@ export const styles = StyleSheet.create({
|
||||
alignItems: "center",
|
||||
},
|
||||
bindButton: {
|
||||
padding: 10,
|
||||
marginTop: 10,
|
||||
marginBottom: 10,
|
||||
backgroundColor: "#007AFF",
|
||||
borderRadius: 5,
|
||||
width: "90%",
|
||||
height: 55,
|
||||
height: 45,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
bindButtonText: {
|
||||
fontSize: 16,
|
||||
fontWeight: "bold",
|
||||
fontSize: 14,
|
||||
// fontWeight: "bold",
|
||||
color: "#fff",
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user