10 changed files with 560 additions and 126 deletions
@ -0,0 +1,57 @@ |
|||||||
|
.goods_info_card_component { |
||||||
|
display: flex; |
||||||
|
align-items: flex-start; |
||||||
|
|
||||||
|
// 商品图片 |
||||||
|
.goods_image { |
||||||
|
width: 208px; |
||||||
|
height: 208px; |
||||||
|
border-radius: 8px; |
||||||
|
flex-shrink: 0; |
||||||
|
} |
||||||
|
|
||||||
|
// 商品信息 |
||||||
|
.goods_info { |
||||||
|
flex: 1; |
||||||
|
margin-left: 30px; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
padding: 10px 0; |
||||||
|
|
||||||
|
.goods_name { |
||||||
|
font-size: 30px; |
||||||
|
color: #000000; |
||||||
|
font-weight: 600; |
||||||
|
line-height: 1.4; |
||||||
|
margin-bottom: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
// 价格行 |
||||||
|
.price_row { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
|
||||||
|
// 有间距的情况(用于订单详情页) |
||||||
|
// &.with_separator { |
||||||
|
margin-top: 56px; // 实现 padding-top: 66px 的效果(66-10=56) |
||||||
|
// } |
||||||
|
|
||||||
|
.price_text { |
||||||
|
font-size: 30px; |
||||||
|
font-weight: 500; |
||||||
|
|
||||||
|
.price_label { |
||||||
|
color: #000000; |
||||||
|
font-weight: 400; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 右侧按钮区域 |
||||||
|
.right_button_area { |
||||||
|
margin-left: 20px; |
||||||
|
flex-shrink: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,72 @@ |
|||||||
|
/** |
||||||
|
* 商品信息卡片组件 |
||||||
|
* 用于商品消费、订单详情、退款结果等页面 |
||||||
|
*/ |
||||||
|
import { View, Text } from '@tarojs/components' |
||||||
|
import { Image } from '@taroify/core' |
||||||
|
import { ReactNode } from 'react' |
||||||
|
import './index.scss' |
||||||
|
|
||||||
|
export interface GoodsInfoCardProps { |
||||||
|
// 基础信息
|
||||||
|
image: string // 商品图片
|
||||||
|
name: string // 商品名称
|
||||||
|
|
||||||
|
// 金额显示
|
||||||
|
priceLabel?: string // 金额标签(如 "退款:")
|
||||||
|
price: number // 金额
|
||||||
|
priceColor?: string // 金额颜色(默认 #FF3A24)
|
||||||
|
|
||||||
|
// 右侧操作按钮(可选)
|
||||||
|
rightButton?: ReactNode // 自定义右侧按钮
|
||||||
|
|
||||||
|
// 样式定制
|
||||||
|
containerClassName?: string // 容器额外类名
|
||||||
|
showPriceSeparator?: boolean // 是否显示价格和名称之间的间距(默认 true)
|
||||||
|
} |
||||||
|
|
||||||
|
const GoodsInfoCard: React.FC<GoodsInfoCardProps> = ({ |
||||||
|
image, |
||||||
|
name, |
||||||
|
priceLabel, |
||||||
|
price, |
||||||
|
priceColor = '#FF3A24', |
||||||
|
rightButton, |
||||||
|
containerClassName = '', |
||||||
|
showPriceSeparator = true |
||||||
|
}) => { |
||||||
|
return ( |
||||||
|
<View className={`goods_info_card_component ${containerClassName}`}> |
||||||
|
{/* 商品图片 */} |
||||||
|
<Image |
||||||
|
className="goods_image" |
||||||
|
src={image} |
||||||
|
mode="aspectFill" |
||||||
|
width={208} |
||||||
|
height={208} |
||||||
|
/> |
||||||
|
|
||||||
|
{/* 商品信息 */} |
||||||
|
<View className="goods_info"> |
||||||
|
<Text className="goods_name">{name}</Text> |
||||||
|
|
||||||
|
{/* 价格/退款金额行 */} |
||||||
|
<View className={`price_row ${showPriceSeparator ? 'with_separator' : ''}`}> |
||||||
|
<Text className="price_text" style={{ color: priceColor }}> |
||||||
|
{priceLabel && <Text className="price_label">{priceLabel} </Text>} |
||||||
|
¥ {price.toFixed(2)} |
||||||
|
</Text> |
||||||
|
|
||||||
|
{/* 右侧按钮区域 */} |
||||||
|
{rightButton && ( |
||||||
|
<View className="right_button_area"> |
||||||
|
{rightButton} |
||||||
|
</View> |
||||||
|
)} |
||||||
|
</View> |
||||||
|
</View> |
||||||
|
</View> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default GoodsInfoCard |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
export default { |
||||||
|
navigationBarTitleText: '商品消费', |
||||||
|
navigationBarBackgroundColor: '#FFFFFF', |
||||||
|
navigationBarTextStyle: 'black', |
||||||
|
} |
||||||
@ -0,0 +1,112 @@ |
|||||||
|
.refund_result_page { |
||||||
|
min-height: 100vh; |
||||||
|
background-color: #F2F3F5; |
||||||
|
padding: 30px; |
||||||
|
|
||||||
|
// 退款结果状态卡片 |
||||||
|
.result_status_card { |
||||||
|
background-color: #FFFFFF; |
||||||
|
border-radius: 12px; |
||||||
|
padding: 50px 30px; |
||||||
|
margin-bottom: 30px; |
||||||
|
text-align: center; |
||||||
|
|
||||||
|
.status_title { |
||||||
|
display: block; |
||||||
|
font-size: 40px; |
||||||
|
font-weight: 600; |
||||||
|
margin-bottom: 30px; |
||||||
|
|
||||||
|
&.success { |
||||||
|
color: #000000; |
||||||
|
} |
||||||
|
|
||||||
|
&.failed { |
||||||
|
color: #EE0A24; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 成功:退回账户信息 |
||||||
|
.refund_account { |
||||||
|
display: block; |
||||||
|
font-size: 28px; |
||||||
|
color: #333333; |
||||||
|
line-height: 1.5; |
||||||
|
} |
||||||
|
|
||||||
|
// 失败:原因行 |
||||||
|
.fail_reason_row { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
padding: 0 20px; |
||||||
|
|
||||||
|
.reason_label { |
||||||
|
font-size: 28px; |
||||||
|
color: #333333; |
||||||
|
} |
||||||
|
|
||||||
|
.reason_value { |
||||||
|
font-size: 28px; |
||||||
|
color: #333333; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 商品信息卡片 |
||||||
|
.goods_info_card { |
||||||
|
background-color: #FFFFFF; |
||||||
|
border-radius: 12px; |
||||||
|
padding: 30px; |
||||||
|
margin-bottom: 30px; |
||||||
|
} |
||||||
|
|
||||||
|
// 退款详细信息卡片 |
||||||
|
.refund_detail_card { |
||||||
|
background-color: #FFFFFF; |
||||||
|
border-radius: 12px; |
||||||
|
padding: 30px; |
||||||
|
|
||||||
|
.info_list { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
gap: 20px; |
||||||
|
|
||||||
|
.info_row { |
||||||
|
display: flex; |
||||||
|
align-items: flex-start; |
||||||
|
|
||||||
|
.info_label { |
||||||
|
width: 180px; |
||||||
|
font-size: 28px; |
||||||
|
color: #333333; |
||||||
|
flex-shrink: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.info_value { |
||||||
|
flex: 1; |
||||||
|
margin-left: 30px; |
||||||
|
font-size: 28px; |
||||||
|
color: #595959; |
||||||
|
text-align: left; |
||||||
|
word-break: break-all; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 虚线分隔 |
||||||
|
.divider { |
||||||
|
height: 1PX; |
||||||
|
border-bottom: 1PX dashed #D3D8DE; |
||||||
|
margin: 30px 0; |
||||||
|
} |
||||||
|
|
||||||
|
// 联系商家(仅失败时显示) |
||||||
|
.merchant_contact { |
||||||
|
.contact_text { |
||||||
|
font-size: 28px; |
||||||
|
color: #333333; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,181 @@ |
|||||||
|
/** |
||||||
|
* 商品订单退款结果页 |
||||||
|
*/ |
||||||
|
import { View, Text } from '@tarojs/components' |
||||||
|
import { useState } from 'react' |
||||||
|
import Taro, { useLoad } from '@tarojs/taro' |
||||||
|
import GoodsInfoCard from '@/components/GoodsInfoCard' |
||||||
|
import './index.scss' |
||||||
|
|
||||||
|
// 退款结果类型
|
||||||
|
type RefundResultType = 'success' | 'failed' |
||||||
|
|
||||||
|
// 商品信息接口
|
||||||
|
interface GoodsInfo { |
||||||
|
id: string |
||||||
|
image: string |
||||||
|
name: string |
||||||
|
refundAmount: number |
||||||
|
} |
||||||
|
|
||||||
|
// 退款结果信息接口
|
||||||
|
interface RefundResultInfo { |
||||||
|
resultType: RefundResultType // 退款结果类型
|
||||||
|
goods: GoodsInfo // 商品信息
|
||||||
|
|
||||||
|
// 成功时的字段
|
||||||
|
refundAccount?: string // 退回账户(微信/支付宝/银行卡)
|
||||||
|
|
||||||
|
// 失败时的字段
|
||||||
|
failReason?: string // 失败原因
|
||||||
|
|
||||||
|
// 通用字段
|
||||||
|
refundReason: string // 退款原因
|
||||||
|
applyAmount: string // 申请金额
|
||||||
|
applyTime: string // 申请时间
|
||||||
|
|
||||||
|
// 成功时额外字段
|
||||||
|
refundCompleteTime?: string // 退款完结时间
|
||||||
|
refundNo?: string // 退款编号
|
||||||
|
|
||||||
|
// 门店信息
|
||||||
|
storeName: string // 消费门店
|
||||||
|
address: string // 地址
|
||||||
|
merchantPhone?: string // 商家电话(失败时显示)
|
||||||
|
} |
||||||
|
|
||||||
|
const GoodsRefundResult = () => { |
||||||
|
const [pageType, setPageType] = useState<RefundResultType>('success') |
||||||
|
|
||||||
|
// 模拟退款结果数据
|
||||||
|
const [refundInfo] = useState<RefundResultInfo>({ |
||||||
|
resultType: 'success', |
||||||
|
goods: { |
||||||
|
id: '1', |
||||||
|
image: 'https://img01.yzcdn.cn/vant/cat.jpeg', |
||||||
|
name: '美汁源Minute Maid果粒橙 橙汁饮料 1.25l/瓶', |
||||||
|
refundAmount: 12.50 |
||||||
|
}, |
||||||
|
refundAccount: '微信/支付宝/银行卡(中国银行6666)', |
||||||
|
refundReason: '计算错误', |
||||||
|
applyAmount: '12.50元', |
||||||
|
applyTime: '2025-01-01 12:00:00', |
||||||
|
refundCompleteTime: '2025-01-01 12:06:00', |
||||||
|
refundNo: 'a202501011206060000', |
||||||
|
storeName: 'XXXXXXXXX店', |
||||||
|
address: 'XXX市XXXXXXX区XXXXXXXXXX街道XXX大厦101', |
||||||
|
merchantPhone: '16688889999', |
||||||
|
failReason: '已成功取货' |
||||||
|
}) |
||||||
|
|
||||||
|
useLoad(() => { |
||||||
|
console.log('退款结果页面加载') |
||||||
|
|
||||||
|
// 从 URL 获取页面类型
|
||||||
|
const router = Taro.getCurrentInstance().router |
||||||
|
if (router?.params) { |
||||||
|
const { type } = router.params |
||||||
|
if (type === 'success' || type === 'failed') { |
||||||
|
setPageType(type as RefundResultType) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
// 联系商家
|
||||||
|
const handleCallMerchant = () => { |
||||||
|
if (refundInfo.merchantPhone) { |
||||||
|
Taro.makePhoneCall({ |
||||||
|
phoneNumber: refundInfo.merchantPhone |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<View className="refund_result_page"> |
||||||
|
{/* 退款结果状态卡片 */} |
||||||
|
<View className="result_status_card"> |
||||||
|
<Text className={`status_title ${pageType === 'success' ? 'success' : 'failed'}`}> |
||||||
|
{pageType === 'success' ? '退款成功' : '退款失败'} |
||||||
|
</Text> |
||||||
|
|
||||||
|
{pageType === 'success' ? ( |
||||||
|
// 成功:显示退回账户信息
|
||||||
|
<Text className="refund_account"> |
||||||
|
退回{refundInfo.refundAccount} ¥ {refundInfo.goods.refundAmount.toFixed(2)} |
||||||
|
</Text> |
||||||
|
) : ( |
||||||
|
// 失败:显示失败原因
|
||||||
|
<View className="fail_reason_row"> |
||||||
|
<Text className="reason_label">原因</Text> |
||||||
|
<Text className="reason_value">{refundInfo.failReason}</Text> |
||||||
|
</View> |
||||||
|
)} |
||||||
|
</View> |
||||||
|
|
||||||
|
{/* 商品信息卡片 */} |
||||||
|
<View className="goods_info_card"> |
||||||
|
<GoodsInfoCard |
||||||
|
image={refundInfo.goods.image} |
||||||
|
name={refundInfo.goods.name} |
||||||
|
priceLabel="退款:" |
||||||
|
price={refundInfo.goods.refundAmount} |
||||||
|
priceColor="#000000" |
||||||
|
showPriceSeparator={false} |
||||||
|
/> |
||||||
|
</View> |
||||||
|
|
||||||
|
{/* 退款详细信息卡片 */} |
||||||
|
<View className="refund_detail_card"> |
||||||
|
<View className="info_list"> |
||||||
|
<View className="info_row"> |
||||||
|
<Text className="info_label">退款原因</Text> |
||||||
|
<Text className="info_value">{refundInfo.refundReason}</Text> |
||||||
|
</View> |
||||||
|
<View className="info_row"> |
||||||
|
<Text className="info_label">申请金额</Text> |
||||||
|
<Text className="info_value">{refundInfo.applyAmount}</Text> |
||||||
|
</View> |
||||||
|
<View className="info_row"> |
||||||
|
<Text className="info_label">申请时间</Text> |
||||||
|
<Text className="info_value">{refundInfo.applyTime}</Text> |
||||||
|
</View> |
||||||
|
|
||||||
|
{/* 成功时显示退款完结和退款编号 */} |
||||||
|
{pageType === 'success' && ( |
||||||
|
<> |
||||||
|
<View className="info_row"> |
||||||
|
<Text className="info_label">退款完结</Text> |
||||||
|
<Text className="info_value">{refundInfo.refundCompleteTime}</Text> |
||||||
|
</View> |
||||||
|
<View className="info_row"> |
||||||
|
<Text className="info_label">退款编号</Text> |
||||||
|
<Text className="info_value">{refundInfo.refundNo}</Text> |
||||||
|
</View> |
||||||
|
</> |
||||||
|
)} |
||||||
|
|
||||||
|
<View className="info_row"> |
||||||
|
<Text className="info_label">消费门店</Text> |
||||||
|
<Text className="info_value">{refundInfo.storeName}</Text> |
||||||
|
</View> |
||||||
|
<View className="info_row"> |
||||||
|
<Text className="info_label">地址</Text> |
||||||
|
<Text className="info_value">{refundInfo.address}</Text> |
||||||
|
</View> |
||||||
|
</View> |
||||||
|
|
||||||
|
{/* 失败时显示联系商家 */} |
||||||
|
{pageType === 'failed' && refundInfo.merchantPhone && ( |
||||||
|
<> |
||||||
|
<View className="divider" /> |
||||||
|
<View className="merchant_contact" onClick={handleCallMerchant}> |
||||||
|
<Text className="contact_text">联系商家:{refundInfo.merchantPhone}</Text> |
||||||
|
</View> |
||||||
|
</> |
||||||
|
)} |
||||||
|
</View> |
||||||
|
</View> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
export default GoodsRefundResult |
||||||
Loading…
Reference in new issue