引入 Element Plus 主题定制和主题皮肤 composable,将全局 样式拆分为组件级独立 CSS 文件(侧边栏、顶栏、工作台等), 统一色彩变量和间距规范,重构所有视图和组件样式以适配新 主题系统,优化图表和知识图谱组件视觉表现,提取审计和差 旅报销相关子组件。
153 lines
6.0 KiB
Vue
153 lines
6.0 KiB
Vue
<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>
|