Sfoglia il codice sorgente

feat(zfgl): 添加合同收据管理功能

- 实现了合同收据的查询、批量删除和附件下载功能
- 添加了搜索表单、数据表格和分页组件
- 优化了页面布局和样式
nahida 10 mesi fa
parent
commit
979be258bc
1 ha cambiato i file con 405 aggiunte e 0 eliminazioni
  1. 405 0
      src/views/zfgl/zfsjgl.vue

+ 405 - 0
src/views/zfgl/zfsjgl.vue

@@ -0,0 +1,405 @@
+<script setup lang="ts">
+import { onMounted, reactive, ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Download, RefreshCw, Search, Trash2 } from 'lucide-vue-next'
+import { clientGet, clientPost } from '@/utils/request.ts'
+
+interface AReceiptInfo {
+  id?: string
+  contractId?: string
+  receiptNumber?: string
+  payer?: string
+  paymentMethod?: string
+  totalAmount?: number
+  rent?: number
+  propertyFee?: number
+  deposit?: number
+  waterFee?: number
+  receiptReason?: string
+  attachmentUrl?: string
+  accountingDate?: string
+  generationDate?: string
+  createTime?: string
+  updateTime?: string
+}
+
+interface AReceiptInfoResponse extends BaseResponse {
+  data: PageType<AReceiptInfo>
+}
+
+// 响应式数据
+const loading = ref(false)
+const tableData = ref<AReceiptInfo[]>([])
+const selectedRows = ref<AReceiptInfo[]>([])
+const total = ref(0)
+
+const MINIO_URL = import.meta.env.VITE_MINIO_BASE_URL
+
+// 搜索表单
+const searchForm = reactive({
+  receiptNumber: '',
+  payer: '',
+  paymentMethod: '',
+  pageNum: 1,
+  pageSize: 10,
+})
+
+// 收款方式选项
+const paymentMethods = [
+  { label: '转账', value: '转账' },
+  { label: '扫码', value: '扫码' },
+  { label: '其他', value: '其他' },
+]
+
+// 获取列表数据
+const getList = async () => {
+  loading.value = true
+  try {
+    const res = await clientGet<
+      {
+        receiptNumber: string
+        payer: string
+        paymentMethod: string
+      },
+      AReceiptInfoResponse
+    >('/AReceiptInfo/findByPage', {
+      params: {
+        pageNum: searchForm.pageNum,
+        pageSize: searchForm.pageSize,
+        receiptNumber: searchForm.receiptNumber,
+        payer: searchForm.payer,
+        paymentMethod: searchForm.paymentMethod,
+      },
+    })
+
+    if (res.code !== 200) {
+      ElMessage.error(res.msg)
+      return
+    }
+
+    tableData.value = res.data.records
+    total.value = res.data.total
+  } catch (error) {
+    console.error(error)
+    ElMessage.error('获取数据失败')
+  } finally {
+    loading.value = false
+  }
+}
+
+// 搜索
+const handleSearch = () => {
+  searchForm.pageNum = 1
+  getList()
+}
+
+// 重置搜索
+const handleReset = () => {
+  searchForm.receiptNumber = ''
+  searchForm.payer = ''
+  searchForm.paymentMethod = ''
+  searchForm.pageNum = 1
+  getList()
+}
+
+// 批量删除
+const handleBatchDelete = async () => {
+  if (selectedRows.value.length === 0) {
+    ElMessage.warning('请选择要删除的数据')
+    return
+  }
+
+  try {
+    await ElMessageBox.confirm(
+      `确定要删除选中的 ${selectedRows.value.length} 条记录吗?`,
+      '确认删除',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      },
+    )
+
+    const ids = selectedRows.value.map((row) => row.id!).filter(Boolean)
+    const res = await clientPost<string[], BaseResponse>('/AReceiptInfo/deleteBatch', ids)
+
+    if (res.code !== 200) {
+      ElMessage.error(res.msg)
+      return
+    }
+
+    ElMessage.success(res.msg)
+    selectedRows.value = []
+    getList()
+  } catch (error) {
+    console.error(error)
+    // 用户取消删除
+  }
+}
+
+// 表格选择变化
+const handleSelectionChange = (selection: AReceiptInfo[]) => {
+  selectedRows.value = selection
+}
+
+// 分页变化
+const handlePageChange = (page: number) => {
+  searchForm.pageNum = page
+  getList()
+}
+
+// 每页条数变化
+const handleSizeChange = (size: number) => {
+  searchForm.pageSize = size
+  searchForm.pageNum = 1
+  getList()
+}
+
+// 格式化金额
+const formatAmount = (amount: number | undefined) => {
+  return amount ? `¥${amount.toLocaleString()}` : '-'
+}
+
+// 格式化日期
+const formatDate = (date: string | undefined) => {
+  return date ? new Date(date).toLocaleDateString() : '-'
+}
+
+// 下载附件
+const handleDownloadAttachment = async (row: AReceiptInfo) => {
+  if (!row.attachmentUrl) {
+    ElMessage.warning('该记录没有附件')
+    return
+  }
+
+  try {
+    // 如果attachmentUrl是完整的URL,直接下载
+    if (row.attachmentUrl.startsWith('http')) {
+      // 创建一个临时的a标签进行下载
+      const link = document.createElement('a')
+      link.href = row.attachmentUrl
+      link.download = `收据附件_${row.receiptNumber || row.id}.${getFileExtension(row.attachmentUrl)}`
+      link.target = '_blank'
+      document.body.appendChild(link)
+      link.click()
+      document.body.removeChild(link)
+      ElMessage.success('开始下载附件')
+    } else {
+      // 如果是相对路径则拼上MINIO_URL下载
+      const url = MINIO_URL + row.attachmentUrl
+      // 创建一个临时的a标签进行下载
+      const link = document.createElement('a')
+      link.href = url
+      link.download = `收据附件_${row.receiptNumber || row.id}.${getFileExtension(url)}`
+      link.target = '_blank'
+      document.body.appendChild(link)
+      link.click()
+      document.body.removeChild(link)
+      ElMessage.success('开始下载附件')
+    }
+  } catch (error) {
+    console.error('下载附件失败:', error)
+    ElMessage.error('下载附件失败,请稍后重试')
+  }
+}
+
+// 获取文件扩展名
+const getFileExtension = (url: string): string => {
+  const parts = url.split('.')
+  return parts.length > 1 ? parts[parts.length - 1] : 'pdf'
+}
+
+onMounted(() => {
+  getList()
+})
+</script>
+
+<template>
+  <div class="p-6 bg-gray-50 min-h-screen">
+    <div class="bg-white rounded-lg shadow-sm">
+      <!-- 页面标题 -->
+      <div class="px-6 py-4 border-b border-gray-200">
+        <h1 class="text-xl font-semibold text-gray-900">合同收据管理</h1>
+      </div>
+
+      <!-- 搜索表单 -->
+      <div class="p-6 border-b border-gray-200">
+        <el-form :model="searchForm" inline class="search-form">
+          <el-form-item label="收据单号">
+            <el-input
+              v-model="searchForm.receiptNumber"
+              placeholder="请输入收据单号"
+              clearable
+              class="w-48"
+              @keyup.enter="handleSearch"
+            />
+          </el-form-item>
+
+          <el-form-item label="交款单位">
+            <el-input
+              v-model="searchForm.payer"
+              placeholder="请输入交款单位"
+              clearable
+              class="w-48"
+              @keyup.enter="handleSearch"
+            />
+          </el-form-item>
+
+          <el-form-item label="收款方式">
+            <el-select
+              v-model="searchForm.paymentMethod"
+              placeholder="请选择收款方式"
+              clearable
+              style="width: 12rem"
+            >
+              <el-option
+                v-for="item in paymentMethods"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item>
+            <el-button type="primary" @click="handleSearch" :loading="loading">
+              <Search class="w-4 h-4 mr-1" v-if="!loading" />
+              搜索
+            </el-button>
+            <el-button @click="handleReset">
+              <RefreshCw class="w-4 h-4 mr-1" />
+              重置
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <!-- 操作按钮 -->
+      <div class="px-6 py-4 border-b border-gray-200">
+        <div class="flex justify-between items-center">
+          <div class="flex gap-2">
+            <el-button
+              type="danger"
+              :disabled="selectedRows.length === 0"
+              @click="handleBatchDelete"
+            >
+              <Trash2 class="w-4 h-4 mr-1" />
+              批量删除 ({{ selectedRows.length }})
+            </el-button>
+          </div>
+
+          <div class="text-sm text-gray-500">共 {{ total }} 条记录</div>
+        </div>
+      </div>
+
+      <!-- 数据表格 -->
+      <div class="px-6">
+        <el-table
+          :data="tableData"
+          v-loading="loading"
+          @selection-change="handleSelectionChange"
+          stripe
+          class="w-full"
+        >
+          <el-table-column type="selection" width="55" />
+
+          <el-table-column prop="receiptNumber" label="收据单号" width="180" />
+
+          <el-table-column prop="payer" label="交款单位" min-width="150" />
+
+          <el-table-column prop="paymentMethod" label="收款方式" width="100" />
+
+          <el-table-column prop="totalAmount" label="合计金额" width="120" align="right">
+            <template #default="{ row }">
+              <span class="font-medium text-green-600">
+                {{ formatAmount(row.totalAmount) }}
+              </span>
+            </template>
+          </el-table-column>
+
+          <el-table-column prop="rent" label="租金" width="100" align="right">
+            <template #default="{ row }">
+              {{ formatAmount(row.rent) }}
+            </template>
+          </el-table-column>
+
+          <el-table-column prop="propertyFee" label="物业费" width="100" align="right">
+            <template #default="{ row }">
+              {{ formatAmount(row.propertyFee) }}
+            </template>
+          </el-table-column>
+
+          <el-table-column prop="deposit" label="押金" width="100" align="right">
+            <template #default="{ row }">
+              {{ formatAmount(row.deposit) }}
+            </template>
+          </el-table-column>
+
+          <el-table-column prop="waterFee" label="水费" width="100" align="right">
+            <template #default="{ row }">
+              {{ formatAmount(row.waterFee) }}
+            </template>
+          </el-table-column>
+
+          <el-table-column prop="receiptReason" label="收款事由" min-width="150" />
+
+          <!--          <el-table-column prop="accountingDate" label="入账日期" width="100">-->
+          <!--            <template #default="{ row }">-->
+          <!--              {{ formatDate(row.accountingDate) }}-->
+          <!--            </template>-->
+          <!--          </el-table-column>-->
+
+          <el-table-column prop="generationDate" label="生成日期" width="100">
+            <template #default="{ row }">
+              {{ formatDate(row.generationDate) }}
+            </template>
+          </el-table-column>
+
+          <el-table-column label="操作" width="120" fixed="right">
+            <template #default="{ row }">
+              <el-button
+                type="primary"
+                size="small"
+                link
+                v-if="row.attachmentUrl"
+                @click="handleDownloadAttachment(row)"
+              >
+                <Download class="w-3 h-3 mr-1" />
+                下载附件
+              </el-button>
+              <span v-else class="text-gray-400 text-xs">无附件</span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <!-- 分页 -->
+      <div class="px-6 py-4 border-t border-gray-200">
+        <el-pagination
+          v-model:current-page="searchForm.pageNum"
+          v-model:page-size="searchForm.pageSize"
+          :page-sizes="[10, 20, 50, 100]"
+          :total="total"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="handleSizeChange"
+          @current-change="handlePageChange"
+          class="justify-end"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+:deep(.el-table) {
+  font-size: 14px;
+}
+
+:deep(.el-pagination) {
+  justify-content: flex-end;
+}
+
+:deep(.search-form .el-form-item) {
+  margin-bottom: 16px;
+}
+</style>