You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1314 lines
43 KiB
1314 lines
43 KiB
import React, { useState } from "react"; |
|
import { |
|
View, |
|
Text, |
|
Image, |
|
StyleSheet, |
|
TouchableOpacity, |
|
TextInput, |
|
KeyboardAvoidingView, |
|
Platform, |
|
ScrollView, |
|
SafeAreaView, |
|
StatusBar, |
|
Modal, |
|
Alert, |
|
} from "react-native"; |
|
import BackIcon from "../../components/BackIcon"; |
|
import fontSize from "../../utils/fontsizeUtils"; |
|
import { LinearGradient } from "expo-linear-gradient"; |
|
import widthUtils from "../../utils/widthUtils"; |
|
import TrapezoidIcon from "../../components/TrapezoidIcon"; |
|
import { useNavigation } from "@react-navigation/native"; |
|
import * as ImagePicker from "expo-image-picker"; |
|
import * as FileSystem from "expo-file-system"; |
|
import { inquiriesApi, InquiryFormData } from "../../services/api/inquiries"; |
|
import DownArrowIcon from "../../components/DownArrowIcon"; |
|
|
|
export const InquiryScreen = () => { |
|
const [searchImg, setSearchImg] = useState(""); |
|
const [showImagePickerModal, setShowImagePickerModal] = useState(false); |
|
const [status, setStatus] = useState(0); |
|
const [galleryUsed, setGalleryUsed] = useState(false); |
|
const [formData, setFormData] = useState({ |
|
name: "", |
|
quantity: "", |
|
material: "", |
|
link: "", |
|
remark: "", |
|
}); |
|
const [isSubmitting, setIsSubmitting] = useState(false); |
|
const [inquiryStatus, setInquiryStatus] = useState(0); // 0: 请求报价, 1: 进行中 |
|
const [lastInquiry, setLastInquiry] = useState<any>(null); |
|
const [activeTab, setActiveTab] = useState(0); // 0: 请求报价, 1: 进行中, 2: 已完成 |
|
const [inquiries, setInquiries] = useState<any[]>([]); // 询盘列表 |
|
const [completedInquiries, setCompletedInquiries] = useState<any[]>([]); // 已完成询盘列表 |
|
const [page, setPage] = useState(1); // 当前页码 |
|
const [loading, setLoading] = useState(false); // 加载状态 |
|
const [hasMore, setHasMore] = useState(true); // 是否还有更多数据 |
|
const [refreshing, setRefreshing] = useState(false); // 下拉刷新状态 |
|
const navigation = useNavigation(); |
|
|
|
// 清理expo-image-picker临时文件 |
|
const cleanupImagePickerCache = async () => { |
|
try { |
|
const cacheDir = `${FileSystem.cacheDirectory}ImagePicker`; |
|
await FileSystem.deleteAsync(cacheDir, { idempotent: true }); |
|
console.log("已清理ImagePicker缓存"); |
|
setGalleryUsed(false); |
|
} catch (error) { |
|
console.log("清理缓存错误", error); |
|
} |
|
}; |
|
|
|
// 处理从相册选择 |
|
const handleChooseFromGallery = async () => { |
|
console.log("handleChooseFromGallery"); |
|
setShowImagePickerModal(false); |
|
|
|
setTimeout(async () => { |
|
try { |
|
const permissionResult = |
|
await ImagePicker.requestMediaLibraryPermissionsAsync(); |
|
if (permissionResult.status !== "granted") { |
|
console.log("相册权限被拒绝"); |
|
return; |
|
} |
|
|
|
const result = await ImagePicker.launchImageLibraryAsync({ |
|
mediaTypes: ImagePicker.MediaTypeOptions.Images, |
|
allowsEditing: true, |
|
aspect: [4, 3], |
|
quality: 1, |
|
}); |
|
|
|
if (!result.canceled && result.assets && result.assets.length > 0) { |
|
console.log("相册选择成功:", result.assets[0].uri); |
|
setSearchImg(result.assets[0].uri); |
|
await cleanupImagePickerCache(); |
|
} |
|
} catch (error: any) { |
|
console.error("相册错误:", error); |
|
await cleanupImagePickerCache(); |
|
} |
|
}, 500); |
|
}; |
|
|
|
// 处理相机拍照 |
|
const handleTakePhoto = async () => { |
|
console.log("handleTakePhoto"); |
|
setShowImagePickerModal(false); |
|
|
|
setTimeout(async () => { |
|
try { |
|
const permissionResult = |
|
await ImagePicker.requestCameraPermissionsAsync(); |
|
if (permissionResult.status !== "granted") { |
|
console.log("相机权限被拒绝"); |
|
return; |
|
} |
|
|
|
const result = await ImagePicker.launchCameraAsync({ |
|
mediaTypes: ImagePicker.MediaTypeOptions.Images, |
|
allowsEditing: true, |
|
aspect: [4, 3], |
|
quality: 1, |
|
}); |
|
|
|
if (!result.canceled && result.assets && result.assets.length > 0) { |
|
console.log("拍照成功:", result.assets[0].uri); |
|
setSearchImg(result.assets[0].uri); |
|
} |
|
|
|
await cleanupImagePickerCache(); |
|
} catch (error: any) { |
|
console.error("相机错误:", error); |
|
await cleanupImagePickerCache(); |
|
} |
|
}, 500); |
|
}; |
|
|
|
// 重置应用状态函数 |
|
const resetAppState = () => { |
|
setGalleryUsed(false); |
|
cleanupImagePickerCache(); |
|
Alert.alert("已重置", "现在您可以使用相机功能了"); |
|
}; |
|
|
|
const updataImg = () => { |
|
setShowImagePickerModal(true); |
|
}; |
|
|
|
const handleSubmit = async () => { |
|
if (!searchImg) { |
|
Alert.alert("提示", "请先上传图片"); |
|
return; |
|
} |
|
|
|
if (!formData.quantity) { |
|
Alert.alert("提示", "请输入数量"); |
|
return; |
|
} |
|
|
|
try { |
|
setIsSubmitting(true); |
|
|
|
// Create FormData object |
|
const submitData = new FormData() as InquiryFormData; |
|
|
|
// Add image to FormData |
|
const imageUri = searchImg; |
|
const filename = imageUri.split("/").pop() || "image.jpg"; |
|
const match = /\.(\w+)$/.exec(filename); |
|
const type = match ? `image/${match[1]}` : "image/jpeg"; |
|
|
|
// 创建图片对象 |
|
const imageObject = { |
|
uri: Platform.OS === "ios" ? imageUri.replace("file://", "") : imageUri, |
|
name: filename, |
|
type: type, |
|
}; |
|
|
|
// 将图片对象转换为 Blob |
|
const imageFetchResponse = await fetch(imageObject.uri); |
|
const imageBlob = await imageFetchResponse.blob(); |
|
|
|
// 添加图片到 FormData |
|
submitData.append("image", imageBlob, filename); |
|
|
|
// Add other form fields |
|
submitData.append("name", formData.name); |
|
submitData.append("quantity", formData.quantity); |
|
submitData.append("material", formData.material); |
|
submitData.append("link", formData.link); |
|
submitData.append("remark", formData.remark); |
|
|
|
console.log("Submitting form data:", { |
|
image: imageUri, |
|
name: formData.name, |
|
quantity: formData.quantity, |
|
material: formData.material, |
|
link: formData.link, |
|
remark: formData.remark, |
|
}); |
|
|
|
// Submit the inquiry |
|
try { |
|
const response = await inquiriesApi.createInquiry(submitData); |
|
console.log("Inquiry created:", response); |
|
setStatus(response.status); |
|
if (response.status === 1) { |
|
setLastInquiry(response); |
|
} |
|
} catch (error) { |
|
Alert.alert("错误", "提交失败,请重试"); |
|
} |
|
// Reset form and show success message |
|
setSearchImg(""); |
|
setFormData({ |
|
name: "", |
|
quantity: "", |
|
material: "", |
|
link: "", |
|
remark: "", |
|
}); |
|
} catch (error) { |
|
console.error("Error creating inquiry:", error); |
|
Alert.alert("错误", "提交失败,请重试"); |
|
} finally { |
|
setIsSubmitting(false); |
|
} |
|
}; |
|
|
|
// 获取询盘列表 |
|
const fetchInquiries = async (pageNum = 1, refresh = false) => { |
|
try { |
|
if (!hasMore && !refresh) return; // 没有更多数据且不是刷新操作,直接返回 |
|
|
|
setLoading(true); |
|
const response = await inquiriesApi.getInquiries(pageNum,10); |
|
console.log("Inquiries fetched:", response); |
|
|
|
// 处理响应数据,兼容不同格式 |
|
const inquiryData = response.items.filter(item => { |
|
return item.status === (activeTab === 1 ? 1 : 2); |
|
}); |
|
|
|
if (inquiryData && inquiryData.length >= 0) { |
|
if (refresh) { |
|
if (activeTab === 1) { |
|
setInquiries(inquiryData); |
|
} else { |
|
setCompletedInquiries(inquiryData); |
|
} |
|
} else { |
|
if (activeTab === 1) { |
|
setInquiries(prev => [...prev, ...inquiryData]); |
|
} else { |
|
setCompletedInquiries(prev => [...prev, ...inquiryData]); |
|
} |
|
} |
|
|
|
// 判断是否还有更多数据 |
|
setHasMore(inquiryData.length > 0); |
|
setPage(pageNum); |
|
} |
|
} catch (error) { |
|
console.error("Error fetching inquiries:", error); |
|
Alert.alert("错误", "获取询盘列表失败"); |
|
} finally { |
|
setLoading(false); |
|
setRefreshing(false); |
|
} |
|
}; |
|
|
|
// 加载更多 |
|
const handleLoadMore = () => { |
|
if (loading || !hasMore) return; |
|
fetchInquiries(page + 1); |
|
}; |
|
|
|
// 检测滚动到底部 |
|
const handleScroll = (event: any) => { |
|
if ((activeTab !== 1 && activeTab !== 2) || loading || !hasMore) return; |
|
|
|
const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent; |
|
const paddingToBottom = 20; // 距离底部多少触发加载 |
|
|
|
if (layoutMeasurement.height + contentOffset.y >= |
|
contentSize.height - paddingToBottom) { |
|
handleLoadMore(); |
|
} |
|
}; |
|
|
|
// Tab切换时加载对应数据 |
|
React.useEffect(() => { |
|
if (activeTab === 1 || activeTab === 2) { |
|
fetchInquiries(1, true); |
|
} |
|
}, [activeTab]); |
|
|
|
return ( |
|
<SafeAreaView style={styles.safeArea}> |
|
<StatusBar barStyle="dark-content" backgroundColor="#C8DFFF" /> |
|
<KeyboardAvoidingView |
|
behavior={Platform.OS === "ios" ? "padding" : "height"} |
|
style={styles.keyboardAvoidingContainer} |
|
keyboardVerticalOffset={Platform.OS === "ios" ? 100 : 0} |
|
> |
|
<View style={styles.productInquirySection1}> |
|
<LinearGradient |
|
colors={["#C8DFFF", "#ECF5FF"]} |
|
style={styles.headerGradient} |
|
start={{ x: 0, y: 0 }} |
|
end={{ x: 0, y: 1 }} |
|
> |
|
<View> |
|
<View style={styles.titleContainer}> |
|
<TouchableOpacity |
|
style={styles.backButton} |
|
onPress={() => navigation.goBack()} |
|
> |
|
<BackIcon size={fontSize(24)} /> |
|
</TouchableOpacity> |
|
<View style={styles.titleTextContainer}> |
|
<Text style={styles.titleText}>图片询盘</Text> |
|
</View> |
|
<View style={styles.placeholder} /> |
|
</View> |
|
|
|
<View style={styles.heardContainer}> |
|
<View> |
|
<Text style={styles.heardContainer1Text}> |
|
通过上传图片,{"\n"}即可获取产品报价 |
|
</Text> |
|
</View> |
|
<View> |
|
<Text style={styles.heardContainer1Img}> |
|
<Image |
|
source={require("../../../assets/img/image_7a9fbefc.png")} |
|
style={styles.heardContainer1Img} |
|
/> |
|
</Text> |
|
</View> |
|
</View> |
|
</View> |
|
</LinearGradient> |
|
|
|
<View style={styles.productQuoteSection}> |
|
<View style={styles.tabContainer}> |
|
{[ |
|
{ label: "请求报价", id: 0 }, |
|
{ label: "进行中", id: 1 }, |
|
{ label: "已完成", id: 2 } |
|
].map((tab) => ( |
|
<TouchableOpacity |
|
key={tab.id} |
|
onPress={() => setActiveTab(tab.id)} |
|
style={[ |
|
styles.tabButton, |
|
activeTab === tab.id && styles.activeTabButton |
|
]} |
|
> |
|
<Text |
|
style={[ |
|
styles.tabButtonText, |
|
activeTab === tab.id && styles.activeTabButtonText |
|
]} |
|
> |
|
{tab.label} |
|
</Text> |
|
</TouchableOpacity> |
|
))} |
|
</View> |
|
|
|
{activeTab === 0 && ( |
|
<ScrollView |
|
contentContainerStyle={styles.scrollContent} |
|
keyboardShouldPersistTaps="handled" |
|
showsVerticalScrollIndicator={false} |
|
> |
|
{searchImg ? ( |
|
<View style={styles.container}> |
|
<View style={styles.cardContainerWithButtons}> |
|
<View style={styles.productCardContainer}> |
|
<View style={styles.productCardContainer1}> |
|
<Image |
|
source={ |
|
searchImg |
|
? { uri: searchImg } |
|
: require("../../../assets/img/image_8f3bf967.png") |
|
} |
|
style={styles.articleThumbnailContainer} |
|
/> |
|
<View style={styles.articleTitleContainer}> |
|
<Text style={styles.elegantText}>商品名称</Text> |
|
<TextInput |
|
style={styles.articleTitleContainer1} |
|
value={formData.name} |
|
onChangeText={(text) => |
|
setFormData((prev) => ({ ...prev, name: text })) |
|
} |
|
placeholder="请输入商品名称" |
|
/> |
|
</View> |
|
</View> |
|
<View style={styles.flexRowWithContent}> |
|
<View style={styles.centerColumnWithText}> |
|
<Text style={styles.quantityLabelTextStyle}> |
|
<Text style={styles.highlightedText}>*</Text> |
|
<Text>数量</Text> |
|
</Text> |
|
<TextInput |
|
style={styles.quantityContainer} |
|
value={formData.quantity} |
|
onChangeText={(text) => |
|
setFormData((prev) => ({ |
|
...prev, |
|
quantity: text, |
|
})) |
|
} |
|
placeholder="请输入数量" |
|
keyboardType="numeric" |
|
/> |
|
</View> |
|
<View style={styles.matiereContainer}> |
|
<Text style={styles.quantityLabelTextStyle}> |
|
材质 |
|
</Text> |
|
<TextInput |
|
style={styles.quantityContainer} |
|
value={formData.material} |
|
onChangeText={(text) => |
|
setFormData((prev) => ({ |
|
...prev, |
|
material: text, |
|
})) |
|
} |
|
placeholder="请输入材质" |
|
/> |
|
</View> |
|
</View> |
|
<View style={styles.linkContainer}> |
|
<Text style={styles.elegantText}>链接</Text> |
|
<TextInput |
|
style={styles.contentWrapper} |
|
value={formData.link} |
|
onChangeText={(text) => |
|
setFormData((prev) => ({ ...prev, link: text })) |
|
} |
|
placeholder="请输入链接" |
|
multiline={true} |
|
/> |
|
</View> |
|
<View style={styles.linkContainer}> |
|
<Text style={styles.elegantText}>备注</Text> |
|
<TextInput |
|
style={styles.contentWrapper} |
|
value={formData.remark} |
|
onChangeText={(text) => |
|
setFormData((prev) => ({ ...prev, remark: text })) |
|
} |
|
placeholder="请输入备注" |
|
multiline={true} |
|
/> |
|
</View> |
|
</View> |
|
<View style={styles.buttonGroupConfirmation}> |
|
<TouchableOpacity |
|
style={styles.cancelButtonStyle} |
|
onPress={() => setSearchImg("")} |
|
> |
|
<Text style={styles.cancelButtonText}>取消</Text> |
|
</TouchableOpacity> |
|
<TouchableOpacity |
|
style={[ |
|
styles.confirmButtonStyle, |
|
isSubmitting && styles.disabledButton, |
|
]} |
|
onPress={handleSubmit} |
|
disabled={isSubmitting} |
|
> |
|
<Text style={styles.confirmButtonText}> |
|
{isSubmitting ? "提交中..." : "确认"} |
|
</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
</View> |
|
) : ( |
|
<View style={styles.productInfoContainer}> |
|
<View style={styles.productImageUploadSection}> |
|
<View style={styles.productInfoContainer1}> |
|
<Image |
|
source={require("../../../assets/img/image_fac2b0a9.png")} |
|
style={styles.productImageIcon} |
|
resizeMode="cover" |
|
/> |
|
<View style={styles.productQuoteContainer}> |
|
<Text style={styles.productInfoHeading}> |
|
通过图片获取产品报价 |
|
</Text> |
|
<Text style={styles.productInfoMessage1}> |
|
上传产品图片,{"\n"}我们将为您提供详细报价{"\n"} |
|
和产品信息。 |
|
</Text> |
|
</View> |
|
</View> |
|
<View style={styles.photoUploadContainer}> |
|
<TouchableOpacity |
|
style={styles.photoUploadContainer1} |
|
onPress={updataImg} |
|
> |
|
<LinearGradient |
|
colors={["#F5F9FF", "#D8E8FF", "#B9D6FF"]} |
|
style={styles.gradientBackground} |
|
start={{ x: 0, y: 0 }} |
|
end={{ x: 0, y: 1 }} |
|
> |
|
<View style={styles.photoUploadPromptContainer}> |
|
<Text style={styles.centerHeadingBoldWhite}> |
|
拍照或上传图片 |
|
</Text> |
|
</View> |
|
</LinearGradient> |
|
</TouchableOpacity> |
|
</View> |
|
</View> |
|
</View> |
|
)} |
|
</ScrollView> |
|
)} |
|
</View> |
|
</View> |
|
|
|
{activeTab === 1 && ( |
|
<ScrollView |
|
style={{ flex: 1, backgroundColor: "white" }} |
|
contentContainerStyle={{ paddingBottom: 16 }} |
|
onScroll={handleScroll} |
|
scrollEventThrottle={16} |
|
> |
|
{inquiries.length > 0 ? ( |
|
<> |
|
{inquiries.map((inquiry, index) => ( |
|
<View |
|
key={inquiry.id || index} |
|
style={{ |
|
backgroundColor: "#f2f6ff", |
|
borderRadius: 16, |
|
margin: 16, |
|
marginBottom: 8, |
|
shadowColor: "#000", |
|
shadowOpacity: 0.05, |
|
shadowRadius: 4, |
|
elevation: 2, |
|
}} |
|
> |
|
{/* 顶部蓝色条 */} |
|
<View |
|
style={{ |
|
backgroundColor: "#c8e0ff", |
|
borderTopLeftRadius: 16, |
|
borderTopRightRadius: 16, |
|
flexDirection: "row", |
|
justifyContent: "space-between", |
|
alignItems: "center", |
|
paddingHorizontal: 20, |
|
paddingVertical: 10, |
|
}} |
|
> |
|
<Text |
|
style={{ color: "#006fe1", fontWeight: "bold", fontSize: 16 }} |
|
> |
|
Devis en cours |
|
</Text> |
|
<Text style={{ color: "#006fe1", fontSize: 14 }}> |
|
{inquiry.create_time || new Date().toLocaleString()} |
|
</Text> |
|
</View> |
|
{/* 内容区 */} |
|
<View |
|
style={{ |
|
flexDirection: "row", |
|
padding: 20, |
|
backgroundColor: "#f2f6ff", |
|
borderBottomLeftRadius: 16, |
|
borderBottomRightRadius: 16, |
|
}} |
|
> |
|
<Image |
|
source={ |
|
inquiry.image_url |
|
? { uri: inquiry.image_url } |
|
: require("../../../assets/img/image_8f3bf967.png") |
|
} |
|
style={{ |
|
width: 80, |
|
height: 80, |
|
borderRadius: 8, |
|
marginRight: 18, |
|
backgroundColor: "#fff", |
|
}} |
|
/> |
|
<View style={{ flex: 1 }}> |
|
<Text |
|
style={{ |
|
fontWeight: "bold", |
|
fontSize: 18, |
|
marginBottom: 8, |
|
}} |
|
> |
|
{inquiry.name || "Nom d'article"} |
|
</Text> |
|
<View style={{ flexDirection: "row", marginBottom: 8 }}> |
|
<View> |
|
<Text style={{ color: "#888", fontSize: 14 }}> |
|
Quantité |
|
</Text> |
|
<Text style={{ fontSize: 16, fontWeight: "bold" }}> |
|
{inquiry.quantity || "--"} |
|
</Text> |
|
</View> |
|
<View style={{ marginLeft: 32 }}> |
|
<Text style={{ color: "#888", fontSize: 14 }}> |
|
Matière |
|
</Text> |
|
<Text style={{ fontSize: 16, fontWeight: "bold" }}> |
|
{inquiry.material || "--"} |
|
</Text> |
|
</View> |
|
</View> |
|
<View |
|
style={{ |
|
flexDirection: "row", |
|
alignItems: "center", |
|
marginBottom: 4, |
|
}} |
|
> |
|
<Text |
|
style={{ color: "#888", fontSize: 14, marginRight: 8 }} |
|
> |
|
Lien |
|
</Text> |
|
<Text style={{ flex: 1, fontSize: 14 }} numberOfLines={1}> |
|
{inquiry.link || "无"} |
|
</Text> |
|
<View style={{ flexDirection: "row", alignItems: "center", marginLeft: 8 }}> |
|
<Text style={{ color: "#888" }}>Plus</Text> |
|
<View style={{ marginLeft: 4 }}> |
|
<DownArrowIcon size={12} color="#888" rotation={0} /> |
|
</View> |
|
</View> |
|
</View> |
|
<View style={{ flexDirection: "row", alignItems: "center" }}> |
|
<Text |
|
style={{ color: "#888", fontSize: 14, marginRight: 8 }} |
|
> |
|
Remarque |
|
</Text> |
|
<Text style={{ flex: 1, fontSize: 14 }} numberOfLines={1}> |
|
{inquiry.remark || "无"} |
|
</Text> |
|
<View style={{ flexDirection: "row", alignItems: "center", marginLeft: 8 }}> |
|
<Text style={{ color: "#888" }}>Plus</Text> |
|
<View style={{ marginLeft: 4 }}> |
|
<DownArrowIcon size={12} color="#888" rotation={0} /> |
|
</View> |
|
</View> |
|
</View> |
|
</View> |
|
</View> |
|
</View> |
|
))} |
|
{/* 底部加载更多 */} |
|
{loading && ( |
|
<View style={styles.loadingContainer}> |
|
<Text style={styles.loadingText}>加载中...</Text> |
|
</View> |
|
)} |
|
{!hasMore && inquiries.length > 0 && ( |
|
<Text style={styles.noMoreText}>没有更多数据了</Text> |
|
)} |
|
</> |
|
) : loading ? ( |
|
<View style={styles.loadingContainer}> |
|
<Text style={styles.loadingText}>加载中...</Text> |
|
</View> |
|
) : ( |
|
<View style={styles.emptyContainer}> |
|
<Text style={styles.emptyText}>暂无进行中的询盘</Text> |
|
</View> |
|
)} |
|
</ScrollView> |
|
)} |
|
{activeTab === 2 && ( |
|
<ScrollView |
|
style={{ flex: 1, backgroundColor: "white" }} |
|
contentContainerStyle={{ paddingBottom: 16 }} |
|
onScroll={handleScroll} |
|
scrollEventThrottle={16} |
|
> |
|
{completedInquiries.length > 0 ? ( |
|
<> |
|
{completedInquiries.map((inquiry, index) => ( |
|
<View |
|
key={inquiry.id || index} |
|
style={{ |
|
backgroundColor: "#f2f6ff", |
|
borderRadius: 16, |
|
margin: 16, |
|
marginBottom: 8, |
|
shadowColor: "#000", |
|
shadowOpacity: 0.05, |
|
shadowRadius: 4, |
|
elevation: 2, |
|
}} |
|
> |
|
{/* 顶部蓝色条 */} |
|
<View |
|
style={{ |
|
backgroundColor: "#c8e0ff", |
|
borderTopLeftRadius: 16, |
|
borderTopRightRadius: 16, |
|
flexDirection: "row", |
|
justifyContent: "space-between", |
|
alignItems: "center", |
|
paddingHorizontal: 20, |
|
paddingVertical: 10, |
|
}} |
|
> |
|
<Text |
|
style={{ color: "#006fe1", fontWeight: "bold", fontSize: 16 }} |
|
> |
|
Devis terminé |
|
</Text> |
|
<Text style={{ color: "#006fe1", fontSize: 14 }}> |
|
{inquiry.create_time || new Date().toLocaleString()} |
|
</Text> |
|
</View> |
|
{/* 内容区 */} |
|
<View |
|
style={{ |
|
flexDirection: "row", |
|
padding: 20, |
|
backgroundColor: "#f2f6ff", |
|
borderBottomLeftRadius: 16, |
|
borderBottomRightRadius: 16, |
|
}} |
|
> |
|
<Image |
|
source={ |
|
inquiry.image_url |
|
? { uri: inquiry.image_url } |
|
: require("../../../assets/img/image_8f3bf967.png") |
|
} |
|
style={{ |
|
width: 80, |
|
height: 80, |
|
borderRadius: 8, |
|
marginRight: 18, |
|
backgroundColor: "#fff", |
|
}} |
|
/> |
|
<View style={{ flex: 1 }}> |
|
<Text |
|
style={{ |
|
fontWeight: "bold", |
|
fontSize: 18, |
|
marginBottom: 8, |
|
}} |
|
> |
|
{inquiry.name || "Nom d'article"} |
|
</Text> |
|
<View style={{ flexDirection: "row", marginBottom: 8 }}> |
|
<View> |
|
<Text style={{ color: "#888", fontSize: 14 }}> |
|
Quantité |
|
</Text> |
|
<Text style={{ fontSize: 16, fontWeight: "bold" }}> |
|
{inquiry.quantity || "--"} |
|
</Text> |
|
</View> |
|
<View style={{ marginLeft: 32 }}> |
|
<Text style={{ color: "#888", fontSize: 14 }}> |
|
Matière |
|
</Text> |
|
<Text style={{ fontSize: 16, fontWeight: "bold" }}> |
|
{inquiry.material || "--"} |
|
</Text> |
|
</View> |
|
</View> |
|
<View |
|
style={{ |
|
flexDirection: "row", |
|
alignItems: "center", |
|
marginBottom: 4, |
|
}} |
|
> |
|
<Text |
|
style={{ color: "#888", fontSize: 14, marginRight: 8 }} |
|
> |
|
Lien |
|
</Text> |
|
<Text style={{ flex: 1, fontSize: 14 }} numberOfLines={1}> |
|
{inquiry.link || "无"} |
|
</Text> |
|
<View style={{ flexDirection: "row", alignItems: "center", marginLeft: 8 }}> |
|
<Text style={{ color: "#888" }}>Plus</Text> |
|
<View style={{ marginLeft: 4 }}> |
|
<DownArrowIcon size={12} color="#888" rotation={0} /> |
|
</View> |
|
</View> |
|
</View> |
|
<View style={{ flexDirection: "row", alignItems: "center" }}> |
|
<Text |
|
style={{ color: "#888", fontSize: 14, marginRight: 8 }} |
|
> |
|
Remarque |
|
</Text> |
|
<Text style={{ flex: 1, fontSize: 14 }} numberOfLines={1}> |
|
{inquiry.remark || "无"} |
|
</Text> |
|
<View style={{ flexDirection: "row", alignItems: "center", marginLeft: 8 }}> |
|
<Text style={{ color: "#888" }}>Plus</Text> |
|
<View style={{ marginLeft: 4 }}> |
|
<DownArrowIcon size={12} color="#888" rotation={0} /> |
|
</View> |
|
</View> |
|
</View> |
|
</View> |
|
</View> |
|
</View> |
|
))} |
|
{/* 底部加载更多 */} |
|
{loading && ( |
|
<View style={styles.loadingContainer}> |
|
<Text style={styles.loadingText}>加载中...</Text> |
|
</View> |
|
)} |
|
{!hasMore && completedInquiries.length > 0 && ( |
|
<Text style={styles.noMoreText}>没有更多数据了</Text> |
|
)} |
|
</> |
|
) : loading ? ( |
|
<View style={styles.loadingContainer}> |
|
<Text style={styles.loadingText}>加载中...</Text> |
|
</View> |
|
) : ( |
|
<View style={styles.emptyContainer}> |
|
<Text style={styles.emptyText}>暂无已完成的询盘</Text> |
|
</View> |
|
)} |
|
</ScrollView> |
|
)} |
|
</KeyboardAvoidingView> |
|
|
|
{/* Image Picker Modal */} |
|
<Modal |
|
visible={showImagePickerModal} |
|
animationType="slide" |
|
transparent={true} |
|
onRequestClose={() => setShowImagePickerModal(false)} |
|
> |
|
<TouchableOpacity |
|
style={styles.imagePickerOverlay} |
|
activeOpacity={1} |
|
onPress={() => setShowImagePickerModal(false)} |
|
> |
|
<View style={styles.imagePickerContent}> |
|
{!galleryUsed ? ( |
|
<TouchableOpacity |
|
style={styles.imagePickerOption} |
|
onPress={handleTakePhoto} |
|
> |
|
<Text style={styles.imagePickerText}>拍照</Text> |
|
</TouchableOpacity> |
|
) : ( |
|
<TouchableOpacity |
|
style={styles.imagePickerOption} |
|
onPress={resetAppState} |
|
> |
|
<Text style={styles.imagePickerText}>重置相机功能</Text> |
|
</TouchableOpacity> |
|
)} |
|
|
|
<View style={styles.imagePickerDivider} /> |
|
|
|
<TouchableOpacity |
|
style={styles.imagePickerOption} |
|
onPress={handleChooseFromGallery} |
|
> |
|
<Text style={styles.imagePickerText}>从相册选择</Text> |
|
</TouchableOpacity> |
|
|
|
<TouchableOpacity |
|
style={styles.imagePickerCancelButton} |
|
onPress={() => setShowImagePickerModal(false)} |
|
> |
|
<Text style={styles.imagePickerCancelText}>取消</Text> |
|
</TouchableOpacity> |
|
</View> |
|
</TouchableOpacity> |
|
</Modal> |
|
</SafeAreaView> |
|
); |
|
}; |
|
|
|
const styles = StyleSheet.create({ |
|
safeArea: { |
|
flex: 1, |
|
backgroundColor: "#C8DFFF", |
|
}, |
|
keyboardAvoidingContainer: { |
|
flex: 1, |
|
width: "100%", |
|
}, |
|
container: { |
|
flex: 1, |
|
width: "100%", |
|
}, |
|
scrollContent: { |
|
flexGrow: 1, |
|
}, |
|
productInquirySection1: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
backgroundColor: "#f0f0f0", |
|
}, |
|
titleContainer: { |
|
paddingHorizontal: 16, |
|
paddingTop: 16, |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "space-between", |
|
}, |
|
backButton: { |
|
width: widthUtils(24, 24).width, |
|
}, |
|
titleTextContainer: { |
|
flex: 1, |
|
alignItems: "center", |
|
}, |
|
titleText: { |
|
fontSize: fontSize(18), |
|
fontWeight: "600", |
|
textAlign: "center", |
|
}, |
|
placeholder: { |
|
width: widthUtils(24, 24).width, |
|
opacity: 0, |
|
}, |
|
heardContainer: { |
|
paddingLeft: 16, |
|
paddingRight: 16, |
|
flexDirection: "row", |
|
justifyContent: "space-between", |
|
height: 234, |
|
marginTop: 50, |
|
}, |
|
|
|
heardContainer1Text: { |
|
fontSize: 16, |
|
fontWeight: 400, |
|
color: "#000", |
|
}, |
|
heardContainer1Img: { |
|
width: 116, |
|
height: 116, |
|
}, |
|
productQuoteSection: { |
|
paddingRight: 16, |
|
paddingLeft: 16, |
|
marginTop: -110, |
|
}, |
|
tabContainer: { |
|
flexDirection: "row", |
|
justifyContent: "space-between", |
|
paddingHorizontal: 16, |
|
marginBottom: 16, |
|
}, |
|
tabButton: { |
|
width: (widthUtils(375, 375).width - 64) / 3, |
|
height: 44, |
|
backgroundColor: "#f5f8ff", |
|
borderRadius: 8, |
|
alignItems: "center", |
|
justifyContent: "center", |
|
borderWidth: 1, |
|
borderColor: "#e0e0e0", |
|
}, |
|
activeTabButton: { |
|
backgroundColor: "#006fe1", |
|
borderColor: "#006fe1", |
|
shadowColor: "#006fe1", |
|
shadowOpacity: 0.2, |
|
shadowRadius: 4, |
|
elevation: 2, |
|
}, |
|
tabButtonText: { |
|
color: "#888", |
|
fontWeight: "500", |
|
fontSize: 14, |
|
}, |
|
activeTabButtonText: { |
|
color: "#fff", |
|
fontWeight: "bold", |
|
}, |
|
productInfoContainer: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "center", |
|
backgroundColor: "#0766e9", |
|
borderBottomLeftRadius: 10, |
|
borderBottomRightRadius: 10, |
|
paddingHorizontal: 16, |
|
paddingTop: 16, |
|
}, |
|
productImageUploadSection: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "flex-start", |
|
maxWidth: "100%", |
|
height: 300, |
|
paddingBottom: 24, |
|
borderBottomLeftRadius: 10, |
|
borderBottomRightRadius: 10, |
|
}, |
|
productInfoContainer1: { |
|
flexDirection: "column", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
paddingTop: 24, |
|
paddingBottom: 22, |
|
paddingLeft: 29, |
|
paddingRight: 29, |
|
}, |
|
productImageIcon: { |
|
width: 60, |
|
height: 60, |
|
borderWidth: 0, |
|
}, |
|
productQuoteContainer: { |
|
flexDirection: "column", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
marginTop: 15, |
|
}, |
|
productInfoHeading: { |
|
fontWeight: "900", |
|
fontSize: 16, |
|
lineHeight: 20, |
|
color: "white", |
|
}, |
|
productInfoMessage1: { |
|
marginTop: 7, |
|
fontWeight: "400", |
|
fontSize: 12, |
|
lineHeight: 16, |
|
color: "white", |
|
textAlign: "center", |
|
}, |
|
photoUploadContainer: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "center", |
|
height: widthUtils(80, 80).height, |
|
paddingRight: 29, |
|
paddingLeft: 29, |
|
}, |
|
photoUploadContainer1: { |
|
flexDirection: "column", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
borderRadius: 30, |
|
shadowColor: "#fd5000", |
|
shadowOffset: { width: 2, height: 3 }, |
|
shadowOpacity: 0.2, |
|
shadowRadius: 4, |
|
elevation: 3, |
|
overflow: "hidden", |
|
height: "100%", |
|
}, |
|
gradientBackground: { |
|
width: "100%", |
|
height: "100%", |
|
justifyContent: "center", |
|
alignItems: "center", |
|
}, |
|
photoUploadPromptContainer: { |
|
flexDirection: "column", |
|
alignItems: "flex-end", |
|
justifyContent: "center", |
|
height: "100%", |
|
paddingRight: 20, |
|
}, |
|
centerHeadingBoldWhite: { |
|
fontWeight: "700", |
|
fontSize: 16, |
|
lineHeight: 20, |
|
color: "#002FA7", |
|
textAlign: "right", |
|
}, |
|
headerGradient: { |
|
paddingBottom: 20, |
|
}, |
|
labelItemTextThree: { |
|
position: "absolute", |
|
color: "#808080", |
|
fontSize: 14, |
|
fontWeight: "600", |
|
width: "33%", |
|
textAlign: "center", |
|
paddingHorizontal: 10, |
|
flexWrap: "wrap", |
|
lineHeight: 16, |
|
right: 0, |
|
top: "50%", |
|
transform: [{ translateY: -8 }], |
|
}, |
|
cardContainerWithButtons: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "center", |
|
paddingVertical: 20, |
|
paddingHorizontal: 16, |
|
paddingBottom: 38, |
|
backgroundColor: "white", |
|
borderBottomLeftRadius: 10, |
|
borderBottomRightRadius: 10, |
|
}, |
|
productCardContainer: { |
|
flexDirection: "column", |
|
gap: 18, |
|
alignItems: "stretch", |
|
justifyContent: "flex-start", |
|
paddingTop: 26, |
|
paddingRight: 28, |
|
paddingBottom: 23, |
|
paddingLeft: 24, |
|
backgroundColor: "#f2f6ff", |
|
}, |
|
productCardContainer1: { |
|
flexDirection: "row", |
|
alignItems: "flex-end", |
|
justifyContent: "flex-start", |
|
}, |
|
articleThumbnailContainer: { |
|
width: 76, |
|
height: 76, |
|
borderWidth: 0, |
|
borderRadius: 5, |
|
resizeMode: "cover", |
|
}, |
|
articleTitleContainer: { |
|
width: widthUtils(221, 221).width, |
|
marginLeft: 11, |
|
}, |
|
elegantText: { |
|
padding: 0, |
|
margin: 0, |
|
fontFamily: "PingFang SC", |
|
fontSize: 12, |
|
fontWeight: "500", |
|
color: "#676b74", |
|
}, |
|
articleTitleContainer1: { |
|
width: "100%", |
|
height: 50, |
|
marginTop: 9, |
|
backgroundColor: "white", |
|
}, |
|
flexRowWithContent: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "flex-start", |
|
}, |
|
centerColumnWithText: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "center", |
|
width: widthUtils(152, 152).width, |
|
}, |
|
quantityLabelTextStyle: { |
|
padding: 0, |
|
margin: 0, |
|
fontFamily: "PingFang SC", |
|
fontSize: 12, |
|
fontWeight: "500", |
|
color: "#676b74", |
|
}, |
|
highlightedText: { |
|
fontFamily: "PingFang SC", |
|
fontSize: 12, |
|
fontWeight: "500", |
|
color: "#fe1e00", |
|
}, |
|
quantityContainer: { |
|
height: 40, |
|
backgroundColor: "white", |
|
}, |
|
matiereContainer: { |
|
flexDirection: "column", |
|
alignItems: "stretch", |
|
justifyContent: "center", |
|
width: widthUtils(151, 151).width, |
|
marginLeft: 7, |
|
}, |
|
linkContainer: {}, |
|
contentWrapper: { |
|
width: "100%", |
|
height: 70, |
|
backgroundColor: "white", |
|
}, |
|
buttonGroupConfirmation: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
justifyContent: "center", |
|
marginTop: 26, |
|
marginRight: 14, |
|
marginLeft: 9, |
|
}, |
|
cancelButtonStyle: { |
|
width: 160, |
|
minWidth: 160, |
|
height: 46, |
|
justifyContent: "center", |
|
alignItems: "center", |
|
backgroundColor: "#f2f3f5", |
|
borderRadius: 43, |
|
}, |
|
confirmButtonStyle: { |
|
width: 160, |
|
minWidth: 160, |
|
height: 46, |
|
marginLeft: 19, |
|
justifyContent: "center", |
|
alignItems: "center", |
|
backgroundColor: "#002fa7", |
|
borderRadius: 43, |
|
}, |
|
cancelButtonText: { |
|
fontFamily: "Source Han Sans CN", |
|
fontSize: 16, |
|
fontWeight: "500", |
|
lineHeight: 22, |
|
color: "#333333", |
|
}, |
|
confirmButtonText: { |
|
fontFamily: "Source Han Sans CN", |
|
fontSize: 16, |
|
fontWeight: "500", |
|
lineHeight: 22, |
|
color: "white", |
|
}, |
|
imagePickerOverlay: { |
|
flex: 1, |
|
backgroundColor: "rgba(0, 0, 0, 0.5)", |
|
justifyContent: "flex-end", |
|
}, |
|
imagePickerContent: { |
|
backgroundColor: "#fff", |
|
borderTopLeftRadius: 20, |
|
borderTopRightRadius: 20, |
|
paddingTop: 20, |
|
}, |
|
imagePickerOption: { |
|
flexDirection: "row", |
|
alignItems: "center", |
|
paddingVertical: 16, |
|
paddingHorizontal: 20, |
|
}, |
|
imagePickerText: { |
|
fontSize: fontSize(16), |
|
marginLeft: 12, |
|
color: "#333", |
|
}, |
|
imagePickerDivider: { |
|
height: 1, |
|
backgroundColor: "#f0f0f0", |
|
marginHorizontal: 20, |
|
}, |
|
imagePickerCancelButton: { |
|
alignItems: "center", |
|
paddingVertical: 16, |
|
marginTop: 8, |
|
borderTopWidth: 1, |
|
borderTopColor: "#f0f0f0", |
|
}, |
|
imagePickerCancelText: { |
|
fontSize: fontSize(16), |
|
color: "#999", |
|
}, |
|
disabledButton: { |
|
opacity: 0.7, |
|
}, |
|
loadingContainer: { |
|
padding: 16, |
|
alignItems: "center", |
|
justifyContent: "center", |
|
}, |
|
loadingText: { |
|
color: "#888", |
|
fontSize: 14, |
|
}, |
|
noMoreText: { |
|
textAlign: "center", |
|
color: "#888", |
|
fontSize: 14, |
|
padding: 16, |
|
}, |
|
emptyContainer: { |
|
flex: 1, |
|
padding: 32, |
|
alignItems: "center", |
|
justifyContent: "center", |
|
backgroundColor: "white", |
|
margin: 16, |
|
borderRadius: 16, |
|
}, |
|
emptyText: { |
|
color: "#888", |
|
fontSize: 16, |
|
}, |
|
});
|
|
|