feat: 完善支付订单功能,新增订单数据结构和详情展示,更新相关表单和表格配置
							parent
							
								
									d0870beb40
								
							
						
					
					
						commit
						3be7961de5
					
				|  | @ -6,8 +6,13 @@ export namespace PayOrderApi { | ||||||
|   /** 支付订单信息 */ |   /** 支付订单信息 */ | ||||||
|   export interface Order { |   export interface Order { | ||||||
|     id: number; |     id: number; | ||||||
|  |     no: string; | ||||||
|  |     price: number; | ||||||
|  |     channelFeePrice: number; | ||||||
|  |     refundPrice: number; | ||||||
|     merchantId: number; |     merchantId: number; | ||||||
|     appId: number; |     appId: number; | ||||||
|  |     appName: string; | ||||||
|     channelId: number; |     channelId: number; | ||||||
|     channelCode: string; |     channelCode: string; | ||||||
|     merchantOrderId: string; |     merchantOrderId: string; | ||||||
|  | @ -29,7 +34,9 @@ export namespace PayOrderApi { | ||||||
|     refundAmount: number; |     refundAmount: number; | ||||||
|     channelUserId: string; |     channelUserId: string; | ||||||
|     channelOrderNo: string; |     channelOrderNo: string; | ||||||
|  |     channelNotifyData: string; | ||||||
|     createTime: Date; |     createTime: Date; | ||||||
|  |     updateTime: Date; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** 支付订单分页请求 */ |   /** 支付订单分页请求 */ | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ const gridOptions: VxeGridProps = { | ||||||
|     keyField: 'id', |     keyField: 'id', | ||||||
|   }, |   }, | ||||||
|   // 表格全局唯一表示 保存列配置需要用到 |   // 表格全局唯一表示 保存列配置需要用到 | ||||||
|   id: 'system-notifyMessage-index', |   id: 'pay-app-index', | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const [BasicTable, tableApi] = useVbenVxeGrid({ | const [BasicTable, tableApi] = useVbenVxeGrid({ | ||||||
|  |  | ||||||
|  | @ -49,7 +49,7 @@ const [BasicModal, modalApi] = useVbenModal({ | ||||||
|     modalApi.modalLoading(true); |     modalApi.modalLoading(true); | ||||||
| 
 | 
 | ||||||
|     const { id, payCode } = modalApi.getData() as { |     const { id, payCode } = modalApi.getData() as { | ||||||
|       id?: string; |       id?: number; | ||||||
|       payCode?: string; |       payCode?: string; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,144 @@ | ||||||
|  | import type { FormSchemaGetter } from '#/adapter/form'; | ||||||
|  | import type { VxeGridProps } from '#/adapter/vxe-table'; | ||||||
|  | 
 | ||||||
|  | import { DICT_TYPE, getDictOptions } from '#/utils/dict'; | ||||||
|  | 
 | ||||||
|  | export const querySchema: FormSchemaGetter = () => [ | ||||||
|  |   { | ||||||
|  |     component: 'Input', | ||||||
|  |     fieldName: 'appId', | ||||||
|  |     label: '应用编号', | ||||||
|  |     componentProps: { | ||||||
|  |       placeholder: '请输入应用编号', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     component: 'Select', | ||||||
|  |     fieldName: 'channelCode', | ||||||
|  |     label: '支付渠道', | ||||||
|  |     componentProps: { | ||||||
|  |       placeholder: '请选择开启状态', | ||||||
|  |       options: getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE, 'string'), | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     component: 'Input', | ||||||
|  |     fieldName: 'merchantOrderId', | ||||||
|  |     label: '商户单号', | ||||||
|  |     componentProps: { | ||||||
|  |       placeholder: '请输入商户单号', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     component: 'Input', | ||||||
|  |     fieldName: 'no', | ||||||
|  |     label: '支付单号', | ||||||
|  |     componentProps: { | ||||||
|  |       placeholder: '请输入支付单号', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     component: 'Input', | ||||||
|  |     fieldName: 'channelOrderNo', | ||||||
|  |     label: '渠道单号', | ||||||
|  |     componentProps: { | ||||||
|  |       placeholder: '请输入渠道单号', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     component: 'Select', | ||||||
|  |     fieldName: 'status', | ||||||
|  |     label: '支付状态', | ||||||
|  |     componentProps: { | ||||||
|  |       placeholder: '请选择支付状态', | ||||||
|  |       options: getDictOptions(DICT_TYPE.PAY_ORDER_STATUS, 'number'), | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     component: 'RangePicker', | ||||||
|  |     fieldName: 'createTime', | ||||||
|  |     label: '创建时间', | ||||||
|  |     componentProps: { | ||||||
|  |       placeholder: ['开始日期', '结束日期'], | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | export const columns: VxeGridProps['columns'] = [ | ||||||
|  |   { type: 'checkbox', width: 60 }, | ||||||
|  |   { | ||||||
|  |     title: '编号', | ||||||
|  |     field: 'id', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '支付金额', | ||||||
|  |     field: 'price', | ||||||
|  |     slots: { | ||||||
|  |       default: ({ row }) => { | ||||||
|  |         return `¥${(row.price || 0 / 100).toFixed(2)}`; | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '退款金额', | ||||||
|  |     field: 'refundPrice', | ||||||
|  |     slots: { | ||||||
|  |       default: ({ row }) => { | ||||||
|  |         return `¥${(row.refundPrice || 0 / 100).toFixed(2)}`; | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '手续金额', | ||||||
|  |     field: 'channelFeePrice', | ||||||
|  |     slots: { | ||||||
|  |       default: ({ row }) => { | ||||||
|  |         return `¥${(row.channelFeePrice || 0 / 100).toFixed(2)}`; | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '订单号', | ||||||
|  |     field: 'no', | ||||||
|  |     slots: { | ||||||
|  |       default: 'no', | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '支付状态', | ||||||
|  |     field: 'status', | ||||||
|  |     cellRender: { | ||||||
|  |       name: 'CellDict', | ||||||
|  |       props: { type: DICT_TYPE.PAY_ORDER_STATUS }, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '支付渠道', | ||||||
|  |     field: 'channelCode', | ||||||
|  |     cellRender: { | ||||||
|  |       name: 'CellDict', | ||||||
|  |       props: { type: DICT_TYPE.PAY_CHANNEL_CODE }, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '支付时间', | ||||||
|  |     field: 'successTime', | ||||||
|  |     minWidth: 180, | ||||||
|  |     formatter: 'formatDateTime', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '支付应用', | ||||||
|  |     field: 'appName', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '商品标题', | ||||||
|  |     field: 'subject', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     field: 'action', | ||||||
|  |     fixed: 'right', | ||||||
|  |     slots: { default: 'action' }, | ||||||
|  |     title: '操作', | ||||||
|  |     minWidth: 80, | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  | @ -1,13 +1,89 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { Page } from '@vben/common-ui'; | import type { VbenFormProps } from '@vben/common-ui'; | ||||||
| 
 | 
 | ||||||
| import { Button } from 'ant-design-vue'; | import type { VxeGridProps } from '#/adapter/vxe-table'; | ||||||
| 
 | 
 | ||||||
|  | import { Page, useVbenModal } from '@vben/common-ui'; | ||||||
|  | 
 | ||||||
|  | import { Tag } from 'ant-design-vue'; | ||||||
|  | 
 | ||||||
|  | import { useVbenVxeGrid } from '#/adapter/vxe-table'; | ||||||
|  | import * as OrderApi from '#/api/pay/order'; | ||||||
| import { DocAlert } from '#/components/doc-alert'; | import { DocAlert } from '#/components/doc-alert'; | ||||||
|  | 
 | ||||||
|  | import { columns, querySchema } from './data'; | ||||||
|  | import detailFrom from './modules/OrderDetail.vue'; | ||||||
|  | 
 | ||||||
|  | const formOptions: VbenFormProps = { | ||||||
|  |   commonConfig: { | ||||||
|  |     labelWidth: 100, | ||||||
|  |     componentProps: { | ||||||
|  |       allowClear: true, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   schema: querySchema(), | ||||||
|  |   wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4', | ||||||
|  |   // 处理区间选择器RangePicker时间格式 将一个字段映射为两个字段 搜索/导出会用到 | ||||||
|  |   // 不需要直接删除 | ||||||
|  |   // fieldMappingTime: [ | ||||||
|  |   //  [ | ||||||
|  |   //    'createTime', | ||||||
|  |   //    ['params[beginTime]', 'params[endTime]'], | ||||||
|  |   //    ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'], | ||||||
|  |   //  ], | ||||||
|  |   // ], | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const gridOptions: VxeGridProps = { | ||||||
|  |   checkboxConfig: { | ||||||
|  |     // 高亮 | ||||||
|  |     highlight: true, | ||||||
|  |     // 翻页时保留选中状态 | ||||||
|  |     reserve: true, | ||||||
|  |     // 点击行选中 | ||||||
|  |     // trigger: 'row', | ||||||
|  |   }, | ||||||
|  |   columns, | ||||||
|  |   height: 'auto', | ||||||
|  |   keepSource: true, | ||||||
|  |   pagerConfig: {}, | ||||||
|  |   proxyConfig: { | ||||||
|  |     ajax: { | ||||||
|  |       query: async ({ page }, formValues = {}) => { | ||||||
|  |         return await OrderApi.getOrderPage({ | ||||||
|  |           pageNum: page.currentPage, | ||||||
|  |           pageSize: page.pageSize, | ||||||
|  |           ...formValues, | ||||||
|  |         }); | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   rowConfig: { | ||||||
|  |     keyField: 'id', | ||||||
|  |   }, | ||||||
|  |   // 表格全局唯一表示 保存列配置需要用到 | ||||||
|  |   id: 'pay-order-index', | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const [BasicTable] = useVbenVxeGrid({ | ||||||
|  |   formOptions, | ||||||
|  |   gridOptions, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const [DetailModal, modalDetailApi] = useVbenModal({ | ||||||
|  |   connectedComponent: detailFrom, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | const openDetail = (id: number) => { | ||||||
|  |   modalDetailApi.setData({ | ||||||
|  |     id, | ||||||
|  |   }); | ||||||
|  |   modalDetailApi.open(); | ||||||
|  | }; | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
|   <Page> |   <Page :auto-content-height="true"> | ||||||
|     <DocAlert |     <DocAlert | ||||||
|       title="支付宝支付接入" |       title="支付宝支付接入" | ||||||
|       url="https://doc.iocoder.cn/pay/alipay-pay-demo/" |       url="https://doc.iocoder.cn/pay/alipay-pay-demo/" | ||||||
|  | @ -20,23 +96,29 @@ import { DocAlert } from '#/components/doc-alert'; | ||||||
|       title="微信小程序支付接入" |       title="微信小程序支付接入" | ||||||
|       url="https://doc.iocoder.cn/pay/wx-lite-pay-demo/" |       url="https://doc.iocoder.cn/pay/wx-lite-pay-demo/" | ||||||
|     /> |     /> | ||||||
|     <Button |     <BasicTable> | ||||||
|       danger |       <template #action="{ row }"> | ||||||
|  |         <a-button | ||||||
|           type="link" |           type="link" | ||||||
|       target="_blank" |           v-access:code="['pay:order:query']" | ||||||
|       href="https://github.com/yudaocode/yudao-ui-admin-vue3" |           @click="openDetail(row.id)" | ||||||
|         > |         > | ||||||
|       该功能支持 Vue3 + element-plus 版本! |           {{ $t('ui.actionTitle.detail') }} | ||||||
|     </Button> |         </a-button> | ||||||
|     <br /> |       </template> | ||||||
|     <Button |       <template #no="{ row }"> | ||||||
|       type="link" |         <p class="order-font"> | ||||||
|       target="_blank" |           <Tag size="small" color="blue"> 商户</Tag> {{ row.merchantOrderId }} | ||||||
|       href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/pay/order/index" |         </p> | ||||||
|     > |         <p class="order-font" v-if="row.no"> | ||||||
|       可参考 |           <Tag size="small" color="orange">支付</Tag> {{ row.no }} | ||||||
|       https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/pay/order/index |         </p> | ||||||
|       代码,pull request 贡献给我们! |         <p class="order-font" v-if="row.channelOrderNo"> | ||||||
|     </Button> |           <Tag size="small" color="green">渠道</Tag> | ||||||
|  |           {{ row.channelOrderNo }} | ||||||
|  |         </p> | ||||||
|  |       </template> | ||||||
|  |     </BasicTable> | ||||||
|  |     <DetailModal /> | ||||||
|   </Page> |   </Page> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,125 @@ | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { ref } from 'vue'; | ||||||
|  | 
 | ||||||
|  | import { useVbenModal } from '@vben/common-ui'; | ||||||
|  | import { formatDateTime } from '@vben/utils'; | ||||||
|  | 
 | ||||||
|  | import { Descriptions, Divider, Tag } from 'ant-design-vue'; | ||||||
|  | 
 | ||||||
|  | import * as OrderApi from '#/api/pay/order'; | ||||||
|  | import { DictTag } from '#/components/dict-tag'; | ||||||
|  | import { DICT_TYPE } from '#/utils/dict'; | ||||||
|  | 
 | ||||||
|  | const detailData = ref<OrderApi.PayOrderApi.Order>(); | ||||||
|  | 
 | ||||||
|  | const [BasicModal, modalApi] = useVbenModal({ | ||||||
|  |   fullscreenButton: false, | ||||||
|  |   showCancelButton: false, | ||||||
|  |   showConfirmButton: false, | ||||||
|  |   onOpenChange: async (isOpen) => { | ||||||
|  |     if (!isOpen) { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |     modalApi.modalLoading(true); | ||||||
|  | 
 | ||||||
|  |     const { id } = modalApi.getData() as { | ||||||
|  |       id: number; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     detailData.value = await OrderApi.getOrderDetail(id); | ||||||
|  | 
 | ||||||
|  |     modalApi.modalLoading(false); | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | <template> | ||||||
|  |   <BasicModal :close-on-click-modal="false" title="订单详情" class="w-[700px]"> | ||||||
|  |     <Descriptions :column="2"> | ||||||
|  |       <Descriptions.Item label="商户单号"> | ||||||
|  |         {{ detailData?.merchantOrderId }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="支付单号"> | ||||||
|  |         {{ detailData?.no }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="应用编号"> | ||||||
|  |         {{ detailData?.appId }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="应用名称"> | ||||||
|  |         {{ detailData?.appName }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="支付状态"> | ||||||
|  |         <DictTag | ||||||
|  |           size="small" | ||||||
|  |           :type="DICT_TYPE.PAY_ORDER_STATUS" | ||||||
|  |           :value="detailData?.status" | ||||||
|  |         /> | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="支付金额"> | ||||||
|  |         <Tag color="green" size="small"> | ||||||
|  |           ¥{{ (detailData?.price || 0 / 100.0).toFixed(2) }} | ||||||
|  |         </Tag> | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="手续费"> | ||||||
|  |         <Tag color="orange" size="small"> | ||||||
|  |           ¥{{ (detailData?.channelFeePrice || 0 / 100.0).toFixed(2) }} | ||||||
|  |         </Tag> | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="手续费比例"> | ||||||
|  |         {{ (detailData?.channelFeeRate || 0 / 100.0).toFixed(2) }}% | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="支付时间"> | ||||||
|  |         {{ formatDateTime(detailData?.successTime) }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="失效时间"> | ||||||
|  |         {{ formatDateTime(detailData?.expireTime) }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="创建时间"> | ||||||
|  |         {{ formatDateTime(detailData?.createTime) }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="更新时间"> | ||||||
|  |         {{ formatDateTime(detailData?.updateTime) }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |     </Descriptions> | ||||||
|  |     <Divider /> | ||||||
|  |     <Descriptions :column="2"> | ||||||
|  |       <Descriptions.Item label="商品标题"> | ||||||
|  |         {{ detailData?.subject }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="商品描述"> | ||||||
|  |         {{ detailData?.body }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="支付渠道"> | ||||||
|  |         <DictTag | ||||||
|  |           size="small" | ||||||
|  |           :type="DICT_TYPE.PAY_CHANNEL_CODE" | ||||||
|  |           :value="detailData?.channelCode" | ||||||
|  |         /> | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="支付 IP"> | ||||||
|  |         {{ detailData?.userIp }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="渠道单号"> | ||||||
|  |         <Tag size="small" color="green" v-if="detailData?.channelOrderNo"> | ||||||
|  |           {{ detailData?.channelOrderNo }} | ||||||
|  |         </Tag> | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="渠道用户"> | ||||||
|  |         {{ detailData?.channelUserId }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="退款金额" :span="2"> | ||||||
|  |         <Tag size="small" color="red"> | ||||||
|  |           ¥{{ (detailData?.refundPrice || 0 / 100.0).toFixed(2) }} | ||||||
|  |         </Tag> | ||||||
|  |       </Descriptions.Item> | ||||||
|  |       <Descriptions.Item label="通知 URL"> | ||||||
|  |         {{ detailData?.notifyUrl }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |     </Descriptions> | ||||||
|  |     <Divider /> | ||||||
|  |     <Descriptions :column="1"> | ||||||
|  |       <Descriptions.Item label="支付通道异步回调内容"> | ||||||
|  |         {{ detailData?.channelNotifyData }} | ||||||
|  |       </Descriptions.Item> | ||||||
|  |     </Descriptions> | ||||||
|  |   </BasicModal> | ||||||
|  | </template> | ||||||
|  | @ -16,7 +16,8 @@ | ||||||
|     "delete": "删除{0}", |     "delete": "删除{0}", | ||||||
|     "view": "查看{0}", |     "view": "查看{0}", | ||||||
|     "import": "导入", |     "import": "导入", | ||||||
|     "export": "导出" |     "export": "导出", | ||||||
|  |     "detail": "详情" | ||||||
|   }, |   }, | ||||||
|   "actionMessage": { |   "actionMessage": { | ||||||
|     "deleteConfirm": "确定删除 {0} 吗?", |     "deleteConfirm": "确定删除 {0} 吗?", | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 痴货
						痴货