feat: ask页面

This commit is contained in:
jinyaqiu 2025-08-06 18:57:18 +08:00
parent 142c8e44b6
commit 53efa37fb6
8 changed files with 117 additions and 55 deletions

View File

@ -149,13 +149,7 @@ const MemoList = () => {
onPress={() => handleMemoPress(item)} onPress={() => handleMemoPress(item)}
activeOpacity={0.7} activeOpacity={0.7}
> >
<View className="w-[3rem] h-[3rem] z-1"> <ChatSvg />
<ChatSvg
width="100%"
height="100%"
preserveAspectRatio="xMidYMid meet"
/>
</View>
<View style={styles.memoContent}> <View style={styles.memoContent}>
<Text <Text
style={styles.memoTitle} style={styles.memoTitle}
@ -316,6 +310,7 @@ const styles = StyleSheet.create({
flex: 1, flex: 1,
marginLeft: 12, marginLeft: 12,
justifyContent: 'center', justifyContent: 'center',
gap: 2
}, },
memoTitle: { memoTitle: {
fontSize: 16, fontSize: 16,

View File

@ -1,26 +1,26 @@
<svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="60" height="60" viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="30" cy="30" r="30" fill="white"/> <circle cx="30" cy="30" r="30" fill="white"/>
<mask id="chat_mask0_555_1115" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="60" height="60"> <mask id="mask0_106_1225" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="60" height="60">
<circle cx="30" cy="30" r="30" fill="white"/> <circle cx="30" cy="30" r="30" fill="white"/>
</mask> </mask>
<g mask="url(#chat_mask0_555_1115)"> <g mask="url(#mask0_106_1225)">
<path d="M-12.302 16.2692C6.49892 -16.2949 53.5011 -16.2949 72.302 16.2692L85.1259 38.4808C103.927 71.0449 80.4256 111.75 42.8238 111.75H17.1762C-20.4256 111.75 -43.9267 71.0449 -25.1258 38.4808L-12.302 16.2692Z" fill="#FFD18A"/> <path d="M-12.302 16.2692C6.49892 -16.2949 53.5011 -16.2949 72.302 16.2692L85.1259 38.4808C103.927 71.0449 80.4256 111.75 42.8238 111.75H17.1762C-20.4256 111.75 -43.9267 71.0449 -25.1258 38.4808L-12.302 16.2692Z" fill="#FFD18A"/>
<rect x="27.116" y="14.1538" width="1.92308" height="2.69231" rx="0.961539" transform="rotate(-180 27.116 14.1538)" fill="#4C320C"/> <rect x="27.1162" y="14.1539" width="1.92308" height="2.69231" rx="0.961539" transform="rotate(-180 27.1162 14.1539)" fill="#4C320C"/>
<rect x="34.0383" y="14.1538" width="1.92308" height="2.69231" rx="0.961539" transform="rotate(-180 34.0383 14.1538)" fill="#4C320C"/> <rect x="34.0381" y="14.1539" width="1.92308" height="2.69231" rx="0.961539" transform="rotate(-180 34.0381 14.1539)" fill="#4C320C"/>
<path d="M2.43174 33.8473C15.7285 14.5172 44.2728 14.5172 57.5695 33.8473L72.7134 55.8628C87.985 78.0639 72.0909 108.288 45.1445 108.288H14.8567C-12.0897 108.288 -27.9838 78.0639 -12.7122 55.8628L2.43174 33.8473Z" fill="#FFF8DE"/> <path d="M2.43174 33.8474C15.7285 14.5173 44.2728 14.5173 57.5695 33.8474L72.7134 55.8629C87.985 78.064 72.0909 108.288 45.1445 108.288H14.8567C-12.0897 108.288 -27.9838 78.064 -12.7122 55.8629L2.43174 33.8474Z" fill="#FFF8DE"/>
<g filter="url(#filter0_i_555_1115)"> <g filter="url(#filter0_i_106_1225)">
<ellipse cx="56.7313" cy="30.5" rx="31.5385" ry="22.5" fill="#FFF8DE"/> <ellipse cx="56.7318" cy="30.5001" rx="31.5385" ry="22.5" fill="#FFF8DE"/>
</g> </g>
<g filter="url(#filter1_i_555_1115)"> <g filter="url(#filter1_i_106_1225)">
<ellipse cx="3.07711" cy="30.5" rx="31.3462" ry="22.5" fill="#FFF8DE"/> <ellipse cx="3.07662" cy="30.5001" rx="31.3462" ry="22.5" fill="#FFF8DE"/>
</g> </g>
<ellipse cx="29.8075" cy="19.3464" rx="2.30769" ry="1.73077" transform="rotate(180 29.8075 19.3464)" fill="#FFB8B9"/> <ellipse cx="29.8075" cy="19.3463" rx="2.30769" ry="1.73077" transform="rotate(180 29.8075 19.3463)" fill="#FFB8B9"/>
<ellipse cx="5.49476" cy="2.19199" rx="5.49476" ry="2.19199" transform="matrix(0.912659 0.408721 0.408721 -0.912659 41.571 57.001)" fill="#FFD38D"/> <ellipse cx="5.49476" cy="2.19199" rx="5.49476" ry="2.19199" transform="matrix(0.912659 0.408721 0.408721 -0.912659 41.5713 57.0012)" fill="#FFD38D"/>
<ellipse cx="12.2567" cy="57.2463" rx="5.49476" ry="2.19199" transform="rotate(155.875 12.2567 57.2463)" fill="#FFD38D"/> <ellipse cx="12.2572" cy="57.2465" rx="5.49476" ry="2.19199" transform="rotate(155.875 12.2572 57.2465)" fill="#FFD38D"/>
<path d="M29.4743 21.2693C29.6224 21.0129 29.9925 21.0129 30.1405 21.2693L30.4736 21.8462C30.6216 22.1026 30.4366 22.4232 30.1405 22.4232H29.4743C29.1782 22.4232 28.9932 22.1026 29.1412 21.8462L29.4743 21.2693Z" fill="#4C320C"/> <path d="M29.4741 21.2693C29.6221 21.0129 29.9922 21.0129 30.1403 21.2693L30.4733 21.8462C30.6214 22.1026 30.4363 22.4232 30.1403 22.4232H29.4741C29.178 22.4232 28.993 22.1026 29.141 21.8462L29.4741 21.2693Z" fill="#4C320C"/>
</g> </g>
<defs> <defs>
<filter id="chat_filter0_i_555_1115" x="21.7313" y="8" width="66.5384" height="46.1538" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> <filter id="filter0_i_106_1225" x="21.7318" y="8.00012" width="66.5387" height="46.1538" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/> <feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/> <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
@ -28,9 +28,9 @@
<feGaussianBlur stdDeviation="3.17308"/> <feGaussianBlur stdDeviation="3.17308"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/> <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.713726 0 0 0 0 0.270588 0 0 0 1 0"/> <feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.713726 0 0 0 0 0.270588 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_555_1115"/> <feBlend mode="normal" in2="shape" result="effect1_innerShadow_106_1225"/>
</filter> </filter>
<filter id="chat_filter1_i_555_1115" x="-28.269" y="8" width="66.5385" height="45" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> <filter id="filter1_i_106_1225" x="-28.2695" y="8.00012" width="66.5385" height="45" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/> <feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/> <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
@ -38,7 +38,7 @@
<feGaussianBlur stdDeviation="2.11538"/> <feGaussianBlur stdDeviation="2.11538"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/> <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.713974 0 0 0 0 0.272498 0 0 0 1 0"/> <feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.713974 0 0 0 0 0.272498 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_555_1115"/> <feBlend mode="normal" in2="shape" result="effect1_innerShadow_106_1225"/>
</filter> </filter>
</defs> </defs>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,19 @@
<svg width="402" height="154" viewBox="0 0 402 154" fill="none" xmlns="http://www.w3.org/2000/svg">
<ellipse cx="18.1921" cy="109.346" rx="5.76923" ry="2.5" fill="#AC7E35"/>
<ellipse cx="80.4997" cy="108.192" rx="5.76923" ry="2.5" fill="#AC7E35"/>
<g filter="url(#filter0_d_0_1)">
<path d="M434.5 115C434.5 136.539 417.039 154 395.5 154H9C-12.5391 154 -30 136.539 -30 115V108C-30 86.4609 -12.5391 69 9 69H128.878C135.302 69 140 75.0761 140 81.5C140 110.495 163.505 134 192.5 134C221.495 134 245 110.495 245 81.5C245 75.0761 249.698 69 256.122 69H395.5C417.039 69 434.5 86.4609 434.5 108V115Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d_0_1" x="-39.1" y="57.9" width="482.7" height="103.2" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-2"/>
<feGaussianBlur stdDeviation="4.55"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_0_1"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_0_1" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -304,6 +304,7 @@ const styles = StyleSheet.create({
borderRadius: 25, borderRadius: 25,
paddingHorizontal: 20, paddingHorizontal: 20,
paddingVertical: 13, paddingVertical: 13,
lineHeight: 20,
fontSize: 16, fontSize: 16,
width: '100%', // 确保输入框宽度撑满 width: '100%', // 确保输入框宽度撑满
paddingRight: 50 paddingRight: 50

View File

@ -1,11 +1,11 @@
import React from 'react';
import { View, Pressable, Image, StyleSheet } from 'react-native';
import ContextMenu from "../../gusture/contextMenu";
import DownloadSvg from "@/assets/icons/svg/download.svg";
import CancelSvg from "@/assets/icons/svg/cancel.svg"; import CancelSvg from "@/assets/icons/svg/cancel.svg";
import DownloadSvg from "@/assets/icons/svg/download.svg";
import { ContentPart } from "@/types/ask"; import { ContentPart } from "@/types/ask";
import { TFunction } from 'i18next'; import { TFunction } from 'i18next';
import React from 'react';
import { Image, Pressable, StyleSheet, Text as ThemedText, View } from 'react-native';
import { saveMediaToGallery } from "../../ask/utils"; import { saveMediaToGallery } from "../../ask/utils";
import ContextMenu from "../../gusture/contextMenu";
interface MediaGridProps { interface MediaGridProps {
mediaItems: ContentPart[]; mediaItems: ContentPart[];
@ -16,18 +16,32 @@ interface MediaGridProps {
} }
const MediaGrid = ({ mediaItems, setModalVisible, setCancel, cancel, t }: MediaGridProps) => { const MediaGrid = ({ mediaItems, setModalVisible, setCancel, cancel, t }: MediaGridProps) => {
// 只取前6个元素2行每行3个 // Only show up to 6 images (2 rows of 3)
const displayItems = mediaItems.slice(0, 6); const displayItems = mediaItems.slice(0, 6);
const itemCount = displayItems.length;
// Calculate item width based on number of items
const getItemWidth = () => {
if (itemCount === 1) return '100%';
if (itemCount === 2) return '49%';
return '32%'; // For 3+ items
};
// Calculate container style based on number of items
const getContainerStyle = () => {
if (itemCount === 1) return styles.singleItemContainer;
return styles.multiItemContainer;
};
return ( return (
<View className="flex-row flex-wrap justify-between"> <View style={[styles.container, getContainerStyle()]}>
{displayItems.map((media) => ( {displayItems.map((media, index) => (
<Pressable <Pressable
key={media.id} key={media.id}
onPress={() => { onPress={() => {
setModalVisible({ visible: true, data: media }); setModalVisible({ visible: true, data: media });
}} }}
className="mb-2 w-[32%] aspect-square" style={[styles.imageContainer, { width: getItemWidth() }]}
> >
<ContextMenu <ContextMenu
items={[ items={[
@ -51,7 +65,48 @@ const MediaGrid = ({ mediaItems, setModalVisible, setCancel, cancel, t }: MediaG
} }
]} ]}
cancel={cancel} cancel={cancel}
menuStyle={{ menuStyle={styles.contextMenu}
>
<Image
source={{ uri: media?.url }}
style={styles.image}
resizeMode="cover"
loadingIndicatorSource={require('@/assets/images/png/placeholder.png')}
/>
{itemCount > 3 && index === 5 && mediaItems.length > 6 && (
<View style={styles.overlay}>
<ThemedText style={styles.overlayText}>+{mediaItems.length - 5}</ThemedText>
</View>
)}
</ContextMenu>
</Pressable>
))}
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
},
singleItemContainer: {
width: '100%',
},
multiItemContainer: {
width: '100%',
},
imageContainer: {
marginBottom: 8,
aspectRatio: 1,
},
image: {
width: '100%',
height: '100%',
borderRadius: 8,
},
contextMenu: {
backgroundColor: 'white', backgroundColor: 'white',
borderRadius: 8, borderRadius: 8,
padding: 8, padding: 8,
@ -61,21 +116,19 @@ const MediaGrid = ({ mediaItems, setModalVisible, setCancel, cancel, t }: MediaG
shadowOpacity: 0.25, shadowOpacity: 0.25,
shadowRadius: 4, shadowRadius: 4,
elevation: 5, elevation: 5,
}} },
> overlay: {
<Image ...StyleSheet.absoluteFillObject,
source={{ uri: media?.url }} backgroundColor: 'rgba(0,0,0,0.5)',
className="w-full h-full rounded-xl" borderRadius: 8,
resizeMode="cover" justifyContent: 'center',
loadingIndicatorSource={require('@/assets/images/png/placeholder.png')} alignItems: 'center',
/> },
</ContextMenu> overlayText: {
</Pressable> color: 'white',
))} fontSize: 24,
</View> fontWeight: 'bold',
); },
}; });
export default MediaGrid; export default MediaGrid;

View File

@ -98,13 +98,7 @@ const AskNavbar = ({ wsStatus }: AskNavbarProps) => {
position: 'absolute', position: 'absolute',
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0
backgroundColor: 'white',
shadowColor: '#000',
shadowOffset: { width: 0, height: -4 },
shadowOpacity: 0.1,
shadowRadius: 8,
elevation: 10,
}, },
backgroundImage: { backgroundImage: {
width, width,
@ -132,7 +126,7 @@ const AskNavbar = ({ wsStatus }: AskNavbarProps) => {
centerButton: { centerButton: {
position: 'absolute', position: 'absolute',
left: width / 2, left: width / 2,
top: -42.5, // Adjust this value to move the button up or down top: -30, // Adjust this value to move the button up or down
marginLeft: -42.5, // Half of the button width (85/2) marginLeft: -42.5, // Half of the button width (85/2)
width: 85, width: 85,
height: 85, height: 85,
@ -168,7 +162,7 @@ const AskNavbar = ({ wsStatus }: AskNavbarProps) => {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Image source={require('@/assets/images/png/owner/ask.png')} style={{ width: width, height: 80, resizeMode: 'cover' }} /> <Image source={require('@/assets/images/png/owner/ask.png')} style={{ width: width * 1.18, height: 100, resizeMode: 'cover', marginLeft: -width * 0.07 }} />
<View style={styles.navContainer}> <View style={styles.navContainer}>
<TouchableOpacity <TouchableOpacity
onPress={() => navigateTo('/memo-list')} onPress={() => navigateTo('/memo-list')}
@ -186,7 +180,7 @@ const AskNavbar = ({ wsStatus }: AskNavbarProps) => {
style={styles.centerButton} style={styles.centerButton}
> >
<View style={styles.statusIndicator} /> <View style={styles.statusIndicator} />
<CenterButtonSvg /> <Image source={require('@/assets/images/png/owner/askIP.png')} />
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity <TouchableOpacity