forked from gxwebsoft/mp-10550
新增:余额支付、微信支付、下单确认功能
This commit is contained in:
@@ -153,5 +153,6 @@ export interface ShopOrderParam extends PageParam {
|
|||||||
orderStatus?: number;
|
orderStatus?: number;
|
||||||
payType?: number;
|
payType?: number;
|
||||||
isInvoice?: boolean;
|
isInvoice?: boolean;
|
||||||
|
userId?: number;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import type { ApiResult, PageResult } from '@/api/index';
|
import type {ApiResult, PageResult} from '@/api/index';
|
||||||
import type { Payment, PaymentParam } from './model';
|
import type {Payment, PaymentParam} from './model';
|
||||||
import type { Order } from '@/api/shop/order/model';
|
import type {ShopOrder} from '@/api/shop/shopOrder/model';
|
||||||
|
import {SERVER_API_URL} from "@/utils/server";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询支付方式
|
* 分页查询支付方式
|
||||||
*/
|
*/
|
||||||
export async function pagePayment(params: PaymentParam) {
|
export async function pagePayment(params: PaymentParam) {
|
||||||
const res = await request.get<ApiResult<PageResult<Payment>>>(
|
const res = await request.get<ApiResult<PageResult<Payment>>>(
|
||||||
'/system/payment/page',
|
SERVER_API_URL + '/system/payment/page',
|
||||||
{
|
params
|
||||||
params
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -24,10 +23,8 @@ export async function pagePayment(params: PaymentParam) {
|
|||||||
*/
|
*/
|
||||||
export async function listPayment(params?: PaymentParam) {
|
export async function listPayment(params?: PaymentParam) {
|
||||||
const res = await request.get<ApiResult<Payment[]>>(
|
const res = await request.get<ApiResult<Payment[]>>(
|
||||||
'/system/payment',
|
SERVER_API_URL + '/system/payment',
|
||||||
{
|
params
|
||||||
params
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
if (res.code === 0 && res.data) {
|
if (res.code === 0 && res.data) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -40,7 +37,7 @@ export async function listPayment(params?: PaymentParam) {
|
|||||||
*/
|
*/
|
||||||
export async function addPayment(data: Payment) {
|
export async function addPayment(data: Payment) {
|
||||||
const res = await request.post<ApiResult<unknown>>(
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
'/system/payment',
|
SERVER_API_URL + '/system/payment',
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
@@ -54,7 +51,7 @@ export async function addPayment(data: Payment) {
|
|||||||
*/
|
*/
|
||||||
export async function updatePayment(data: Payment) {
|
export async function updatePayment(data: Payment) {
|
||||||
const res = await request.put<ApiResult<unknown>>(
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
'/system/payment',
|
SERVER_API_URL + '/system/payment',
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
@@ -68,7 +65,7 @@ export async function updatePayment(data: Payment) {
|
|||||||
*/
|
*/
|
||||||
export async function removePayment(id?: number) {
|
export async function removePayment(id?: number) {
|
||||||
const res = await request.del<ApiResult<unknown>>(
|
const res = await request.del<ApiResult<unknown>>(
|
||||||
'/system/payment/' + id
|
SERVER_API_URL + '/system/payment/' + id
|
||||||
);
|
);
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
return res.message;
|
return res.message;
|
||||||
@@ -81,7 +78,7 @@ export async function removePayment(id?: number) {
|
|||||||
*/
|
*/
|
||||||
export async function removeBatchPayment(data: (number | undefined)[]) {
|
export async function removeBatchPayment(data: (number | undefined)[]) {
|
||||||
const res = await request.del<ApiResult<unknown>>(
|
const res = await request.del<ApiResult<unknown>>(
|
||||||
'/system/payment/batch',
|
SERVER_API_URL + '/system/payment/batch',
|
||||||
{
|
{
|
||||||
data
|
data
|
||||||
}
|
}
|
||||||
@@ -97,7 +94,7 @@ export async function removeBatchPayment(data: (number | undefined)[]) {
|
|||||||
*/
|
*/
|
||||||
export async function getPayment(id: number) {
|
export async function getPayment(id: number) {
|
||||||
const res = await request.get<ApiResult<Payment>>(
|
const res = await request.get<ApiResult<Payment>>(
|
||||||
'/system/payment/' + id
|
SERVER_API_URL + '/system/payment/' + id
|
||||||
);
|
);
|
||||||
if (res.code === 0 && res.data) {
|
if (res.code === 0 && res.data) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@@ -108,9 +105,9 @@ export async function getPayment(id: number) {
|
|||||||
/**
|
/**
|
||||||
* 生成支付二维码(微信native)
|
* 生成支付二维码(微信native)
|
||||||
*/
|
*/
|
||||||
export async function getNativeCode(data: Order) {
|
export async function getNativeCode(data: ShopOrder) {
|
||||||
const res = await request.post<ApiResult<unknown>>(
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
'/system/wx-native-pay/codeUrl',
|
SERVER_API_URL + '/system/wx-native-pay/codeUrl',
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
@@ -118,3 +115,31 @@ export async function getNativeCode(data: Order) {
|
|||||||
}
|
}
|
||||||
return Promise.reject(new Error(res.message));
|
return Promise.reject(new Error(res.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用余额支付
|
||||||
|
*/
|
||||||
|
export async function payByBalance(data: ShopOrder) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
SERVER_API_URL + '/system/payment/balancePay',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.code === 0) {
|
||||||
|
return res.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择支付方式
|
||||||
|
*/
|
||||||
|
export async function selectPayment(params?: PaymentParam) {
|
||||||
|
const res = await request.get<ApiResult<Payment[]>>(
|
||||||
|
SERVER_API_URL + '/system/payment/select',
|
||||||
|
params
|
||||||
|
);
|
||||||
|
if (res.code === 0) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.message));
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { PageParam } from '@/api';
|
import type { PageParam } from '@/api/index';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付方式
|
* 支付方式
|
||||||
|
|||||||
181
src/pages/order/components/OrderList.tsx
Normal file
181
src/pages/order/components/OrderList.tsx
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
import {Avatar, Cell, Space, Tabs, Button, TabPane} from '@nutui/nutui-react-taro'
|
||||||
|
import {useEffect, useState, CSSProperties} from "react";
|
||||||
|
import Taro from '@tarojs/taro';
|
||||||
|
import {InfiniteLoading} from '@nutui/nutui-react-taro'
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import {pageShopOrder} from "@/api/shop/shopOrder";
|
||||||
|
import {ShopOrder} from "@/api/shop/shopOrder/model";
|
||||||
|
import {copyText} from "@/utils/common";
|
||||||
|
|
||||||
|
const InfiniteUlStyle: CSSProperties = {
|
||||||
|
marginTop: '84px',
|
||||||
|
height: '82vh',
|
||||||
|
width: '100%',
|
||||||
|
padding: '0',
|
||||||
|
overflowY: 'auto',
|
||||||
|
overflowX: 'hidden',
|
||||||
|
}
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
index: 0,
|
||||||
|
key: '全部',
|
||||||
|
title: '全部'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 1,
|
||||||
|
key: '待付款',
|
||||||
|
title: '待付款'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 2,
|
||||||
|
key: '待发货',
|
||||||
|
title: '待发货'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 3,
|
||||||
|
key: '已收货',
|
||||||
|
title: '已收货'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
index: 4,
|
||||||
|
key: '已完成',
|
||||||
|
title: '已完成'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
function OrderList(props: any) {
|
||||||
|
const [list, setList] = useState<ShopOrder[]>([])
|
||||||
|
const [page, setPage] = useState(1)
|
||||||
|
const [hasMore, setHasMore] = useState(true)
|
||||||
|
const [tapIndex, setTapIndex] = useState<string | number>('0')
|
||||||
|
|
||||||
|
console.log(props.statusBarHeight, 'ppp')
|
||||||
|
|
||||||
|
const getOrderStatusParams = (index: string | number) => {
|
||||||
|
let params: { payStatus?: number; deliveryStatus?: number; orderStatus?: number } = {};
|
||||||
|
switch (index) {
|
||||||
|
case '1': // 待付款
|
||||||
|
params.payStatus = 0;
|
||||||
|
break;
|
||||||
|
case '2': // 待发货
|
||||||
|
params.payStatus = 1;
|
||||||
|
params.deliveryStatus = 10;
|
||||||
|
break;
|
||||||
|
case '3': // 已收货
|
||||||
|
params.deliveryStatus = 30;
|
||||||
|
break;
|
||||||
|
case '4': // 已完成
|
||||||
|
params.orderStatus = 1;
|
||||||
|
break;
|
||||||
|
case '0': // 全部
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
};
|
||||||
|
|
||||||
|
const reload = async (resetPage = false) => {
|
||||||
|
const currentPage = resetPage ? 1 : page;
|
||||||
|
const params = getOrderStatusParams(tapIndex);
|
||||||
|
pageShopOrder({ page: currentPage, ...params }).then(res => {
|
||||||
|
let newList: ShopOrder[] | undefined = [];
|
||||||
|
if (res?.list && res?.list.length > 0) {
|
||||||
|
newList = resetPage ? res.list : list?.concat(res.list);
|
||||||
|
setHasMore(true);
|
||||||
|
} else {
|
||||||
|
newList = res?.list;
|
||||||
|
setHasMore(false);
|
||||||
|
}
|
||||||
|
setList(newList || []);
|
||||||
|
setPage(currentPage);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const reloadMore = async () => {
|
||||||
|
setPage(page + 1);
|
||||||
|
reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
reload(true); // 首次加载或tab切换时重置页码
|
||||||
|
}, [tapIndex]); // 监听tapIndex变化
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Tabs
|
||||||
|
align={'left'}
|
||||||
|
className={'fixed left-0'}
|
||||||
|
style={{ top: '84px'}}
|
||||||
|
tabStyle={{ backgroundColor: 'transparent'}}
|
||||||
|
value={tapIndex}
|
||||||
|
onChange={(paneKey) => {
|
||||||
|
setTapIndex(paneKey)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
tabs?.map((item, index) => {
|
||||||
|
return <TabPane key={index} title={item.title}></TabPane>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Tabs>
|
||||||
|
<div style={InfiniteUlStyle} id="scroll">
|
||||||
|
<InfiniteLoading
|
||||||
|
target="scroll"
|
||||||
|
hasMore={hasMore}
|
||||||
|
onLoadMore={reloadMore}
|
||||||
|
onScroll={() => {
|
||||||
|
|
||||||
|
}}
|
||||||
|
onScrollToUpper={() => {
|
||||||
|
|
||||||
|
}}
|
||||||
|
loadingText={
|
||||||
|
<>
|
||||||
|
加载中
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
loadMoreText={
|
||||||
|
<>
|
||||||
|
没有更多了
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{props.data?.map(item => {
|
||||||
|
return (
|
||||||
|
<Cell style={{padding: '16px'}} onClick={() => Taro.navigateTo({url: `/shop/orderDetail/index?orderId=${item.orderId}`})}>
|
||||||
|
<Space direction={'vertical'} className={'w-full flex flex-col'}>
|
||||||
|
<div className={'order-no flex justify-between'}>
|
||||||
|
<span className={'text-gray-700 font-bold text-sm'}
|
||||||
|
onClick={(e) => {e.stopPropagation(); copyText(`${item.orderNo}`)}}>{item.orderNo}</span>
|
||||||
|
<span className={'text-orange-500'}>待付款</span> {/* 这里可以根据item.orderStatus显示不同的状态 */}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={'create-time text-gray-400 text-xs'}>{dayjs(item.createTime).format('YYYY年MM月DD日 HH:mm:ss')}</div>
|
||||||
|
<div className={'goods-info'}>
|
||||||
|
<div className={'flex items-center'}>
|
||||||
|
<div className={'flex items-center'}>
|
||||||
|
<Avatar
|
||||||
|
src='34'
|
||||||
|
size={'45'}
|
||||||
|
shape={'square'}
|
||||||
|
/>
|
||||||
|
<div className={'ml-2'}>{item.realName}</div>
|
||||||
|
</div>
|
||||||
|
<div className={'text-gray-400 text-xs'}>{item.totalNum}件商品</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={' w-full text-right'}>实付金额:¥{item.payPrice}</div>
|
||||||
|
<Space className={'btn flex justify-end'}>
|
||||||
|
<Button size={'small'}>发货</Button>
|
||||||
|
</Space>
|
||||||
|
</Space>
|
||||||
|
</Cell>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</InfiniteLoading>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrderList
|
||||||
@@ -1,13 +1,25 @@
|
|||||||
import {useEffect, useState} from "react"; // 添加 useCallback 引入
|
import {useState} from "react"; // 添加 useCallback 引入
|
||||||
import Taro from '@tarojs/taro';
|
import Taro, {useDidShow} from '@tarojs/taro'
|
||||||
import {NavBar, Space} from '@nutui/nutui-react-taro'
|
import {NavBar, Space} from '@nutui/nutui-react-taro'
|
||||||
import {Search} from '@nutui/icons-react-taro'
|
import {Search} from '@nutui/icons-react-taro'
|
||||||
import OrderList from "@/components/OrderList";
|
import OrderList from "./components/OrderList";
|
||||||
|
import {ShopOrder} from "@/api/shop/shopOrder/model";
|
||||||
|
import {pageShopOrder} from "@/api/shop/shopOrder";
|
||||||
import './order.scss'
|
import './order.scss'
|
||||||
|
|
||||||
function Order() {
|
function Order() {
|
||||||
const [statusBarHeight, setStatusBarHeight] = useState<number>()
|
const [statusBarHeight, setStatusBarHeight] = useState<number>()
|
||||||
|
const [list, setList] = useState<ShopOrder[]>([])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
|
const reload = async () => {
|
||||||
|
const orders = await pageShopOrder({userId: Taro.getStorageSync('UserId')})
|
||||||
|
if (orders) {
|
||||||
|
setList(orders.list || [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useDidShow(() => {
|
||||||
Taro.getSystemInfo({
|
Taro.getSystemInfo({
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
setStatusBarHeight(res.statusBarHeight)
|
setStatusBarHeight(res.statusBarHeight)
|
||||||
@@ -18,7 +30,8 @@ function Order() {
|
|||||||
backgroundColor: '#ffffff', // 状态栏+导航栏背景色
|
backgroundColor: '#ffffff', // 状态栏+导航栏背景色
|
||||||
frontColor: 'black', // 状态栏文字颜色(仅支持 black/white)
|
frontColor: 'black', // 状态栏文字颜色(仅支持 black/white)
|
||||||
});
|
});
|
||||||
}, []); // 新增: 添加滚动事件监听
|
reload().then()
|
||||||
|
}); // 新增: 添加滚动事件监听
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -45,7 +58,7 @@ function Order() {
|
|||||||
>
|
>
|
||||||
<span>订单</span>
|
<span>订单</span>
|
||||||
</NavBar>
|
</NavBar>
|
||||||
<OrderList/>
|
<OrderList data={list}/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ function UserCard() {
|
|||||||
<div className={'flex justify-around mt-5'}>
|
<div className={'flex justify-around mt-5'}>
|
||||||
<div className={'item flex justify-center flex-col items-center'}>
|
<div className={'item flex justify-center flex-col items-center'}>
|
||||||
<span className={'text-sm text-gray-500'}>余额</span>
|
<span className={'text-sm text-gray-500'}>余额</span>
|
||||||
<span className={'text-xl'}>¥ 0.00</span>
|
<span className={'text-xl'}>¥ {userInfo?.balance}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={'item flex justify-center flex-col items-center'}>
|
<div className={'item flex justify-center flex-col items-center'}>
|
||||||
<span className={'text-sm text-gray-500'}>优惠券</span>
|
<span className={'text-sm text-gray-500'}>优惠券</span>
|
||||||
|
|||||||
@@ -15,13 +15,30 @@
|
|||||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
.total-price {
|
.total-price {
|
||||||
flex: 1;
|
display: flex;
|
||||||
text-align: right;
|
align-items: center;
|
||||||
margin-right: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.submit-btn {
|
.submit-btn {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.address-bottom-line{
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 24rpx 24rpx 0 0;
|
||||||
|
background: #fff;
|
||||||
|
padding: 26rpx 49rpx 0 34rpx;
|
||||||
|
position: relative;
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 5px;
|
||||||
|
background: repeating-linear-gradient(-45deg, #ff6c6c, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0,
|
||||||
|
#1989fa 45%, transparent 0, transparent 50%);
|
||||||
|
background-size: 120px;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import {Image, Button, Cell, CellGroup, Input, TextArea, Space} from '@nutui/nutui-react-taro'
|
import {Image, Button, Cell, CellGroup, Input, Space, ActionSheet} from '@nutui/nutui-react-taro'
|
||||||
import {Location} from '@nutui/icons-react-taro'
|
import {Location, ArrowRight} from '@nutui/icons-react-taro'
|
||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
import {ShopGoods} from "@/api/shop/shopGoods/model";
|
import {ShopGoods} from "@/api/shop/shopGoods/model";
|
||||||
import {getShopGoods} from "@/api/shop/shopGoods";
|
import {getShopGoods} from "@/api/shop/shopGoods";
|
||||||
@@ -8,18 +8,138 @@ import {View} from '@tarojs/components';
|
|||||||
import {listShopUserAddress} from "@/api/shop/shopUserAddress";
|
import {listShopUserAddress} from "@/api/shop/shopUserAddress";
|
||||||
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
|
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
import Gap from "@/components/Gap";
|
||||||
|
import {TenantId} from "@/config/app";
|
||||||
|
import {payByBalance, selectPayment} from "@/api/system/payment";
|
||||||
|
import {Payment} from "@/api/system/payment/model";
|
||||||
|
|
||||||
const OrderConfirm = () => {
|
const OrderConfirm = () => {
|
||||||
const [goods, setGoods] = useState<ShopGoods | null>(null);
|
const [goods, setGoods] = useState<ShopGoods | null>(null);
|
||||||
const [address, setAddress] = useState<ShopUserAddress>()
|
const [address, setAddress] = useState<ShopUserAddress>()
|
||||||
|
const [payments, setPayments] = useState<any[]>([])
|
||||||
|
const [payment, setPayment] = useState<Payment>()
|
||||||
|
const [isVisible, setIsVisible] = useState<boolean>(false)
|
||||||
const router = Taro.getCurrentInstance().router;
|
const router = Taro.getCurrentInstance().router;
|
||||||
const goodsId = router?.params?.goodsId;
|
const goodsId = router?.params?.goodsId;
|
||||||
|
|
||||||
const reload = async () => {
|
const reload = async () => {
|
||||||
|
// 默认收货地址
|
||||||
const address = await listShopUserAddress({isDefault: true});
|
const address = await listShopUserAddress({isDefault: true});
|
||||||
if(address.length > 0){
|
if (address.length > 0) {
|
||||||
setAddress(address[0])
|
setAddress(address[0])
|
||||||
}
|
}
|
||||||
|
// 支付方式
|
||||||
|
const paymentList = await selectPayment({});
|
||||||
|
if (paymentList && paymentList.length > 0) {
|
||||||
|
setPayments(paymentList?.map((d, _) => {
|
||||||
|
return {
|
||||||
|
type: d.type,
|
||||||
|
name: d.name,
|
||||||
|
description: d.comments
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
setPayment(paymentList[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSelect = (item: any) => {
|
||||||
|
setPayment(payments.find(payment => payment.name === item.name))
|
||||||
|
setIsVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPay = async (goods: ShopGoods) => {
|
||||||
|
// 支付方式
|
||||||
|
if (payment?.type == 0) {
|
||||||
|
await onBalancePay(goods)
|
||||||
|
}
|
||||||
|
if (payment?.type == 1) {
|
||||||
|
await onWxPay(goods)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onBalancePay = async (goods: ShopGoods) => {
|
||||||
|
Taro.showLoading({title: '支付中...'})
|
||||||
|
payByBalance({
|
||||||
|
payType: goods.type,
|
||||||
|
payPrice: goods.price,
|
||||||
|
totalPrice: goods.price,
|
||||||
|
userId: Taro.getStorageSync('UserId'),
|
||||||
|
tenantId: Number(TenantId)
|
||||||
|
}).then().finally(() => {
|
||||||
|
Taro.showToast({
|
||||||
|
title: '支付成功',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 2000
|
||||||
|
})
|
||||||
|
Taro.hideLoading()
|
||||||
|
setTimeout(() => {
|
||||||
|
// Taro.switchTab({url: '/pages/order/order'})
|
||||||
|
}, 2000)
|
||||||
|
}).catch(() => {
|
||||||
|
Taro.hideLoading()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onWxPay = async (goods: ShopGoods) => {
|
||||||
|
Taro.showLoading({title: '支付中...'})
|
||||||
|
Taro.request({
|
||||||
|
// url: 'https://cms-api.websoft.top/api/shop/shop-order',
|
||||||
|
url: 'http://127.0.0.1:9200/api/shop/shop-order',
|
||||||
|
method: 'POST',
|
||||||
|
header: {
|
||||||
|
'content-type': 'application/json',
|
||||||
|
'Authorization': Taro.getStorageSync('access_token'),
|
||||||
|
TenantId
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
totalPrice: goods.price,
|
||||||
|
payPrice: goods.price,
|
||||||
|
tenantId: TenantId,
|
||||||
|
payType: goods.type,
|
||||||
|
comments: goods.name,
|
||||||
|
name: goods.name
|
||||||
|
},
|
||||||
|
success: function (res) {
|
||||||
|
Taro.hideLoading()
|
||||||
|
const data = res.data.data
|
||||||
|
console.log(data, 'payInfo')
|
||||||
|
// Taro.showToast({
|
||||||
|
// title: '下单成功',
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// setTimeout(() => {
|
||||||
|
// Taro.switchTab({
|
||||||
|
// url: '/pages/order/order'
|
||||||
|
// })
|
||||||
|
// }, 1000);
|
||||||
|
// return false;
|
||||||
|
if (data) {
|
||||||
|
Taro.requestPayment({
|
||||||
|
timeStamp: data.timeStamp,
|
||||||
|
nonceStr: data.nonceStr,
|
||||||
|
package: data.package,
|
||||||
|
signType: data.signType,
|
||||||
|
paySign: data.paySign,
|
||||||
|
success: function (res) {
|
||||||
|
if (res.errMsg == "requestPayment:ok") {
|
||||||
|
console.log('购买成功')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: function (res) {
|
||||||
|
console.log(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: function (msg) {
|
||||||
|
console.log('支付失败')
|
||||||
|
Taro.hideLoading()
|
||||||
|
Taro.showToast({
|
||||||
|
title: `${msg}`,
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -42,11 +162,18 @@ const OrderConfirm = () => {
|
|||||||
<CellGroup>
|
<CellGroup>
|
||||||
{
|
{
|
||||||
address && (
|
address && (
|
||||||
<Cell>
|
<Cell className={'address-bottom-line'} onClick={() => Taro.navigateTo({url: '/user/address/index'})}>
|
||||||
<Space>
|
<Space>
|
||||||
<Location/>
|
<Location/>
|
||||||
<View>送至</View>
|
<View className={'flex flex-col w-full justify-between items-start'}>
|
||||||
<View>{address.fullAddress}</View>
|
<Space className={'flex flex-row w-full font-medium'}>
|
||||||
|
<View className={'flex-wrap text-nowrap whitespace-nowrap'}>送至</View>
|
||||||
|
<View style={{width: '64%'}}
|
||||||
|
className={'line-clamp-1 relative'}>{address.province} {address.city} {address.region} {address.address}
|
||||||
|
</View>
|
||||||
|
</Space>
|
||||||
|
<View className={'pt-1 pb-3 text-gray-500'}>{address.name} {address.phone}</View>
|
||||||
|
</View>
|
||||||
</Space>
|
</Space>
|
||||||
</Cell>
|
</Cell>
|
||||||
)
|
)
|
||||||
@@ -62,40 +189,72 @@ const OrderConfirm = () => {
|
|||||||
</CellGroup>
|
</CellGroup>
|
||||||
|
|
||||||
<CellGroup>
|
<CellGroup>
|
||||||
<Cell>
|
<Cell key={goods.goodsId}>
|
||||||
<div className={'flex items-center'}>
|
<Space>
|
||||||
<Image src={goods.image} width="80" height="80" lazyLoad={false}/>
|
<Image src={goods.image} mode={'aspectFill'} style={{
|
||||||
<div className={'ml-2'}>
|
width: '80px',
|
||||||
<div className={'text-sm font-bold'}>{goods.name}</div>
|
height: '80px',
|
||||||
<div className={'text-red-500 text-lg'}>¥{goods.price}</div>
|
}} lazyLoad={false}/>
|
||||||
</div>
|
<View className={'flex flex-col'}>
|
||||||
|
<View className={'font-medium w-full'}>{goods.name}</View>
|
||||||
|
<View className={'number text-gray-400 text-sm py-2'}>80g/袋</View>
|
||||||
|
<Space className={'flex justify-start items-center'}>
|
||||||
|
<View className={'text-red-500'}>¥{goods.price}</View>
|
||||||
|
<View className={'text-gray-500 text-sm'}>x 1</View>
|
||||||
|
</Space>
|
||||||
|
</View>
|
||||||
|
</Space>
|
||||||
|
</Cell>
|
||||||
|
</CellGroup>
|
||||||
|
|
||||||
|
<CellGroup>
|
||||||
|
<Cell title={`商品总价(共1件)`} extra={<View className={'font-medium'}>{'¥' + goods.price}</View>}/>
|
||||||
|
{/*<Cell title={'优惠券'} extra={(*/}
|
||||||
|
{/* <View className={'flex justify-between items-center'}>*/}
|
||||||
|
{/* <View className={'text-red-500 text-sm mr-1'}>-¥0.00</View>*/}
|
||||||
|
{/* <ArrowRight className={'text-gray-400'} size={14}/>*/}
|
||||||
|
{/* </View>*/}
|
||||||
|
{/*)}/>*/}
|
||||||
|
{/*<Cell title={'配送费'} extra={'¥' + 10}/>*/}
|
||||||
|
<Cell title={'订单备注'} extra={(
|
||||||
|
<Input placeholder={'选填,请先和商家协商一致'} style={{padding: '0'}}/>
|
||||||
|
)}/>
|
||||||
|
</CellGroup>
|
||||||
|
|
||||||
|
<CellGroup>
|
||||||
|
<Cell
|
||||||
|
title={'支付方式'}
|
||||||
|
extra={(
|
||||||
|
<View className={'flex items-center gap-2'}>
|
||||||
|
<View className={'text-gray-900'}>{payment?.name}</View>
|
||||||
|
<ArrowRight className={'text-gray-400'} size={14}/>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
onClick={() => setIsVisible(true)}
|
||||||
|
/>
|
||||||
|
</CellGroup>
|
||||||
|
|
||||||
|
<ActionSheet
|
||||||
|
visible={isVisible}
|
||||||
|
options={payments}
|
||||||
|
onSelect={handleSelect}
|
||||||
|
onCancel={() => setIsVisible(false)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Gap height={50}/>
|
||||||
|
|
||||||
|
<div className={'fixed z-50 bg-white w-full bottom-0 left-0 pt-4 pb-10'} style={{
|
||||||
|
boxShadow: '0 -2px 4px 0 rgba(0,0,0,0.10)'
|
||||||
|
}}>
|
||||||
|
<View className={'btn-bar flex justify-between items-center'}>
|
||||||
|
<div className={'flex justify-center items-center mx-4'}>
|
||||||
|
<span className={'total-price text-sm text-gray-500'}>实付金额:</span>
|
||||||
|
<span className={'text-red-500 text-xl font-bold'}>¥{goods.price}</span>
|
||||||
</div>
|
</div>
|
||||||
</Cell>
|
<div className={'buy-btn mx-4'}>
|
||||||
</CellGroup>
|
<Button type="success" size="large" onClick={() => onPay(goods)}>立即付款</Button>
|
||||||
|
</div>
|
||||||
<CellGroup title="收货信息">
|
</View>
|
||||||
<Cell title="收货人">
|
|
||||||
<Input placeholder="请输入收货人姓名"/>
|
|
||||||
</Cell>
|
|
||||||
<Cell title="手机号">
|
|
||||||
<Input placeholder="请输入手机号" type="tel"/>
|
|
||||||
</Cell>
|
|
||||||
<Cell title="收货地址">
|
|
||||||
<TextArea placeholder="请输入详细收货地址"/>
|
|
||||||
</Cell>
|
|
||||||
</CellGroup>
|
|
||||||
|
|
||||||
<CellGroup title="订单备注">
|
|
||||||
<Cell>
|
|
||||||
<TextArea placeholder="请输入订单备注"/>
|
|
||||||
</Cell>
|
|
||||||
</CellGroup>
|
|
||||||
|
|
||||||
<div className={'fixed-bottom'}>
|
|
||||||
<div className={'total-price'}>
|
|
||||||
合计:<span className={'text-red-500 text-xl font-bold'}>¥{goods.price}</span>
|
|
||||||
</div>
|
|
||||||
<Button type="primary" size="large" className={'submit-btn'}>提交订单</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
4
src/shop/orderConfirmCart/index.config.ts
Normal file
4
src/shop/orderConfirmCart/index.config.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export default definePageConfig({
|
||||||
|
navigationBarTitleText: '订单确认',
|
||||||
|
navigationBarTextStyle: 'black'
|
||||||
|
})
|
||||||
44
src/shop/orderConfirmCart/index.scss
Normal file
44
src/shop/orderConfirmCart/index.scss
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
.order-confirm-page {
|
||||||
|
padding-bottom: 100px; // 留出底部固定按钮的空间
|
||||||
|
|
||||||
|
.fixed-bottom {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
|
.total-price {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.address-bottom-line{
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 24rpx 24rpx 0 0;
|
||||||
|
background: #fff;
|
||||||
|
padding: 26rpx 49rpx 0 34rpx;
|
||||||
|
position: relative;
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 5px;
|
||||||
|
background: repeating-linear-gradient(-45deg, #ff6c6c, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0,
|
||||||
|
#1989fa 45%, transparent 0, transparent 50%);
|
||||||
|
background-size: 120px;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
132
src/shop/orderConfirmCart/index.tsx
Normal file
132
src/shop/orderConfirmCart/index.tsx
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {Image, Button, Cell, CellGroup, Input, Space} from '@nutui/nutui-react-taro'
|
||||||
|
import {Location, ArrowRight} from '@nutui/icons-react-taro'
|
||||||
|
import Taro from '@tarojs/taro'
|
||||||
|
import {ShopGoods} from "@/api/shop/shopGoods/model";
|
||||||
|
import {getShopGoods} from "@/api/shop/shopGoods";
|
||||||
|
import {View} from '@tarojs/components';
|
||||||
|
import {listShopUserAddress} from "@/api/shop/shopUserAddress";
|
||||||
|
import {ShopUserAddress} from "@/api/shop/shopUserAddress/model";
|
||||||
|
import './index.scss'
|
||||||
|
import {useCart} from "@/hooks/useCart";
|
||||||
|
import Gap from "@/components/Gap";
|
||||||
|
|
||||||
|
const OrderConfirm = () => {
|
||||||
|
const [goods, setGoods] = useState<ShopGoods | null>(null);
|
||||||
|
const [address, setAddress] = useState<ShopUserAddress>()
|
||||||
|
const router = Taro.getCurrentInstance().router;
|
||||||
|
const goodsId = router?.params?.goodsId;
|
||||||
|
|
||||||
|
const {
|
||||||
|
cartItems
|
||||||
|
} = useCart();
|
||||||
|
|
||||||
|
const reload = async () => {
|
||||||
|
const address = await listShopUserAddress({isDefault: true});
|
||||||
|
if (address.length > 0) {
|
||||||
|
console.log(address, '111')
|
||||||
|
setAddress(address[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (goodsId) {
|
||||||
|
getShopGoods(Number(goodsId)).then(res => {
|
||||||
|
setGoods(res);
|
||||||
|
}).catch(error => {
|
||||||
|
console.error("Failed to fetch goods detail:", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
reload().then()
|
||||||
|
}, [goodsId]);
|
||||||
|
|
||||||
|
if (!goods) {
|
||||||
|
return <div>加载中...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'order-confirm-page'}>
|
||||||
|
<CellGroup>
|
||||||
|
{
|
||||||
|
address && (
|
||||||
|
<Cell className={'address-bottom-line'} onClick={() => Taro.navigateTo({url: '/user/address/index'})}>
|
||||||
|
<Space>
|
||||||
|
<Location/>
|
||||||
|
<View className={'flex flex-col w-full justify-between items-start'}>
|
||||||
|
<Space className={'flex flex-row w-full font-medium'}>
|
||||||
|
<View className={'flex-wrap text-nowrap whitespace-nowrap'}>送至</View>
|
||||||
|
<View style={{width: '64%'}}
|
||||||
|
className={'line-clamp-1 relative'}>{address.province} {address.city} {address.region} {address.address}
|
||||||
|
</View>
|
||||||
|
</Space>
|
||||||
|
<View className={'pt-1 pb-3 text-gray-500'}>{address.name} {address.phone}</View>
|
||||||
|
</View>
|
||||||
|
</Space>
|
||||||
|
</Cell>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{!address && (
|
||||||
|
<Cell className={''} onClick={() => Taro.navigateTo({url: '/user/address/index'})}>
|
||||||
|
<Space>
|
||||||
|
<Location/>
|
||||||
|
添加收货地址
|
||||||
|
</Space>
|
||||||
|
</Cell>
|
||||||
|
)}
|
||||||
|
</CellGroup>
|
||||||
|
|
||||||
|
<CellGroup>
|
||||||
|
{cartItems.map((goods, _) => (
|
||||||
|
<Cell key={goods.goodsId}>
|
||||||
|
<Space>
|
||||||
|
<Image src={goods.image} mode={'aspectFill'} style={{
|
||||||
|
width: '80px',
|
||||||
|
height: '80px',
|
||||||
|
}} lazyLoad={false}/>
|
||||||
|
<View className={'flex flex-col'}>
|
||||||
|
<View className={'font-medium w-full'}>{goods.name}</View>
|
||||||
|
<View className={'number text-gray-400 text-sm py-2'}>80g/袋</View>
|
||||||
|
<Space className={'flex justify-start items-center'}>
|
||||||
|
<View className={'text-red-500'}>¥{goods.price}</View>
|
||||||
|
<View className={'text-gray-500 text-sm'}>x {goods.quantity}</View>
|
||||||
|
</Space>
|
||||||
|
</View>
|
||||||
|
</Space>
|
||||||
|
</Cell>
|
||||||
|
))}
|
||||||
|
</CellGroup>
|
||||||
|
|
||||||
|
<CellGroup>
|
||||||
|
<Cell title={'商品总价(共3件)'} extra={<View className={'font-medium'}>{'¥' + goods.price}</View>}/>
|
||||||
|
<Cell title={'优惠券'} extra={(
|
||||||
|
<View className={'flex justify-between items-center'}>
|
||||||
|
<View className={'text-red-500 text-sm mr-1'}>-¥10.00</View>
|
||||||
|
<ArrowRight className={'text-gray-400'} size={14}/>
|
||||||
|
</View>
|
||||||
|
)}/>
|
||||||
|
{/*<Cell title={'配送费'} extra={'¥' + 10}/>*/}
|
||||||
|
<Cell title={'订单备注'} extra={(
|
||||||
|
<Input placeholder={'选填,请先和商家协商一致'} style={{ padding: '0'}}/>
|
||||||
|
)}/>
|
||||||
|
</CellGroup>
|
||||||
|
|
||||||
|
<Gap height={50} />
|
||||||
|
|
||||||
|
<div className={'fixed z-50 bg-white w-full bottom-0 left-0 pt-4 pb-10'} style={{
|
||||||
|
boxShadow: '0 -2px 4px 0 rgba(0,0,0,0.10)'
|
||||||
|
}}>
|
||||||
|
<View className={'btn-bar flex justify-between items-center'}>
|
||||||
|
<div className={'flex justify-center items-center mx-4'}>
|
||||||
|
<span className={'total-price text-sm text-gray-500'}>实付金额:</span>
|
||||||
|
<span className={'text-red-500 text-xl font-bold'}>¥{goods.price}</span>
|
||||||
|
</div>
|
||||||
|
<div className={'buy-btn mx-4'}>
|
||||||
|
<Button type="success" size="large">立即付款</Button>
|
||||||
|
</div>
|
||||||
|
</View>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OrderConfirm;
|
||||||
@@ -27,7 +27,7 @@ const Address = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDefault = async (item) => {
|
const onDefault = async (item: ShopUserAddress) => {
|
||||||
if (address) {
|
if (address) {
|
||||||
await updateShopUserAddress({
|
await updateShopUserAddress({
|
||||||
...address,
|
...address,
|
||||||
@@ -54,6 +54,22 @@ const Address = () => {
|
|||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selectAddress = async (item: ShopUserAddress) => {
|
||||||
|
if (address) {
|
||||||
|
await updateShopUserAddress({
|
||||||
|
...address,
|
||||||
|
isDefault: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await updateShopUserAddress({
|
||||||
|
id: item.id,
|
||||||
|
isDefault: true
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
Taro.navigateBack()
|
||||||
|
},500)
|
||||||
|
}
|
||||||
|
|
||||||
useDidShow(() => {
|
useDidShow(() => {
|
||||||
reload()
|
reload()
|
||||||
});
|
});
|
||||||
@@ -97,7 +113,7 @@ const Address = () => {
|
|||||||
</CellGroup>
|
</CellGroup>
|
||||||
{list.map((item, _) => (
|
{list.map((item, _) => (
|
||||||
<Cell.Group>
|
<Cell.Group>
|
||||||
<Cell className={'flex flex-col gap-1'}>
|
<Cell className={'flex flex-col gap-1'} onClick={() => selectAddress(item)}>
|
||||||
<View>
|
<View>
|
||||||
<View className={'font-medium text-sm'}>{item.name} {item.phone}</View>
|
<View className={'font-medium text-sm'}>{item.name} {item.phone}</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {User} from "@/api/system/user/model";
|
|||||||
// 模版套餐ID - 请根据实际情况修改
|
// 模版套餐ID - 请根据实际情况修改
|
||||||
export const TEMPLATE_ID = '10550';
|
export const TEMPLATE_ID = '10550';
|
||||||
// 服务接口 - 请根据实际情况修改
|
// 服务接口 - 请根据实际情况修改
|
||||||
export const SERVER_API_URL = 'https://server.websoft.top/api';
|
export const SERVER_API_URL = 'https://server.gxwebsoft.com/api';
|
||||||
// export const SERVER_API_URL = 'http://127.0.0.1:8000/api';
|
// export const SERVER_API_URL = 'http://127.0.0.1:8000/api';
|
||||||
/**
|
/**
|
||||||
* 保存用户信息到本地存储
|
* 保存用户信息到本地存储
|
||||||
|
|||||||
Reference in New Issue
Block a user