Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
5ec30361
authored
Mar 22, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 修复支付可能存在的缺陷
parent
984baf60
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
263 additions
and
90 deletions
+263
-90
src/api/user.ts
+5
-4
src/components/WxConcat/index.tsx
+49
-0
src/pages/api/user/checkPayResult.ts
+41
-29
src/pages/api/user/getBill.ts
+1
-1
src/pages/api/user/getPayCode.ts
+12
-2
src/pages/api/user/getPayOrders.ts
+31
-0
src/pages/chat/components/SlideBar.tsx
+2
-29
src/pages/number/components/PayModal.tsx
+19
-15
src/pages/number/setting.tsx
+84
-6
src/service/models/pay.ts
+9
-3
src/service/models/user.ts
+1
-1
src/types/mongoSchema.d.ts
+9
-0
No files found.
src/api/user.ts
View file @
5ec30361
...
@@ -4,7 +4,7 @@ import { ResLogin } from './response/user';
...
@@ -4,7 +4,7 @@ import { ResLogin } from './response/user';
import
{
EmailTypeEnum
}
from
'@/constants/common'
;
import
{
EmailTypeEnum
}
from
'@/constants/common'
;
import
{
UserType
,
UserUpdateParams
}
from
'@/types/user'
;
import
{
UserType
,
UserUpdateParams
}
from
'@/types/user'
;
import
type
{
PagingData
,
RequestPaging
}
from
'@/types'
;
import
type
{
PagingData
,
RequestPaging
}
from
'@/types'
;
import
{
BillSchema
}
from
'@/types/mongoSchema'
;
import
{
BillSchema
,
PaySchema
}
from
'@/types/mongoSchema'
;
import
{
adaptBill
}
from
'@/utils/adapt'
;
import
{
adaptBill
}
from
'@/utils/adapt'
;
export
const
sendCodeToEmail
=
({
email
,
type
}:
{
email
:
string
;
type
:
`
${
EmailTypeEnum
}
`
})
=>
export
const
sendCodeToEmail
=
({
email
,
type
}:
{
email
:
string
;
type
:
`
${
EmailTypeEnum
}
`
})
=>
...
@@ -56,11 +56,12 @@ export const getUserBills = (data: RequestPaging) =>
...
@@ -56,11 +56,12 @@ export const getUserBills = (data: RequestPaging) =>
data
:
res
.
data
.
map
((
bill
)
=>
adaptBill
(
bill
))
data
:
res
.
data
.
map
((
bill
)
=>
adaptBill
(
bill
))
}));
}));
export
const
getPayOrders
=
()
=>
GET
<
PaySchema
[]
>
(
`/user/getPayOrders`
);
export
const
getPayCode
=
(
amount
:
number
)
=>
export
const
getPayCode
=
(
amount
:
number
)
=>
GET
<
{
GET
<
{
codeUrl
:
string
;
codeUrl
:
string
;
order
Id
:
string
;
pay
Id
:
string
;
}
>
(
`/user/getPayCode?amount=
${
amount
}
`
);
}
>
(
`/user/getPayCode?amount=
${
amount
}
`
);
export
const
checkPayResult
=
(
orderId
:
string
)
=>
export
const
checkPayResult
=
(
payId
:
string
)
=>
GET
<
number
>
(
`/user/checkPayResult?payId=
${
payId
}
`
);
GET
<
number
>
(
`/user/checkPayResult?orderId=
${
orderId
}
`
);
src/components/WxConcat/index.tsx
0 → 100644
View file @
5ec30361
import
React
from
'react'
;
import
{
Box
,
Button
,
Modal
,
ModalOverlay
,
ModalContent
,
ModalHeader
,
ModalFooter
,
ModalBody
,
ModalCloseButton
,
useColorModeValue
}
from
'@chakra-ui/react'
;
import
Image
from
'next/image'
;
const
WxConcat
=
({
onClose
}:
{
onClose
:
()
=>
void
})
=>
{
return
(
<
Modal
isOpen=
{
true
}
onClose=
{
onClose
}
>
<
ModalOverlay
/>
<
ModalContent
color=
{
useColorModeValue
(
'blackAlpha.700'
,
'white'
)
}
>
<
ModalHeader
>
wx交流群
</
ModalHeader
>
<
ModalCloseButton
/>
<
ModalBody
textAlign=
{
'center'
}
>
<
Image
style=
{
{
margin
:
'auto'
}
}
src=
{
'/imgs/wxcode.jpg'
}
width=
{
200
}
height=
{
200
}
alt=
""
/>
<
Box
mt=
{
2
}
>
微信号:
{
' '
}
<
Box
as=
{
'span'
}
userSelect=
{
'all'
}
>
YNyiqi
</
Box
>
</
Box
>
</
ModalBody
>
<
ModalFooter
>
<
Button
variant=
{
'outline'
}
onClick=
{
onClose
}
>
关闭
</
Button
>
</
ModalFooter
>
</
ModalContent
>
</
Modal
>
);
};
export
default
WxConcat
;
src/pages/api/user/checkPayResult.ts
View file @
5ec30361
...
@@ -3,56 +3,68 @@ import { jsonRes } from '@/service/response';
...
@@ -3,56 +3,68 @@ import { jsonRes } from '@/service/response';
import
axios
from
'axios'
;
import
axios
from
'axios'
;
import
{
connectToDatabase
,
User
,
Pay
}
from
'@/service/mongo'
;
import
{
connectToDatabase
,
User
,
Pay
}
from
'@/service/mongo'
;
import
{
authToken
}
from
'@/service/utils/tools'
;
import
{
authToken
}
from
'@/service/utils/tools'
;
import
{
formatPrice
}
from
'@/utils/user
'
;
import
{
PaySchema
}
from
'@/types/mongoSchema
'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
try
{
const
{
authorization
}
=
req
.
headers
;
const
{
authorization
}
=
req
.
headers
;
let
{
orderId
}
=
req
.
query
as
{
order
Id
:
string
};
let
{
payId
}
=
req
.
query
as
{
pay
Id
:
string
};
const
userId
=
await
authToken
(
authorization
);
const
userId
=
await
authToken
(
authorization
);
const
{
data
}
=
await
axios
.
get
(
`https://sif268.laf.dev/wechat-order-query?order_number=
${
orderId
}
&api_key=
${
process
.
env
.
WXPAYCODE
}
`
);
if
(
data
.
trade_state
===
'SUCCESS'
)
{
await
connectToDatabase
();
await
connectToDatabase
();
// 重复记录校验
// 查找订单记录校验
const
count
=
await
Pay
.
count
({
const
payOrder
=
await
Pay
.
findById
<
PaySchema
>
(
payId
);
orderId
});
if
(
count
>
0
)
{
if
(
!
payOrder
)
{
throw
new
Error
(
'订单重复,请刷新'
);
throw
new
Error
(
'订单不存在'
);
}
if
(
payOrder
.
status
!==
'NOTPAY'
)
{
throw
new
Error
(
'订单已结算'
);
}
}
// 计算实际充值。把分转成数据库的值
const
{
data
}
=
await
axios
.
get
(
const
price
=
data
.
amount
.
total
*
0.01
*
100000
;
`https://sif268.laf.dev/wechat-order-query?order_number=
${
payOrder
.
orderId
}
&api_key=
${
process
.
env
.
WXPAYCODE
}
`
let
payId
;
);
if
(
data
.
trade_state
===
'SUCCESS'
)
{
// 订单已支付
try
{
try
{
// 充值记录 +1
// 更新订单状态
const
payRecord
=
await
Pay
.
create
({
const
updateRes
=
await
Pay
.
updateOne
(
userId
,
{
price
,
_id
:
payId
,
orderId
status
:
'NOTPAY'
});
},
payId
=
payRecord
.
_id
;
{
// 充钱
status
:
'SUCCESS'
}
);
if
(
updateRes
.
modifiedCount
===
1
)
{
// 给用户账号充钱
await
User
.
findByIdAndUpdate
(
userId
,
{
await
User
.
findByIdAndUpdate
(
userId
,
{
$inc
:
{
balance
:
price
}
$inc
:
{
balance
:
payOrder
.
price
}
});
});
}
catch
(
error
)
{
payId
&&
Pay
.
findByIdAndDelete
(
payId
);
}
jsonRes
(
res
,
{
jsonRes
(
res
,
{
data
:
'success'
data
:
'success'
});
});
}
}
catch
(
error
)
{
await
Pay
.
findByIdAndUpdate
(
payId
,
{
status
:
'NOTPAY'
});
console
.
log
(
error
);
}
}
else
if
(
data
.
trade_state
===
'CLOSED'
)
{
// 订单已关闭
await
Pay
.
findByIdAndUpdate
(
payId
,
{
status
:
'CLOSED'
});
}
else
{
}
else
{
throw
new
Error
(
data
.
trade_state_desc
);
throw
new
Error
(
data
.
trade_state_desc
);
}
}
throw
new
Error
(
'订单已过期'
);
}
catch
(
err
)
{
}
catch
(
err
)
{
console
.
log
(
err
);
console
.
log
(
err
);
jsonRes
(
res
,
{
jsonRes
(
res
,
{
...
...
src/pages/api/user/getBill.ts
View file @
5ec30361
...
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -25,7 +25,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const
bills
=
await
Bill
.
find
<
BillSchema
>
({
const
bills
=
await
Bill
.
find
<
BillSchema
>
({
userId
userId
})
})
.
sort
({
createdAt
:
-
1
})
// 按照创建时间倒序排列
.
sort
({
time
:
-
1
})
// 按照创建时间倒序排列
.
skip
((
pageNum
-
1
)
*
pageSize
)
.
skip
((
pageNum
-
1
)
*
pageSize
)
.
limit
(
pageSize
);
.
limit
(
pageSize
);
...
...
src/pages/api/user/getPayCode.ts
View file @
5ec30361
...
@@ -4,6 +4,8 @@ import { jsonRes } from '@/service/response';
...
@@ -4,6 +4,8 @@ import { jsonRes } from '@/service/response';
import
axios
from
'axios'
;
import
axios
from
'axios'
;
import
{
authToken
}
from
'@/service/utils/tools'
;
import
{
authToken
}
from
'@/service/utils/tools'
;
import
{
customAlphabet
}
from
'nanoid'
;
import
{
customAlphabet
}
from
'nanoid'
;
import
{
connectToDatabase
,
Pay
}
from
'@/service/mongo'
;
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyz1234567890'
,
20
);
const
nanoid
=
customAlphabet
(
'abcdefghijklmnopqrstuvwxyz1234567890'
,
20
);
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
...
@@ -15,9 +17,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -15,9 +17,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
if
(
!
authorization
)
{
if
(
!
authorization
)
{
throw
new
Error
(
'缺少登录凭证'
);
throw
new
Error
(
'缺少登录凭证'
);
}
}
await
authToken
(
authorization
);
const
userId
=
await
authToken
(
authorization
);
const
id
=
nanoid
();
const
id
=
nanoid
();
await
connectToDatabase
();
const
response
=
await
axios
({
const
response
=
await
axios
({
url
:
'https://sif268.laf.dev/wechat-pay'
,
url
:
'https://sif268.laf.dev/wechat-pay'
,
...
@@ -29,9 +32,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -29,9 +32,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}
}
});
});
// 充值记录 + 1
const
payOrder
=
await
Pay
.
create
({
userId
,
price
:
amount
*
100000
,
orderId
:
id
});
jsonRes
(
res
,
{
jsonRes
(
res
,
{
data
:
{
data
:
{
orderId
:
id
,
payId
:
payOrder
.
_
id
,
codeUrl
:
response
.
data
?.
code_url
codeUrl
:
response
.
data
?.
code_url
}
}
});
});
...
...
src/pages/api/user/getPayOrders.ts
0 → 100644
View file @
5ec30361
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@/service/response'
;
import
{
authToken
}
from
'@/service/utils/tools'
;
import
{
connectToDatabase
,
Pay
}
from
'@/service/mongo'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
const
{
authorization
}
=
req
.
headers
;
if
(
!
authorization
)
{
throw
new
Error
(
'缺少登录凭证'
);
}
const
userId
=
await
authToken
(
authorization
);
await
connectToDatabase
();
const
records
=
await
Pay
.
find
({
userId
}).
sort
({
createTime
:
-
1
});
jsonRes
(
res
,
{
data
:
records
});
}
catch
(
err
)
{
console
.
log
(
err
);
jsonRes
(
res
,
{
code
:
500
,
error
:
err
});
}
}
src/pages/chat/components/SlideBar.tsx
View file @
5ec30361
...
@@ -32,7 +32,7 @@ import { useCopyData } from '@/utils/tools';
...
@@ -32,7 +32,7 @@ import { useCopyData } from '@/utils/tools';
import
Markdown
from
'@/components/Markdown'
;
import
Markdown
from
'@/components/Markdown'
;
import
{
shareHint
}
from
'@/constants/common'
;
import
{
shareHint
}
from
'@/constants/common'
;
import
{
getChatSiteId
}
from
'@/api/chat'
;
import
{
getChatSiteId
}
from
'@/api/chat'
;
import
Image
from
'next/image
'
;
import
WxConcat
from
'@/components/WxConcat
'
;
const
SlideBar
=
({
const
SlideBar
=
({
name
,
name
,
...
@@ -305,34 +305,7 @@ const SlideBar = ({
...
@@ -305,34 +305,7 @@ const SlideBar = ({
</
ModalContent
>
</
ModalContent
>
</
Modal
>
</
Modal
>
{
/* wx 联系 */
}
{
/* wx 联系 */
}
<
Modal
isOpen=
{
isOpenWx
}
onClose=
{
onCloseWx
}
>
{
isOpenWx
&&
<
WxConcat
onClose=
{
onCloseWx
}
/>
}
<
ModalOverlay
/>
<
ModalContent
color=
{
useColorModeValue
(
'blackAlpha.700'
,
'white'
)
}
>
<
ModalHeader
>
wx交流群
</
ModalHeader
>
<
ModalCloseButton
/>
<
ModalBody
textAlign=
{
'center'
}
>
<
Image
style=
{
{
margin
:
'auto'
}
}
src=
{
'/imgs/wxcode.jpg'
}
width=
{
200
}
height=
{
200
}
alt=
""
/>
<
Box
mt=
{
2
}
>
微信号:
{
' '
}
<
Box
as=
{
'span'
}
userSelect=
{
'all'
}
>
YNyiqi
</
Box
>
</
Box
>
</
ModalBody
>
<
ModalFooter
>
<
Button
variant=
{
'outline'
}
onClick=
{
onCloseWx
}
>
关闭
</
Button
>
</
ModalFooter
>
</
ModalContent
>
</
Modal
>
</
Flex
>
</
Flex
>
);
);
};
};
...
...
src/pages/number/components/PayModal.tsx
View file @
5ec30361
...
@@ -15,14 +15,14 @@ import {
...
@@ -15,14 +15,14 @@ import {
import
{
getPayCode
,
checkPayResult
}
from
'@/api/user'
;
import
{
getPayCode
,
checkPayResult
}
from
'@/api/user'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
use
UserStore
}
from
'@/store/us
er'
;
import
{
use
Router
}
from
'next/rout
er'
;
const
PayModal
=
({
onClose
}:
{
onClose
:
()
=>
void
})
=>
{
const
PayModal
=
({
onClose
}:
{
onClose
:
()
=>
void
})
=>
{
const
router
=
useRouter
();
const
{
toast
}
=
useToast
();
const
{
toast
}
=
useToast
();
const
{
initUserInfo
}
=
useUserStore
();
const
[
inputVal
,
setInputVal
]
=
useState
<
number
|
''
>
(
''
);
const
[
inputVal
,
setInputVal
]
=
useState
<
number
|
''
>
(
''
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
orderId
,
setOrder
Id
]
=
useState
(
''
);
const
[
payId
,
setPay
Id
]
=
useState
(
''
);
const
handleClickPay
=
useCallback
(
async
()
=>
{
const
handleClickPay
=
useCallback
(
async
()
=>
{
if
(
!
inputVal
||
inputVal
<=
0
||
isNaN
(
+
inputVal
))
return
;
if
(
!
inputVal
||
inputVal
<=
0
||
isNaN
(
+
inputVal
))
return
;
...
@@ -38,7 +38,7 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
...
@@ -38,7 +38,7 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
colorLight
:
'#ffffff'
,
colorLight
:
'#ffffff'
,
correctLevel
:
QRCode
.
CorrectLevel
.
H
correctLevel
:
QRCode
.
CorrectLevel
.
H
});
});
set
OrderId
(
res
.
order
Id
);
set
PayId
(
res
.
pay
Id
);
}
catch
(
error
)
{
}
catch
(
error
)
{
toast
({
toast
({
title
:
'出现了一些意外...'
,
title
:
'出现了一些意外...'
,
...
@@ -50,21 +50,20 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
...
@@ -50,21 +50,20 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
},
[
inputVal
,
toast
]);
},
[
inputVal
,
toast
]);
useQuery
(
useQuery
(
[
order
Id
],
[
pay
Id
],
()
=>
{
()
=>
{
if
(
!
order
Id
)
return
null
;
if
(
!
pay
Id
)
return
null
;
return
checkPayResult
(
order
Id
);
return
checkPayResult
(
pay
Id
);
},
},
{
{
refetchInterval
:
2000
,
refetchInterval
:
2000
,
onSuccess
(
res
)
{
onSuccess
(
res
)
{
if
(
!
res
)
return
;
if
(
!
res
)
return
;
onClose
();
initUserInfo
();
toast
({
toast
({
title
:
'充值成功'
,
title
:
'充值成功'
,
status
:
'success'
status
:
'success'
});
});
router
.
reload
();
}
}
}
}
);
);
...
@@ -74,17 +73,17 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
...
@@ -74,17 +73,17 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
<
Modal
<
Modal
isOpen=
{
true
}
isOpen=
{
true
}
onClose=
{
()
=>
{
onClose=
{
()
=>
{
if
(
order
Id
)
return
;
if
(
pay
Id
)
return
;
onClose
();
onClose
();
}
}
}
}
>
>
<
ModalOverlay
/>
<
ModalOverlay
/>
<
ModalContent
>
<
ModalContent
>
<
ModalHeader
>
充值
</
ModalHeader
>
<
ModalHeader
>
充值
</
ModalHeader
>
{
!
order
Id
&&
<
ModalCloseButton
/>
}
{
!
pay
Id
&&
<
ModalCloseButton
/>
}
<
ModalBody
>
<
ModalBody
>
{
!
order
Id
&&
(
{
!
pay
Id
&&
(
<>
<>
<
Grid
gridTemplateColumns=
{
'repeat(4,1fr)'
}
gridGap=
{
5
}
mb=
{
4
}
>
<
Grid
gridTemplateColumns=
{
'repeat(4,1fr)'
}
gridGap=
{
5
}
mb=
{
4
}
>
{
[
5
,
10
,
20
,
50
].
map
((
item
)
=>
(
{
[
5
,
10
,
20
,
50
].
map
((
item
)
=>
(
...
@@ -112,18 +111,23 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
...
@@ -112,18 +111,23 @@ const PayModal = ({ onClose }: { onClose: () => void }) => {
)
}
)
}
{
/* 付费二维码 */
}
{
/* 付费二维码 */
}
<
Box
textAlign=
{
'center'
}
>
<
Box
textAlign=
{
'center'
}
>
{
order
Id
&&
<
Box
mb=
{
3
}
>
请微信扫码支付:
{
inputVal
}
元,请勿关闭页面
</
Box
>
}
{
pay
Id
&&
<
Box
mb=
{
3
}
>
请微信扫码支付:
{
inputVal
}
元,请勿关闭页面
</
Box
>
}
<
Box
id=
{
'payQRCode'
}
display=
{
'inline-block'
}
></
Box
>
<
Box
id=
{
'payQRCode'
}
display=
{
'inline-block'
}
></
Box
>
</
Box
>
</
Box
>
</
ModalBody
>
</
ModalBody
>
<
ModalFooter
>
<
ModalFooter
>
{
!
order
Id
&&
(
{
!
pay
Id
&&
(
<>
<>
<
Button
colorScheme=
{
'gray'
}
onClick=
{
onClose
}
>
<
Button
colorScheme=
{
'gray'
}
onClick=
{
onClose
}
>
取消
取消
</
Button
>
</
Button
>
<
Button
ml=
{
3
}
isLoading=
{
loading
}
onClick=
{
handleClickPay
}
>
<
Button
ml=
{
3
}
isLoading=
{
loading
}
isDisabled=
{
!
inputVal
||
inputVal
===
0
}
onClick=
{
handleClickPay
}
>
获取充值二维码
获取充值二维码
</
Button
>
</
Button
>
</>
</>
...
...
src/pages/number/setting.tsx
View file @
5ec30361
...
@@ -13,12 +13,13 @@ import {
...
@@ -13,12 +13,13 @@ import {
TableContainer
,
TableContainer
,
Select
,
Select
,
Input
,
Input
,
IconButton
IconButton
,
useDisclosure
}
from
'@chakra-ui/react'
;
}
from
'@chakra-ui/react'
;
import
{
DeleteIcon
}
from
'@chakra-ui/icons'
;
import
{
DeleteIcon
}
from
'@chakra-ui/icons'
;
import
{
useForm
,
useFieldArray
}
from
'react-hook-form'
;
import
{
useForm
,
useFieldArray
}
from
'react-hook-form'
;
import
{
UserUpdateParams
}
from
'@/types/user'
;
import
{
UserUpdateParams
}
from
'@/types/user'
;
import
{
putUserInfo
,
getUserBills
}
from
'@/api/user'
;
import
{
putUserInfo
,
getUserBills
,
getPayOrders
,
checkPayResult
}
from
'@/api/user'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useGlobalStore
}
from
'@/store/global'
;
import
{
useUserStore
}
from
'@/store/user'
;
import
{
useUserStore
}
from
'@/store/user'
;
...
@@ -27,6 +28,10 @@ import { usePaging } from '@/hooks/usePaging';
...
@@ -27,6 +28,10 @@ import { usePaging } from '@/hooks/usePaging';
import
type
{
UserBillType
}
from
'@/types/user'
;
import
type
{
UserBillType
}
from
'@/types/user'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
{
useQuery
}
from
'@tanstack/react-query'
;
import
dynamic
from
'next/dynamic'
;
import
dynamic
from
'next/dynamic'
;
import
{
PaySchema
}
from
'@/types/mongoSchema'
;
import
dayjs
from
'dayjs'
;
import
{
formatPrice
}
from
'@/utils/user'
;
import
WxConcat
from
'@/components/WxConcat'
;
const
PayModal
=
dynamic
(()
=>
import
(
'./components/PayModal'
));
const
PayModal
=
dynamic
(()
=>
import
(
'./components/PayModal'
));
...
@@ -37,6 +42,7 @@ const NumberSetting = () => {
...
@@ -37,6 +42,7 @@ const NumberSetting = () => {
defaultValues
:
userInfo
as
UserType
defaultValues
:
userInfo
as
UserType
});
});
const
[
showPay
,
setShowPay
]
=
useState
(
false
);
const
[
showPay
,
setShowPay
]
=
useState
(
false
);
const
{
isOpen
:
isOpenWx
,
onOpen
:
onOpenWx
,
onClose
:
onCloseWx
}
=
useDisclosure
();
const
{
toast
}
=
useToast
();
const
{
toast
}
=
useToast
();
const
{
const
{
fields
:
accounts
,
fields
:
accounts
,
...
@@ -50,6 +56,7 @@ const NumberSetting = () => {
...
@@ -50,6 +56,7 @@ const NumberSetting = () => {
api
:
getUserBills
,
api
:
getUserBills
,
pageSize
:
30
pageSize
:
30
});
});
const
[
payOrders
,
setPayOrders
]
=
useState
<
PaySchema
[]
>
([]);
const
onclickSave
=
useCallback
(
const
onclickSave
=
useCallback
(
async
(
data
:
UserUpdateParams
)
=>
{
async
(
data
:
UserUpdateParams
)
=>
{
...
@@ -69,6 +76,31 @@ const NumberSetting = () => {
...
@@ -69,6 +76,31 @@ const NumberSetting = () => {
useQuery
([
'init'
],
initUserInfo
);
useQuery
([
'init'
],
initUserInfo
);
useQuery
([
'initPayOrder'
],
getPayOrders
,
{
onSuccess
(
res
)
{
setPayOrders
(
res
);
}
});
const
handleRefreshPayOrder
=
useCallback
(
async
(
payId
:
string
)
=>
{
try
{
setLoading
(
true
);
await
checkPayResult
(
payId
);
const
res
=
await
getPayOrders
();
setPayOrders
(
res
);
}
catch
(
error
:
any
)
{
toast
({
title
:
error
?.
message
,
status
:
'warning'
});
console
.
log
(
error
);
}
setLoading
(
false
);
},
[
setLoading
,
toast
]
);
return
(
return
(
<>
<>
<
Card
px=
{
6
}
py=
{
4
}
>
<
Card
px=
{
6
}
py=
{
4
}
>
...
@@ -162,10 +194,54 @@ const NumberSetting = () => {
...
@@ -162,10 +194,54 @@ const NumberSetting = () => {
</
TableContainer
>
</
TableContainer
>
</
Card
>
</
Card
>
<
Card
mt=
{
6
}
px=
{
6
}
py=
{
4
}
>
<
Card
mt=
{
6
}
px=
{
6
}
py=
{
4
}
>
<
Flex
alignItems=
{
'flex-end'
}
>
<
Box
fontSize=
{
'xl'
}
fontWeight=
{
'bold'
}
>
<
Box
fontSize=
{
'xl'
}
fontWeight=
{
'bold'
}
>
使用
记录
充值
记录
</
Box
>
</
Box
>
<
TableContainer
>
<
Button
onClick=
{
onOpenWx
}
size=
{
'xs'
}
ml=
{
4
}
variant=
{
'outline'
}
>
异常问题,wx联系
</
Button
>
</
Flex
>
<
TableContainer
maxH=
{
'400px'
}
overflowY=
{
'auto'
}
>
<
Table
>
<
Thead
>
<
Tr
>
<
Th
>
订单号
</
Th
>
<
Th
>
时间
</
Th
>
<
Th
>
金额
</
Th
>
<
Th
>
消费
</
Th
>
<
Th
></
Th
>
</
Tr
>
</
Thead
>
<
Tbody
fontSize=
{
'sm'
}
>
{
payOrders
.
map
((
item
)
=>
(
<
Tr
key=
{
item
.
_id
}
>
<
Td
>
{
item
.
orderId
}
</
Td
>
<
Td
>
{
item
.
createTime
?
dayjs
(
item
.
createTime
).
format
(
'YYYY/MM/DD HH:mm:ss'
)
:
'-'
}
</
Td
>
<
Td
whiteSpace=
"pre-wrap"
wordBreak=
{
'break-all'
}
>
{
formatPrice
(
item
.
price
)
}
元
</
Td
>
<
Td
>
{
item
.
status
}
</
Td
>
<
Td
>
{
item
.
status
===
'NOTPAY'
&&
(
<
Button
onClick=
{
()
=>
handleRefreshPayOrder
(
item
.
_id
)
}
size=
{
'sm'
}
>
更新
</
Button
>
)
}
</
Td
>
</
Tr
>
))
}
</
Tbody
>
</
Table
>
</
TableContainer
>
</
Card
>
<
Card
mt=
{
6
}
px=
{
6
}
py=
{
4
}
>
<
Box
fontSize=
{
'xl'
}
fontWeight=
{
'bold'
}
>
使用记录(最新30条)
</
Box
>
<
TableContainer
maxH=
{
'400px'
}
overflowY=
{
'auto'
}
>
<
Table
>
<
Table
>
<
Thead
>
<
Thead
>
<
Tr
>
<
Tr
>
...
@@ -177,8 +253,8 @@ const NumberSetting = () => {
...
@@ -177,8 +253,8 @@ const NumberSetting = () => {
<
Tbody
fontSize=
{
'sm'
}
>
<
Tbody
fontSize=
{
'sm'
}
>
{
bills
.
map
((
item
)
=>
(
{
bills
.
map
((
item
)
=>
(
<
Tr
key=
{
item
.
id
}
>
<
Tr
key=
{
item
.
id
}
>
<
Td
minW=
{
'200px'
}
>
{
item
.
time
}
</
Td
>
<
Td
>
{
item
.
time
}
</
Td
>
<
Td
minW=
{
'200px'
}
whiteSpace=
"pre-wrap"
wordBreak=
{
'break-all'
}
>
<
Td
whiteSpace=
"pre-wrap"
wordBreak=
{
'break-all'
}
>
{
item
.
textLen
}
{
item
.
textLen
}
</
Td
>
</
Td
>
<
Td
>
{
item
.
price
}
元
</
Td
>
<
Td
>
{
item
.
price
}
元
</
Td
>
...
@@ -189,6 +265,8 @@ const NumberSetting = () => {
...
@@ -189,6 +265,8 @@ const NumberSetting = () => {
</
TableContainer
>
</
TableContainer
>
</
Card
>
</
Card
>
{
showPay
&&
<
PayModal
onClose=
{
()
=>
setShowPay
(
false
)
}
/>
}
{
showPay
&&
<
PayModal
onClose=
{
()
=>
setShowPay
(
false
)
}
/>
}
{
/* wx 联系 */
}
{
isOpenWx
&&
<
WxConcat
onClose=
{
onCloseWx
}
/>
}
</>
</>
);
);
};
};
...
...
src/service/models/pay.ts
View file @
5ec30361
...
@@ -6,9 +6,9 @@ const PaySchema = new Schema({
...
@@ -6,9 +6,9 @@ const PaySchema = new Schema({
ref
:
'user'
,
ref
:
'user'
,
required
:
true
required
:
true
},
},
t
ime
:
{
createT
ime
:
{
type
:
Number
,
type
:
Date
,
default
:
()
=>
Date
.
now
()
default
:
()
=>
new
Date
()
},
},
price
:
{
price
:
{
type
:
Number
,
type
:
Number
,
...
@@ -17,6 +17,12 @@ const PaySchema = new Schema({
...
@@ -17,6 +17,12 @@ const PaySchema = new Schema({
orderId
:
{
orderId
:
{
type
:
String
,
type
:
String
,
required
:
true
required
:
true
},
status
:
{
// 支付的状态
type
:
String
,
default
:
'NOTPAY'
,
enum
:
[
'SUCCESS'
,
'REFUND'
,
'NOTPAY'
,
'CLOSED'
]
}
}
});
});
...
...
src/service/models/user.ts
View file @
5ec30361
...
@@ -16,7 +16,7 @@ const UserSchema = new Schema({
...
@@ -16,7 +16,7 @@ const UserSchema = new Schema({
},
},
balance
:
{
balance
:
{
type
:
Number
,
type
:
Number
,
default
:
0.5
default
:
0.5
*
100000
},
},
accounts
:
[
accounts
:
[
{
{
...
...
src/types/mongoSchema.d.ts
View file @
5ec30361
...
@@ -85,3 +85,12 @@ export interface BillSchema {
...
@@ -85,3 +85,12 @@ export interface BillSchema {
textLen
:
number
;
textLen
:
number
;
price
:
number
;
price
:
number
;
}
}
export
interface
PaySchema
{
_id
:
string
;
userId
:
string
;
createTime
:
Date
;
price
:
number
;
orderId
:
string
;
status
:
'SUCCESS'
|
'REFUND'
|
'NOTPAY'
|
'CLOSED'
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment