Files
his/openhis-ui-vue3/src/views/maintainSystem/Inspection/PackageManagement.vue
duzhongxu b03f563df4 206
检验项目设置-》套餐设置:卫生机构字段取值当前登录账户的科室名称了
210 检验项目设置-》套餐管理:卫生机构筛选字段下拉选项取值错误
2026-03-24 16:42:24 +08:00

1083 lines
28 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>
<!-- 调试信息如果看到这个注释说明模板已加载 -->
<div class="package-management" @vue:mounted="console.log('PackageManagement 模板已挂载')">
<!-- 左侧导航栏 -->
<nav class="sidebar" :class="{ active: sidebarActive }">
<div class="sidebar-item" @click="navigateToTab(0)">检验类型</div>
<div class="sidebar-item" @click="navigateToTab(1)">检验项目</div>
<div class="sidebar-item active" @click="navigateToTab(2)">套餐设置</div>
</nav>
<!-- 主内容区域 -->
<main class="content">
<!-- 导航切换按钮响应式 -->
<div class="menu-toggle" @click="toggleSidebar">
<i class="fas fa-bars"></i>
</div>
<!-- 查询过滤区域 -->
<section class="filter-bar">
<div class="filter-item">
<label>日期</label>
<input type="date" v-model="searchParams.startDate" placeholder="开始日期">
<span></span>
<input type="date" v-model="searchParams.endDate" placeholder="结束日期">
</div>
<div class="filter-item">
<label>卫生机构</label>
<el-select
v-model="selectedTenantId"
placeholder="请选择机构"
style="width: 150px;"
clearable
@change="handleSearch"
>
<el-option
v-for="item in tenantOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="filter-item">
<label>套餐名称</label>
<input type="text" v-model="searchParams.packageName" placeholder="套餐名称">
</div>
<div class="filter-item">
<label>套餐级别</label>
<select v-model="searchParams.packageLevel">
<option value="">请选择套餐级别</option>
<option value="全院套餐">全院套餐</option>
<option value="科室套餐">科室套餐</option>
<option value="个人套餐">个人套餐</option>
</select>
</div>
<div class="filter-item">
<label>套餐类别</label>
<select>
<option>检验套餐</option>
</select>
</div>
<div class="filter-item filter-item-department">
<label>科室</label>
<el-tree-select
v-model="searchParams.department"
placeholder="请选择科室"
:data="departments"
:props="{
value: 'name',
label: 'name',
children: 'children'
}"
value-key="name"
check-strictly
:expand-on-click-node="false"
clearable
style="width: 200px;"
/>
</div>
<div class="filter-item">
<label>用户</label>
<select></select>
</div>
<!-- 操作按钮组 -->
<div class="button-group">
<button class="btn btn-search" @click="handleSearch"><i class="fas fa-search" style="margin-right: 6px;"></i>查询</button>
<button class="btn btn-reset" @click="handleReset"><i class="fas fa-redo" style="margin-right: 6px;"></i>重置</button>
<button class="btn btn-primary" @click="handleAdd"><i class="fas fa-plus" style="margin-right: 6px;"></i>新增</button>
<button class="btn btn-export" @click="handleExport"><i class="fas fa-download" style="margin-right: 6px;"></i>导出</button>
<button class="btn btn-copy" @click="returnToPackageSetup"><i class="fas fa-arrow-left" style="margin-right: 6px;"></i>返回</button>
</div>
</section>
<!-- 表格区域 -->
<section class="table-container">
<table>
<thead>
<tr>
<th>ID</th>
<th>卫生机构</th>
<th>日期</th>
<th>套餐名称</th>
<th>套餐类别</th>
<th>套餐级别</th>
<th>科室</th>
<th>用户</th>
<th class="text-right">金额</th>
<th class="text-right">服务费</th>
<th class="text-right">总金额</th>
<th>组合套餐</th>
<th>显示套餐名</th>
<th>启用标志</th>
<th>操作人</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in filteredData" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.hospital }}</td>
<td>{{ item.date }}</td>
<td>{{ item.name }}</td>
<td>{{ item.type }}</td>
<td>{{ item.level }}</td>
<td>{{ item.dept || '-' }}</td>
<td>{{ item.user || '-' }}</td>
<td class="text-right">{{ item.amount.toFixed(2) }}</td>
<td class="text-right">{{ item.fee.toFixed(2) }}</td>
<td class="text-right">{{ item.total.toFixed(2) }}</td>
<td><span class="status-tag" :class="item.combined === '是' ? 'status-no' : 'status-yes'">{{ item.combined }}</span></td>
<td><span class="status-tag" :class="item.display === '是' ? 'status-yes' : 'status-no'">{{ item.display }}</span></td>
<td><span class="status-tag" :class="item.enabled === '是' ? 'status-yes' : 'status-no'">{{ item.enabled }}</span></td>
<td>{{ item.operator }}</td>
<td class="action-cell">
<div class="action-btns">
<button class="action-btn edit-btn" @click="handleEdit(item)">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
</button>
<button class="action-btn view-btn" @click="handleView(item)">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
<circle cx="12" cy="12" r="3"></circle>
</svg>
</button>
<button class="action-btn delete-btn" @click="handleDelete(item)">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
<line x1="10" y1="11" x2="10" y2="17"></line>
<line x1="14" y1="11" x2="14" y2="17"></line>
</svg>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</section>
<!-- 分页组件 -->
<div class="pagination">
<button
class="page-btn"
:disabled="currentPage === 1"
@click="handlePrevPage"
>&lt;</button>
<button
v-for="page in pageButtons"
:key="page"
class="page-btn"
:class="{ active: page === currentPage }"
:disabled="page === '...'"
@click="handlePageChange(page)"
>{{ page }}</button>
<button
class="page-btn"
:disabled="currentPage >= totalPages || totalPages <= 1"
@click="handleNextPage"
>&gt;</button>
<div class="total-count">总数{{ total }}</div>
</div>
</main>
</div>
</template>
<script setup>
import {computed, onMounted, ref} from 'vue';
import {useRouter} from 'vue-router';
import {ElMessage} from 'element-plus';
import {getLocationTree} from '@/views/charge/outpatientregistration/components/outpatientregistration';
import {listInspectionPackage} from '@/api/system/inspectionPackage';
import { getTenantPage } from '@/api/system/tenant';
// 创建路由实例
const router = useRouter();
// 侧边栏状态
const sidebarActive = ref(false);
// 科室数据
const departments = ref([]);
// 获取科室数据 - 与门诊挂号页面保持一致
function getDepartmentList() {
console.log('调用getLocationTree API...');
getLocationTree().then((response) => {
// 检查数据结构并转换为适合el-tree-select的格式
if (Array.isArray(response.data)) {
// 直接使用数组数据
departments.value = response.data;
} else if (response.data && response.data.records) {
// 处理分页格式数据
departments.value = response.data.records;
} else if (response.data && response.data.rows) {
// 处理另一种分页格式数据
departments.value = response.data.rows;
} else {
departments.value = [];
}
}).catch((error) => {
departments.value = [];
});
}
// 获取科室数据 - 与门诊挂号页面保持一致,在组件初始化时直接调用
getDepartmentList();
// 表格数据 - 从API获取
const tableData = ref([])
const loading = ref(false)
const total = ref(0)
// 分页参数
const currentPage = ref(1)
const pageSize = ref(10)
// 获取当前日期的函数格式为YYYY-MM-DD
function getCurrentDate() {
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
// 搜索参数
const searchParams = ref({
startDate: getCurrentDate(),
endDate: getCurrentDate(),
packageName: '',
packageLevel: '',
department: ''
});
// 从API加载数据
async function loadData() {
try {
loading.value = true
// 构建查询参数(匹配后端 InspectionPackage 实体字段)
const params = {
pageNum: currentPage.value,
pageSize: pageSize.value,
packageCategory: '检验套餐' // InspectionPackage 使用 packageCategory 而不是 packageType
}
// 处理日期范围(后端可能不支持日期范围查询,先保留)
// if (searchParams.value.startDate) {
// params.startDate = searchParams.value.startDate
// }
// if (searchParams.value.endDate) {
// params.endDate = searchParams.value.endDate
// }
if (selectedTenantId.value) {
params.tenantId = selectedTenantId.value;
}
if (searchParams.value.packageName) {
params.packageName = searchParams.value.packageName
}
if (searchParams.value.packageLevel) {
params.packageLevel = searchParams.value.packageLevel
}
if (searchParams.value.department) {
params.department = searchParams.value.department
}
const response = await listInspectionPackage(params)
if (response) {
// 处理不同的响应格式优先按若依风格response.rows / response.total
let dataList = []
let totalCount = 0
// 优先检查 response.dataaxios 包装的响应)
if (response.data) {
const data = response.data
if (Array.isArray(data.rows)) {
// TableDataInfo 格式:{ rows: [], total: 0 }
dataList = data.rows
totalCount = data.total || 0
} else if (Array.isArray(data.records)) {
// MyBatis Plus 分页格式
dataList = data.records
totalCount = data.total || 0
} else if (Array.isArray(data)) {
// 直接是数组
dataList = data
totalCount = data.length
}
} else if (Array.isArray(response.rows)) {
// 直接是 TableDataInfo 格式
dataList = response.rows
totalCount = response.total || 0
} else if (Array.isArray(response)) {
// 直接返回数组
dataList = response
totalCount = response.length
}
total.value = totalCount
// 转换数据格式以匹配前端显示InspectionPackage 字段映射)
tableData.value = (dataList || []).map(item => {
const mappedItem = {
id: item.basicInformationId || item.id, // 优先使用 basicInformationId
packageId: item.packageId || item.basicInformationId || item.id, // 保存packageId用于跳转
basicInformationId: item.basicInformationId, // 保存原始basicInformationId
// 兼容旧逻辑:有些地方把主键当成 departmentId 使用注意真正的科室ID仍在后端字段 departmentId 上)
departmentId: item.basicInformationId || item.id || item.packageId,
hospital: item.orgName || '演示医院',
date: item.createTime ? (item.createTime.split('T')[0] || item.createTime.substring(0, 10)) : '',
name: item.packageName || '',
type: item.packageCategory || '检验套餐',
level: item.packageLevel || '',
dept: item.department || '',
user: item.userId || '',
amount: parseFloat(item.packageAmount || 0),
fee: parseFloat(item.serviceFee || 0),
total: parseFloat(item.packageAmount || 0) + parseFloat(item.serviceFee || 0),
combined: item.enablePackagePrice === true ? '是' : '否',
display: item.showPackageName === true ? '是' : '否',
enabled: item.isDisabled === true ? '否' : '是',
operator: item.createBy || ''
}
return mappedItem
})
} else {
tableData.value = []
total.value = 0
}
} catch (error) {
ElMessage.error('加载数据失败: ' + (error.message || '未知错误'))
tableData.value = []
total.value = 0
} finally {
loading.value = false
}
}
const selectedTenantId = ref(null); // 绑定下拉框的值
const tenantOptions = ref([]); // 存储机构选项
const loadingTenant = ref(false);
// 获取机构列表函数
const fetchTenantList = async () => {
if (loadingTenant.value) return;
loadingTenant.value = true;
try {
const response = await getTenantPage({ pageNum: 1, pageSize: 100 });
if (response.code !== 200) throw new Error(response.msg || '获取机构列表失败');
let tenantData = [];
const data = response.data;
if (Array.isArray(data)) {
tenantData = data;
} else if (data && typeof data === 'object') {
tenantData = data.records || data.rows || data.list || [];
}
// 过滤启用的机构
const activeTenants = (Array.isArray(tenantData) ? tenantData : []).filter(item => item && item.status === "0");
// 生成下拉选项
tenantOptions.value = activeTenants.map(item => ({
value: item.id,
label: item.tenantName || item.name || item.orgName || String(item.id)
}));
// 默认选中 ID=1 或第一个
if (activeTenants.length > 0) {
const zhonglianHospital = activeTenants.find(item => item.id === 1);
selectedTenantId.value = zhonglianHospital ? 1 : activeTenants[0].id;
}
} catch (error) {
console.error('获取机构列表失败:', error);
tenantOptions.value = [];
} finally {
loadingTenant.value = false;
}
};
// 初始化数据
// 整合后的 onMounted 钩子
onMounted(async () => {
// 1. 加载科室数据
getDepartmentList();
// 2. 加载机构列表 (包含默认选中逻辑)
await fetchTenantList();
// 3. 等待 DOM 更新
await nextTick();
// 4. 防御性检查
if (tenantOptions.value.length > 0 && !selectedTenantId.value) {
selectedTenantId.value = tenantOptions.value[0].value;
}
// 5. 加载表格数据
loadData();
});
// 过滤后的数据 - 现在直接从API获取这里保留前端过滤作为补充
const filteredData = computed(() => {
return tableData.value
});
// 返回套餐设置主界面
function returnToPackageSetup() {
router.push('/maintainSystem/Inspection?tab=2');
}
// 导航到指定标签页
function navigateToTab(tabIndex) {
router.push(`/maintainSystem/Inspection?tab=${tabIndex}`);
}
// 切换侧边栏
function toggleSidebar() {
sidebarActive.value = !sidebarActive.value;
}
// 处理查询
function handleSearch() {
currentPage.value = 1; // 搜索时重置到第一页
loadData()
}
// 处理重置
function handleReset() {
searchParams.value = {
startDate: getCurrentDate(),
endDate: getCurrentDate(),
packageName: '',
packageLevel: '',
department: ''
};
currentPage.value = 1; // 重置到第一页
loadData()
}
// 计算总页数
const totalPages = computed(() => {
const pages = Math.ceil(total.value / pageSize.value)
return pages > 0 ? pages : 1 // 至少返回1页
})
// 处理分页 - 上一页
function handlePrevPage() {
if (currentPage.value > 1) {
currentPage.value--
loadData()
}
}
// 处理分页 - 下一页
function handleNextPage() {
if (currentPage.value < totalPages.value) {
currentPage.value++
loadData()
} else {
}
}
// 处理分页 - 跳转到指定页
function handlePageChange(page) {
if (page === '...') {
return // 省略号不可点击
}
if (page >= 1 && page <= totalPages.value && page !== currentPage.value) {
currentPage.value = page
loadData()
} else {
}
}
// 生成分页按钮数组
const pageButtons = computed(() => {
const buttons = []
const total = totalPages.value
const current = currentPage.value
if (total <= 0) {
// 如果没有数据至少显示第1页
buttons.push(1)
return buttons
}
if (total <= 7) {
// 如果总页数小于等于7显示所有页码
for (let i = 1; i <= total; i++) {
buttons.push(i)
}
} else {
// 如果总页数大于7显示省略号
if (current <= 4) {
// 当前页在前4页
for (let i = 1; i <= 5; i++) {
buttons.push(i)
}
buttons.push('...')
buttons.push(total)
} else if (current >= total - 3) {
// 当前页在后4页
buttons.push(1)
buttons.push('...')
for (let i = total - 4; i <= total; i++) {
buttons.push(i)
}
} else {
// 当前页在中间
buttons.push(1)
buttons.push('...')
for (let i = current - 1; i <= current + 1; i++) {
buttons.push(i)
}
buttons.push('...')
buttons.push(total)
}
}
return buttons
})
// 处理新增
function handleAdd() {
router.push('/maintainSystem/Inspection?tab=2');
}
// 处理编辑
function handleEdit(item) {
// 跳转到套餐设置主界面并传递套餐ID用于加载数据
// 后端接口使用 basicInformationId 作为路径参数
const packageId = item.basicInformationId || item.id;
if (!packageId) {
ElMessage.error('无法获取套餐ID请刷新页面后重试');
return;
}
router.push({
path: '/maintainSystem/Inspection',
query: {
tab: '2',
packageId: packageId,
mode: 'edit'
}
});
}
// 处理查看
function handleView(item) {
// 跳转到套餐设置主界面并传递套餐ID用于加载数据
// 后端接口使用 basicInformationId 作为路径参数
const packageId = item.basicInformationId || item.id;
if (!packageId) {
ElMessage.error('无法获取套餐ID请刷新页面后重试');
return;
}
router.push({
path: '/maintainSystem/Inspection',
query: {
tab: '2',
packageId: packageId,
mode: 'view'
}
});
}
// 处理删除
function handleDelete(item) {
if (confirm(`确定要删除套餐 "${item.name}" 吗?`)) {
const index = tableData.value.findIndex(i => i.id === item.id);
if (index !== -1) {
tableData.value.splice(index, 1);
alert(`套餐 "${item.name}" 已删除`);
}
}
}
// 处理导出
function handleExport() {
// 获取当前筛选后的数据
const dataToExport = filteredData.value;
// 转换为CSV格式
const csvContent = convertToCSV(dataToExport);
// 创建下载链接
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('download', `套餐数据_${new Date().toISOString().slice(0,10)}.csv`);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// 将数据转换为CSV格式的函数
function convertToCSV(data) {
if (data.length === 0) return '';
// 获取表头
const headers = Object.keys(data[0]);
// 构建CSV内容
let csv = headers.join(',') + '\n';
// 添加数据行
data.forEach(row => {
const values = headers.map(header => {
// 处理可能包含逗号的值
const value = row[header] === null || row[header] === undefined ? '' : row[header];
return `"${value.toString().replace(/"/g, '""')}"`;
});
csv += values.join(',') + '\n';
});
return csv;
}
</script>
<style>
:root {
--background: #FFFFFF;
--primary: #5C8DFF;
--primary-hover: #7DA3FF;
--text-primary: #333333;
--text-secondary: #666666;
--text-disabled: #CCCCCC;
--danger: #FF6B6B;
--border: #E0E0E0;
--header-bg: #F5F5F5;
--row-hover: #FAFAFA;
--table-border: #E8E8E8;
--sidebar-width: 200px;
--content-padding: 24px;
--secondary: #8E8E93;
--secondary-hover: #A7A7AB;
--success: #4CAF50;
--info: #2196F3;
--btn-search: #6c757d;
--btn-reset: #17a2b8;
--btn-add: #28a745;
--btn-export: #17a2b8;
--btn-copy: #6c757d;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
/* 移除body样式避免影响其他页面 */
.package-management {
display: flex;
height: 100vh;
background-color: var(--background);
color: var(--text-primary);
overflow: hidden;
}
/* 左侧导航栏 */
.sidebar {
width: var(--sidebar-width);
background-color: var(--background);
border-right: 1px solid var(--border);
height: 100%;
display: flex;
flex-direction: column;
}
.sidebar-item {
padding: 16px 24px;
font-size: 14px;
color: var(--text-primary);
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
}
.sidebar-item:hover {
background-color: #f0f8ff;
}
.sidebar-item.active {
background-color: var(--primary);
color: white;
}
/* 主内容区域 */
.content {
flex: 1;
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
/* 查询过滤栏 */
.filter-bar {
padding: 16px var(--content-padding);
border-bottom: 1px solid var(--border);
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: center;
}
.filter-item {
display: flex;
align-items: center;
gap: 8px;
}
.filter-item-department {
min-width: 280px;
}
.filter-item-department .el-tree-select {
width: 100%;
}
.filter-item label {
font-size: 14px;
color: var(--text-secondary);
white-space: nowrap;
}
input, select {
height: 32px;
border-radius: 4px;
border: 1px solid var(--border);
padding: 0 8px;
font-size: 14px;
min-width: 120px;
}
input:focus, select:focus {
outline: none;
border-color: var(--primary);
}
/* 按钮样式 */
.btn {
padding: 6px 16px;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
height: 36px;
display: inline-flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
border: none;
box-shadow: 0 1px 2px rgba(0,0,0,0.05);
min-width: 80px;
}
.btn-primary {
background-color: var(--primary);
color: white;
border: 1px solid var(--primary);
box-shadow: 0 2px 4px rgba(92, 141, 255, 0.2);
}
.btn-text {
background-color: #F5F7FA;
color: var(--secondary);
border: 1px solid var(--border);
}
.btn-search {
background-color: var(--btn-search);
color: white;
}
.btn-reset {
background-color: var(--btn-reset);
color: white;
}
.btn-export {
background-color: var(--btn-export);
color: white;
}
.btn-copy {
background-color: var(--btn-copy);
color: white;
}
.btn-text:hover {
background-color: #EBEEF2;
color: var(--text-primary);
border-color: var(--secondary-hover);
}
.btn-danger {
background-color: var(--danger);
color: white;
}
.btn:hover {
opacity: 0.9;
}
.btn-primary:hover {
background-color: var(--primary-hover);
border-color: var(--primary-hover);
}
.button-group {
display: flex;
gap: 12px;
margin-left: auto;
flex-wrap: wrap;
}
/* 表格区域 */
.table-container {
flex: 1;
overflow: auto;
padding: 0 var(--content-padding) var(--content-padding);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
th, td {
padding: 8px;
text-align: left;
border-bottom: 1px solid var(--table-border);
}
th {
background-color: var(--header-bg);
font-weight: 500;
position: sticky;
top: 0;
}
tr:hover {
background-color: var(--row-hover);
}
.text-right {
text-align: right;
}
/* 状态标签 */
.status-tag {
padding: 0 8px;
border-radius: 2px;
font-size: 12px;
height: 20px;
display: inline-flex;
align-items: center;
justify-content: center;
}
.status-yes {
background-color: #f6ffed;
border: 1px solid #b7eb8f;
color: #389e0d;
}
.status-no {
background-color: #fff2f0;
border: 1px solid #ffccc7;
color: var(--danger);
}
/* 操作列 */
.action-cell {
display: flex;
justify-content: center;
gap: 8px;
position: relative;
z-index: 10;
}
.action-btns {
display: flex;
justify-content: center;
gap: 8px;
}
.action-btn {
width: 28px;
height: 28px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: none;
transition: all 0.2s ease;
font-size: 16px;
font-weight: bold;
position: relative;
z-index: 10;
background-color: #66b1ff;
color: white;
}
.edit-btn {
background-color: #FFC107;
color: white;
font-size: 14px;
}
.view-btn {
background-color: #1890FF;
color: white;
}
.delete-btn {
background-color: #FF4D4F;
color: white;
font-size: 14px;
z-index: 20;
pointer-events: auto;
}
/* 分页样式 */
.pagination {
display: flex;
justify-content: center;
align-items: center;
padding: 16px 0;
gap: 8px;
}
.page-btn {
width: 32px;
height: 32px;
border-radius: 4px;
border: 1px solid var(--border);
background-color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s;
}
.page-btn:hover:not(:disabled) {
background-color: #f0f8ff;
border-color: var(--primary);
}
.page-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
}
.page-btn:not(:disabled) {
cursor: pointer;
}
.page-btn.active {
background-color: var(--primary);
color: white;
border: none;
}
.total-count {
margin-left: 16px;
font-size: 14px;
color: var(--text-secondary);
}
/* 响应式设计 */
@media (max-width: 1200px) {
.sidebar {
transform: translateX(calc(-1 * var(--sidebar-width)));
position: absolute;
z-index: 100;
transition: transform 0.3s;
}
.sidebar.active {
transform: translateX(0);
}
.menu-toggle {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
position: absolute;
top: 16px;
left: 16px;
z-index: 101;
cursor: pointer;
background: white;
border: 1px solid var(--border);
border-radius: 4px;
}
.filter-bar {
padding-top: 64px;
}
}
</style>
<style scoped>
/* 移除未使用的图标样式 */
</style>
<style scoped>
/* 移除自动生成的未使用样式 */
</style>