heli-mes/mes-ui/mes-ui-admin-vue3/src/views/heli/orderys/invoivce.vue
2025-07-18 19:28:24 +08:00

497 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="1200px">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="160px"
v-loading="formLoading"
>
<!-- 基础信息 横向布局 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">基础信息</span>
</template>
<el-row>
<el-col :span="8">
<el-form-item label="发票号码" prop="number">
<el-input :disabled="detailDisabled" class="!w-260px" v-model="formData.number" placeholder="请输入发票号码" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="开票日期" prop="billingDate">
<el-date-picker
:disabled="detailDisabled"
v-model="formData.billingDate"
type="date"
value-format="x"
class="!w-260px"
placeholder="选择开票日期"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="发票金额" prop="amount">
<el-input-number :disabled="detailDisabled" class="!w-260px" :precision="2" :min="0" v-model="formData.amount" placeholder="请输入发票金额" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item label="发票类型" prop="type">
<el-select :disabled="detailDisabled" class="!w-260px" v-model="formData.type" placeholder="请选择发票类型">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HELI_INVOICE_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="税率(%" prop="rate">
<el-input-number :disabled="detailDisabled" class="!w-260px" :precision="0" :min="0" v-model="formData.rate" placeholder="请输入税率" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="对应订单" prop="orderId">
<el-input disabledclass="!w-260px" v-model="formData.orderCode" readonly>
<!-- <template #append><el-button disabled :icon="Search" /></template>-->
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="16">
<el-form-item label="备注" prop="remark">
<el-input :disabled="detailDisabled" type="textarea" v-model="formData.remark" show-word-limit maxlength="200" placeholder="请输入备注"/>
</el-form-item>
</el-col>
</el-row>
</el-card>
<!-- 表格类信息 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">附件信息</span>
</template>
<el-row>
<el-col>
<el-card class="hl-incard">
<el-col v-if="active != 'detail'">
<el-upload
ref="uploadRef" :file-list="uploadFiles" multiple :action="uploadUrl" :headers="{
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}" name="files" :show-file-list="false" :auto-upload="false" :on-success="handleAvatarSuccess" :data="uploadData" :on-change="uploadChange" class="upload-file-uploader">
<el-button type="primary">
<Icon icon="ep:upload-filled" />上传
</el-button>
</el-upload>
</el-col>
<el-table :key="tableKey" :data="formData.attachments" v-loading.fullscreen.lock="uploading" element-loading-text="附件上传中..." element-loading-background="rgba(122, 122, 122, 0.6)" class="hl-table">
<el-table-column fixed type="index" width="100" label="序号" align="center" />
<el-table-column prop="name" label="文件名称" align="center" />
<el-table-column prop="createTime" align="center" label="上传时间" :formatter="dateFormatter" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button v-if="active != 'detail'" link type="danger" size="small" @click="handleDeleteAttachment(scope.$index)">
删除
</el-button>
<el-button v-if="!!scope.row.id" link type="primary" size="small" @click="downloadAttachment(scope.row.name, scope.row.url)">
下载
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
</el-row>
</el-card>
</el-form>
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">开票信息</span>
<el-button type="primary" size="large" @click="submitForm" style="margin-left: 30px">保存</el-button>
<el-button @click="resetForm"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
</template>
<el-row>
<el-col>
<el-card class="hl-incard">
<el-form ref="OrderYsDetailSubFormRef" :model="list" label-width="0" v-loading="loading1">
<el-table :data="list" class="hl-table" @row-click="rowClick" >
<el-table-column type="index" label="序号" align="center" min-width="60" fixed />
<el-table-column label="发票号码" align="center" prop="number" />
<el-table-column
fixed
label="开票日期"
align="center"
prop="billingDate"
:formatter="dateFormatter2"
width="140"
/>
<el-table-column label="发票金额" align="center" prop="amount" />
<el-table-column label="发票类型" align="center" prop="type" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.HELI_INVOICE_TYPE" :value="scope.row.type" />
</template>
</el-table-column>
<el-table-column label="税率(%)" align="center" prop="rate" />
<el-table-column label="订单" align="center" prop="orderCode" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" width="120" fixed="right">
<template #default="scope">
<el-button link type="danger" size="small" @click.prevent="handleDelete(scope.row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-form>
</el-card>
</el-col>
</el-row>
</el-card>
<template #footer>
<!-- <el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>-->
<el-button @click="emits"> </el-button>
</template>
</Dialog>
<ProjectDialog v-if="businessType == 'FINANCE_MAKE_INVOICE'" ref="orderDialog" @success="handleSelectedOrder" />
<PurchaseDialog v-if="businessType == 'FINANCE_RECEIVE_INVOICE'" ref="orderDialog" @success="handleSelectedPurchaseOrder" />
</template>
<script setup lang="ts">
import {inject, ref} from 'vue'
import * as InvoiceApi from '@/api/heli/invoice'
import {useCommonStore} from '@/store/modules/common'
import {getAccessToken, getTenantId} from '@/utils/auth'
import {dateFormatter, dateFormatter2} from '@/utils/formatTime'
import {DICT_TYPE, getStrDictOptions} from '@/utils/dict'
import {UploadUserFile} from 'element-plus'
import {deleteFileLogic, downloadFile, getFilePage} from '@/api/infra/file'
import download from '@/utils/download'
import ProjectDialog from "@/views/heli/invoice/projectDialog.vue"
import PurchaseDialog from "@/views/heli/invoice/purchaseDialog.vue"
import type { UploadProps } from 'element-plus'
import {getList} from "@/api/heli/saleordercost";
import {getInvoicePages} from "@/api/heli/invoice";
import * as OrderYsApi from "@/api/heli/orderys";
const loading1 = ref(true) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
// defineOptions({ name: 'InvoiceDetail' })
const reload: any = inject('reload')
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const commonStore = useCommonStore()
const emit = defineEmits(['success']) // 定义 success 事件用于操作成功后的回调
const active = toRef(commonStore.getStore('active'))
const currentId = toRef(commonStore.getStore('id'))
const businessType = toRef(commonStore.getStore('businessType'))
const formLoading = ref(false)
const flag = ref(true)
const dialogTitle = ref('')
const detailDisabled = ref(false)
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
createTime: [],
id:undefined,
type:undefined,
})
const formData: any = ref({
id: undefined,
businessType: "FINANCE_MAKE_INVOICE",
orderId: undefined,
number: undefined,
type: "2",
billingDate: undefined,
amount: undefined,
rate: 13,
remark: undefined,
submitter: undefined,
submitTime: undefined,
canceller: undefined,
cancelTime: undefined,
status: 1,
attachments: [],
active: undefined,
activeOpinion: ''
})
const tableKey = ref(0);
const dialogVisible = ref(false) // 弹窗的是否展示
const detailId = ref()
const projectCodes = ref()
const projectIds = ref()
const formRef = ref() // 表单 Ref
const formRules = reactive({
orderId: [{ required: true, message: '对应订单不能为空', trigger: 'blur' }],
number: [{ required: true, message: '发票号码不能为空', trigger: 'blur' }],
type: [{ required: true, message: '发票类型不能为空', trigger: 'change' }],
billingDate: [{ required: true, message: '开票日期不能为空', trigger: 'blur' }],
amount: [{ required: true, message: '发票金额不能为空', trigger: 'blur' }],
rate: [{ required: true, message: '税率不能为空', trigger: 'blur' }],
})
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
businessType: "FINANCE_MAKE_INVOICE",
number: undefined,
type:"2",
billingDate: undefined,
amount: undefined,
rate: 13,
remark: undefined,
submitter: undefined,
submitTime: undefined,
canceller: undefined,
cancelTime: undefined,
status: 1,
attachments: [],
active: undefined,
activeOpinion: '',
orderId:projectIds.value,
orderCode:projectCodes.value
}
// formRef.value?.resetFields()
}
const getList = async (id) => {
queryParams.id=id
queryParams.type="FINANCE_MAKE_INVOICE"
loading1.value = true
try {
const data=await InvoiceApi.getInvoicePages(queryParams)
list.value = data.list
total.value = data.total
flag.value=true
} finally {
loading1.value = false
}
}
const emits = async () => {
dialogVisible.value = false
emit('success')
}
const queryData = async (id?: number) => {
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await InvoiceApi.getInvoice(id, "FINANCE_MAKE_INVOICE")
// 附件信息
let attParams = {
pageNo: 1,
pageSize: 99,
businessId: id,
businessType: "FINANCE_MAKE_INVOICE",
businessFileType:"FINANCE_MAKE_INVOICE"
}
formData.value.attachments = (await getFilePage(attParams)).list
} finally {
formLoading.value = false
}
}
}
/** 处理某一行的点击 */
const rowClick = async (row) => {
queryData(row.id)
}
const submitForm = async () => {
formData.value.active = "SAVE"
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
formData.value.cgOrderIdId=detailId.value
const data = formData.value as unknown as InvoiceApi.InvoiceVO
let dataId = await InvoiceApi.operateInvoice(data)
// 上传附件
if (uploadFiles.value.length > 0) {
flag.value=false
uploadData.value.businessId = dataId
await uploadRef.value!.submit()
message.success(t('common.operationSuccess'))
let jumpActive = 'update'
commonStore.setStore('id', dataId)
commonStore.setStore('active', jumpActive)
commonStore.setStore('businessType', "FINANCE_MAKE_INVOICE")
uploadFiles.value=[]
resetForm();
getList(detailId.value)
}else{
message.success(t('common.operationSuccess'))
let jumpActive = 'update'
commonStore.setStore('id', dataId)
commonStore.setStore('active', jumpActive)
commonStore.setStore('businessType', "FINANCE_MAKE_INVOICE")
resetForm();
getList(detailId.value)
}
} finally {
formLoading.value = false
}
}
// ====================附件信息 开始=======================================
const uploading = ref(false)
const uploadUrl = ref(import.meta.env.VITE_UPLOAD_BATCH_URL)
const uploadRef = ref()
const uploadFiles = ref<UploadUserFile[]>([])
const uploadData = ref({
businessType: "FINANCE_MAKE_INVOICE",
businessId: formData.value.id,
businessFileType:"FINANCE_MAKE_INVOICE"
})
const handleAvatarSuccess: UploadProps['onSuccess'] = async (
response,
uploadFile
) => {
let attParams = {
pageNo: 1,
pageSize: 99,
businessId: null,
businessType: "FINANCE_MAKE_INVOICE",
businessFileType:"FINANCE_MAKE_INVOICE"
}
uploading.value = true;
// formData.value.attachments = (await getFilePage(attParams)).list
// await reload()
// formData.value.attachments=[]
uploading.value = false;
}
// 下载文件
const downloadAttachment = async (name, url) => {
const baseUrl = import.meta.env.VITE_BASE_URL;
url =baseUrl+'/admin-api/'+ url.split('/admin-api/')[1]; const data = await downloadFile(url)
download.any(data, name)
}
const uploadChange = (file, files) => {
uploadFiles.value = files
refreshAttachments(files)
}
const open = async (id?: number,projectId,projectCode) => {
resetForm()
dialogVisible.value = true
detailId.value=id
projectIds.value=projectId
projectCodes.value=projectCode
formData.value.orderId = projectId
formData.value.orderCode = projectCode
formData.value.cgOrderIdId=id
uploadFiles.value=[]
getList(id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await InvoiceApi.deleteInvoice(id)
message.success(t('common.delSuccess'))
resetForm()
// 刷新列表
await getList(detailId.value)
} catch {}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
const refreshAttachments = (files) => {
if (flag.value){
formData.value.attachments = formData.value.attachments.filter((value, index, array) => {
return value.id
})
for (let i = 0; i < files.length; i++) {
let file = files[i]
file.createTime = new Date()
console.log(file)
formData.value.attachments.push(file)
}
// 排序
formData.value.attachments.sort((v1, v2) => v1.createTime - v2.createTime)
}
}
// 删除附件
const handleDeleteAttachment = async (index) => {
const deletedAttachments = formData.value.attachments.splice(index, 1)
for (let i = 0; i < deletedAttachments.length; i++) {
const attachment = deletedAttachments[i]
if (attachment.id) {
// 清理已上传文件
await deleteFileLogic(attachment.id)
}
// 清理待上传文件
uploadFiles.value = uploadFiles.value.filter((file1) => {
return file1.name != attachment.name
})
}
}
const orderDialog = ref()
// const openOrderDialog = () => {
// orderDialog.value?.open()
// }
const handleSelectedOrder = (order) => {
formData.value.orderId = order.id
formData.value.orderCode = order.code
}
const handleSelectedPurchaseOrder = (order) => {
formData.value.orderId = order.id
formData.value.orderCode = order.purchaseNo
}
// onMounted(() => {
// dialogTitle.value = t('action.' + active.value)
// if ('detail' == active.value) {
// detailDisabled.value = true
// }
// queryData(currentId.value)
// })
</script>
<style scoped>
.upload-file-uploader {
margin-bottom: 10px;
display: inline-block;
margin-right: 20px;
}
</style>