REVIEW 退款订单

This commit is contained in:
YunaiV 2023-04-11 23:01:51 +08:00
parent 8863d1d080
commit 30cf8008ce
4 changed files with 277 additions and 334 deletions

View File

@ -233,7 +233,7 @@ import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
import * as MerchantApi from '@/api/pay/merchant' import * as MerchantApi from '@/api/pay/merchant'
import * as OrderApi from '@/api/pay/order' import * as OrderApi from '@/api/pay/order'
import OrderDetail from '@/views/pay/order/OrderDetail.vue' import OrderDetail from './OrderDetail.vue'
const message = useMessage() // const message = useMessage() //
import download from '@/utils/download' import download from '@/utils/download'
@ -314,7 +314,7 @@ const handleExport = async () => {
/** 预览详情 */ /** 预览详情 */
const detailRef = ref() const detailRef = ref()
const openDetail = (id?: number) => { const openDetail = (id: number) => {
detailRef.value.open(id) detailRef.value.open(id)
} }

View File

@ -0,0 +1,115 @@
<template>
<Dialog title="详情" v-model="dialogVisible" width="50%">
<el-descriptions :column="2">
<el-descriptions-item label="商户名称">{{ detailData.merchantName }}</el-descriptions-item>
<el-descriptions-item label="应用名称">{{ detailData.appName }}</el-descriptions-item>
<el-descriptions-item label="商品名称">{{ detailData.subject }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2">
<el-descriptions-item label="商户退款单号">
<el-tag>{{ detailData.merchantRefundNo }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="商户订单号">
{{ detailData.merchantOrderId }}
</el-descriptions-item>
<el-descriptions-item label="交易订单号">{{ detailData.tradeNo }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2">
<el-descriptions-item label="支付金额">
<el-tag type="success">{{ parseFloat(detailData.payAmount / 100, 2).toFixed(2) }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="退款金额">
<el-tag class="tag-purple">
{{ parseFloat(detailData.refundAmount / 100).toFixed(2) }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="退款类型">
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="detailData.type" />
</el-descriptions-item>
<el-descriptions-item label="退款状态">
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="detailData.status" />
</el-descriptions-item>
<el-descriptions-item label="创建时间">
{{ formatDate(detailData.createTime) }}
</el-descriptions-item>
<el-descriptions-item label="退款成功时间">
{{ formatDate(detailData.successTime) }}
</el-descriptions-item>
<el-descriptions-item label="退款失效时间">
{{ formatDate(detailData.expireTime) }}
</el-descriptions-item>
<el-descriptions-item label="更新时间">
{{ formatDate(detailData.updateTime) }}
</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2">
<el-descriptions-item label="支付渠道">
{{ detailData.channelCodeName }}
</el-descriptions-item>
<el-descriptions-item label="支付 IP">
{{ detailData.userIp }}
</el-descriptions-item>
<el-descriptions-item label="回调地址">{{ detailData.notifyUrl }}</el-descriptions-item>
<el-descriptions-item label="回调状态">
<dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="detailData.notifyStatus" />
</el-descriptions-item>
<el-descriptions-item label="回调时间">
{{ formatDate(detailData.notifyTime) }}
</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2">
<el-descriptions-item label="渠道订单号">
{{ detailData.channelOrderNo }}
</el-descriptions-item>
<el-descriptions-item label="渠道退款单号">
{{ detailData.channelRefundNo }}
</el-descriptions-item>
<el-descriptions-item label="渠道错误码">
{{ detailData.channelErrorCode }}
</el-descriptions-item>
<el-descriptions-item label="渠道错误码描述">
{{ detailData.channelErrorMsg }}
</el-descriptions-item>
</el-descriptions>
<br />
<el-descriptions :column="1" direction="vertical" border>
<el-descriptions-item label="渠道额外参数">
{{ detailData.channelExtras }}
</el-descriptions-item>
<el-descriptions-item label="退款原因">{{ detailData.reason }}</el-descriptions-item>
</el-descriptions>
</Dialog>
</template>
<script setup lang="ts" name="refundForm">
import { DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import * as RefundApi from '@/api/pay/refund'
const dialogVisible = ref(false) //
const detailLoading = ref(false) //
const detailData = ref({})
/** 打开弹窗 */
const open = async (id: number) => {
dialogVisible.value = true
//
detailLoading.value = true
try {
detailData.value = await RefundApi.getRefund(id)
} finally {
detailLoading.value = false
}
}
defineExpose({ open }) // open
</script>
<style>
.tag-purple {
color: #722ed1;
background: #f9f0ff;
border-color: #d3adf7;
}
</style>

View File

@ -1,10 +1,10 @@
<template> <template>
<ContentWrap>
<!-- 搜索工作栏 --> <!-- 搜索工作栏 -->
<ContentWrap>
<el-form <el-form
class="-mb-15px"
:model="queryParams" :model="queryParams"
ref="queryFormRef" ref="queryFormRef"
size="small"
:inline="true" :inline="true"
label-width="120px" label-width="120px"
> >
@ -12,18 +12,8 @@
<el-select <el-select
v-model="queryParams.merchantId" v-model="queryParams.merchantId"
clearable clearable
@clear="
() => {
queryParams.merchantId = null
}
"
filterable
remote
reserve-keyword
placeholder="请选择所属商户" placeholder="请选择所属商户"
@change="handleGetAppListByMerchantId" class="!w-240px"
:remote-method="handleGetMerchantListByName"
:loading="merchantLoading"
> >
<el-option <el-option
v-for="item in merchantList" v-for="item in merchantList"
@ -34,7 +24,12 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="应用编号" prop="appId"> <el-form-item label="应用编号" prop="appId">
<el-select clearable v-model="queryParams.appId" filterable placeholder="请选择应用信息"> <el-select
v-model="queryParams.appId"
clearable
placeholder="请选择应用信息"
class="!w-240px"
>
<el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -43,14 +38,10 @@
v-model="queryParams.channelCode" v-model="queryParams.channelCode"
placeholder="请输入渠道编码" placeholder="请输入渠道编码"
clearable clearable
@clear=" class="!w-240px"
() => {
queryParams.channelCode = null
}
"
> >
<el-option <el-option
v-for="dict in getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)" v-for="dict in getStrDictOptions(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)"
:key="dict.value" :key="dict.value"
:label="dict.label" :label="dict.label"
:value="dict.value" :value="dict.value"
@ -58,12 +49,17 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="退款类型" prop="type"> <el-form-item label="退款类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择退款类型" clearable> <el-select
v-model="queryParams.type"
placeholder="请选择退款类型"
clearable
class="!w-240px"
>
<el-option <el-option
v-for="dict in getDictOptions(DICT_TYPE.PAY_REFUND_ORDER_TYPE)" v-for="dict in getIntDictOptions(DICT_TYPE.PAY_REFUND_ORDER_TYPE)"
:key="parseInt(dict.value)" :key="dict.value"
:label="dict.label" :label="dict.label"
:value="parseInt(dict.value)" :value="dict.value"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -73,15 +69,21 @@
placeholder="请输入商户退款订单号" placeholder="请输入商户退款订单号"
clearable clearable
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
class="!w-240px"
/> />
</el-form-item> </el-form-item>
<el-form-item label="退款状态" prop="status"> <el-form-item label="退款状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择退款状态" clearable> <el-select
v-model="queryParams.status"
placeholder="请选择退款状态"
clearable
class="!w-240px"
>
<el-option <el-option
v-for="dict in getDictOptions(DICT_TYPE.PAY_REFUND_ORDER_STATUS)" v-for="dict in getIntDictOptions(DICT_TYPE.PAY_REFUND_ORDER_STATUS)"
:key="parseInt(dict.value)" :key="dict.value"
:label="dict.label" :label="dict.label"
:value="parseInt(dict.value)" :value="dict.value"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -90,12 +92,13 @@
v-model="queryParams.notifyStatus" v-model="queryParams.notifyStatus"
placeholder="请选择通知商户退款结果的回调状态" placeholder="请选择通知商户退款结果的回调状态"
clearable clearable
class="!w-240px"
> >
<el-option <el-option
v-for="dict in getDictOptions(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS)" v-for="dict in getIntDictOptions(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS)"
:key="parseInt(dict.value)" :key="dict.value"
:label="dict.label" :label="dict.label"
:value="parseInt(dict.value)" :value="dict.value"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -111,14 +114,8 @@
/> />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button @click="handleQuery"> <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<Icon icon="ep:search" class="mr-5px" /> <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
搜索
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" />
重置
</el-button>
<el-button <el-button
type="success" type="success"
plain plain
@ -126,12 +123,13 @@
:loading="exportLoading" :loading="exportLoading"
v-hasPermi="['system:tenant:export']" v-hasPermi="['system:tenant:export']"
> >
<Icon icon="ep:download" class="mr-5px" /> <Icon icon="ep:download" class="mr-5px" /> 导出
导出
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</ContentWrap> </ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list"> <el-table v-loading="loading" :data="list">
<el-table-column label="编号" align="center" prop="id" /> <el-table-column label="编号" align="center" prop="id" />
<el-table-column label="商户名称" align="center" prop="merchantName" width="120" /> <el-table-column label="商户名称" align="center" prop="merchantName" width="120" />
@ -142,7 +140,7 @@
<el-table-column label="商户订单号" align="left" width="230"> <el-table-column label="商户订单号" align="left" width="230">
<template #default="scope"> <template #default="scope">
<p class="order-font"> <p class="order-font">
<el-tag size="small">退款</el-tag> <el-tag>退款</el-tag>
{{ scope.row.merchantRefundNo }} {{ scope.row.merchantRefundNo }}
</p> </p>
<p class="order-font"> <p class="order-font">
@ -154,11 +152,11 @@
<el-table-column label="支付订单号" align="center" prop="merchantRefundNo" width="250"> <el-table-column label="支付订单号" align="center" prop="merchantRefundNo" width="250">
<template #default="scope"> <template #default="scope">
<p class="order-font"> <p class="order-font">
<el-tag size="small">交易</el-tag> <el-tag>交易</el-tag>
{{ scope.row.tradeNo }} {{ scope.row.tradeNo }}
</p> </p>
<p class="order-font"> <p class="order-font">
<el-tag size="small" type="warning">渠道</el-tag> <el-tag type="warning">渠道</el-tag>
{{ scope.row.channelOrderNo }} {{ scope.row.channelOrderNo }}
</p> </p>
</template> </template>
@ -199,35 +197,29 @@
label="创建时间" label="创建时间"
align="center" align="center"
prop="createTime" prop="createTime"
width="100" width="180"
:formatter="dateFormatter" :formatter="dateFormatter"
/> />
<el-table-column <el-table-column
label="退款成功时间" label="退款成功时间"
align="center" align="center"
prop="successTime" prop="successTime"
width="100" width="180"
:formatter="dateFormatter" :formatter="dateFormatter"
/> />
<el-table-column <el-table-column label="操作" align="center" fixed="right">
label="操作"
align="center"
fixed="right"
class-name="small-padding fixed-width"
>
<template #default="scope"> <template #default="scope">
<el-button <el-button
size="small" type="primary"
type="text" link
icon="el-icon-search" @click="openDetail(scope.row.id)"
@click="openForm(scope.row.id)"
v-hasPermi="['pay:order:query']" v-hasPermi="['pay:order:query']"
>查看详情 >
详情
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<ContentWrap>
<!-- 分页 --> <!-- 分页 -->
<Pagination <Pagination
:total="total" :total="total"
@ -236,27 +228,22 @@
@pagination="getList" @pagination="getList"
/> />
</ContentWrap> </ContentWrap>
<!-- 表单弹窗预览 --> <!-- 表单弹窗预览 -->
<RefundForm ref="formRef" @success="getList" /> <RefundDetail ref="detailRef" @success="getList" />
</template> </template>
<script setup lang="ts" name="Refund"> <script setup lang="ts" name="PayRefund">
import * as AppApi from '@/api/pay/app' import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import * as MerchantApi from '@/api/pay/merchant' import * as MerchantApi from '@/api/pay/merchant'
import * as RefundApi from '@/api/pay/refund' import * as RefundApi from '@/api/pay/refund'
import { DICT_TYPE, getDictOptions } from '@/utils/dict' import RefundDetail from './RefundDetail.vue'
import download from '@/utils/download'
import { dateFormatter } from '@/utils/formatTime'
import RefundForm from '@/views/pay/refund/refundForm.vue'
const merchantLoading = ref(false) //
const message = useMessage() // const message = useMessage() //
const appList = ref([]) // import download from '@/utils/download'
const merchantList = ref([]) //
const exportLoading = ref(false) //
const loading = ref(false) // const loading = ref(false) //
const total = ref(0) // const total = ref(0) //
const list = ref([]) // const list = ref([]) //
const queryFormRef = ref() //
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
@ -286,26 +273,10 @@ const queryParams = reactive({
notifyTime: [], notifyTime: [],
createTime: [] createTime: []
}) })
const queryFormRef = ref() //
/** const exportLoading = ref(false) //
* 根据商户 ID 查询支付应用信息 const appList = ref([]) //
*/ const merchantList = ref([]) //
const handleGetAppListByMerchantId = () => {
queryParams.appId = undefined
if (queryParams.merchantId) {
AppApi.getAppListByMerchantId(queryParams.merchantId).then((response) => {
appList.value = response.data
})
}
}
/**
* 根据商户名称模糊匹配商户信息
* @param name 商户名称
*/
const handleGetMerchantListByName = async (name) => {
merchantList.value = await MerchantApi.getMerchantListByName(name)
}
/** 搜索按钮操作 */ /** 搜索按钮操作 */
const handleQuery = () => { const handleQuery = () => {
@ -333,21 +304,32 @@ const resetQuery = () => {
/** 导出按钮操作 */ /** 导出按钮操作 */
const handleExport = async () => { const handleExport = async () => {
try {
// //
await message.exportConfirm() await message.exportConfirm()
// //
exportLoading.value = true exportLoading.value = true
const data = await RefundApi.exportRefund(queryParams) const data = await RefundApi.exportRefund(queryParams)
download.excel(data, '退款订单.xls') download.excel(data, '支付订单.xls')
} catch {
} finally {
exportLoading.value = false
}
} }
/** 预览详情 */ /** 预览详情 */
const formRef = ref() const detailRef = ref()
const openForm = (id?: number) => { const openDetail = (id: number) => {
formRef.value.open(id) detailRef.value.open(id)
} }
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {
await getList() await getList()
//
merchantList.value = await MerchantApi.getMerchantListByName()
// TODO
// appList.value = await AppApi.getAppListByMerchantId()
}) })
</script> </script>

View File

@ -1,154 +0,0 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="50%">
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="商户名称">{{ refundDetail.merchantName }}</el-descriptions-item>
<el-descriptions-item label="应用名称">{{ refundDetail.appName }}</el-descriptions-item>
<el-descriptions-item label="商品名称">{{ refundDetail.subject }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="商户退款单号">
<el-tag size="small">{{ refundDetail.merchantRefundNo }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="商户订单号"
>{{ refundDetail.merchantOrderId }}
</el-descriptions-item>
<el-descriptions-item label="交易订单号">{{ refundDetail.tradeNo }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="支付金额">
{{ parseFloat(refundDetail.payAmount / 100).toFixed(2) }}
</el-descriptions-item>
<el-descriptions-item label="退款金额" size="small">
<el-tag class="tag-purple" size="small">
{{ parseFloat(refundDetail.refundAmount / 100).toFixed(2) }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="退款类型">
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="refundDetail.type" />
</el-descriptions-item>
<el-descriptions-item label="退款状态">
<dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="refundDetail.status" />
</el-descriptions-item>
<el-descriptions-item label="创建时间"
>{{ formatDate(refundDetail.createTime) }}
</el-descriptions-item>
<el-descriptions-item label="退款成功时间"
>{{ formatDate(refundDetail.successTime) }}
</el-descriptions-item>
<el-descriptions-item label="退款失效时间"
>{{ formatDate(refundDetail.expireTime) }}
</el-descriptions-item>
<el-descriptions-item label="更新时间"
>{{ formatDate(refundDetail.updateTime) }}
</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="支付渠道">
{{ refundDetail.channelCodeName }}
</el-descriptions-item>
<el-descriptions-item label="支付IP" size="small">
{{ refundDetail.userIp }}
</el-descriptions-item>
<el-descriptions-item label="回调地址">{{ refundDetail.notifyUrl }}</el-descriptions-item>
<el-descriptions-item label="回调状态">
<dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="refundDetail.notifyStatus" />
</el-descriptions-item>
<el-descriptions-item label="回调时间"
>{{ formatDate(refundDetail.notifyTime) }}
</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="2" label-class-name="desc-label">
<el-descriptions-item label="渠道订单号"
>{{ refundDetail.channelOrderNo }}
</el-descriptions-item>
<el-descriptions-item label="渠道退款单号"
>{{ refundDetail.channelRefundNo }}
</el-descriptions-item>
<el-descriptions-item label="渠道错误码"
>{{ refundDetail.channelErrorCode }}
</el-descriptions-item>
<el-descriptions-item label="渠道错误码描述"
>{{ refundDetail.channelErrorMsg }}
</el-descriptions-item>
</el-descriptions>
<br />
<el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
<el-descriptions-item label="渠道额外参数"
>{{ refundDetail.channelExtras }}
</el-descriptions-item>
<el-descriptions-item label="退款原因">{{ refundDetail.reason }}</el-descriptions-item>
</el-descriptions>
</Dialog>
</template>
<script setup lang="ts" name="refundForm">
import { DICT_TYPE } from '@/utils/dict'
import * as RefundApi from '@/api/pay/refund'
import { formatDate } from '@/utils/formatTime'
const { t } = useI18n() //
// const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('退款订单详情') //
const formLoading = ref(false) // 12
const defaultrefundDetail = {
id: null,
appId: null,
appName: '',
channelCode: '',
channelCodeName: '',
channelErrorCode: '',
channelErrorMsg: '',
channelExtras: '',
channelId: null,
channelOrderNo: '',
channelRefundNo: '',
createTime: null,
expireTime: null,
merchantId: null,
merchantName: '',
merchantOrderId: '',
merchantRefundNo: '',
notifyStatus: null,
notifyTime: null,
notifyUrl: '',
orderId: null,
payAmount: null,
reason: '',
refundAmount: null,
status: null,
subject: '',
successTime: null,
tradeNo: '',
type: null,
userIp: ''
}
const refundDetail = ref(JSON.parse(JSON.stringify(defaultrefundDetail)))
/** 打开弹窗 */
const open = async (id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.preview')
//
if (id) {
formLoading.value = true
try {
refundDetail.value = await RefundApi.getRefundApi(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
</script>
<style>
.tag-purple {
color: #722ed1;
background: #f9f0ff;
border-color: #d3adf7;
}
</style>