753 lines
19 KiB
Vue
Executable File
753 lines
19 KiB
Vue
Executable File
<template>
|
|
<div class="my-card-management-container">
|
|
<!-- 顶部标题 -->
|
|
<div class="page-header">
|
|
<h2 class="page-title">我的报卡</h2>
|
|
</div>
|
|
|
|
<!-- 统计卡片区 -->
|
|
<div class="statistics-section">
|
|
<div class="stat-card">
|
|
<div class="stat-icon-wrap stat-icon-purple">
|
|
<el-icon class="stat-icon-inner"><DataAnalysis /></el-icon>
|
|
</div>
|
|
<div class="stat-content">
|
|
<div class="stat-value">{{ statistics.totalCount || 0 }}</div>
|
|
<div class="stat-label">总报卡数</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon-wrap stat-icon-red">
|
|
<el-icon class="stat-icon-inner"><Warning /></el-icon>
|
|
</div>
|
|
<div class="stat-content">
|
|
<div class="stat-value">{{ statistics.pendingFailedCount || 0 }}</div>
|
|
<div class="stat-label">待提交</div>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-icon-wrap stat-icon-green">
|
|
<el-icon class="stat-icon-inner"><CircleCheck /></el-icon>
|
|
</div>
|
|
<div class="stat-content">
|
|
<div class="stat-value">{{ statistics.reportedCount || 0 }}</div>
|
|
<div class="stat-label">已成功上报</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 高级筛选区 -->
|
|
<div class="filter-section">
|
|
<div class="filter-title">高级筛选</div>
|
|
<div class="filter-row">
|
|
<div class="filter-item">
|
|
<span class="filter-label">日期范围</span>
|
|
<el-date-picker
|
|
v-model="queryParams.dateRange"
|
|
type="daterange"
|
|
range-separator="至"
|
|
start-placeholder="年/月/日"
|
|
end-placeholder="年/月/日"
|
|
value-format="YYYY-MM-DD"
|
|
class="filter-date-picker"
|
|
/>
|
|
</div>
|
|
<div class="filter-item">
|
|
<span class="filter-label">状态</span>
|
|
<el-select v-model="queryParams.status" placeholder="全部状态" clearable class="filter-select">
|
|
<el-option label="全部状态" value="" />
|
|
<el-option label="待提交" value="0" />
|
|
<el-option label="已提交" value="1" />
|
|
<el-option label="已审核" value="2" />
|
|
<el-option label="已上报" value="3" />
|
|
<el-option label="失败" value="4" />
|
|
<el-option label="作废" value="6" />
|
|
</el-select>
|
|
</div>
|
|
<div class="filter-item">
|
|
<span class="filter-label">报卡名称</span>
|
|
<el-input
|
|
v-model="queryParams.keyword"
|
|
placeholder="输入报卡名称..."
|
|
clearable
|
|
class="filter-input"
|
|
@keyup.enter="handleQuery"
|
|
/>
|
|
</div>
|
|
<div class="filter-actions">
|
|
<el-button class="btn-apply" type="primary" @click="handleQuery">
|
|
<el-icon><Check /></el-icon>
|
|
应用筛选
|
|
</el-button>
|
|
<el-button class="btn-reset" @click="handleReset">
|
|
<el-icon><RefreshRight /></el-icon>
|
|
重置条件
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 数据表格区 -->
|
|
<div class="table-section">
|
|
<el-table
|
|
ref="tableRef"
|
|
v-loading="loading"
|
|
:data="cardList"
|
|
@selection-change="handleSelectionChange"
|
|
border
|
|
stripe
|
|
:height="tableHeight"
|
|
virtualized
|
|
:virtualized-row-height="48"
|
|
>
|
|
<el-table-column type="selection" width="50" align="center" />
|
|
<el-table-column label="卡片ID" prop="cardNo" min-width="155" />
|
|
<el-table-column label="患者姓名" prop="patName" width="90" />
|
|
<el-table-column label="身份证号" prop="idNo" min-width="170" />
|
|
<el-table-column label="联系电话" prop="phone" width="120" />
|
|
<el-table-column label="就诊卡号" prop="visitCardNo" width="110" />
|
|
<el-table-column label="报卡名称" prop="cardName" min-width="120" />
|
|
<el-table-column label="提交时间" prop="submitTime" width="110" align="center" />
|
|
<el-table-column label="状态" prop="status" width="80" align="center">
|
|
<template #default="{ row }">
|
|
<span :class="['status-tag', 'status-' + row.status]">
|
|
{{ getStatusName(row.status) }}
|
|
</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="操作" width="160" align="center" fixed="right">
|
|
<template #default="{ row }">
|
|
<el-button type="primary" link size="small" @click="handleView(row)">查看</el-button>
|
|
<el-button v-if="row.status == 0" type="primary" link size="small" @click="handleEdit(row)">编辑</el-button>
|
|
<el-button v-if="row.status == 0" type="success" link size="small" @click="handleSubmit(row)">提交</el-button>
|
|
<el-button v-if="row.status == 1" type="warning" link size="small" @click="handleWithdraw(row)">撤回</el-button>
|
|
<el-button v-if="row.status == 3" type="primary" link size="small" @click="handleExport(row)">导出</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<div class="pagination-section">
|
|
<el-pagination
|
|
v-model:current-page="queryParams.pageNo"
|
|
v-model:page-size="queryParams.pageSize"
|
|
:page-sizes="[10, 20, 50, 100]"
|
|
:total="total"
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|
@size-change="getList"
|
|
@current-change="getList"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 底部批量操作栏 -->
|
|
<div class="bottom-action-bar">
|
|
<div class="bottom-action-left">
|
|
<el-checkbox v-model="isAllSelected" @change="handleSelectAll">全选</el-checkbox>
|
|
<span class="selected-info">已选择 {{ selectedRows.length }} 个项目</span>
|
|
</div>
|
|
<div class="bottom-action-right">
|
|
<el-button class="btn-batch-delete" :disabled="selectedRows.length === 0" @click="handleBatchDelete">批量删除</el-button>
|
|
<el-button class="btn-batch-submit" type="primary" :disabled="selectedRows.length === 0" @click="handleBatchSubmit">批量提交</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<InfectiousDiseaseReportDialog
|
|
ref="infectiousDiseaseReportRef"
|
|
:read-only="detailMode === 'view'"
|
|
@success="detailVisible = false"
|
|
@close="detailVisible = false"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, reactive, onMounted, onActivated, onBeforeUnmount, nextTick, computed } from 'vue';
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
import { DataAnalysis, Warning, CircleCheck, Check, RefreshRight } from '@element-plus/icons-vue';
|
|
import InfectiousDiseaseReportDialog from '../components/diagnosis/infectiousDiseaseReportDialog.vue';
|
|
import {
|
|
getDoctorCardStatistics,
|
|
getDoctorCardList,
|
|
submitCard,
|
|
withdrawCard,
|
|
batchSubmitCards,
|
|
batchDeleteCards,
|
|
exportCardToWord,
|
|
getCardDetail,
|
|
} from './api';
|
|
|
|
const loading = ref(false);
|
|
const cardList = ref([]);
|
|
const total = ref(0);
|
|
const selectedRows = ref([]);
|
|
const isAllSelected = ref(false);
|
|
const tableRef = ref(null);
|
|
|
|
const statistics = ref({
|
|
totalCount: 0,
|
|
pendingFailedCount: 0,
|
|
reportedCount: 0,
|
|
});
|
|
|
|
const queryParams = reactive({
|
|
pageNo: 1,
|
|
pageSize: 10,
|
|
dateRange: [],
|
|
status: '',
|
|
keyword: '',
|
|
});
|
|
|
|
const detailVisible = ref(false);
|
|
const detailMode = ref('view');
|
|
const infectiousDiseaseReportRef = ref(null);
|
|
|
|
// 计算表格高度:根据视口高度动态调整
|
|
const tableHeight = computed(() => {
|
|
// 视口高度 - 顶部导航(约60px) - 标题(40px) - 统计卡片(120px) - 筛选区(100px)
|
|
// - 分页(60px) - 底部操作栏(60px) - 上下边距(80px) - 额外缓冲(20px)
|
|
return window.innerHeight - 540;
|
|
});
|
|
|
|
// 监听窗口大小变化,确保表格高度自适应
|
|
let resizeObserver = null;
|
|
|
|
const statusMap = {
|
|
0: { name: '待提交', type: 'warning' },
|
|
1: { name: '已提交', type: 'primary' },
|
|
2: { name: '已审核', type: 'success' },
|
|
3: { name: '已上报', type: 'success' },
|
|
4: { name: '失败', type: 'danger' },
|
|
5: { name: '退回', type: 'danger' },
|
|
6: { name: '作废', type: 'info' },
|
|
};
|
|
|
|
const ageUnitMap = {
|
|
'1': '岁',
|
|
'2': '月',
|
|
'3': '天',
|
|
};
|
|
|
|
function getStatusName(status) {
|
|
return statusMap[status]?.name || '未知';
|
|
}
|
|
|
|
function getStatusType(status) {
|
|
return statusMap[status]?.type || 'info';
|
|
}
|
|
|
|
function getAgeUnit(unit) {
|
|
return ageUnitMap[unit] || '岁';
|
|
}
|
|
|
|
async function getStatistics() {
|
|
try {
|
|
const res = await getDoctorCardStatistics();
|
|
console.log('统计数据响应:', res);
|
|
if (res.code === 200) {
|
|
statistics.value = res.data || { totalCount: 0, pendingFailedCount: 0, reportedCount: 0 };
|
|
} else {
|
|
console.error('获取统计数据失败:', res.msg);
|
|
ElMessage.error(res.msg || '获取统计数据失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('获取统计数据异常:', error);
|
|
ElMessage.error('获取统计数据失败');
|
|
}
|
|
}
|
|
|
|
async function getList() {
|
|
loading.value = true;
|
|
try {
|
|
const params = { ...queryParams };
|
|
if (params.dateRange && params.dateRange.length === 2) {
|
|
params.startDate = params.dateRange[0];
|
|
params.endDate = params.dateRange[1];
|
|
}
|
|
delete params.dateRange;
|
|
|
|
console.log('查询参数:', params);
|
|
const res = await getDoctorCardList(params);
|
|
console.log('列表数据响应:', res);
|
|
if (res.code === 200) {
|
|
cardList.value = res.data?.list || [];
|
|
total.value = res.data?.total || 0;
|
|
console.log('列表数据:', cardList.value, '总数:', total.value);
|
|
} else {
|
|
console.error('获取列表失败:', res.msg);
|
|
ElMessage.error(res.msg || '获取数据失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('获取列表异常:', error);
|
|
ElMessage.error('获取数据失败');
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
function handleQuery() {
|
|
queryParams.pageNo = 1;
|
|
getList();
|
|
}
|
|
|
|
function handleReset() {
|
|
queryParams.pageNo = 1;
|
|
queryParams.pageSize = 10;
|
|
queryParams.dateRange = [];
|
|
queryParams.status = '';
|
|
queryParams.keyword = '';
|
|
getList();
|
|
}
|
|
|
|
function handleSelectionChange(selection) {
|
|
selectedRows.value = selection;
|
|
isAllSelected.value = selection.length === cardList.value.length && cardList.value.length > 0;
|
|
}
|
|
|
|
function handleSelectAll(val) {
|
|
nextTick(() => {
|
|
if (tableRef.value) {
|
|
tableRef.value.toggleAllSelection();
|
|
}
|
|
});
|
|
}
|
|
|
|
async function handleView(row) {
|
|
try {
|
|
const res = await getCardDetail(row.cardNo);
|
|
if (res.code === 200) {
|
|
detailMode.value = 'view';
|
|
detailVisible.value = true;
|
|
nextTick(() => {
|
|
infectiousDiseaseReportRef.value?.showReport(res.data || {});
|
|
});
|
|
}
|
|
} catch (error) {
|
|
ElMessage.error('获取详情失败');
|
|
}
|
|
}
|
|
|
|
async function handleEdit(row) {
|
|
try {
|
|
const res = await getCardDetail(row.cardNo);
|
|
if (res.code === 200) {
|
|
detailMode.value = 'edit';
|
|
detailVisible.value = true;
|
|
nextTick(() => {
|
|
infectiousDiseaseReportRef.value?.showReport(res.data || {}, false);
|
|
});
|
|
}
|
|
} catch (error) {
|
|
ElMessage.error('获取详情失败');
|
|
}
|
|
}
|
|
|
|
async function handleSubmit(row) {
|
|
try {
|
|
await ElMessageBox.confirm('确认提交该报卡?', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning',
|
|
});
|
|
const res = await submitCard(row.cardNo);
|
|
if (res.code === 200) {
|
|
ElMessage.success('提交成功');
|
|
getStatistics();
|
|
getList();
|
|
} else {
|
|
ElMessage.error(res.msg || '提交失败');
|
|
}
|
|
} catch (error) {
|
|
if (error !== 'cancel') {
|
|
ElMessage.error('提交失败');
|
|
}
|
|
}
|
|
}
|
|
|
|
async function handleWithdraw(row) {
|
|
try {
|
|
await ElMessageBox.confirm('确认撤回该报卡?', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning',
|
|
});
|
|
const res = await withdrawCard(row.cardNo);
|
|
if (res.code === 200) {
|
|
ElMessage.success('撤回成功');
|
|
getStatistics();
|
|
getList();
|
|
} else {
|
|
ElMessage.error(res.msg || '撤回失败');
|
|
}
|
|
} catch (error) {
|
|
if (error !== 'cancel') {
|
|
ElMessage.error('撤回失败');
|
|
}
|
|
}
|
|
}
|
|
|
|
async function handleBatchSubmit() {
|
|
const validRows = selectedRows.value.filter(row => row.status == 0);
|
|
if (validRows.length === 0) {
|
|
ElMessage.warning('只能提交待提交状态的报卡');
|
|
return;
|
|
}
|
|
try {
|
|
await ElMessageBox.confirm(`确认提交选中的 ${validRows.length} 条报卡?`, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning',
|
|
});
|
|
const cardNos = validRows.map(row => row.cardNo);
|
|
const res = await batchSubmitCards(cardNos);
|
|
if (res.code === 200) {
|
|
ElMessage.success(res.msg || '批量提交成功');
|
|
getStatistics();
|
|
getList();
|
|
} else {
|
|
ElMessage.error(res.msg || '批量提交失败');
|
|
}
|
|
} catch (error) {
|
|
if (error !== 'cancel') {
|
|
ElMessage.error('批量提交失败');
|
|
}
|
|
}
|
|
}
|
|
|
|
async function handleBatchDelete() {
|
|
const validRows = selectedRows.value.filter(row => row.status == 0);
|
|
if (validRows.length === 0) {
|
|
ElMessage.warning('只能删除待提交状态的报卡');
|
|
return;
|
|
}
|
|
try {
|
|
await ElMessageBox.confirm(`确认删除选中的 ${validRows.length} 条报卡?删除后状态将变为作废。`, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning',
|
|
});
|
|
const cardNos = validRows.map(row => row.cardNo);
|
|
const res = await batchDeleteCards(cardNos);
|
|
if (res.code === 200) {
|
|
ElMessage.success(res.msg || '批量删除成功');
|
|
getStatistics();
|
|
getList();
|
|
} else {
|
|
ElMessage.error(res.msg || '批量删除失败');
|
|
}
|
|
} catch (error) {
|
|
if (error !== 'cancel') {
|
|
ElMessage.error('批量删除失败');
|
|
}
|
|
}
|
|
}
|
|
|
|
async function handleExport(row) {
|
|
try {
|
|
const res = await exportCardToWord(row.cardNo);
|
|
const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
|
|
const url = window.URL.createObjectURL(blob);
|
|
const link = document.createElement('a');
|
|
link.href = url;
|
|
link.download = `传染病报告卡-${row.cardNo}.docx`;
|
|
link.click();
|
|
window.URL.revokeObjectURL(url);
|
|
} catch (error) {
|
|
ElMessage.error('导出失败');
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
console.log('页面首次加载 - onMounted');
|
|
getStatistics();
|
|
getList();
|
|
|
|
// 添加窗口大小变化监听
|
|
window.addEventListener('resize', handleResize);
|
|
});
|
|
|
|
// 处理 keep-alive 缓存场景:从其他页面返回时重新加载数据
|
|
onActivated(() => {
|
|
console.log('页面被激活 - onActivated');
|
|
getStatistics();
|
|
getList();
|
|
});
|
|
|
|
// 组件卸载时移除事件监听
|
|
onBeforeUnmount(() => {
|
|
window.removeEventListener('resize', handleResize);
|
|
});
|
|
|
|
// 窗口大小变化处理函数
|
|
function handleResize() {
|
|
// 触发计算属性重新计算
|
|
nextTick(() => {
|
|
if (tableRef.value) {
|
|
tableRef.value.doLayout();
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.my-card-management-container {
|
|
padding: 20px;
|
|
background-color: #f5f7fa;
|
|
min-height: calc(100vh - 84px);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
}
|
|
|
|
/* 页面标题 */
|
|
.page-header {
|
|
margin-bottom: 0;
|
|
}
|
|
.page-title {
|
|
font-size: 20px;
|
|
font-weight: 600;
|
|
color: #1e293b;
|
|
margin: 0;
|
|
}
|
|
|
|
/* 统计卡片区 */
|
|
.statistics-section {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 16px;
|
|
}
|
|
|
|
.stat-card {
|
|
background: #fff;
|
|
border-radius: 12px;
|
|
padding: 20px 24px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16px;
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
|
|
border: 1px solid #f0f0f0;
|
|
transition: box-shadow 0.2s;
|
|
}
|
|
.stat-card:hover {
|
|
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
/* 图标容器 */
|
|
.stat-icon-wrap {
|
|
width: 52px;
|
|
height: 52px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
}
|
|
.stat-icon-purple {
|
|
background: linear-gradient(135deg, #818cf8 0%, #6366f1 100%);
|
|
}
|
|
.stat-icon-red {
|
|
background: linear-gradient(135deg, #fca5a5 0%, #ef4444 100%);
|
|
}
|
|
.stat-icon-green {
|
|
background: linear-gradient(135deg, #6ee7b7 0%, #10b981 100%);
|
|
}
|
|
.stat-icon-inner {
|
|
font-size: 24px;
|
|
color: #fff;
|
|
}
|
|
|
|
.stat-content {
|
|
flex: 1;
|
|
}
|
|
.stat-value {
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
color: #1e293b;
|
|
line-height: 1.2;
|
|
}
|
|
.stat-label {
|
|
font-size: 13px;
|
|
color: #64748b;
|
|
margin-top: 4px;
|
|
}
|
|
|
|
/* 高级筛选区 */
|
|
.filter-section {
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
padding: 16px 20px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
border: 1px solid #f0f0f0;
|
|
}
|
|
.filter-title {
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: #1e293b;
|
|
margin-bottom: 14px;
|
|
}
|
|
.filter-row {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
}
|
|
.filter-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.filter-label {
|
|
font-size: 13px;
|
|
color: #475569;
|
|
white-space: nowrap;
|
|
flex-shrink: 0;
|
|
}
|
|
.filter-date-picker {
|
|
width: 240px;
|
|
}
|
|
.filter-select {
|
|
width: 140px;
|
|
}
|
|
.filter-input {
|
|
width: 180px;
|
|
}
|
|
.filter-actions {
|
|
display: flex;
|
|
gap: 8px;
|
|
margin-left: auto;
|
|
}
|
|
.btn-apply {
|
|
background-color: #6366f1;
|
|
border-color: #6366f1;
|
|
}
|
|
.btn-apply:hover {
|
|
background-color: #4f46e5;
|
|
border-color: #4f46e5;
|
|
}
|
|
.btn-reset {
|
|
color: #475569;
|
|
}
|
|
|
|
/* 表格区 */
|
|
.table-section {
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
border: 1px solid #f0f0f0;
|
|
}
|
|
|
|
/* 状态标签 */
|
|
.status-tag {
|
|
display: inline-block;
|
|
padding: 2px 8px;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
line-height: 1.6;
|
|
}
|
|
/* 已上报 - 绿 */
|
|
.status-3 {
|
|
color: #16a34a;
|
|
background: #dcfce7;
|
|
border: 1px solid #bbf7d0;
|
|
}
|
|
/* 已审核 - 蓝 */
|
|
.status-2 {
|
|
color: #2563eb;
|
|
background: #dbeafe;
|
|
border: 1px solid #bfdbfe;
|
|
}
|
|
/* 失败 - 红 */
|
|
.status-4 {
|
|
color: #dc2626;
|
|
background: #fee2e2;
|
|
border: 1px solid #fecaca;
|
|
}
|
|
/* 已提交 - 绿 */
|
|
.status-1 {
|
|
color: #16a34a;
|
|
background: #dcfce7;
|
|
border: 1px solid #bbf7d0;
|
|
}
|
|
/* 待提交 - 橙 */
|
|
.status-0 {
|
|
color: #d97706;
|
|
background: #fef3c7;
|
|
border: 1px solid #fde68a;
|
|
}
|
|
/* 作废 - 灰 */
|
|
.status-6 {
|
|
color: #64748b;
|
|
background: #f1f5f9;
|
|
border: 1px solid #e2e8f0;
|
|
}
|
|
/* 退回 - 红 */
|
|
.status-5 {
|
|
color: #dc2626;
|
|
background: #fee2e2;
|
|
border: 1px solid #fecaca;
|
|
}
|
|
|
|
/* 分页 */
|
|
.pagination-section {
|
|
margin-top: 16px;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
/* 底部批量操作栏 */
|
|
.bottom-action-bar {
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
padding: 12px 20px;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
border: 1px solid #f0f0f0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
.bottom-action-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
.selected-info {
|
|
font-size: 13px;
|
|
color: #64748b;
|
|
}
|
|
.bottom-action-right {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
.btn-batch-delete {
|
|
color: #dc2626;
|
|
border-color: #fecaca;
|
|
background: #fff;
|
|
}
|
|
.btn-batch-delete:hover {
|
|
background: #fee2e2;
|
|
border-color: #fca5a5;
|
|
}
|
|
.btn-batch-submit {
|
|
background-color: #6366f1;
|
|
border-color: #6366f1;
|
|
font-weight: 500;
|
|
}
|
|
.btn-batch-submit:hover {
|
|
background-color: #4f46e5;
|
|
border-color: #4f46e5;
|
|
}
|
|
|
|
@media (max-width: 992px) {
|
|
.statistics-section {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
.filter-row {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
}
|
|
.filter-actions {
|
|
margin-left: 0;
|
|
}
|
|
}
|
|
</style> |