修改自适应

This commit is contained in:
2026-08-19 08:53:50 +08:00
parent 0e797c39f4
commit ec5cf96d0b
14 changed files with 941 additions and 48 deletions
@@ -1,6 +1,6 @@
<template>
<el-dialog v-model="visible" title="报销详情" width="980px" destroy-on-close>
<el-descriptions v-if="detail" :column="3" border>
<el-dialog v-model="visible" title="报销详情" width="980px" class="reimburse-detail-dialog" destroy-on-close>
<el-descriptions v-if="detail" :column="isMobile ? 1 : 3" border>
<el-descriptions-item label="状态">
<el-tag :type="statusType(detail.status)">{{ statusLabel(detail.status) }}</el-tag>
</el-descriptions-item>
@@ -46,6 +46,7 @@
</template>
。识别结果可修改,确认后请保存。
</p>
<div class="table-scroll">
<el-table :data="amountCompare.details" border size="small" max-height="280">
<el-table-column prop="expense_type" label="费用类型" min-width="100" />
<el-table-column prop="name" label="发票文件" min-width="160" show-overflow-tooltip />
@@ -72,6 +73,7 @@
</template>
</el-table-column>
</el-table>
</div>
<div class="compare-actions">
<el-button v-if="isDraft" type="primary" size="small" :loading="amountSaving" @click="handleSaveReceiptAmounts">
保存发票金额
@@ -80,6 +82,7 @@
</div>
</div>
<div class="table-scroll">
<el-table :data="detail?.items || []" border size="small">
<el-table-column prop="expense_type" label="费用类型" min-width="120" />
<el-table-column prop="expense_date" label="发生日期" width="120" />
@@ -140,6 +143,7 @@
</el-table-column>
<template #empty><el-empty description="暂无费用明细" :image-size="60" /></template>
</el-table>
</div>
<input
ref="invoiceFileInputRef"
@@ -150,7 +154,7 @@
@change="handleInvoiceFileInputChange"
/>
<el-dialog v-model="receiptPreviewVisible" title="查看票据" width="980px" append-to-body destroy-on-close>
<el-dialog v-model="receiptPreviewVisible" title="查看票据" width="980px" class="receipt-preview-dialog" append-to-body destroy-on-close>
<div v-if="receiptList.length" class="receipt-preview">
<aside class="receipt-list">
<el-select
@@ -242,6 +246,7 @@
v-model="manualConfirmVisible"
title="手动确认"
width="420px"
class="manual-confirm-dialog"
append-to-body
destroy-on-close
>
@@ -280,7 +285,7 @@
</template>
<script setup>
import { computed, ref, watch } from 'vue'
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { uploadFile } from '@/api/file'
import { deleteReimbursementItem, submitReimbursement, updateReimbursementItem, updateReimbursementStatus } from '@/api/reimburse'
@@ -353,6 +358,18 @@ const amountSaving = ref(false)
const amountCompare = ref(null)
const pendingAmountCompare = ref(false)
const isMobile = ref(false)
const checkMobile = () => {
isMobile.value = window.innerWidth <= 768
}
onMounted(() => {
checkMobile()
window.addEventListener('resize', checkMobile)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', checkMobile)
})
const compareSummary = computed(() => {
if (!amountCompare.value?.details) {
return {
@@ -1125,4 +1142,97 @@ const formatDateTime = value => value ? new Date(value).toLocaleString('zh-CN',
color: #67c23a;
font-weight: 600;
}
.table-scroll {
width: 100%;
}
@media (max-width: 768px) {
.section-header {
flex-wrap: wrap;
gap: 8px;
margin-top: 16px;
}
.section-actions {
flex-wrap: wrap;
}
.table-scroll {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
:deep(.el-table) {
min-width: 640px;
}
}
.amount-compare-card {
padding: 12px;
}
.amount-compare-summary {
gap: 12px 20px;
}
.compare-item strong {
font-size: 16px;
}
.receipt-preview {
flex-direction: column;
min-height: 0;
gap: 12px;
}
.receipt-list {
flex: 0 0 auto;
max-height: 170px;
padding-right: 0;
padding-bottom: 10px;
border-right: 0;
border-bottom: 1px solid var(--el-border-color-light);
}
.receipt-thumb {
min-height: 56px;
}
.receipt-image {
max-height: 420px;
}
.receipt-pdf {
height: 420px;
}
.detail-toolbar {
flex-wrap: wrap;
gap: 10px;
}
}
</style>
<style lang="less">
/* 弹窗会 teleport 到 body,需非 scoped 样式覆盖宽度 */
@media (max-width: 768px) {
.reimburse-detail-dialog,
.receipt-preview-dialog,
.manual-confirm-dialog,
.reimburse-edit-dialog,
.reimburse-item-form-dialog,
.expense-type-dialog,
.expense-type-form-dialog {
width: 92% !important;
margin-top: 6vh;
.el-dialog__body {
padding: 16px;
}
}
.reimburse-item-form-dialog .item-form .el-form-item__label {
width: 70px !important;
}
}
</style>
@@ -1,5 +1,5 @@
<template>
<el-dialog v-model="visible" :title="title" width="720px" destroy-on-close>
<el-dialog v-model="visible" :title="title" width="720px" class="reimburse-edit-dialog" destroy-on-close>
<el-form ref="formRef" :model="form" :rules="formRules" label-width="90px">
<el-form-item label="申请日期" prop="apply_date">
<el-date-picker
@@ -3,6 +3,7 @@
v-model="visible"
title="报销类别管理"
width="720px"
class="expense-type-dialog"
append-to-body
destroy-on-close
@open="loadList"
@@ -12,6 +13,7 @@
<el-button type="primary" :icon="Plus" @click="openForm()">新增专有费项</el-button>
</div>
<div class="table-scroll">
<el-table v-loading="loading" :data="list" stripe max-height="420">
<el-table-column prop="name" label="费项名称" min-width="140" />
<el-table-column prop="sort_order" label="排序" width="80" align="center" />
@@ -40,11 +42,13 @@
</el-table-column>
<template #empty><el-empty description="暂无费项" /></template>
</el-table>
</div>
<el-dialog
v-model="formVisible"
:title="editingId ? '编辑专有费项' : '新增专有费项'"
width="420px"
class="expense-type-form-dialog"
append-to-body
destroy-on-close
>
@@ -193,4 +197,29 @@ const handleDelete = async row => {
color: #c0c4cc;
font-size: 13px;
}
.table-scroll {
width: 100%;
}
@media (max-width: 768px) {
.toolbar {
flex-direction: column;
align-items: stretch;
gap: 10px;
.el-button {
margin-left: 0;
}
}
.table-scroll {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
:deep(.el-table) {
min-width: 520px;
}
}
}
</style>
@@ -3,6 +3,7 @@
v-model="visible"
:title="editingItemId ? '编辑费用明细' : '添加费用明细'"
width="860px"
class="reimburse-item-form-dialog"
append-to-body
destroy-on-close
>
@@ -34,7 +35,7 @@
<el-form :model="item" :rules="rules" label-width="80px" class="item-form">
<el-row :gutter="16">
<el-col :span="8">
<el-col :span="8" :xs="24">
<el-form-item label="费用类型" prop="expense_type">
<el-select v-model="item.expense_type" placeholder="请选择" style="width: 100%">
<el-option
@@ -46,7 +47,7 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-col :span="8" :xs="24">
<el-form-item label="发生日期" prop="expense_date">
<el-date-picker
v-model="item.expense_date"
@@ -56,7 +57,7 @@
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-col :span="8" :xs="24">
<el-form-item label="金额" prop="amount">
<el-input-number
v-model="item.amount"
@@ -250,4 +251,22 @@ watch(
margin-bottom: 0;
}
}
@media (max-width: 768px) {
.batch-toolbar {
flex-wrap: wrap;
gap: 8px;
}
.item-list {
max-height: none;
padding-right: 0;
}
.item-card {
:deep(.el-card__body) {
padding: 12px;
}
}
}
</style>
+85 -7
View File
@@ -30,7 +30,7 @@
v-model="filters.status"
clearable
placeholder="全部状态"
style="width: 150px"
class="status-select"
>
<el-option
v-for="item in statusOptions"
@@ -50,7 +50,8 @@
</div>
<div class="table-card">
<el-table v-loading="loading" :data="list" stripe>
<div class="table-scroll">
<el-table v-loading="loading" :data="list" stripe>
<el-table-column prop="status" label="状态" width="80">
<template #default="{ row }">
<el-tag :type="statusType(row.status)">{{
@@ -76,12 +77,17 @@
>
<template #default="{ row }">{{ row.description || "-" }}</template>
</el-table-column>
<el-table-column prop="create_time" label="创建时间" width="175">
<el-table-column
v-if="!isMobile"
prop="create_time"
label="创建时间"
width="175"
>
<template #default="{ row }">{{
formatDateTime(row.create_time)
}}</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300">
<el-table-column label="操作" fixed="right" :width="isMobile ? 220 : 300">
<template #default="{ row }">
<el-button link type="primary" @click="openDetail(row.id)"
>详情</el-button
@@ -117,13 +123,14 @@
</template>
</el-table-column>
<template #empty><el-empty description="暂无报销记录" /></template>
</el-table>
</el-table>
</div>
<div class="pagination">
<el-pagination
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
layout="total, sizes, prev, pager, next, jumper"
:layout="isMobile ? 'prev, pager, next' : 'total, sizes, prev, pager, next, jumper'"
@update:current-page="pagination.page = $event"
@update:page-size="pagination.pageSize = $event"
@current-change="loadList"
@@ -156,7 +163,7 @@
</template>
<script setup>
import { computed, onMounted, reactive, ref } from "vue";
import { computed, onBeforeUnmount, onMounted, reactive, ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus, Refresh, Search, Setting } from "@element-plus/icons-vue";
import ReimburseEdit from "./components/edit.vue";
@@ -196,6 +203,11 @@ const records = ref([]);
const expenseTypeOptions = ref([]);
const exportingId = ref(0);
const isMobile = ref(false);
const checkMobile = () => {
isMobile.value = window.innerWidth <= 768;
};
const emptyForm = () => ({
apply_date: new Date().toISOString().slice(0, 10),
description: "",
@@ -360,9 +372,15 @@ const statusType = (value) =>
5: "success",
})[value] || "info";
onMounted(() => {
checkMobile();
window.addEventListener("resize", checkMobile);
loadExpenseTypes();
loadList();
});
onBeforeUnmount(() => {
window.removeEventListener("resize", checkMobile);
});
</script>
<style lang="less" scoped>
@@ -413,6 +431,14 @@ onMounted(() => {
margin-bottom: 0;
}
.status-select {
width: 150px;
}
.table-scroll {
width: 100%;
}
.pagination {
display: flex;
justify-content: flex-end;
@@ -425,12 +451,64 @@ onMounted(() => {
}
.page-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.header-actions {
width: 100%;
flex-wrap: wrap;
.el-button {
margin-left: 0;
}
}
.page-header h2 {
font-size: 18px;
}
.filter-card,
.table-card {
padding: 12px;
}
.filter-card {
:deep(.el-form--inline .el-form-item) {
display: block;
width: 100%;
margin-right: 0;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
:deep(.el-form-item__content) {
width: 100%;
flex-wrap: wrap;
}
:deep(.el-input),
.status-select {
width: 100%;
}
}
.table-scroll {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
:deep(.el-table) {
min-width: 560px;
}
}
.pagination {
justify-content: center;
margin-top: 12px;
}
}
</style>