Procházet zdrojové kódy

REVIEW 支付应用、支付订单

YunaiV před 1 rokem
rodič
revize
8863d1d080

+ 2 - 2
src/api/pay/merchant/index.ts

@@ -39,9 +39,9 @@ export const getMerchant = (id: number) => {
 }
 
 // 根据商户名称搜索商户列表
-export const getMerchantListByName = (name: string) => {
+export const getMerchantListByName = (name?: string) => {
   return request.get({
-    url: '/pay/merchant/list-by-name?id=',
+    url: '/pay/merchant/list-by-name',
     params: {
       name: name
     }

+ 5 - 0
src/api/pay/order/index.ts

@@ -88,6 +88,11 @@ export const getOrder = async (id: number) => {
   return await request.get({ url: '/pay/order/get?id=' + id })
 }
 
+// 获得支付订单的明细
+export const getOrderDetail = async (id: number) => {
+  return await request.get({ url: '/pay/order/get-detail?id=' + id })
+}
+
 // 新增支付订单
 export const createOrder = async (data: OrderVO) => {
   return await request.post({ url: '/pay/order/create', data })

+ 14 - 11
src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue

@@ -188,7 +188,13 @@
       <!-- <div id="js-properties-panel" class="panel"></div> -->
       <!-- <div class="my-process-designer__canvas" ref="bpmn-canvas"></div> -->
     </div>
-    <XModal title="预览" width="80%" height="90%" v-model="previewModelVisible" destroy-on-close>
+    <Dialog
+      title="预览"
+      v-model="previewModelVisible"
+      width="80%"
+      :scroll="true"
+      max-height="600px"
+    >
       <!-- append-to-body -->
       <div v-highlight>
         <code class="hljs">
@@ -196,10 +202,7 @@
           {{ previewResult }}
         </code>
       </div>
-      <!-- <pre>
-        <code class="hljs" v-html="highlightedCode(previewType, previewResult)"></code>
-      </pre> -->
-    </XModal>
+    </Dialog>
   </div>
 </template>
 
@@ -231,7 +234,7 @@ import activitiModdleExtension from './plugins/extension-moddle/activiti'
 import flowableModdleExtension from './plugins/extension-moddle/flowable'
 // 引入json转换与高亮
 // import xml2js from 'xml-js'
-import xml2js from 'fast-xml-parser'
+// import xml2js from 'fast-xml-parser'
 import { XmlNode, XmlNodeType, parseXmlString } from 'steady-xml'
 // 代码高亮插件
 // import hljs from 'highlight.js/lib/highlight'
@@ -626,7 +629,7 @@ const elementsAlign = (align) => {
 const previewProcessXML = () => {
   console.log(bpmnModeler.saveXML, 'bpmnModeler')
   bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
-    console.log(xml, 'xml111111')
+    // console.log(xml, 'xml111111')
     previewResult.value = xml
     previewType.value = 'xml'
     previewModelVisible.value = true
@@ -634,7 +637,7 @@ const previewProcessXML = () => {
 }
 const previewProcessJson = () => {
   bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
-    console.log(xml, 'xml')
+    // console.log(xml, 'xml')
 
     // const rootNode = parseXmlString(xml)
     // console.log(rootNode, 'rootNoderootNode')
@@ -644,9 +647,9 @@ const previewProcessJson = () => {
     // console.log(JSON.stringify(rootNodes.parent.toJsObject()), 'rootNodes.toJSON()')
     // console.log(JSON.stringify(rootNodes.parent.toJSON()), 'rootNodes.toJSON()')
 
-    const parser = new xml2js.XMLParser()
-    let jObj = parser.parse(xml)
-    console.log(jObj, 'jObjjObjjObjjObjjObj')
+    // const parser = new xml2js.XMLParser()
+    // let jObj = parser.parse(xml)
+    // console.log(jObj, 'jObjjObjjObjjObjjObj')
     // const builder = new xml2js.XMLBuilder(xml)
     // const xmlContent = builder
     // console.log(xmlContent, 'xmlContent')

+ 0 - 1
src/types/auto-imports.d.ts

@@ -6,7 +6,6 @@ export {}
 declare global {
   const DICT_TYPE: typeof import('@/utils/dict')['DICT_TYPE']
   const EffectScope: typeof import('vue')['EffectScope']
-  const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
   const computed: typeof import('vue')['computed']
   const createApp: typeof import('vue')['createApp']
   const customRef: typeof import('vue')['customRef']

+ 3 - 3
src/views/bpm/oa/leave/detail.vue

@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="详情" v-model="modelVisible" :scroll="true" :max-height="200">
+  <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="200">
     <el-descriptions border :column="1">
       <el-descriptions-item label="请假类型">
         <dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="detailData.type" />
@@ -21,13 +21,13 @@ import { DICT_TYPE } from '@/utils/dict'
 import { formatDate } from '@/utils/formatTime'
 import * as LeaveApi from '@/api/bpm/leave'
 
-const modelVisible = ref(false) // 弹窗的是否展示
+const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单的加载中
 const detailData = ref() // 详情数据
 
 /** 打开弹窗 */
 const open = async (data: LeaveApi.LeaveVO) => {
-  modelVisible.value = true
+  dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {

+ 5 - 21
src/views/pay/app/AppForm.vue

@@ -1,5 +1,5 @@
 <template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible" width="50%">
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
       ref="formRef"
       :model="formData"
@@ -10,17 +10,8 @@
       <el-form-item label="应用名" prop="name">
         <el-input v-model="formData.name" placeholder="请输入应用名" />
       </el-form-item>
-
       <el-form-item label="所属商户" prop="merchantId">
-        <el-select
-          v-model="formData.merchantId"
-          filterable
-          remote
-          reserve-keyword
-          placeholder="请选择所属商户"
-          :remote-method="handleGetMerchantListByName"
-          :loading="formLoading"
-        >
+        <el-select v-model="formData.merchantId" placeholder="请选择所属商户">
           <el-option
             v-for="item in merchantList"
             :key="item.id"
@@ -61,9 +52,9 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import * as AppApi from '@/api/pay/app'
 import * as MerchantApi from '@/api/pay/merchant'
 import { CommonStatusEnum } from '@/utils/constants'
-
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
+
 const dialogVisible = ref(false) // 弹窗的是否展示
 const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
@@ -104,7 +95,8 @@ const open = async (type: string, id?: number) => {
       formLoading.value = false
     }
   }
-  await handleGetMerchantListByName(null)
+  // 加载商户列表
+  merchantList.value = await MerchantApi.getMerchantListByName()
 }
 defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 
@@ -134,14 +126,6 @@ const submitForm = async () => {
   }
 }
 
-/**
- * 根据商户名称模糊匹配商户信息
- * @param name 商户名称
- */
-const handleGetMerchantListByName = async (name) => {
-  merchantList.value = await MerchantApi.getMerchantListByName(name)
-}
-
 /** 重置表单 */
 const resetForm = () => {
   formData.value = {

+ 53 - 65
src/views/pay/app/index.vue

@@ -52,24 +52,16 @@
           class="!w-240px"
         />
       </el-form-item>
-
       <el-form-item>
-        <el-button @click="handleQuery">
-          <Icon icon="ep:search" class="mr-5px" />
-          搜索
-        </el-button>
-        <el-button @click="resetQuery">
-          <Icon icon="ep:refresh" class="mr-5px" />
-          重置
-        </el-button>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" />搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" />重置</el-button>
         <el-button
           type="primary"
           plain
           @click="openForm('create')"
           v-hasPermi="['system:tenant:create']"
         >
-          <Icon icon="ep:plus" class="mr-5px" />
-          新增
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
         </el-button>
         <el-button
           type="success"
@@ -78,8 +70,7 @@
           :loading="exportLoading"
           v-hasPermi="['system:tenant:export']"
         >
-          <Icon icon="ep:download" class="mr-5px" />
-          导出
+          <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
       </el-form-item>
     </el-form>
@@ -97,13 +88,13 @@
       </el-table-column>
       <el-table-column label="商户名称" align="center" prop="payMerchant.name" />
       <el-table-column label="支付宝配置" align="center">
-        <el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center">
+        <el-table-column :label="PayChannelEnum.ALIPAY_APP.name" align="center">
           <template #default="scope">
             <el-button
               type="success"
-              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_APP.code)"
+              v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_APP.code)"
               @click="
-                handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_APP.code, payType.ALIPAY)
+                handleUpdateChannel(scope.row, PayChannelEnum.ALIPAY_APP.code, PayType.ALIPAY)
               "
               circle
             >
@@ -114,20 +105,20 @@
               type="danger"
               circle
               @click="
-                handleCreateChannel(scope.row, payChannelEnum.ALIPAY_APP.code, payType.ALIPAY)
+                handleCreateChannel(scope.row, PayChannelEnum.ALIPAY_APP.code, PayType.ALIPAY)
               "
             >
               <Icon icon="ep:close" />
             </el-button>
           </template>
         </el-table-column>
-        <el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center">
+        <el-table-column :label="PayChannelEnum.ALIPAY_PC.name" align="center">
           <template #default="scope">
             <el-button
               type="success"
               circle
-              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_PC.code)"
-              @click="handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_PC.code, payType.ALIPAY)"
+              v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_PC.code)"
+              @click="handleUpdateChannel(scope.row, PayChannelEnum.ALIPAY_PC.code, PayType.ALIPAY)"
             >
               <Icon icon="ep:check" />
             </el-button>
@@ -135,20 +126,20 @@
               v-else
               type="danger"
               circle
-              @click="handleCreateChannel(scope.row, payChannelEnum.ALIPAY_PC.code, payType.ALIPAY)"
+              @click="handleCreateChannel(scope.row, PayChannelEnum.ALIPAY_PC.code, PayType.ALIPAY)"
             >
               <Icon icon="ep:close" />
             </el-button>
           </template>
         </el-table-column>
-        <el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center">
+        <el-table-column :label="PayChannelEnum.ALIPAY_WAP.name" align="center">
           <template #default="scope">
             <el-button
               type="success"
               circle
-              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_WAP.code)"
+              v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_WAP.code)"
               @click="
-                handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_WAP.code, payType.ALIPAY)
+                handleUpdateChannel(scope.row, PayChannelEnum.ALIPAY_WAP.code, PayType.ALIPAY)
               "
             >
               <Icon icon="ep:check" />
@@ -158,20 +149,20 @@
               type="danger"
               circle
               @click="
-                handleCreateChannel(scope.row, payChannelEnum.ALIPAY_WAP.code, payType.ALIPAY)
+                handleCreateChannel(scope.row, PayChannelEnum.ALIPAY_WAP.code, PayType.ALIPAY)
               "
             >
               <Icon icon="ep:close" />
             </el-button>
           </template>
         </el-table-column>
-        <el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center">
+        <el-table-column :label="PayChannelEnum.ALIPAY_QR.name" align="center">
           <template #default="scope">
             <el-button
               type="success"
               circle
-              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_QR.code)"
-              @click="handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_QR.code, payType.ALIPAY)"
+              v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_QR.code)"
+              @click="handleUpdateChannel(scope.row, PayChannelEnum.ALIPAY_QR.code, PayType.ALIPAY)"
             >
               <Icon icon="ep:check" />
             </el-button>
@@ -179,20 +170,20 @@
               v-else
               type="danger"
               circle
-              @click="handleCreateChannel(scope.row, payChannelEnum.ALIPAY_QR.code, payType.ALIPAY)"
+              @click="handleCreateChannel(scope.row, PayChannelEnum.ALIPAY_QR.code, PayType.ALIPAY)"
             >
               <Icon icon="ep:close" />
             </el-button>
           </template>
         </el-table-column>
-        <el-table-column :label="payChannelEnum.ALIPAY_BAR.name" align="center">
+        <el-table-column :label="PayChannelEnum.ALIPAY_BAR.name" align="center">
           <template #default="scope">
             <el-button
               type="success"
               circle
-              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_BAR.code)"
+              v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_BAR.code)"
               @click="
-                handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_BAR.code, payType.ALIPAY)
+                handleUpdateChannel(scope.row, PayChannelEnum.ALIPAY_BAR.code, PayType.ALIPAY)
               "
             >
               <Icon icon="ep:check" />
@@ -202,7 +193,7 @@
               type="danger"
               circle
               @click="
-                handleCreateChannel(scope.row, payChannelEnum.ALIPAY_BAR.code, payType.ALIPAY)
+                handleCreateChannel(scope.row, PayChannelEnum.ALIPAY_BAR.code, PayType.ALIPAY)
               "
             >
               <Icon icon="ep:close" />
@@ -211,13 +202,13 @@
         </el-table-column>
       </el-table-column>
       <el-table-column label="微信配置" align="center">
-        <el-table-column :label="payChannelEnum.WX_LITE.name" align="center">
+        <el-table-column :label="PayChannelEnum.WX_LITE.name" align="center">
           <template #default="scope">
             <el-button
               type="success"
               circle
-              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.WX_LITE.code)"
-              @click="handleUpdateChannel(scope.row, payChannelEnum.WX_LITE.code, payType.WECHAT)"
+              v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.WX_LITE.code)"
+              @click="handleUpdateChannel(scope.row, PayChannelEnum.WX_LITE.code, PayType.WECHAT)"
             >
               <Icon icon="ep:check" />
             </el-button>
@@ -225,19 +216,19 @@
               v-else
               type="danger"
               circle
-              @click="handleCreateChannel(scope.row, payChannelEnum.WX_LITE.code, payType.WECHAT)"
+              @click="handleCreateChannel(scope.row, PayChannelEnum.WX_LITE.code, PayType.WECHAT)"
             >
               <Icon icon="ep:close" />
             </el-button>
           </template>
         </el-table-column>
-        <el-table-column :label="payChannelEnum.WX_PUB.name" align="center">
+        <el-table-column :label="PayChannelEnum.WX_PUB.name" align="center">
           <template #default="scope">
             <el-button
               type="success"
               circle
-              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.WX_PUB.code)"
-              @click="handleUpdateChannel(scope.row, payChannelEnum.WX_PUB.code, payType.WECHAT)"
+              v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.WX_PUB.code)"
+              @click="handleUpdateChannel(scope.row, PayChannelEnum.WX_PUB.code, PayType.WECHAT)"
             >
               <Icon icon="ep:check" />
             </el-button>
@@ -245,19 +236,19 @@
               v-else
               type="danger"
               circle
-              @click="handleCreateChannel(scope.row, payChannelEnum.WX_PUB.code, payType.WECHAT)"
+              @click="handleCreateChannel(scope.row, PayChannelEnum.WX_PUB.code, PayType.WECHAT)"
             >
               <Icon icon="ep:close" />
             </el-button>
           </template>
         </el-table-column>
-        <el-table-column :label="payChannelEnum.WX_APP.name" align="center">
+        <el-table-column :label="PayChannelEnum.WX_APP.name" align="center">
           <template #default="scope">
             <el-button
               type="success"
               circle
-              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.WX_APP.code)"
-              @click="handleUpdateChannel(scope.row, payChannelEnum.WX_APP.code, payType.WECHAT)"
+              v-if="isChannelExists(scope.row.channelCodes, PayChannelEnum.WX_APP.code)"
+              @click="handleUpdateChannel(scope.row, PayChannelEnum.WX_APP.code, PayType.WECHAT)"
             >
               <Icon icon="ep:check" />
             </el-button>
@@ -265,7 +256,7 @@
               v-else
               type="danger"
               circle
-              @click="handleCreateChannel(scope.row, payChannelEnum.WX_APP.code, payType.WECHAT)"
+              @click="handleCreateChannel(scope.row, PayChannelEnum.WX_APP.code, PayType.WECHAT)"
             >
               <Icon icon="ep:close" />
             </el-button>
@@ -312,15 +303,13 @@
   <!-- 表单弹窗:添加/修改 -->
   <AppForm ref="formRef" @success="getList" />
 </template>
-<script setup lang="ts" name="App">
+<script setup lang="ts" name="PayApp">
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { dateFormatter } from '@/utils/formatTime'
 import download from '@/utils/download'
 import * as AppApi from '@/api/pay/app'
-import ContentWrap from '@/components/ContentWrap/src/ContentWrap.vue'
-import { dateFormatter } from '@/utils/formatTime'
 import AppForm from '@/views/pay/app/AppForm.vue'
-import { PayChannelEnum as payChannelEnum, PayType } from '@/utils/constants'
-
+import { PayChannelEnum, PayType } from '@/utils/constants'
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
@@ -342,22 +331,15 @@ const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
 const channelParam = reactive({
   loading: false,
-  // 是否修改
-  edit: false,
-  // 微信是否显示
-  wechatOpen: false,
-  // 支付宝是否显示
-  aliPayOpen: false,
-  // 应用ID
-  appId: null,
-  // 渠道编码
-  payCode: null,
+  edit: false, // 是否修改
+  wechatOpen: false, // 微信是否显示
+  aliPayOpen: false, // 支付宝是否显示
+  appId: null, // 应用 ID
+  payCode: null, // 渠道编码
   // 商户对象
   payMerchant: {
-    // 编号
-    id: null,
-    // 名称
-    name: null
+    id: null, // 编号
+    name: null // 名称
   }
 }) // 微信组件传参参数
 
@@ -421,23 +403,28 @@ const handleExport = async () => {
 
 /**
  * 根据渠道编码判断渠道列表中是否存在
+ *
  * @param channels 渠道列表
  * @param channelCode 渠道编码
  */
-const judgeChannelExist = (channels, channelCode) => {
+const isChannelExists = (channels, channelCode) => {
   if (!channels) {
     return false
   }
   return channels.indexOf(channelCode) !== -1
 }
 
+// TODO @芋艿:handleUpdateChannel 和 handleCreateChannel 合并,成为 openChannelForm
 /**
  * 修改支付渠道信息
+ *
  * @param row 行记录
  * @param payCode 支付编码
  * @param type 支付类型
  */
 const handleUpdateChannel = async (row, payCode, type) => {
+  // TODO @芋艿:表单未实现
+  message.alert('待实现')
   await settingChannelParam(row, payCode, type)
   channelParam.edit = true
   channelParam.loading = true
@@ -447,6 +434,7 @@ const handleUpdateChannel = async (row, payCode, type) => {
  * 新增支付渠道信息
  */
 const handleCreateChannel = async (row, payCode, type) => {
+  message.alert('待实现')
   await settingChannelParam(row, payCode, type)
   channelParam.edit = false
   channelParam.loading = false

+ 115 - 0
src/views/pay/order/OrderDetail.vue

@@ -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.merchantOrderId }}</el-tag>
+      </el-descriptions-item>
+      <el-descriptions-item label="渠道订单号">
+        <el-tag class="tag-purple">{{ detailData.channelOrderNo }}</el-tag>
+      </el-descriptions-item>
+      <el-descriptions-item label="支付订单号">
+        <el-tag v-if="detailData.payOrderExtension" class="tag-pink">
+          {{ detailData.payOrderExtension.no }}
+        </el-tag>
+      </el-descriptions-item>
+      <el-descriptions-item label="金额">
+        <el-tag type="success">¥{{ parseFloat(detailData.amount / 100, 2).toFixed(2) }}</el-tag>
+      </el-descriptions-item>
+      <el-descriptions-item label="手续费">
+        <el-tag type="warning">
+          ¥{{ parseFloat(detailData.channelFeeAmount / 100, 2).toFixed(2) }}
+        </el-tag>
+      </el-descriptions-item>
+      <el-descriptions-item label="手续费比例">
+        {{ parseFloat(detailData.channelFeeRate / 100, 2) }}%
+      </el-descriptions-item>
+      <el-descriptions-item label="支付状态">
+        <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="detailData.status" />
+      </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="回调地址">{{ detailData.notifyUrl }}</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.notifyTime) }}
+      </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="退款状态">
+        <dict-tag :type="DICT_TYPE.PAY_ORDER_REFUND_STATUS" :value="detailData.refundStatus" />
+      </el-descriptions-item>
+      <el-descriptions-item label="退款次数">{{ detailData.refundTimes }}</el-descriptions-item>
+      <el-descriptions-item label="退款金额">
+        <el-tag type="warning">
+          {{ parseFloat(detailData.refundAmount / 100, 2) }}
+        </el-tag>
+      </el-descriptions-item>
+    </el-descriptions>
+    <el-divider />
+    <el-descriptions :column="1" direction="vertical" border>
+      <el-descriptions-item label="商品描述">
+        {{ detailData.body }}
+      </el-descriptions-item>
+      <el-descriptions-item label="支付通道异步回调内容">
+        <div style="width: 700px; overflow: auto">
+          {{ detailData.payOrderExtension?.channelNotifyData }}
+        </div>
+      </el-descriptions-item>
+    </el-descriptions>
+  </Dialog>
+</template>
+<script setup lang="ts" name="orderForm">
+import { DICT_TYPE } from '@/utils/dict'
+import * as OrderApi from '@/api/pay/order'
+import { formatDate } from '@/utils/formatTime'
+
+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 OrderApi.getOrderDetail(id)
+  } finally {
+    detailLoading.value = false
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+</script>
+<style>
+.tag-purple {
+  color: #722ed1;
+  background: #f9f0ff;
+  border-color: #d3adf7;
+}
+
+.tag-pink {
+  color: #eb2f96;
+  background: #fff0f6;
+  border-color: #ffadd2;
+}
+</style>

+ 83 - 106
src/views/pay/order/index.vue

@@ -5,24 +5,14 @@
       :model="queryParams"
       ref="queryFormRef"
       :inline="true"
-      label-width="120px"
+      label-width="100px"
     >
       <el-form-item label="所属商户" prop="merchantId">
         <el-select
           v-model="queryParams.merchantId"
           clearable
-          @clear="
-            () => {
-              queryParams.merchantId = null
-            }
-          "
-          filterable
-          remote
-          reserve-keyword
           placeholder="请选择所属商户"
-          @change="handleGetAppListByMerchantId"
-          :remote-method="handleGetMerchantListByName"
-          :loading="merchantLoading"
+          class="!w-240px"
         >
           <el-option
             v-for="item in merchantList"
@@ -33,7 +23,12 @@
         </el-select>
       </el-form-item>
       <el-form-item label="应用编号" prop="appId">
-        <el-select clearable v-model="queryParams.appId" filterable placeholder="请选择应用信息">
+        <el-select
+          clearable
+          v-model="queryParams.appId"
+          placeholder="请选择应用信息"
+          class="!w-240px"
+        >
           <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" />
         </el-select>
       </el-form-item>
@@ -42,14 +37,10 @@
           v-model="queryParams.channelCode"
           placeholder="请输入渠道编码"
           clearable
-          @clear="
-            () => {
-              queryParams.channelCode = null
-            }
-          "
+          class="!w-240px"
         >
           <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"
             :label="dict.label"
             :value="dict.value"
@@ -62,6 +53,7 @@
           placeholder="请输入商户订单编号"
           clearable
           @keyup.enter="handleQuery"
+          class="!w-240px"
         />
       </el-form-item>
       <el-form-item label="渠道订单号" prop="channelOrderNo">
@@ -70,25 +62,36 @@
           placeholder="请输入渠道订单号"
           clearable
           @keyup.enter="handleQuery"
+          class="!w-240px"
         />
       </el-form-item>
       <el-form-item label="支付状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择支付状态" clearable size="small">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择支付状态"
+          clearable
+          class="!w-240px"
+        >
           <el-option
-            v-for="dict in getDictOptions(DICT_TYPE.PAY_ORDER_STATUS)"
-            :key="parseInt(dict.value)"
+            v-for="dict in getIntDictOptions(DICT_TYPE.PAY_ORDER_STATUS)"
+            :key="dict.value"
             :label="dict.label"
-            :value="parseInt(dict.value)"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
       <el-form-item label="退款状态" prop="refundStatus">
-        <el-select v-model="queryParams.refundStatus" placeholder="请选择退款状态" clearable>
+        <el-select
+          v-model="queryParams.refundStatus"
+          placeholder="请选择退款状态"
+          clearable
+          class="!w-240px"
+        >
           <el-option
-            v-for="dict in getDictOptions(DICT_TYPE.PAY_ORDER_REFUND_STATUS)"
-            :key="parseInt(dict.value)"
+            v-for="dict in getIntDictOptions(DICT_TYPE.PAY_ORDER_REFUND_STATUS)"
+            :key="dict.value"
             :label="dict.label"
-            :value="parseInt(dict.value)"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -97,12 +100,13 @@
           v-model="queryParams.notifyStatus"
           placeholder="请选择订单回调商户状态"
           clearable
+          class="!w-240px"
         >
           <el-option
-            v-for="dict in getDictOptions(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS)"
-            :key="parseInt(dict.value)"
+            v-for="dict in getIntDictOptions(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS)"
+            :key="dict.value"
             :label="dict.label"
-            :value="parseInt(dict.value)"
+            :value="dict.value"
           />
         </el-select>
       </el-form-item>
@@ -118,14 +122,8 @@
         />
       </el-form-item>
       <el-form-item>
-        <el-button @click="handleQuery">
-          <Icon icon="ep:search" class="mr-5px" />
-          搜索
-        </el-button>
-        <el-button @click="resetQuery">
-          <Icon icon="ep:refresh" class="mr-5px" />
-          重置
-        </el-button>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         <el-button
           type="success"
           plain
@@ -133,13 +131,13 @@
           :loading="exportLoading"
           v-hasPermi="['system:tenant:export']"
         >
-          <Icon icon="ep:download" class="mr-5px" />
-          导出
+          <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
       </el-form-item>
     </el-form>
   </ContentWrap>
-  <content-wrap>
+
+  <ContentWrap>
     <el-table v-loading="loading" :data="list">
       <el-table-column label="订单编号" align="center" prop="id" />
       <el-table-column label="商户名称" align="center" prop="merchantName" width="120" />
@@ -151,17 +149,17 @@
       <el-table-column label="异步通知地址" align="center" prop="notifyUrl" width="250" />
       <el-table-column label="回调状态" align="center" prop="notifyStatus">
         <template #default="scope">
-          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
+          <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="scope.row.notifyStatus" />
         </template>
       </el-table-column>
-      <el-table-column label="支付订单" align="left">
+      <el-table-column label="支付订单" width="280">
         <template #default="scope">
           <p class="order-font">
-            <el-tag size="small">商户</el-tag>
+            <el-tag>商户</el-tag>
             {{ scope.row.merchantOrderId }}
           </p>
           <p class="order-font">
-            <el-tag size="small" type="warning">支付</el-tag>
+            <el-tag type="warning">支付</el-tag>
             {{ scope.row.channelOrderNo }}
           </p>
         </template>
@@ -195,35 +193,29 @@
         label="创建时间"
         align="center"
         prop="createTime"
-        width="100"
+        width="180"
         :formatter="dateFormatter"
       />
       <el-table-column
         label="支付时间"
         align="center"
         prop="successTime"
-        width="100"
+        width="180"
         :formatter="dateFormatter"
       />
-      <el-table-column
-        label="操作"
-        align="center"
-        fixed="right"
-        class-name="small-padding fixed-width"
-      >
+      <el-table-column label="操作" align="center" fixed="right">
         <template #default="scope">
           <el-button
-            size="small"
-            type="text"
-            icon="el-icon-search"
-            @click="openForm(scope.row.id)"
+            type="primary"
+            link
+            @click="openDetail(scope.row.id)"
             v-hasPermi="['pay:order:query']"
-            >查看详情
+          >
+            详情
           </el-button>
         </template>
       </el-table-column>
     </el-table>
-    <!-- 分页组件 -->
     <!-- 分页 -->
     <Pagination
       :total="total"
@@ -231,30 +223,21 @@
       v-model:limit="queryParams.pageSize"
       @pagination="getList"
     />
-  </content-wrap>
+  </ContentWrap>
 
   <!-- 表单弹窗:预览 -->
-  <OrderForm ref="formRef" @success="getList" />
+  <OrderDetail ref="detailRef" @success="getList" />
 </template>
-<script setup lang="ts" name="Order">
-import { DICT_TYPE, getDictOptions } from '@/utils/dict'
-import ContentWrap from '@/components/ContentWrap/src/ContentWrap.vue'
+<script setup lang="ts" name="PayOrder">
+import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
+import { dateFormatter } from '@/utils/formatTime'
 import * as MerchantApi from '@/api/pay/merchant'
 import * as OrderApi from '@/api/pay/order'
-import download from '@/utils/download'
-import * as AppApi from '@/api/pay/app'
-import { dateFormatter } from '@/utils/formatTime'
-import OrderForm from '@/views/pay/order/orderForm.vue'
-
+import OrderDetail from '@/views/pay/order/OrderDetail.vue'
 const message = useMessage() // 消息弹窗
+import download from '@/utils/download'
 
-// const { t } = useI18n() // 国际化
-const queryFormRef = ref() // 搜索的表单
-const merchantList = ref([]) // 商户列表
-const merchantLoading = ref(false) // 商户加载遮罩层
-const appList = ref([]) // 支付应用列表集合
 const loading = ref(false) // 列表的加载中
-const exportLoading = ref(false) // 导出等待
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
 const queryParams = reactive({
@@ -285,26 +268,10 @@ const queryParams = reactive({
   notifyTime: [],
   createTime: []
 })
-
-/**
- * 根据商户名称模糊匹配商户信息
- * @param name 商户名称
- */
-const handleGetMerchantListByName = async (name) => {
-  merchantList.value = await MerchantApi.getMerchantListByName(name)
-}
-
-/**
- * 根据商户 ID 查询支付应用信息
- */
-const handleGetAppListByMerchantId = () => {
-  queryParams.appId = undefined
-  if (queryParams.merchantId) {
-    AppApi.getAppListByMerchantId(queryParams.merchantId).then((response) => {
-      appList.value = response.data
-    })
-  }
-}
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出等待
+const merchantList = ref([]) // 商户列表
+const appList = ref([]) // 支付应用列表集合
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
@@ -332,25 +299,35 @@ const resetQuery = () => {
 
 /** 导出按钮操作 */
 const handleExport = async () => {
-  // 处理查询参数
-  // 导出的二次确认
-  await message.exportConfirm()
-  // 发起导出
-  exportLoading.value = true
-  const data = await OrderApi.exportOrder(queryParams)
-  download.excel(data, '支付订单.xls')
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await OrderApi.exportOrder(queryParams)
+    download.excel(data, '支付订单.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
 }
+
 /** 预览详情 */
-const formRef = ref()
-const openForm = (id?: number) => {
-  formRef.value.open(id)
+const detailRef = ref()
+const openDetail = (id?: number) => {
+  detailRef.value.open(id)
 }
+
 /** 初始化 **/
 onMounted(async () => {
   await getList()
+  // 加载商户列表
+  merchantList.value = await MerchantApi.getMerchantListByName()
+  // 加载 App 列表
+  // TODO 芋艿:候选少一个查询应用列表的接口
+  // appList.value = await AppApi.getAppListByMerchantId()
 })
 </script>
-
 <style>
 .order-font {
   font-size: 12px;

+ 0 - 152
src/views/pay/order/orderForm.vue

@@ -1,152 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible" width="50%">
-    <el-descriptions :column="2" label-class-name="desc-label">
-      <el-descriptions-item label="商户名称">{{ orderDetail.merchantName }}</el-descriptions-item>
-      <el-descriptions-item label="应用名称">{{ orderDetail.appName }}</el-descriptions-item>
-      <el-descriptions-item label="商品名称">{{ orderDetail.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">{{ orderDetail.merchantOrderId }}</el-tag>
-      </el-descriptions-item>
-      <el-descriptions-item label="渠道订单号">
-        <el-tag class="tag-purple" size="small">{{ orderDetail.channelOrderNo }}</el-tag>
-      </el-descriptions-item>
-      <el-descriptions-item label="支付订单号">
-        <el-tag v-if="orderDetail.payOrderExtension.no !== ''" class="tag-pink" size="small">
-          {{ orderDetail.payOrderExtension.no }}
-        </el-tag>
-      </el-descriptions-item>
-      <el-descriptions-item label="金额">
-        <el-tag type="success" size="small">{{ parseFloat(orderDetail.amount / 100, 2) }}</el-tag>
-      </el-descriptions-item>
-      <el-descriptions-item label="手续费">
-        <el-tag type="warning" size="small"
-          >{{ parseFloat(orderDetail.channelFeeAmount / 100, 2) }}
-        </el-tag>
-      </el-descriptions-item>
-      <el-descriptions-item label="手续费比例">
-        {{ parseFloat(orderDetail.channelFeeRate / 100, 2) }}%
-      </el-descriptions-item>
-      <el-descriptions-item label="支付状态">
-        <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="orderDetail.status" />
-      </el-descriptions-item>
-      <el-descriptions-item label="回调状态">
-        <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="orderDetail.notifyStatus" />
-      </el-descriptions-item>
-      <el-descriptions-item label="回调地址">{{ orderDetail.notifyUrl }}</el-descriptions-item>
-      <el-descriptions-item label="创建时间" :formatter="dateFormatter">
-        {{ formatDate(orderDetail.createTime) }}
-      </el-descriptions-item>
-      <el-descriptions-item label="支付时间" :formatter="dateFormatter">
-        {{ formatDate(orderDetail.successTime) }}
-      </el-descriptions-item>
-      <el-descriptions-item label="失效时间" :formatter="dateFormatter">
-        {{ formatDate(orderDetail.expireTime) }}
-      </el-descriptions-item>
-      <el-descriptions-item label="通知时间" :formatter="dateFormatter">
-        {{ formatDate(orderDetail.notifyTime) }}
-      </el-descriptions-item>
-    </el-descriptions>
-    <el-divider />
-    <el-descriptions :column="2" label-class-name="desc-label">
-      <el-descriptions-item label="支付渠道"
-        >{{ orderDetail.channelCodeName }}
-      </el-descriptions-item>
-      <el-descriptions-item label="支付IP">{{ orderDetail.userIp }}</el-descriptions-item>
-      <el-descriptions-item label="退款状态">
-        <dict-tag :type="DICT_TYPE.PAY_ORDER_REFUND_STATUS" :value="orderDetail.refundStatus" />
-      </el-descriptions-item>
-      <el-descriptions-item label="退款次数">{{ orderDetail.refundTimes }}</el-descriptions-item>
-      <el-descriptions-item label="退款金额">
-        <el-tag type="warning">
-          {{ parseFloat(orderDetail.refundAmount / 100, 2) }}
-        </el-tag>
-      </el-descriptions-item>
-    </el-descriptions>
-    <el-divider />
-    <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
-      <el-descriptions-item label="商品描述">
-        {{ orderDetail.body }}
-      </el-descriptions-item>
-      <el-descriptions-item label="支付通道异步回调内容">
-        {{ orderDetail.payOrderExtension.channelNotifyData }}
-      </el-descriptions-item>
-    </el-descriptions>
-  </Dialog>
-</template>
-<script setup lang="ts" name="orderForm">
-import { DICT_TYPE } from '@/utils/dict'
-import * as OrderApi from '@/api/pay/order'
-import { dateFormatter, formatDate } from '@/utils/formatTime'
-
-const { t } = useI18n() // 国际化
-// const message = useMessage() // 消息弹窗
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('订单详情') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const defaultOrderDetail = {
-  merchantName: '',
-  appName: '',
-  channelCodeName: '',
-  subject: '',
-  merchantOrderId: null,
-  channelOrderNo: '',
-  body: '',
-  amount: null,
-  channelFeeRate: null,
-  channelFeeAmount: null,
-  userIp: '',
-  status: null,
-  notifyUrl: '',
-  notifyStatus: null,
-  refundStatus: null,
-  refundTimes: '',
-  refundAmount: null,
-  createTime: '',
-  successTime: '',
-  notifyTime: '',
-  expireTime: '',
-  payOrderExtension: {
-    channelNotifyData: '',
-    no: ''
-  }
-}
-const orderDetail = ref(JSON.parse(JSON.stringify(defaultOrderDetail)))
-
-/** 打开弹窗 */
-const open = async (id?: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.preview')
-  // 修改时,设置数据
-  if (id) {
-    formLoading.value = true
-    try {
-      orderDetail.value = await OrderApi.getOrderDetail(id)
-      if (orderDetail.value.payOrderExtension === null) {
-        orderDetail.value.payOrderExtension = Object.assign(
-          defaultOrderDetail.payOrderExtension,
-          {}
-        )
-      }
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
-</script>
-<style>
-.tag-purple {
-  color: #722ed1;
-  background: #f9f0ff;
-  border-color: #d3adf7;
-}
-
-.tag-pink {
-  color: #eb2f96;
-  background: #fff0f6;
-  border-color: #ffadd2;
-}
-</style>

+ 2 - 2
src/views/pay/refund/index.vue

@@ -227,7 +227,7 @@
       </template>
     </el-table-column>
   </el-table>
-  <content-wrap>
+  <ContentWrap>
     <!-- 分页 -->
     <Pagination
       :total="total"
@@ -235,7 +235,7 @@
       v-model:limit="queryParams.pageSize"
       @pagination="getList"
     />
-  </content-wrap>
+  </ContentWrap>
   <!-- 表单弹窗:预览 -->
   <RefundForm ref="formRef" @success="getList" />
 </template>