<template>
|
<div class="app-container">
|
<!-- 搜索表单 -->
|
<el-form :inline="true" :model="queryParams" class="search-form">
|
<el-form-item label="发票号码">
|
<el-input
|
v-model="queryParams.invoiceNo"
|
placeholder="请输入发票号码"
|
clearable
|
:style="{ width: '200px' }"
|
/>
|
</el-form-item>
|
<el-form-item label="开票状态">
|
<el-select
|
v-model="queryParams.status"
|
placeholder="请选择开票状态"
|
clearable
|
:style="{ width: '150px' }"
|
>
|
<el-option
|
:label="item.label"
|
v-for="item in statusList"
|
:key="item.value"
|
:value="item.value"
|
/>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="开票日期">
|
<el-date-picker
|
v-model="queryParams.dateRange"
|
type="daterange"
|
range-separator="至"
|
start-placeholder="开始日期"
|
end-placeholder="结束日期"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
:style="{ width: '240px' }"
|
/>
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="handleQuery">查询</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
</el-form-item>
|
</el-form>
|
|
<el-card>
|
<!-- 操作按钮区 -->
|
<el-row :gutter="24" class="table-toolbar" justify="space-between">
|
<el-button type="primary" :icon="Plus" @click="handleAdd">
|
新增发票
|
</el-button>
|
<el-button type="success" :icon="Refresh" @click="handleSyncTaxControl">
|
同步税控平台
|
</el-button>
|
<el-button type="warning" :icon="Download" @click="handleBatchDownload">
|
批量下载
|
</el-button>
|
<el-button type="danger" :icon="Delete" @click="handleBatchDelete" :disabled="selectedIds.length === 0">
|
批量删除
|
</el-button>
|
</el-row>
|
|
<!-- 表格组件 -->
|
<el-table
|
v-loading="loading"
|
:data="tableData"
|
@selection-change="handleSelectionChange"
|
border
|
style="width: 100%"
|
>
|
<el-table-column type="selection" width="55" />
|
<el-table-column label="发票号码" prop="invoiceNo" width="180" />
|
<el-table-column label="发票代码" prop="invoiceCode" width="150" />
|
<el-table-column label="开票日期" prop="invoiceDate" width="120" />
|
<el-table-column label="购买方名称" prop="buyerName" width="200" show-overflow-tooltip />
|
<el-table-column label="销售方名称" prop="sellerName" width="200" show-overflow-tooltip />
|
<el-table-column label="金额" prop="amount" width="120">
|
<template #default="scope">
|
{{ scope.row.amount }} 元
|
</template>
|
</el-table-column>
|
<el-table-column label="税额" prop="taxAmount" width="120">
|
<template #default="scope">
|
{{ scope.row.taxAmount }} 元
|
</template>
|
</el-table-column>
|
<el-table-column label="价税合计" prop="totalAmount" width="120">
|
<template #default="scope">
|
{{ scope.row.totalAmount }} 元
|
</template>
|
</el-table-column>
|
<el-table-column label="开票状态" prop="status" width="100">
|
<template #default="scope">
|
<el-tag :type="getStatusType(scope.row.status)">
|
{{ getStatusText(scope.row.status) }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="税控平台状态" prop="taxControlStatus" width="120">
|
<template #default="scope">
|
<el-tag :type="getTaxControlStatusType(scope.row.taxControlStatus)">
|
{{ getTaxControlStatusText(scope.row.taxControlStatus) }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="创建时间" prop="createTime" width="160" />
|
<el-table-column label="操作" width="250" fixed="right">
|
<template #default="scope">
|
<el-button
|
size="small"
|
type="primary"
|
@click="handleView(scope.row)"
|
>
|
查看
|
</el-button>
|
<el-button
|
size="small"
|
type="success"
|
@click="handleDownload(scope.row)"
|
v-if="scope.row.status === 'issued'"
|
>
|
下载
|
</el-button>
|
<el-button
|
size="small"
|
type="warning"
|
@click="handleEdit(scope.row)"
|
v-if="scope.row.status === 'draft'"
|
>
|
编辑
|
</el-button>
|
<el-button
|
size="small"
|
type="danger"
|
@click="handleDelete(scope.row)"
|
v-if="scope.row.status === 'draft'"
|
>
|
删除
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<!-- 分页组件 -->
|
<pagination
|
v-if="total > 0"
|
:page="current"
|
:limit="pageSize"
|
:total="total"
|
@pagination="handlePagination"
|
:layout="'total, prev, pager, next, jumper'"
|
/>
|
</el-card>
|
|
<!-- 新增/编辑对话框 -->
|
<InvoiceDialog
|
v-model:dialogFormVisible="dialogFormVisible"
|
v-model:form="form"
|
:title="title"
|
:is-edit="isEdit"
|
@submit="handleSubmit"
|
@success="handleSuccess"
|
ref="invoiceDialog"
|
/>
|
|
<!-- 查看详情对话框 -->
|
<InvoiceViewDialog
|
v-model:dialogViewVisible="dialogViewVisible"
|
:form="viewForm"
|
title="发票详情"
|
/>
|
|
<!-- 税控平台同步对话框 -->
|
<TaxControlSyncDialog
|
v-model:dialogSyncVisible="dialogSyncVisible"
|
@success="handleSyncSuccess"
|
/>
|
|
<!-- 单个发票下载对话框 -->
|
<DownloadDialog
|
v-model:dialogVisible="downloadDialogVisible"
|
:invoice="currentDownloadInvoice"
|
@success="handleDownloadSuccess"
|
/>
|
|
<!-- 批量下载对话框 -->
|
<BatchDownloadDialog
|
v-model:dialogVisible="batchDownloadDialogVisible"
|
:invoices="batchDownloadInvoices"
|
@success="handleBatchDownloadSuccess"
|
/>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted } from "vue";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
import { Plus, Edit, Delete, Refresh, Download, View } from "@element-plus/icons-vue";
|
import Pagination from "@/components/Pagination";
|
import InvoiceDialog from "./components/InvoiceDialog.vue";
|
import InvoiceViewDialog from "./components/InvoiceViewDialog.vue";
|
import TaxControlSyncDialog from "./components/TaxControlSyncDialog.vue";
|
import DownloadDialog from "./components/DownloadDialog.vue";
|
import BatchDownloadDialog from "./components/BatchDownloadDialog.vue";
|
|
// 响应式数据
|
const loading = ref(false);
|
const tableData = ref([]);
|
const selectedIds = ref([]);
|
const current = ref(1);
|
const pageSize = ref(10);
|
const total = ref(0);
|
const dialogFormVisible = ref(false);
|
const dialogViewVisible = ref(false);
|
const dialogSyncVisible = ref(false);
|
const downloadDialogVisible = ref(false);
|
const batchDownloadDialogVisible = ref(false);
|
const isEdit = ref(false);
|
const title = ref("");
|
const form = ref({});
|
const viewForm = ref({});
|
const currentDownloadInvoice = ref({});
|
const batchDownloadInvoices = ref([]);
|
|
// 查询参数
|
const queryParams = reactive({
|
invoiceNo: "",
|
status: "",
|
dateRange: []
|
});
|
|
// 状态列表
|
const statusList = ref([
|
{ value: "draft", label: "草稿" },
|
{ value: "pending", label: "待开票" },
|
{ value: "issuing", label: "开票中" },
|
{ value: "issued", label: "已开票" },
|
{ value: "failed", label: "开票失败" },
|
{ value: "cancelled", label: "已作废" }
|
]);
|
|
// 模拟数据
|
const mockData = [
|
{
|
id: "1",
|
invoiceNo: "FP20241201001",
|
invoiceCode: "123456789",
|
invoiceDate: "2024-12-01",
|
buyerName: "客户A公司",
|
sellerName: "本公司",
|
amount: 10000.00,
|
taxAmount: 1300.00,
|
totalAmount: 11300.00,
|
status: "issued",
|
taxControlStatus: "synced",
|
createTime: "2024-12-01 10:00:00"
|
},
|
{
|
id: "2",
|
invoiceNo: "FP20241201002",
|
invoiceCode: "123456790",
|
invoiceDate: "2024-12-01",
|
buyerName: "客户B公司",
|
sellerName: "本公司",
|
amount: 5000.00,
|
taxAmount: 650.00,
|
totalAmount: 5650.00,
|
status: "pending",
|
taxControlStatus: "pending",
|
createTime: "2024-12-01 14:30:00"
|
}
|
];
|
|
// 获取状态类型
|
const getStatusType = (status) => {
|
const statusMap = {
|
draft: "",
|
pending: "warning",
|
issuing: "warning",
|
issued: "success",
|
failed: "danger",
|
cancelled: "info"
|
};
|
return statusMap[status] || "";
|
};
|
|
// 获取状态文本
|
const getStatusText = (status) => {
|
const statusMap = {
|
draft: "草稿",
|
pending: "待开票",
|
issuing: "开票中",
|
issued: "已开票",
|
failed: "开票失败",
|
cancelled: "已作废"
|
};
|
return statusMap[status] || status;
|
};
|
|
// 获取税控平台状态类型
|
const getTaxControlStatusType = (status) => {
|
const statusMap = {
|
pending: "warning",
|
syncing: "warning",
|
synced: "success",
|
failed: "danger"
|
};
|
return statusMap[status] || "";
|
};
|
|
// 获取税控平台状态文本
|
const getTaxControlStatusText = (status) => {
|
const statusMap = {
|
pending: "待同步",
|
syncing: "同步中",
|
synced: "已同步",
|
failed: "同步失败"
|
};
|
return statusMap[status] || status;
|
};
|
|
// 查询
|
const handleQuery = () => {
|
current.value = 1;
|
loadData();
|
};
|
|
// 重置查询
|
const resetQuery = () => {
|
Object.assign(queryParams, {
|
invoiceNo: "",
|
status: "",
|
dateRange: []
|
});
|
handleQuery();
|
};
|
|
// 加载数据
|
const loadData = () => {
|
loading.value = true;
|
// 模拟API调用
|
setTimeout(() => {
|
tableData.value = mockData;
|
total.value = mockData.length;
|
loading.value = false;
|
}, 500);
|
};
|
|
// 分页处理
|
const handlePagination = (pagination) => {
|
current.value = pagination.page;
|
pageSize.value = pagination.limit;
|
loadData();
|
};
|
|
// 选择变化
|
const handleSelectionChange = (selection) => {
|
selectedIds.value = selection.map(item => item.id);
|
};
|
|
// 新增
|
const handleAdd = () => {
|
isEdit.value = false;
|
title.value = "新增发票";
|
form.value = {
|
buyerName: "",
|
buyerTaxNo: "",
|
buyerAddress: "",
|
buyerBankAccount: "",
|
sellerName: "本公司",
|
sellerTaxNo: "123456789012345678",
|
sellerAddress: "公司地址",
|
sellerBankAccount: "银行账户",
|
items: [],
|
remark: ""
|
};
|
dialogFormVisible.value = true;
|
};
|
|
// 编辑
|
const handleEdit = (row) => {
|
isEdit.value = true;
|
title.value = "编辑发票";
|
form.value = { ...row };
|
dialogFormVisible.value = true;
|
};
|
|
// 查看
|
const handleView = (row) => {
|
viewForm.value = { ...row };
|
dialogViewVisible.value = true;
|
};
|
|
// 删除
|
const handleDelete = (row) => {
|
ElMessageBox.confirm(
|
`确定要删除发票 ${row.invoiceNo} 吗?`,
|
"提示",
|
{
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning"
|
}
|
).then(() => {
|
// 模拟删除
|
const index = tableData.value.findIndex(item => item.id === row.id);
|
if (index > -1) {
|
tableData.value.splice(index, 1);
|
total.value--;
|
ElMessage.success("删除成功");
|
}
|
});
|
};
|
|
// 批量删除
|
const handleBatchDelete = () => {
|
if (selectedIds.value.length === 0) {
|
ElMessage.warning("请选择要删除的记录");
|
return;
|
}
|
|
ElMessageBox.confirm(
|
`确定要删除选中的 ${selectedIds.value.length} 条记录吗?`,
|
"提示",
|
{
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning"
|
}
|
).then(() => {
|
// 模拟批量删除
|
tableData.value = tableData.value.filter(item => !selectedIds.value.includes(item.id));
|
total.value = tableData.value.length;
|
selectedIds.value = [];
|
ElMessage.success("批量删除成功");
|
});
|
};
|
|
// 下载发票
|
const handleDownload = (row) => {
|
if (row.status !== 'issued') {
|
ElMessage.warning("只有已开票的发票才能下载");
|
return;
|
}
|
|
// 显示下载选项对话框
|
downloadDialogVisible.value = true;
|
currentDownloadInvoice.value = row;
|
};
|
|
// 批量下载
|
const handleBatchDownload = () => {
|
if (selectedIds.value.length === 0) {
|
ElMessage.warning("请选择要下载的记录");
|
return;
|
}
|
|
// 检查选中的发票状态
|
const selectedInvoices = tableData.value.filter(item => selectedIds.value.includes(item.id));
|
const issuedInvoices = selectedInvoices.filter(item => item.status === 'issued');
|
|
if (issuedInvoices.length === 0) {
|
ElMessage.warning("选中的发票中没有已开票的发票");
|
return;
|
}
|
|
if (issuedInvoices.length < selectedInvoices.length) {
|
ElMessage.warning(`选中的${selectedInvoices.length}张发票中,只有${issuedInvoices.length}张已开票,将只下载已开票的发票`);
|
}
|
|
// 显示批量下载选项对话框
|
batchDownloadDialogVisible.value = true;
|
batchDownloadInvoices.value = issuedInvoices;
|
};
|
|
// 同步税控平台
|
const handleSyncTaxControl = () => {
|
dialogSyncVisible.value = true;
|
};
|
|
// 提交表单
|
const handleSubmit = (formData) => {
|
if (isEdit.value) {
|
// 编辑
|
const index = tableData.value.findIndex(item => item.id === formData.id);
|
if (index > -1) {
|
tableData.value[index] = { ...formData };
|
ElMessage.success("编辑成功");
|
}
|
} else {
|
// 新增
|
const newItem = {
|
id: Date.now().toString(),
|
invoiceNo: `FP${Date.now()}`,
|
invoiceCode: "123456789",
|
invoiceDate: new Date().toISOString().split('T')[0],
|
buyerName: formData.buyerName,
|
sellerName: formData.sellerName,
|
amount: formData.items.reduce((sum, item) => sum + (item.amount || 0), 0),
|
taxAmount: formData.items.reduce((sum, item) => sum + (item.taxAmount || 0), 0),
|
totalAmount: formData.items.reduce((sum, item) => sum + (item.totalAmount || 0), 0),
|
status: "draft",
|
taxControlStatus: "pending",
|
createTime: new Date().toLocaleString()
|
};
|
tableData.value.unshift(newItem);
|
total.value++;
|
ElMessage.success("新增成功");
|
}
|
dialogFormVisible.value = false;
|
};
|
|
// 表单成功回调
|
const handleSuccess = () => {
|
loadData();
|
};
|
|
// 同步成功回调
|
const handleSyncSuccess = () => {
|
loadData();
|
ElMessage.success("税控平台同步成功");
|
};
|
|
// 单个下载成功回调
|
const handleDownloadSuccess = () => {
|
downloadDialogVisible.value = false;
|
ElMessage.success("发票下载成功");
|
};
|
|
// 批量下载成功回调
|
const handleBatchDownloadSuccess = () => {
|
batchDownloadDialogVisible.value = false;
|
ElMessage.success("批量下载成功");
|
};
|
|
// 页面加载
|
onMounted(() => {
|
loadData();
|
});
|
</script>
|
|
<style scoped>
|
.search-form {
|
margin-bottom: 20px;
|
}
|
|
.table-toolbar {
|
margin-bottom: 20px;
|
}
|
|
.el-card {
|
margin-bottom: 20px;
|
}
|
</style>
|