feat:财税-报销单 添加支付操作逻辑

dev
yujinlong 7 days ago
parent 831d6ae746
commit 750cd388b5

@ -0,0 +1,76 @@
<template>
<BasicModal v-bind="$attrs" title="支付" width="500px" @register="registerModal">
<BasicForm @register="registerForm" />
<!--右下角按钮-->
<template #footer>
<a-button
pre-icon="ant-design:close-outlined"
type="warning"
:loading="loading"
ghost
style="margin-right: 0.8rem"
@click="closeModal"
>
取消
</a-button>
<a-button
type="success"
:loading="loading"
pre-icon="ant-design:check-outlined"
style="margin-right: 0.8rem"
@click="payNowHandle"
>
立即打款
</a-button>
</template>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { BasicModal, useModalInner } from '/@/components/Modal'
import { BasicForm, useForm } from '/@/components/Form/index'
import { useMessage } from '/@/hooks/web/useMessage'
import { modalFormSchema } from './columns'
import { BankPaymentApi } from './api'
const { createMessage } = useMessage()
const loading = ref(false)
const emit = defineEmits(['success'])
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 100,
schemas: modalFormSchema,
showActionButtonGroup: false,
})
const reimbursementId = ref('')
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
resetFields()
reimbursementId.value = data.id
})
const payNowHandle = async () => {
try {
const values = await validate()
loading.value = true
setModalProps({ confirmLoading: true, loading: true })
const postData = {
...values,
reimbursementId: reimbursementId.value,
}
const res = await BankPaymentApi(postData)
loading.value = false
if (res.succeeded) {
createMessage.success(res.message)
emit('success')
}
closeModal()
} catch (err) {
console.log('err', err)
} finally {
setModalProps({ confirmLoading: false, loading: false })
}
}
</script>

@ -11,6 +11,7 @@ enum Api {
invoiceList = '/feeApi/InInvoicet/GetInInvoicet',
bankList = '/mainApi/ClientBank/GetClientBankList',
getUser = '/mainApi/User/GetUserInfo',
BankPayment = '/feeApi/Reimbursement/BankPayment',
}
// 获取报销单列表 (Auth)
export function ReimbursementGetList(data: PageRequest) {
@ -80,7 +81,7 @@ export function GetInvoiceList(data: PageRequest) {
return request<DataResult>({
url: Api.invoiceList,
method: 'post',
data
data,
})
}
@ -89,7 +90,7 @@ export function GetClientBankList(data) {
return request<DataResult>({
url: Api.bankList,
method: 'post',
data
data,
})
}
@ -98,6 +99,15 @@ export function GetUserInfo(query: { id: string }) {
return request<DataResult>({
url: Api.getUser,
method: 'get',
params: query
params: query,
})
}
// 支付
export function BankPaymentApi(data) {
return request<DataResult>({
url: Api.BankPayment,
method: 'post',
data,
})
}

@ -1,3 +1,4 @@
import { getBankList } from '/@/api/system/org'
import { BasicColumn, FormSchema } from '/@/components/Table'
import { numberThousandFormat } from '/@/utils/commonUtil'
@ -114,4 +115,56 @@ export const searchFormSchema: FormSchema[] = [
colProps: { span: 4 },
component: 'Input',
},
{
field: 'reimbursementType',
label: '状态',
colProps: { span: 4 },
component: 'Select',
componentProps: () => {
return {
options: statusList,
allowClear: true,
}
},
},
]
export const modalFormSchema: FormSchema[] = [
{
field: 'bankId',
label: '支付账户',
colProps: { span: 24 },
rules: [{ required: true }],
component: 'ApiSelect',
isEdit: 0,
componentProps: ({ formModel }) => {
return {
immediate: true,
api: () => {
return new Promise((resolve) => {
getBankList({
pageCondition: { pageIndex: 1, pageSize: 100, sortConditions: [] },
queryCondition:
'[{"FieldName":"paymentAccount","FieldValue":"1","ConditionalType":0}]',
}).then((res) => {
const dataResult = res?.data || []
resolve(dataResult)
})
})
},
labelField: 'bankName',
valueField: 'id',
getPopupContainer: () => document.body,
}
},
},
{
field: 'ledgerAccount',
label: '会计科目',
rules: [{ required: true }],
colProps: { span: 24 },
isEdit: 0,
component: 'Input',
},
]

@ -4,6 +4,7 @@ import { numberThousandFormat, digitUppercase } from '/@/utils/commonUtil'
import { BillItem } from '../columns'
import { GetClientBankList } from '../api'
import { h, nextTick } from 'vue'
import { getDictDropDown } from '/@/api/common'
export type PageType = '' | 'ADD' | 'EDIT' | 'VIEW' | 'AUDIT'
@ -15,6 +16,15 @@ export interface BillDetail extends BillItem {
data: Recordable[]
}
let feeTypeList: LabelValueOptions = []
const res2: API.DataResult = await getDictDropDown({ code: 'Reimbursement_Expense_Ategory' })
if (res2.succeeded) {
feeTypeList = []
res2.data.forEach((e) => {
feeTypeList.push({ label: e.name, value: e.value })
})
}
export const invoiceCodeList: LabelValueOptions = [
{ label: '全电发票(铁路电子客票)', value: '51' },
{ label: '全电发票(航空运输电子客票行程单)', value: '61' },
@ -153,6 +163,14 @@ export const getDetailForm = (type: PageType): FormSchema[] => {
colProps: { span: 4 },
show: false,
},
{
field: 'payeeName',
label: '收款人名称',
colProps: { span: 4 },
isEdit: 1,
dynamicDisabled: true,
component: 'Input',
},
{
field: 'bankName',
label: '开户行',
@ -199,16 +217,34 @@ export const getDetailForm = (type: PageType): FormSchema[] => {
},
},
{
field: 'payeeName',
label: '收款人名称',
field: 'payeeAccountNumber',
label: '收款人账号',
colProps: { span: 4 },
isEdit: 1,
dynamicDisabled: true,
component: 'Input',
},
{
field: 'payeeAccountNumber',
label: '收款人账号',
field: 'amount',
label: '金额',
colProps: { span: 4 },
isEdit: 1,
dynamicDisabled: ['VIEW', 'AUDIT'].includes(type),
component: 'InputNumber',
componentProps: ({ formModel }) => {
return {
precision: 2,
onChange: (e) => {
nextTick(() => {
formModel.amountUppercase = digitUppercase(formModel?.amount || 0)
})
},
}
},
},
{
field: 'amountUppercase',
label: '金额大写',
colProps: { span: 4 },
isEdit: 1,
dynamicDisabled: true,
@ -231,31 +267,24 @@ export const getDetailForm = (type: PageType): FormSchema[] => {
component: 'Input',
},
{
field: 'amount',
label: '金额',
field: 'expenseCategory',
label: '费用类别',
colProps: { span: 4 },
isEdit: 1,
rules: [{ required: true }],
dynamicDisabled: ['VIEW', 'AUDIT'].includes(type),
component: 'InputNumber',
component: 'Select',
isEdit: 1,
componentProps: ({ formModel }) => {
return {
precision: 2,
onChange: (e) => {
nextTick(() => {
formModel.amountUppercase = digitUppercase(formModel?.amount || 0)
})
},
allowClear: true,
showSearch: true,
options: feeTypeList,
getPopupContainer: () => document.body,
labelField: 'bankName',
valueField: 'bankName',
}
},
},
{
field: 'amountUppercase',
label: '金额大写',
colProps: { span: 4 },
isEdit: 1,
dynamicDisabled: true,
component: 'Input',
},
{
show: ['VIEW', 'AUDIT'].includes(type),
field: 'ledgerAccount',

@ -141,8 +141,14 @@ export const columns: BasicColumn[] = [
export const searchFormSchema: FormSchema[] = [
{
field: 'buyerInvoiceName',
label: '购方开票名称',
label: '销方开票名称',
field: 'sellerInvoiceName',
colProps: { span: 4 },
component: 'Input',
},
{
label: '销方开票税号',
field: 'sellerInvoiceTaxNumber',
colProps: { span: 4 },
component: 'Input',
},
@ -156,14 +162,14 @@ export const searchFormSchema: FormSchema[] = [
},
},
{
field: 'invoiceNumber',
label: '发票号码',
field: 'totalAmount',
label: '开票金额',
colProps: { span: 4 },
component: 'Input',
component: 'InputNumber',
},
{
field: 'buyerInvoiceTaxNumber',
label: '购方开票税号',
field: 'invoiceNumber',
label: '发票号码',
colProps: { span: 4 },
component: 'Input',
},

@ -86,7 +86,7 @@
</a-spin>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue'
import { ref, computed, unref, h } from 'vue'
import { Divider } from 'ant-design-vue'
import { BasicTable, useTable, TableAction, ActionItem } from '/@/components/Table'
import SearchTable from './components/SearchTable.vue'
@ -198,6 +198,12 @@
canResize: true,
resizeHeightOffset: 80,
immediate: true,
actionColumn: {
width: 80,
title: '操作',
dataIndex: 'action',
fixed: 'right',
},
})
const copyHandle = (row) => {
@ -250,6 +256,7 @@
ledgerAccount: res.data.ledgerAccount,
voucherNo: res.data.voucherNo,
reason: res.data.reason,
expenseCategory: res.data.expenseCategory,
})
expenseAccountDetail.value = res.data
billTableData.value = res.data?.data || []
@ -270,12 +277,11 @@
const getActionOptList = (record): ActionItem[] => {
return [
{
/* icon: h('i', {
class: 'iconfont icon-xiazai',
style: { color: '#257afa', fontSize: '14px' },
}),
isCustomIcon: true, */
icon: 'ant-design:cloud-download-outlined',
customIcon: h('i', {
class: 'iconfont icon-xiazai',
style: { color: '#257afa', fontSize: '14px' },
}),
isCustomIcon: true,
tooltip: '下载',
onClick: handleDownload.bind(null, record),
},
@ -288,6 +294,7 @@
if (!filePath) {
return createMessage.warning('暂未获取到相关文件')
}
window.open(filePath, '_blank')
}
@ -488,6 +495,11 @@
.fill-form-wrapper {
margin-top: 14px;
}
:deep(.ds-table) {
.table-wrapper {
padding: 0;
}
}
.table-title-box {
.flex_arrange(row, flex-start);
padding: 16px 0 6px 0;

@ -53,11 +53,12 @@
</template>
</template>
</BasicTable>
<PayModal @register="registerModal" @success="handleSuccess" />
</div>
</template>
<script setup lang="ts">
import { unref, h } from 'vue'
import { ReimbursementGetList, ReimbursementDelete } from './api.js'
import { unref, h, computed, ref } from 'vue'
import { ReimbursementGetList, ReimbursementDelete, GetUserInfo } from './api.js'
import { BasicTable, useTable, TableAction, ActionItem } from '/@/components/Table'
import { formatParams } from '/@/hooks/web/common'
import { BillItem, columns, searchFormSchema, statusList } from './columns'
@ -66,7 +67,14 @@
import { useGo } from '/@/hooks/web/usePage'
import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'
import { useAppStore } from '/@/store/modules/app'
import { useUserStore } from '/@/store/modules/user'
import { useModal } from '/@/components/Modal'
import PayModal from './PayModal.vue'
const [registerModal, { openModal }] = useModal()
const appStore = useAppStore()
const userStore = useUserStore()
const go = useGo()
const [registerTable, { reload, setLoading, getSelectRows }] = useTable({
@ -119,9 +127,22 @@
return (item?.[key] as string) || ''
}
const userInfo = computed(() => userStore.getUserInfo)
const userInfoDetail = ref<any>({})
const getUserInfo = async () => {
try {
const userRes = await GetUserInfo({ id: userInfo.value.userId as string })
userInfoDetail.value = userRes.data
} catch (error) {}
}
getUserInfo()
const getActionOptList = (record: BillItem): ActionItem[] => {
const canEditable = [0, 4].includes(record.reimbursementType)
return [
const canPayable = userInfoDetail.value.isFinancialStaff && record.reimbursementType === 2
const optList = [
{
customIcon: h('i', {
class: 'iconfont icon-chakan',
@ -133,6 +154,20 @@
onClick: GoDetailed.bind(null, record),
},
]
return canPayable
? [
...optList,
{
customIcon: h('i', {
class: 'iconfont icon-peizhitubiaosvg-',
style: { color: '#257afa', fontSize: '16px' },
}),
isCustomIcon: true,
tooltip: '支付',
onClick: ToPayHandle.bind(null, record),
},
]
: optList
}
function FnDel() {
if (getSelectRows().length == 0) {
@ -184,6 +219,13 @@
},
})
}
const ToPayHandle = (row: BillItem) => {
openModal(true, row)
}
const handleSuccess = () => {
reload()
}
</script>
<style lang="less" scoped>
.SvgImg {

Loading…
Cancel
Save