355 lines
9.5 KiB
TypeScript
355 lines
9.5 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import { View, Text, TextInput, TouchableOpacity, Image, StyleSheet, ScrollView, ImageBackground } from 'react-native';
|
|
import { TopNavigation, TopNavigationAction, Icon } from '@ui-kitten/components';
|
|
import { useNavigation } from '@react-navigation/native';
|
|
import { apiService } from '../../utils/api';
|
|
import { rpx } from '../../utils/rpx';
|
|
import { uploadImageService } from '../../utils/uploadImg';
|
|
import Toast from 'react-native-toast-message';
|
|
|
|
const BackIcon = (props: any) => (
|
|
<Icon {...props} name='arrow-back' />
|
|
);
|
|
|
|
const Feedback = () => {
|
|
const [currentCount, setCurrentCount] = useState(0);
|
|
const [textValue, setTextValue] = useState('');
|
|
const [imglist, setImglist] = useState<string[]>([]);
|
|
const [list, setList] = useState<any[]>([]);
|
|
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
|
|
const [contactInfo, setContactInfo] = useState('');
|
|
const [type, setType] = useState<number | null>(null);
|
|
const [isFocused, setIsFocused] = useState(false);
|
|
const navigation = useNavigation();
|
|
|
|
useEffect(() => {
|
|
getlist();
|
|
}, []);
|
|
|
|
const toggleCheckbox = (index: number, item: any) => {
|
|
setSelectedIndex(index);
|
|
setType(item.dictSort);
|
|
};
|
|
|
|
const deleteImage = (index: number) => {
|
|
Toast.show({
|
|
type: 'info',
|
|
text1: '提示',
|
|
text2: '确定要删除这张图片吗?',
|
|
onPress: () => setImglist(prev => prev.filter((_, i) => i !== index)),
|
|
});
|
|
};
|
|
|
|
const sub = () => {
|
|
if (selectedIndex === null) {
|
|
Toast.show({ type: 'error', text1: '请选择反馈类型' });
|
|
return;
|
|
}
|
|
if (contactInfo === '') {
|
|
Toast.show({ type: 'error', text1: '请输入联系方式' });
|
|
return;
|
|
}
|
|
if (!textValue.trim()) {
|
|
Toast.show({ type: 'error', text1: '请填写问题描述' });
|
|
return;
|
|
}
|
|
|
|
const data = {
|
|
issueDescription: textValue,
|
|
uploadedImage: imglist.join(','),
|
|
type,
|
|
contactInfo,
|
|
};
|
|
|
|
apiService.postFeedback(data).then((res) => {
|
|
if (res.code == 200) {
|
|
Toast.show({ type: 'success', text1: '提交成功' });
|
|
navigation.goBack();
|
|
} else {
|
|
Toast.show({ type: 'error', text1: res.msg });
|
|
}
|
|
});
|
|
};
|
|
|
|
const getlist = async () => {
|
|
const res = await apiService.getFeedbackType();
|
|
if (res.code === 200) {
|
|
setList(res.data);
|
|
} else {
|
|
Toast.show({ type: 'error', text1: '获取反馈类型失败' });
|
|
}
|
|
};
|
|
|
|
const updateWordCount = (text: string) => {
|
|
const count = text.trim().replace(/\s+/g, '').length;
|
|
if (count > 500) {
|
|
setTextValue(text.slice(0, 500));
|
|
setCurrentCount(500);
|
|
Toast.show({ type: 'info', text1: '字数已达到500字上限' });
|
|
} else {
|
|
setTextValue(text);
|
|
setCurrentCount(count);
|
|
}
|
|
};
|
|
|
|
const handleImageUpload = async () => {
|
|
const urls = await uploadImageService.uploadImage({ multiple: true });
|
|
if (urls.length > 0) {
|
|
setImglist(prev => [...prev, ...urls]);
|
|
}
|
|
};
|
|
|
|
const navigateBack = () => {
|
|
navigation.goBack();
|
|
};
|
|
|
|
const BackAction = () => (
|
|
<TopNavigationAction icon={BackIcon} onPress={navigateBack} />
|
|
);
|
|
|
|
return (
|
|
<ImageBackground
|
|
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/uYRs7Cv2Pbp95w3KjGO3' }}
|
|
style={styles.background}
|
|
>
|
|
<TopNavigation
|
|
title='意见与反馈'
|
|
alignment='center'
|
|
accessoryLeft={BackAction}
|
|
style={styles.topNavigation}
|
|
/>
|
|
<ScrollView style={styles.page}>
|
|
<View style={styles.cardbox}>
|
|
<Text style={styles.tip}>反馈类型<Text style={styles.ipnt}>*</Text></Text>
|
|
<View style={styles.checkbox}>
|
|
{list.map((item, index) => (
|
|
<TouchableOpacity
|
|
key={index}
|
|
style={[styles.check_li, selectedIndex === index && styles.act1]}
|
|
onPress={() => toggleCheckbox(index, item)}
|
|
>
|
|
<Text style={styles.check_li_text}>{item.dictLabel}</Text>
|
|
{selectedIndex === index && (
|
|
<Image
|
|
source={{ uri: 'https://lxnapi.ccttiot.com/bike/img/static/u2jYgqIRlFcHjt20uA90' }}
|
|
style={styles.checkIcon}
|
|
/>
|
|
)}
|
|
</TouchableOpacity>
|
|
))}
|
|
</View>
|
|
</View>
|
|
|
|
<View style={styles.cardbox}>
|
|
<Text style={styles.tip}>问题描述<Text style={styles.ipnt}>*</Text></Text>
|
|
<View style={styles.inputContainer}>
|
|
{!textValue && !isFocused && <Text style={styles.placeholder}>请详细描述您的问题或建议</Text>}
|
|
<TextInput
|
|
style={styles.customTextarea}
|
|
value={textValue}
|
|
onChangeText={updateWordCount}
|
|
multiline
|
|
onFocus={() => setIsFocused(true)}
|
|
onBlur={() => setIsFocused(false)}
|
|
/>
|
|
<Text style={styles.wordCount}>{currentCount}/500</Text>
|
|
</View>
|
|
</View>
|
|
|
|
<View style={styles.cardbox}>
|
|
<Text style={styles.tip}>上传图片</Text>
|
|
<View style={styles.icon}>
|
|
{imglist.map((item, index) => (
|
|
<View key={index} style={styles.imgbox}>
|
|
<Image source={{ uri: item }} style={styles.image} />
|
|
<TouchableOpacity style={styles.deleteBtn} onPress={() => deleteImage(index)}>
|
|
<Image
|
|
source={{ uri: 'https://lxnapi.ccttiot.com/smartmeter/img/static/ui63BrTf8rlk4VAGx8Tf' }}
|
|
style={styles.deleteIcon}
|
|
/>
|
|
</TouchableOpacity>
|
|
</View>
|
|
))}
|
|
{imglist.length < 9 && (
|
|
<TouchableOpacity style={[styles.imgbox, styles.addBtn]} onPress={handleImageUpload}>
|
|
<Image
|
|
source={{ uri: 'https://api.ccttiot.com/smartmeter/img/static/uY8CPw9YE6JxPzcHUaqf' }}
|
|
style={styles.image}
|
|
/>
|
|
</TouchableOpacity>
|
|
)}
|
|
</View>
|
|
</View>
|
|
|
|
<View style={styles.cardbox}>
|
|
<Text style={styles.tip}>联系方式<Text style={styles.ipnt}>*</Text></Text>
|
|
<View style={styles.inputBox}>
|
|
<TextInput
|
|
style={styles.input}
|
|
placeholder="请留下手机号/邮箱/微信号,以便我们回复您"
|
|
value={contactInfo}
|
|
onChangeText={setContactInfo}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
<TouchableOpacity style={styles.btn} onPress={sub}>
|
|
<Text style={styles.btnText}>提交</Text>
|
|
</TouchableOpacity>
|
|
</ScrollView>
|
|
<Toast />
|
|
</ImageBackground>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
background: {
|
|
flex: 1,
|
|
},
|
|
topNavigation: {
|
|
backgroundColor: 'transparent',
|
|
},
|
|
page: {
|
|
flex: 1,
|
|
paddingBottom: rpx(80),
|
|
},
|
|
cardbox: {
|
|
margin: rpx(30),
|
|
padding: rpx(20),
|
|
backgroundColor: '#FFFFFF',
|
|
borderRadius: rpx(20),
|
|
shadowColor: '#000',
|
|
shadowOffset: { width: 0, height: rpx(10) },
|
|
shadowOpacity: 0.08,
|
|
shadowRadius: rpx(10),
|
|
elevation: 2,
|
|
},
|
|
tip: {
|
|
fontWeight: '700',
|
|
fontSize: rpx(32),
|
|
color: '#3D3D3D',
|
|
marginBottom: rpx(10),
|
|
},
|
|
ipnt: {
|
|
color: '#FF4444',
|
|
fontSize: rpx(48),
|
|
},
|
|
checkbox: {
|
|
flexDirection: 'row',
|
|
flexWrap: 'wrap',
|
|
},
|
|
check_li: {
|
|
marginRight: rpx(10),
|
|
marginTop: rpx(18),
|
|
padding: rpx(18),
|
|
borderRadius: rpx(25),
|
|
borderWidth: rpx(2),
|
|
borderColor: '#C4C4C4',
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
},
|
|
act1: {
|
|
borderColor: '#4297F3',
|
|
},
|
|
check_li_text: {
|
|
fontSize: rpx(28),
|
|
},
|
|
checkIcon: {
|
|
position: 'absolute',
|
|
right: rpx(0),
|
|
bottom: rpx(0),
|
|
width: rpx(40),
|
|
height: rpx(20),
|
|
marginLeft: rpx(5),
|
|
borderBottomRightRadius: rpx(20),
|
|
},
|
|
inputContainer: {
|
|
position: 'relative',
|
|
height: rpx(248),
|
|
borderWidth: rpx(2),
|
|
borderColor: '#C7C7C7',
|
|
borderRadius: rpx(20),
|
|
padding: rpx(10),
|
|
marginTop: rpx(40),
|
|
},
|
|
placeholder: {
|
|
position: 'absolute',
|
|
top: rpx(18),
|
|
left: rpx(38),
|
|
color: '#999',
|
|
},
|
|
customTextarea: {
|
|
flex: 1,
|
|
textAlignVertical: 'top',
|
|
paddingTop: rpx(18),
|
|
paddingLeft: rpx(38),
|
|
},
|
|
wordCount: {
|
|
position: 'absolute',
|
|
right: rpx(10),
|
|
bottom: rpx(10),
|
|
fontSize: rpx(12),
|
|
color: '#999',
|
|
},
|
|
icon: {
|
|
flexDirection: 'row',
|
|
flexWrap: 'wrap',
|
|
alignItems: 'center',
|
|
marginTop: rpx(40),
|
|
},
|
|
imgbox: {
|
|
position: 'relative',
|
|
width: '30%',
|
|
marginBottom: rpx(20),
|
|
marginRight: rpx(10),
|
|
},
|
|
image: {
|
|
width: rpx(142),
|
|
height: rpx(142),
|
|
borderRadius: rpx(10),
|
|
},
|
|
deleteBtn: {
|
|
position: 'absolute',
|
|
top: rpx(-16),
|
|
right: rpx(-16),
|
|
width: rpx(32),
|
|
height: rpx(32),
|
|
backgroundColor: '#DCEDFF',
|
|
borderRadius: rpx(16),
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
deleteIcon: {
|
|
width: rpx(20),
|
|
height: rpx(20),
|
|
},
|
|
addBtn: {
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
inputBox: {
|
|
marginTop: rpx(40),
|
|
borderWidth: rpx(2),
|
|
borderColor: '#C7C7C7',
|
|
borderRadius: rpx(20),
|
|
padding: rpx(10),
|
|
},
|
|
input: {
|
|
height: rpx(80),
|
|
paddingLeft: rpx(20),
|
|
},
|
|
btn: {
|
|
margin: rpx(34),
|
|
padding: rpx(15),
|
|
backgroundColor: '#4297F3',
|
|
borderRadius: rpx(54),
|
|
alignItems: 'center',
|
|
},
|
|
btnText: {
|
|
color: '#FFFFFF',
|
|
fontSize: rpx(40),
|
|
fontWeight: '500',
|
|
},
|
|
});
|
|
|
|
export default Feedback; |