Files
X-Financial/web/src/views/RequestsView.vue
caoxiaozhu 2dcc72102d style: 全局 UI 主题皮肤重构与样式模块化
引入 Element Plus 主题定制和主题皮肤 composable,将全局
样式拆分为组件级独立 CSS 文件(侧边栏、顶栏、工作台等),
统一色彩变量和间距规范,重构所有视图和组件样式以适配新
主题系统,优化图表和知识图谱组件视觉表现,提取审计和差
旅报销相关子组件。
2026-05-27 09:17:57 +08:00

153 lines
6.0 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>
<section class="travel-page">
<article class="travel-list panel">
<nav class="status-tabs" aria-label="个人报销状态">
<button
v-for="tab in tabs"
:key="tab"
type="button"
:class="{ active: activeTab === tab }"
@click="activeTab = tab"
>
{{ tab }}
</button>
</nav>
<div class="list-toolbar">
<div class="filter-set">
<div class="list-search">
<i class="mdi mdi-magnify"></i>
<input v-model="listKeyword" type="search" placeholder="搜索单号、事由、报销类型..." />
</div>
<div class="date-range-filter" :class="{ open: datePopover }">
<button class="filter-btn date-range-trigger" type="button" @click="datePopover = !datePopover">
<span class="date-range-label">{{ dateRangeLabel }}</span>
<i class="mdi mdi-calendar"></i>
</button>
<div v-if="datePopover" class="date-range-popover" role="dialog" aria-label="选择时间段">
<header>
<strong>选择时间段</strong>
<button type="button" aria-label="关闭" @click="datePopover = false"><i class="mdi mdi-close"></i></button>
</header>
<div class="date-range-fields">
<label>
<span>开始日期</span>
<input v-model="rangeStart" type="date" />
</label>
<label>
<span>结束日期</span>
<input v-model="rangeEnd" type="date" />
</label>
</div>
<footer>
<button class="ghost-btn" type="button" @click="datePopover = false">取消</button>
<button class="apply-btn" type="button" :disabled="!rangeStart || !rangeEnd" @click="applyDateRange">应用</button>
</footer>
</div>
</div>
<button v-for="filter in filters" :key="filter" type="button" class="filter-btn">
<span>{{ filter }}</span>
<i class="mdi mdi-chevron-down"></i>
</button>
</div>
<button class="create-request-btn" type="button" @click="emit('create-request')">
<i class="mdi mdi-plus-circle-outline"></i>
<span>发起报销</span>
</button>
</div>
<p class="hint"><i class="mdi mdi-information-outline"></i> 点击任意行可查看单据详情</p>
<div class="table-wrap" :class="{ 'is-empty': showEmpty }">
<div v-if="loading" class="table-state">
<TableLoadingState
title="真实报销数据同步中"
message="正在加载后端返回的个人报销单据"
icon="mdi mdi-file-document-outline"
/>
</div>
<div v-else-if="error" class="table-state error">
<i class="mdi mdi-alert-circle-outline"></i>
<strong>报销列表加载失败</strong>
<p>{{ error }}</p>
<button class="retry-btn" type="button" @click="emit('reload')">重新加载</button>
</div>
<TableEmptyState
v-else-if="showEmpty"
:eyebrow="emptyState.eyebrow"
:title="emptyState.title"
:description="emptyState.desc"
:icon="emptyState.icon"
:action-label="emptyState.actionLabel"
:action-icon="emptyState.actionIcon"
:tone="emptyState.tone"
:art-label="emptyState.artLabel"
:tips="emptyState.tips"
@action="handleEmptyAction"
/>
<table v-else>
<colgroup>
<col class="col-id">
<col class="col-type">
<col class="col-title">
<col class="col-occurred">
<col class="col-apply">
<col class="col-amount">
<col class="col-node">
<col class="col-approval">
</colgroup>
<thead>
<tr>
<th>单号</th>
<th>报销类型</th>
<th>报销事由</th>
<th>发生时间</th>
<th>申请时间</th>
<th>金额</th>
<th>当前节点</th>
<th>审批状态</th>
</tr>
</thead>
<tbody>
<tr v-for="row in visibleRows" :key="row.id" @click="emit('ask', row)">
<td><strong class="doc-id">{{ row.documentNo || row.id }}</strong></td>
<td><span class="type-tag" :class="row.typeTone">{{ row.typeLabel }}</span></td>
<td>{{ row.reason }}</td>
<td>{{ row.occurredDisplay }}</td>
<td>{{ row.applyTime }}</td>
<td>{{ row.amountDisplay }}</td>
<td>{{ row.node }}</td>
<td><span class="status-tag" :class="row.approvalTone">{{ row.approval }}</span></td>
</tr>
</tbody>
</table>
</div>
<footer v-if="showTable" class="list-foot">
<span class="page-summary"> {{ totalCount }} 目前第 {{ currentPage }} </span>
<div class="pager" aria-label="分页">
<button class="page-nav" type="button" :disabled="currentPage === 1" aria-label="上一页" @click="currentPage--"><i class="mdi mdi-chevron-left"></i></button>
<button v-for="p in totalPages" :key="p" class="page-number" :class="{ active: currentPage === p }" type="button" :aria-current="currentPage === p ? 'page' : undefined" @click="currentPage = p">{{ p }}</button>
<button class="page-nav" type="button" :disabled="currentPage === totalPages" aria-label="下一页" @click="currentPage++"><i class="mdi mdi-chevron-right"></i></button>
</div>
<EnterpriseSelect
v-model="pageSize"
class="page-size-select"
:options="pageSizeOptions"
size="small"
@change="changePageSize"
/>
</footer>
</article>
</section>
</template>
<script src="./scripts/RequestsView.js"></script>
<style scoped src="../assets/styles/views/requests-view.css"></style>