优化财务仪表盘UI与快捷时间筛选

This commit is contained in:
yml2213
2026-08-20 16:10:55 +08:00
parent 80e329a604
commit 9a52b51c89
25 changed files with 1626 additions and 438 deletions
@@ -234,10 +234,20 @@ function statusType(status: string) {
</el-select>
</el-form-item>
<el-form-item label="开始日期">
<el-date-picker v-model="filters.start_date" class="full-control" type="date" value-format="YYYY-MM-DD" />
<el-date-picker
v-model="filters.start_date"
class="full-control"
type="date"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker v-model="filters.end_date" class="full-control" type="date" value-format="YYYY-MM-DD" />
<el-date-picker
v-model="filters.end_date"
class="full-control"
type="date"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="filters.status" clearable placeholder="全部状态" class="full-control">
@@ -249,7 +259,12 @@ function statusType(status: string) {
<el-input v-model="filters.category" clearable placeholder="按类别精确筛选" />
</el-form-item>
<el-form-item label="关键词">
<el-input v-model="filters.keyword" clearable placeholder="单号、收款方或用途" @keyup.enter="search" />
<el-input
v-model="filters.keyword"
clearable
placeholder="单号、收款方或用途"
@keyup.enter="search"
/>
</el-form-item>
</el-form>
@@ -264,13 +279,17 @@ function statusType(status: string) {
</template>
</el-table-column>
<el-table-column label="开支金额" min-width="135" align="right">
<template #default="{ row }"><strong>{{ money(row.amount_cent) }}</strong></template>
<template #default="{ row }"
><strong>{{ money(row.amount_cent) }}</strong></template
>
</el-table-column>
<el-table-column label="开支时间" min-width="175">
<template #default="{ row }">{{ formatDateTime(row.occurred_at) }}</template>
</el-table-column>
<el-table-column label="状态" width="105" align="center">
<template #default="{ row }"><el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag></template>
<template #default="{ row }"
><el-tag :type="statusType(row.status)">{{ statusLabel(row.status) }}</el-tag></template
>
</el-table-column>
<el-table-column label="录入人" min-width="120">
<template #default="{ row }">{{ row.created_by_name || '-' }}</template>
@@ -280,7 +299,9 @@ function statusType(status: string) {
</el-table-column>
<el-table-column label="操作" width="145" fixed="right">
<template #default="{ row }">
<el-button link type="primary" :icon="View" @click="selectedExpense = row">详情</el-button>
<el-button link type="primary" :icon="View" @click="selectedExpense = row"
>详情</el-button
>
<el-button
v-if="row.status === 'paid' && canManage"
link
@@ -304,60 +325,148 @@ function statusType(status: string) {
@page-change="loadItems"
/>
<el-dialog v-model="createVisible" title="新增运营开支" width="560px" :close-on-click-modal="false">
<el-dialog
v-model="createVisible"
title="新增运营开支"
width="560px"
:close-on-click-modal="false"
>
<el-form class="expense-form" label-position="top" @submit.prevent="submitExpense">
<el-form-item label="开支类别" required>
<el-input v-model="createForm.category" maxlength="50" placeholder="例如:推广投放、办公采购" />
<el-input
v-model="createForm.category"
maxlength="50"
placeholder="例如:推广投放、办公采购"
/>
</el-form-item>
<el-form-item label="收款方" required>
<el-input v-model="createForm.payee_name" maxlength="100" placeholder="姓名或单位名称" />
</el-form-item>
<el-form-item label="开支金额" required>
<el-input-number v-model="createForm.amount_yuan" class="full-control" :min="0.01" :precision="2" :step="100" controls-position="right" />
<el-input-number
v-model="createForm.amount_yuan"
class="full-control"
:min="0.01"
:precision="2"
:step="100"
controls-position="right"
/>
</el-form-item>
<el-form-item label="开支时间" required>
<el-date-picker v-model="createForm.occurred_at" class="full-control" type="datetime" placeholder="选择开支时间" />
<el-date-picker
v-model="createForm.occurred_at"
class="full-control"
type="datetime"
placeholder="选择开支时间"
/>
</el-form-item>
<el-form-item class="expense-form-wide" label="开支用途" required>
<el-input v-model="createForm.remark" type="textarea" :rows="3" maxlength="500" show-word-limit placeholder="填写开支用途" />
<el-input
v-model="createForm.remark"
type="textarea"
:rows="3"
maxlength="500"
show-word-limit
placeholder="填写开支用途"
/>
</el-form-item>
<el-form-item class="expense-form-wide" label="开支凭证(选填)">
<div v-if="createForm.voucher_url" class="voucher-preview">
<AuthImage :source="createForm.voucher_url" :admin="true" fit="cover" :preview-src-list="[createForm.voucher_url]" :image-style="{ width: '104px', height: '104px', borderRadius: '6px' }" />
<el-button class="voucher-remove" circle plain type="danger" :icon="CircleClose" title="移除凭证" @click="createForm.voucher_url = ''" />
<AuthImage
:source="createForm.voucher_url"
:admin="true"
fit="cover"
:preview-src-list="[createForm.voucher_url]"
:image-style="{ width: '104px', height: '104px', borderRadius: '6px' }"
/>
<el-button
class="voucher-remove"
circle
plain
type="danger"
:icon="CircleClose"
title="移除凭证"
@click="createForm.voucher_url = ''"
/>
</div>
<el-upload v-else :show-file-list="false" :http-request="uploadVoucher" accept="image/jpeg,image/png,image/webp">
<el-upload
v-else
:show-file-list="false"
:http-request="uploadVoucher"
accept="image/jpeg,image/png,image/webp"
>
<el-button :icon="UploadFilled" :loading="voucherUploading">上传凭证</el-button>
</el-upload>
</el-form-item>
</el-form>
<template #footer>
<el-button :disabled="createSaving" @click="createVisible = false">取消</el-button>
<el-button type="primary" :loading="createSaving" :disabled="voucherUploading" @click="submitExpense">确认记账</el-button>
<el-button
type="primary"
:loading="createSaving"
:disabled="voucherUploading"
@click="submitExpense"
>确认记账</el-button
>
</template>
</el-dialog>
<el-dialog :model-value="!!selectedExpense" title="运营开支详情" width="620px" @update:model-value="selectedExpense = null">
<el-dialog
:model-value="!!selectedExpense"
title="运营开支详情"
width="620px"
@update:model-value="selectedExpense = null"
>
<el-descriptions v-if="selectedExpense" :column="2" border>
<el-descriptions-item label="开支单号">{{ selectedExpense.expense_no }}</el-descriptions-item>
<el-descriptions-item label="状态"><el-tag :type="statusType(selectedExpense.status)">{{ statusLabel(selectedExpense.status) }}</el-tag></el-descriptions-item>
<el-descriptions-item label="开支单号">{{
selectedExpense.expense_no
}}</el-descriptions-item>
<el-descriptions-item label="状态"
><el-tag :type="statusType(selectedExpense.status)">{{
statusLabel(selectedExpense.status)
}}</el-tag></el-descriptions-item
>
<el-descriptions-item label="开支类别">{{ selectedExpense.category }}</el-descriptions-item>
<el-descriptions-item label="收款方">{{ selectedExpense.payee_name }}</el-descriptions-item>
<el-descriptions-item label="开支金额"><strong>{{ money(selectedExpense.amount_cent) }}</strong></el-descriptions-item>
<el-descriptions-item label="开支时间">{{ formatDateTime(selectedExpense.occurred_at) }}</el-descriptions-item>
<el-descriptions-item label="录入人">{{ selectedExpense.created_by_name || '-' }}</el-descriptions-item>
<el-descriptions-item label="录入时间">{{ formatDateTime(selectedExpense.created_at) }}</el-descriptions-item>
<el-descriptions-item label="开支用途" :span="2">{{ selectedExpense.remark }}</el-descriptions-item>
<el-descriptions-item label="开支金额"
><strong>{{ money(selectedExpense.amount_cent) }}</strong></el-descriptions-item
>
<el-descriptions-item label="开支时间">{{
formatDateTime(selectedExpense.occurred_at)
}}</el-descriptions-item>
<el-descriptions-item label="录入人">{{
selectedExpense.created_by_name || '-'
}}</el-descriptions-item>
<el-descriptions-item label="录入时间">{{
formatDateTime(selectedExpense.created_at)
}}</el-descriptions-item>
<el-descriptions-item label="开支用途" :span="2">{{
selectedExpense.remark
}}</el-descriptions-item>
<el-descriptions-item v-if="selectedExpense.voucher_url" label="开支凭证" :span="2">
<AuthImage :source="selectedExpense.voucher_url" :admin="true" fit="cover" :preview-src-list="[selectedExpense.voucher_url]" :image-style="{ width: '140px', height: '140px', borderRadius: '6px' }" />
<AuthImage
:source="selectedExpense.voucher_url"
:admin="true"
fit="cover"
:preview-src-list="[selectedExpense.voucher_url]"
:image-style="{ width: '140px', height: '140px', borderRadius: '6px' }"
/>
</el-descriptions-item>
<el-descriptions-item v-if="selectedExpense.status === 'voided'" label="作废信息" :span="2">
{{ selectedExpense.voided_by_name || '-' }} · {{ formatDateTime(selectedExpense.voided_at) }} · {{ selectedExpense.void_reason || '-' }}
{{ selectedExpense.voided_by_name || '-' }} ·
{{ formatDateTime(selectedExpense.voided_at) }} · {{ selectedExpense.void_reason || '-' }}
</el-descriptions-item>
</el-descriptions>
<template #footer>
<el-button @click="selectedExpense = null">关闭</el-button>
<el-button v-if="selectedExpense?.status === 'paid' && canManage" type="danger" :icon="CircleClose" :loading="actionID === selectedExpense.id" @click="handleVoid(selectedExpense)">作废记录</el-button>
<el-button
v-if="selectedExpense?.status === 'paid' && canManage"
type="danger"
:icon="CircleClose"
:loading="actionID === selectedExpense.id"
@click="handleVoid(selectedExpense)"
>作废记录</el-button
>
</template>
</el-dialog>
</section>