feat(user): 新增收货地址管理及售后申请页面

- 新增地址类型定义,增强前端地址数据结构
- 新增地址编辑页面,支持地址智能识别和定位选点功能
- 地址编辑支持省市区选择及默认地址设置
- 新增地址列表页面,支持地址展示、删除、编辑和选择功能
- 实现售后申请页面,支持选择售后类型和退款原因
- 售后申请支持商品选择、退款金额计算和凭证上传
- 新增售后详情页面,支持售后状态展示及申请取消
- 优化页面加载和用户交互体验,增加错误提示和权限处理
This commit is contained in:
2026-07-01 12:11:56 +08:00
parent bf6ed504cc
commit 1fa58040f3
636 changed files with 58878 additions and 716 deletions

View File

@@ -0,0 +1,95 @@
import Taro from '@tarojs/taro'
import { isLoggedIn, goToRegister } from './auth'
/**
* 需要登录才能执行的动作类型。
* - 这些点都是"成交前置行为":加购、结算、收藏、领券、查看订单、下单等
* - 业务页(首页/分类/搜索/详情)始终对游客开放,价格字段做脱敏即可
*/
export type LoginRequiredAction =
| 'addToCart'
| 'buyNow'
| 'checkout'
| 'favorite'
| 'receiveCoupon'
| 'viewOrder'
| 'payOrder'
| 'submitComment'
const ACTION_LABEL: Record<LoginRequiredAction, string> = {
addToCart: '加入购物车',
buyNow: '立即购买',
checkout: '结算',
favorite: '收藏',
receiveCoupon: '领取优惠券',
viewOrder: '查看订单',
payOrder: '支付订单',
submitComment: '提交评价',
}
const ACTION_REDIRECT_FALLBACK: Record<LoginRequiredAction, string> = {
addToCart: '/pages/shop/cart',
buyNow: '/pages/shop/cart',
checkout: '/pages/shop/cart',
favorite: '/pages/user/favorite-list',
receiveCoupon: '/pages/index/coupon-center',
viewOrder: '/pages/order/order',
payOrder: '/pages/order/order',
submitComment: '/pages/order/order',
}
export interface RequireLoginOptions {
/** 动作类型,用于生成提示文案 */
action: LoginRequiredAction
/** 登录后跳回的目标 URL相对于本小程序不传则用动作默认值 */
redirect?: string
/** 自定义弹窗标题 */
title?: string
/** 自定义弹窗内容(不传则按 action 自动生成) */
content?: string
/**
* true: 不弹窗,直接跳登录页(仅用于"非常确定用户就要登录"的场景,比如优惠券领取)
* 默认 false: 弹一个非阻塞的二次确认
*/
silent?: boolean
}
/**
* 行为级登录守卫:游客态触发时弹出一个非阻塞的二次确认。
*
* 返回:
* - true : 已登录,可继续执行原动作
* - false : 游客态,已拦截(弹窗点了取消 / 弹窗点了去登录但还在当前页停留)
*
* 微信审核要点:
* 1. 永远不要在 useLaunch / onLoad 里主动调;
* 2. 永远不要在 tabBar 切换时调tabBar 三个页面要 100% 游客可浏览);
* 3. 不要在 onShow 里无脑调,否则审核员每次切回都要点确认,体验差。
*/
export function requireLogin(options: RequireLoginOptions): boolean {
if (isLoggedIn()) return true
const actionLabel = ACTION_LABEL[options.action]
const redirect = options.redirect || ACTION_REDIRECT_FALLBACK[options.action]
const title = options.title || '需要登录'
const content = options.content || `登录后才能${actionLabel},是否前往登录?`
if (options.silent) {
goToRegister({ redirect })
return false
}
Taro.showModal({
title,
content,
confirmText: '去登录',
cancelText: '再逛逛',
confirmColor: '#0e932e',
success: ({ confirm }) => {
if (confirm) {
goToRegister({ redirect })
}
},
})
return false
}