18 changed files with 431 additions and 5 deletions
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.0 KiB |
@ -0,0 +1,43 @@ |
|||||||
|
<template> |
||||||
|
<BasicModal v-bind="$attrs" @register="registerModal" title="发起订单" @ok="handleSubmit"> |
||||||
|
<BasicForm @register="registerForm" /> |
||||||
|
</BasicModal> |
||||||
|
</template> |
||||||
|
<script lang="ts" setup name="PayDemoModal"> |
||||||
|
import { useI18n } from '@/hooks/web/useI18n' |
||||||
|
import { useMessage } from '@/hooks/web/useMessage' |
||||||
|
import { BasicForm, useForm } from '@/components/Form' |
||||||
|
import { BasicModal, useModalInner } from '@/components/Modal' |
||||||
|
import { formSchema } from './demo.data' |
||||||
|
import { createDemoOrder } from '@/api/pay/demo' |
||||||
|
|
||||||
|
const { t } = useI18n() |
||||||
|
const { createMessage } = useMessage() |
||||||
|
const emit = defineEmits(['success', 'register']) |
||||||
|
|
||||||
|
const [registerForm, { resetFields, validate }] = useForm({ |
||||||
|
labelWidth: 120, |
||||||
|
baseColProps: { span: 24 }, |
||||||
|
schemas: formSchema, |
||||||
|
showActionButtonGroup: false, |
||||||
|
actionColOptions: { span: 23 } |
||||||
|
}) |
||||||
|
|
||||||
|
const [registerModal, { setModalProps, closeModal }] = useModalInner(async () => { |
||||||
|
resetFields() |
||||||
|
setModalProps({ confirmLoading: false }) |
||||||
|
}) |
||||||
|
|
||||||
|
async function handleSubmit() { |
||||||
|
try { |
||||||
|
const values = await validate() |
||||||
|
setModalProps({ confirmLoading: true }) |
||||||
|
await createDemoOrder(values) |
||||||
|
closeModal() |
||||||
|
emit('success') |
||||||
|
createMessage.success(t('common.saveSuccessText')) |
||||||
|
} finally { |
||||||
|
setModalProps({ confirmLoading: false }) |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
@ -0,0 +1,110 @@ |
|||||||
|
import { BasicColumn, FormSchema, useRender } from '@/components/Table' |
||||||
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
||||||
|
|
||||||
|
export const columns: BasicColumn[] = [ |
||||||
|
{ |
||||||
|
title: '订单编号', |
||||||
|
dataIndex: 'id', |
||||||
|
width: 100 |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '用户编号', |
||||||
|
dataIndex: 'userId', |
||||||
|
width: 100 |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '商品名字', |
||||||
|
dataIndex: 'spuName', |
||||||
|
width: 100 |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '支付价格', |
||||||
|
dataIndex: 'price', |
||||||
|
width: 100, |
||||||
|
customRender: ({ text }) => { |
||||||
|
return useRender.renderTag('¥' + (text / 100.0).toFixed(2)) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '退款金额', |
||||||
|
dataIndex: 'refundPrice', |
||||||
|
width: 100, |
||||||
|
customRender: ({ text }) => { |
||||||
|
return useRender.renderTag('¥' + (text / 100.0).toFixed(2)) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '支付单号', |
||||||
|
dataIndex: 'payOrderId', |
||||||
|
width: 100 |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '创建时间', |
||||||
|
dataIndex: 'createTime', |
||||||
|
width: 180, |
||||||
|
customRender: ({ text }) => { |
||||||
|
return useRender.renderDate(text) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '是否支付', |
||||||
|
dataIndex: 'payed', |
||||||
|
width: 100, |
||||||
|
customRender: ({ text }) => { |
||||||
|
return useRender.renderDict(text, DICT_TYPE.INFRA_BOOLEAN_STRING) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '支付时间', |
||||||
|
dataIndex: 'payTime', |
||||||
|
width: 180, |
||||||
|
customRender: ({ text }) => { |
||||||
|
return useRender.renderDate(text) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '退款时间', |
||||||
|
dataIndex: 'refundTime', |
||||||
|
width: 180, |
||||||
|
customRender: ({ text }) => { |
||||||
|
return useRender.renderDate(text) |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
export const searchFormSchema: FormSchema[] = [ |
||||||
|
{ |
||||||
|
label: '支付单号', |
||||||
|
field: 'payOrderId', |
||||||
|
component: 'Input', |
||||||
|
colProps: { span: 8 } |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '是否支付', |
||||||
|
field: 'payed', |
||||||
|
component: 'Select', |
||||||
|
componentProps: { |
||||||
|
options: getIntDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING) |
||||||
|
}, |
||||||
|
colProps: { span: 8 } |
||||||
|
} |
||||||
|
] |
||||||
|
|
||||||
|
export const formSchema: FormSchema[] = [ |
||||||
|
{ |
||||||
|
label: '商品', |
||||||
|
field: 'spuId', |
||||||
|
component: 'Select', |
||||||
|
defaultValue: 0, |
||||||
|
required: true, |
||||||
|
componentProps: { |
||||||
|
options: [ |
||||||
|
{ value: 1, label: '华为手机', price: 1 }, |
||||||
|
{ value: 2, label: '小米电视', price: 10 }, |
||||||
|
{ value: 3, label: '苹果手表', price: 100 }, |
||||||
|
{ value: 4, label: '华硕笔记本', price: 1000 }, |
||||||
|
{ value: 5, label: '蔚来汽车', price: 200000 } |
||||||
|
] |
||||||
|
} |
||||||
|
} |
||||||
|
] |
@ -1,3 +1,74 @@ |
|||||||
<template> |
<template> |
||||||
<div>开发中</div> |
<div> |
||||||
|
<BasicTable @register="registerTable"> |
||||||
|
<template #toolbar> |
||||||
|
<a-button type="primary" v-auth="['pay:app:create']" :preIcon="IconEnum.ADD" @click="handleAdd"> 发起订单 </a-button> |
||||||
|
</template> |
||||||
|
<template #bodyCell="{ column, record }"> |
||||||
|
<template v-if="column.key === 'action'"> |
||||||
|
<TableAction |
||||||
|
:actions="[ |
||||||
|
{ icon: IconEnum.EDIT, label: '前往支付', onClick: handlePay.bind(null, record) }, |
||||||
|
{ icon: IconEnum.DELETE, color: 'error', label: '发起退款', onClick: handleRefund.bind(null, record) } |
||||||
|
]" |
||||||
|
/> |
||||||
|
</template> |
||||||
|
</template> |
||||||
|
</BasicTable> |
||||||
|
<DemoModal @register="registerModal" @success="reload()" /> |
||||||
|
</div> |
||||||
</template> |
</template> |
||||||
|
<script lang="ts" setup name="PayDemo"> |
||||||
|
import { useGo } from '@/hooks/web/usePage' |
||||||
|
import { useI18n } from '@/hooks/web/useI18n' |
||||||
|
import { useMessage } from '@/hooks/web/useMessage' |
||||||
|
import { useModal } from '@/components/Modal' |
||||||
|
import DemoModal from './DemoModal.vue' |
||||||
|
import { IconEnum } from '@/enums/appEnum' |
||||||
|
import { BasicTable, useTable, TableAction } from '@/components/Table' |
||||||
|
import { getDemoOrderPage, refundDemoOrder } from '@/api/pay/demo' |
||||||
|
import { columns, searchFormSchema } from './demo.data' |
||||||
|
|
||||||
|
const go = useGo() |
||||||
|
const { t } = useI18n() |
||||||
|
const { createConfirm, createMessage } = useMessage() |
||||||
|
const [registerModal, { openModal }] = useModal() |
||||||
|
|
||||||
|
const [registerTable, { reload }] = useTable({ |
||||||
|
title: '接入示例列表', |
||||||
|
api: getDemoOrderPage, |
||||||
|
columns, |
||||||
|
formConfig: { labelWidth: 120, schemas: searchFormSchema }, |
||||||
|
useSearchForm: true, |
||||||
|
showTableSetting: true, |
||||||
|
actionColumn: { |
||||||
|
width: 180, |
||||||
|
title: t('common.action'), |
||||||
|
dataIndex: 'action', |
||||||
|
fixed: 'right' |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
function handleAdd() { |
||||||
|
openModal(true) |
||||||
|
} |
||||||
|
|
||||||
|
/** 支付按钮操作 */ |
||||||
|
function handlePay(record: Recordable) { |
||||||
|
go('/cashRegister/submit?id=' + record.id) |
||||||
|
} |
||||||
|
|
||||||
|
/** 退款按钮操作 */ |
||||||
|
async function handleRefund(record: Recordable) { |
||||||
|
createConfirm({ |
||||||
|
title: '退款', |
||||||
|
iconType: 'warning', |
||||||
|
content: '是否确认退款编号为"' + record.id + '"的示例订单?', |
||||||
|
async onOk() { |
||||||
|
await refundDemoOrder(record.id) |
||||||
|
createMessage.success(t('common.successText')) |
||||||
|
reload() |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
</script> |
||||||
|
@ -0,0 +1,121 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<Card> |
||||||
|
<Description :bordered="false" :column="3" :data="orderData" :schema="descSchema" /> |
||||||
|
</Card> |
||||||
|
<Card class="mt-4 justify-center"> |
||||||
|
<List :grid="{ column: 8 }" header="选择支付宝支付" :data-source="aliPayChannels"> |
||||||
|
<template #renderItem="{ item }"> |
||||||
|
<ListItem> |
||||||
|
<Card hoverable class="w-30 h-28 mt-3 pb-3"> |
||||||
|
<template #cover> |
||||||
|
<img class="w-40px h-40px mt-2" :src="icons[item.code]" /> |
||||||
|
<p class="mt-3 text-center"> {{ item.name }} </p> |
||||||
|
</template> |
||||||
|
<template #actions> |
||||||
|
<Icon icon="ant-design:alipay-outlined" @click="submit(item.code)" /> |
||||||
|
</template> |
||||||
|
</Card> |
||||||
|
</ListItem> |
||||||
|
</template> |
||||||
|
</List> |
||||||
|
<List :grid="{ column: 8 }" class="mt-4" header="选择微信支付" :data-source="wxPayChannels"> |
||||||
|
<template #renderItem="{ item }"> |
||||||
|
<ListItem> |
||||||
|
<Card hoverable class="w-30 h-28 pt-3 pb-3"> |
||||||
|
<template #cover> |
||||||
|
<img class="w-40px h-40px mt-2" :src="icons[item.code]" /> |
||||||
|
<p class="mt-3 text-center"> {{ item.name }} </p> |
||||||
|
</template> |
||||||
|
</Card> |
||||||
|
</ListItem> |
||||||
|
</template> |
||||||
|
</List> |
||||||
|
<List :grid="{ column: 8 }" class="mt-4" header="选择其它支付" :data-source="otherPayChannels"> |
||||||
|
<template #renderItem="{ item }"> |
||||||
|
<ListItem> |
||||||
|
<Card hoverable class="w-30 h-28 pt-3 pb-3"> |
||||||
|
<template #cover> |
||||||
|
<img class="w-40px h-40px mt-2" :src="icons[item.code]" /> |
||||||
|
<p class="mt-3 text-center"> {{ item.name }} </p> |
||||||
|
</template> |
||||||
|
</Card> |
||||||
|
</ListItem> |
||||||
|
</template> |
||||||
|
</List> |
||||||
|
</Card> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script lang="ts" setup name="PayOrderSubmit"> |
||||||
|
import { ref, onMounted } from 'vue' |
||||||
|
import { Card, List } from 'ant-design-vue' |
||||||
|
import { Description } from '@/components/Description' |
||||||
|
import { descSchema } from './submit.data' |
||||||
|
import { getOrder, submitOrder } from '@/api/pay/order' |
||||||
|
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict' |
||||||
|
import { useRoute } from 'vue-router' |
||||||
|
import alipay_qr from '@/assets/images/pay/icon/alipay_qr.svg' |
||||||
|
import alipay_app from '@/assets/images/pay/icon/alipay_app.svg' |
||||||
|
import alipay_wap from '@/assets/images/pay/icon/alipay_wap.svg' |
||||||
|
import alipay_pc from '@/assets/images/pay/icon/alipay_pc.svg' |
||||||
|
import alipay_bar from '@/assets/images/pay/icon/alipay_bar.svg' |
||||||
|
import wx_app from '@/assets/images/pay/icon/wx_app.svg' |
||||||
|
import wx_lite from '@/assets/images/pay/icon/wx_lite.svg' |
||||||
|
import wx_pub from '@/assets/images/pay/icon/wx_pub.svg' |
||||||
|
import mock from '@/assets/images/pay/icon/mock.svg' |
||||||
|
|
||||||
|
const ListItem = List.Item |
||||||
|
|
||||||
|
const icons = { |
||||||
|
alipay_qr: alipay_qr, |
||||||
|
alipay_app: alipay_app, |
||||||
|
alipay_wap: alipay_wap, |
||||||
|
alipay_pc: alipay_pc, |
||||||
|
alipay_bar: alipay_bar, |
||||||
|
wx_app: wx_app, |
||||||
|
wx_lite: wx_lite, |
||||||
|
wx_pub: wx_pub, |
||||||
|
mock: mock |
||||||
|
} |
||||||
|
|
||||||
|
const { query } = useRoute() |
||||||
|
const orderData = ref() |
||||||
|
const aliPayChannels = ref<any[]>([]) |
||||||
|
const wxPayChannels = ref<any[]>([]) |
||||||
|
const otherPayChannels = ref<any[]>([]) |
||||||
|
|
||||||
|
function initPayChannels() { |
||||||
|
// 微信支付 |
||||||
|
for (const dict of getStrDictOptions(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)) { |
||||||
|
const payChannel = { |
||||||
|
name: dict.label, |
||||||
|
code: dict.value as string |
||||||
|
} |
||||||
|
if (payChannel.code.startsWith('wx_')) { |
||||||
|
wxPayChannels.value.push(payChannel) |
||||||
|
} else if (payChannel.code.startsWith('alipay_')) { |
||||||
|
aliPayChannels.value.push(payChannel) |
||||||
|
} else if (payChannel.code) { |
||||||
|
otherPayChannels.value.push(payChannel) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
async function getDetail() { |
||||||
|
const queryId = query.id as unknown as number |
||||||
|
if (!queryId) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
const res = await getOrder(queryId) |
||||||
|
orderData.value = res |
||||||
|
} |
||||||
|
|
||||||
|
function submit(channelCode) { |
||||||
|
submitOrder({ id: query.id as unknown as number, channelCode }) |
||||||
|
} |
||||||
|
|
||||||
|
onMounted(async () => { |
||||||
|
await initPayChannels() |
||||||
|
await getDetail() |
||||||
|
}) |
||||||
|
</script> |
@ -0,0 +1,38 @@ |
|||||||
|
import { DescItem } from '@/components/Description' |
||||||
|
import { useRender } from '@/components/Table' |
||||||
|
|
||||||
|
export const descSchema: DescItem[] = [ |
||||||
|
{ |
||||||
|
label: '支付单号', |
||||||
|
field: 'id' |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '商品标题', |
||||||
|
field: 'subject' |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '商品内容', |
||||||
|
field: 'body' |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '支付金额', |
||||||
|
field: 'amount', |
||||||
|
render: (curVal) => { |
||||||
|
return useRender.renderText('¥', parseFloat(curVal || 0 / 100).toFixed(2)) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '创建时间', |
||||||
|
field: 'createTime', |
||||||
|
render: (curVal) => { |
||||||
|
return useRender.renderDate(curVal) |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: '过期时间', |
||||||
|
field: 'expireTime', |
||||||
|
render: (curVal) => { |
||||||
|
return useRender.renderDate(curVal) |
||||||
|
} |
||||||
|
} |
||||||
|
] |
Reference in new issue