Files
his/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/index.vue

1275 lines
37 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="check-project-settings">
<!-- 左侧导航栏 -->
<div class="sidebar" style="margin-top: 100px;">
<!-- 明确列出所有导航项 -->
<button
class="menu-item active"
@click="handleMenuClick('检查类型')"
style="display: block; width: 100%; height: 40px; padding: 8px; text-align: center;"
>
检查类型
</button>
<button
class="menu-item"
@click="handleMenuClick('检查方法')"
style="display: block; width: 100%; height: 40px; padding: 8px; text-align: center;"
>
检查方法
</button>
<button
class="menu-item"
@click="handleMenuClick('检查部位')"
style="display: block; width: 100%; height: 40px; padding: 8px; text-align: center;"
>
检查部位
</button>
<button
class="menu-item"
@click="handleMenuClick('套餐设置')"
style="display: block; width: 100%; height: 40px; padding: 8px; text-align: center;"
>
套餐设置
</button>
</div>
<!-- 主内容区域 -->
<div class="content">
<!-- 套餐管理和套餐设置 -->
<template v-if="activeMenu === '套餐设置'">
<!-- 套餐设置界面默认显示 -->
<PackageSettings
v-if="packageView === 'settings'"
:mode="packageMode"
:package-data="currentPackageData"
@switch-to-management="handleSwitchToManagement"
@save-success="handleSaveSuccess"
/>
<!-- 套餐管理界面列表 -->
<PackageManagement
v-else
@switch-to-settings="handleSwitchToSettings"
/>
</template>
<!-- 检查类型的表格视图 -->
<template v-if="activeMenu === '检查类型'">
<div class="header">
<h1>{{ activeMenu }}管理</h1>
<div class="header-actions">
<button class="btn btn-add-new" @click="handleAddNewRow">+
</button>
</div>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th style="width: 50px;"></th>
<th style="width: 100px;">*编码</th>
<th style="width: 150px;">*名称</th>
<th style="width: 150px;">*检查类型</th>
<th style="width: 120px;">选择部位</th>
<th style="width: 150px;">*执行科室</th>
<th style="width: 100px;">序号</th>
<th style="width: 150px;">备注</th>
<th style="width: 120px;">操作</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in tableData"
:key="index"
:class="{ 'editing-row': item.editing, 'child-row': item.row.includes('.') }"
@click="handleRowClick(item)"
>
<td>{{ item.row }}</td>
<td>
<template v-if="item.editing">
<input type="text" placeholder="请输入编码" v-model="item.code">
</template>
<template v-else>
{{ item.code }}
</template>
</td>
<td>
<template v-if="item.editing">
<input type="text" placeholder="请输入名称" v-model="item.name">
</template>
<template v-else>
{{ item.name }}
</template>
</td>
<td>
<template v-if="item.editing">
<select v-model="item.type" :class="{ 'placeholder-text': !item.type }">
<option value="">选择检查类型</option>
<option
v-for="type in checkTypes"
:key="type"
:value="type"
>
{{ type }}
</option>
</select>
</template>
<template v-else>
<span v-if="item.type">{{ item.type }}</span>
<span v-else class="placeholder-text">选择检查类型</span>
</template>
</td>
<td class="checkbox-container">
<input type="checkbox" v-model="item.selected" @click.stop>
</td>
<td>
<template v-if="item.editing">
<select v-model="item.department" :class="{ 'placeholder-text': !item.department }">
<option value="">选择执行科室</option>
<option
v-if="item.department"
:value="item.department"
>
{{ item.department }}
</option>
<option
v-for="dept in departments"
:key="dept.dictValue"
:value="dept.dictLabel"
>
{{ dept.dictLabel }}
</option>
</select>
</template>
<template v-else>
<span v-if="item.department">{{ item.department }}</span>
<span v-else class="placeholder-text">选择执行科室</span>
</template>
</td>
<td>
<template v-if="item.editing">
<input type="text" v-model="item.number">
</template>
<template v-else>
{{ item.number }}
</template>
</td>
<td>
<template v-if="item.editing">
<input type="text" placeholder="请输入备注" v-model="item.remark">
</template>
<template v-else>
{{ item.remark || '' }}
</template>
</td>
<td class="actions">
<template v-if="item.actions">
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
</button>
<button
v-if="!item.row.includes('.')"
class="btn btn-add"
@click.stop="handleAdd(index)"
>
+
</button>
<button class="btn btn-delete" @click.stop="handleDelete(index)">
🗑
</button>
</template>
<template v-else>
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
</button>
<button class="btn btn-delete" @click.stop="handleDelete(index)">
🗑
</button>
</template>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<!-- 检查方法的表格视图 -->
<template v-else-if="activeMenu === '检查方法'">
<div class="header">
<h1>{{ activeMenu }}管理</h1>
<div class="header-actions">
<button class="btn btn-add-new" @click="handleAddNewRow">+
</button>
</div>
</div>
<div class="search-bar">
<div class="search-item">
<label>检查方法</label>
<el-select v-model="searchParams.checkMethod" placeholder="选择检查方法" style="width: 150px">
<el-option
v-for="method in checkMethods"
:key="method.code"
:label="method.name"
:value="method.code"
>
</el-option>
</el-select>
</div>
<div class="search-item">
<label>名称</label>
<el-input placeholder="名称/编码" v-model="searchParams.name" />
</div>
<div class="search-item">
<label>使用套餐</label>
<el-select v-model="searchParams.packageId" placeholder="选择使用套餐" style="width: 150px">
<el-option
v-for="pkg in checkPackages"
:key="pkg.id"
:label="pkg.name"
:value="pkg.id"
>
</el-option>
</el-select>
</div>
<div class="search-actions">
<el-button type="primary" :style="{ backgroundColor: hoverAddButton ? '#8a49e0' : '#722ED1', borderColor: hoverAddButton ? '#8a49e0' : '#722ED1' }" @mouseenter="hoverAddButton = true" @mouseleave="hoverAddButton = false" @click="handleAddNewRow">新增</el-button>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
<el-button type="success" @click="handleExport">导出表格</el-button>
</div>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th style="width: 50px;"></th>
<th style="width: 100px;">*编码</th>
<th style="width: 150px;">*方法名称</th>
<th style="width: 150px;">关联检查类型</th>
<th style="width: 150px;">*执行科室</th>
<th style="width: 100px;">收费金额</th>
<th style="width: 100px;">序号</th>
<th style="width: 150px;">备注</th>
<th style="width: 120px;">操作</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in tableData"
:key="index"
:class="{ 'editing-row': item.editing }"
@click="handleRowClick(item)"
>
<td>{{ item.row }}</td>
<td>
<template v-if="item.editing">
<input type="text" placeholder="请输入编码" v-model="item.code">
</template>
<template v-else>
{{ item.code }}
</template>
</td>
<td>
<template v-if="item.editing">
<input type="text" placeholder="请输入方法名称" v-model="item.name">
</template>
<template v-else>
{{ item.name }}
</template>
</td>
<td>
<template v-if="item.editing">
<select v-model="item.type" :class="{ 'placeholder-text': !item.type }">
<option value="">选择关联检查类型</option>
<option
v-for="type in checkTypes"
:key="type"
:value="type"
>
{{ type }}
</option>
</select>
</template>
<template v-else>
<span v-if="item.type">{{ item.type }}</span>
<span v-else class="placeholder-text">选择关联检查类型</span>
</template>
</td>
<td>
<template v-if="item.editing">
<select v-model="item.department" :class="{ 'placeholder-text': !item.department }">
<option value="">选择执行科室</option>
<option
v-if="item.department"
:value="item.department"
>
{{ item.department }}
</option>
<option
v-for="dept in departments"
:key="dept.dictValue"
:value="dept.dictLabel"
>
{{ dept.dictLabel }}
</option>
</select>
</template>
<template v-else>
<span v-if="item.department">{{ item.department }}</span>
<span v-else class="placeholder-text">选择执行科室</span>
</template>
</td>
<td>
<template v-if="item.editing">
<input type="number" min="0" step="0.01" placeholder="请输入收费金额" v-model="item.amount">
</template>
<template v-else>
{{ item.amount || '0.00' }}
</template>
</td>
<td>
<template v-if="item.editing">
<input type="text" v-model="item.number">
</template>
<template v-else>
{{ item.number || '999999' }}
</template>
</td>
<td>
<template v-if="item.editing">
<input type="text" placeholder="请输入备注" v-model="item.remark">
</template>
<template v-else>
{{ item.remark || '' }}
</template>
</td>
<td class="actions">
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
</button>
<button class="btn btn-delete" @click.stop="handleDelete(index)">
🗑
</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<!-- 检查部位的表格视图 -->
<template v-else-if="activeMenu === '检查部位'">
<div class="header">
<h1>{{ activeMenu }}管理</h1>
<div class="header-actions">
<button class="btn btn-add-new" @click="handleAddNewRow">+
</button>
</div>
</div>
<div class="search-bar">
<div class="search-item">
<label>检查方法</label>
<el-select v-model="searchParams.checkMethod" placeholder="选择检查方法" style="width: 150px">
<el-option
v-for="method in checkMethods"
:key="method.code"
:label="method.name"
:value="method.code"
>
</el-option>
</el-select>
</div>
<div class="search-item">
<label>名称</label>
<el-input placeholder="名称/编码" v-model="searchParams.name" />
</div>
<div class="search-item">
<label>费用套餐</label>
<el-input placeholder="名称" v-model="searchParams.name" />
</div>
<div class="search-actions">
<el-button type="primary" @click="handleAddNewRow">新增</el-button>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
<el-button type="success" @click="handleExport">导出表格</el-button>
</div>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th style="width: 50px;"></th>
<th style="width: 100px;">*编码</th>
<th style="width: 150px;">*部位名称</th>
<th style="width: 120px;">优先级</th>
<th style="width: 100px;">是否可见</th>
<th style="width: 100px;">序号</th>
<th style="width: 150px;">备注</th>
<th style="width: 120px;">操作</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in tableData"
:key="index"
:class="{ 'editing-row': item.editing }"
@click="handleRowClick(item)"
>
<td>{{ item.row }}</td>
<td>
<template v-if="item.editing">
<input type="text" placeholder="请输入编码" v-model="item.code">
</template>
<template v-else>
{{ item.code }}
</template>
</td>
<td>
<template v-if="item.editing">
<input type="text" placeholder="请输入部位名称" v-model="item.name">
</template>
<template v-else>
{{ item.name }}
</template>
</td>
<td>
<template v-if="item.editing">
<input type="number" min="1" placeholder="请输入优先级" v-model="item.priority">
</template>
<template v-else>
{{ item.priority || '1' }}
</template>
</td>
<td>
<template v-if="item.editing">
<select v-model="item.visible">
<option value="1"></option>
<option value="0"></option>
</select>
</template>
<template v-else>
{{ item.visible === '1' ? '' : '' }}
</template>
</td>
<td>
<template v-if="item.editing">
<input type="text" v-model="item.number">
</template>
<template v-else>
{{ item.number || '999999' }}
</template>
</td>
<td>
<template v-if="item.editing">
<input type="text" placeholder="请输入备注" v-model="item.remark">
</template>
<template v-else>
{{ item.remark || '' }}
</template>
</td>
<td class="actions">
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
</button>
<button class="btn btn-delete" @click.stop="handleDelete(index)">
🗑
</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<!-- 分页区域 -->
<div class="pagination">
<button class="pagination-btn"></button>
<span>1</span>
<button class="pagination-btn"></button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { getDicts } from '@/api/system/dict/data';
import { listCheckType, listCheckMethod, listCheckPart, listCheckPackage, addCheckType, updateCheckType, delCheckType } from '@/api/system/checkType';
import PackageSettings from './components/PackageSettings.vue';
import PackageManagement from './components/PackageManagement.vue';
// 菜单数据
const menus = ['检查类型', '检查方法', '检查部位', '套餐设置'];
const activeMenu = ref('检查类型');
// 套餐视图状态: management-套餐管理列表, settings-套餐设置
const packageView = ref('management')
// 套餐设置模式: add-新增, edit-编辑, view-查看
const packageMode = ref('add')
// 当前编辑的套餐数据
const currentPackageData = ref(null)
// 检查类型和科室选项
const checkTypes = ref([]);
const checkMethods = ref([]);
const checkParts = ref([]);
const checkPackages = ref([]);
const departments = ref([]);
// 表格数据
const tableData = reactive([]);
// 搜索条件
const searchParams = reactive({
checkMethod: '',
name: '',
packageId: '',
checkPartCode: '',
checkPartName: '',
visible: ''
});
// 按钮悬停状态
const hoverAddButton = ref(false);
// 从数据库获取所有检查相关数据
onMounted(async () => {
try {
// 获取科室字典数据
const deptResponse = await getDicts('dept');
if (deptResponse && deptResponse.data) {
// 保存完整的科室字典数据,包含编码和名称
departments.value = deptResponse.data;
}
// 获取检查类型数据
const typeResponse = await listCheckType();
if (typeResponse && typeResponse.data) {
// 将数据库返回的检查类型数据转换为表格所需格式
const types = typeResponse.data;
// 获取所有不重复的检查类型值
checkTypes.value = [...new Set(types.map(item => item.type))];
// 构建表格数据
tableData.splice(0, tableData.length);
types.forEach((item, index) => {
tableData.push({
id: item.id, // 保存id字段用于判断是新增还是修改
row: (index + 1).toString(),
code: item.code,
name: item.name,
type: item.type,
selected: true,
department: item.department || '',
number: item.number || '999999',
remark: item.remark || '',
actions: true
});
});
}
// 获取检查方法数据
const methodResponse = await listCheckMethod();
if (methodResponse && methodResponse.data) {
checkMethods.value = methodResponse.data;
}
// 获取检查部位数据
const partResponse = await listCheckPart();
if (partResponse && partResponse.data) {
checkParts.value = partResponse.data;
}
// 获取检查套餐数据
const packageResponse = await listCheckPackage();
if (packageResponse && packageResponse.data) {
checkPackages.value = packageResponse.data;
}
} catch (error) {
console.error('获取数据失败:', error);
// 如果API调用失败显示友好提示
alert('获取检查类型数据失败,请检查网络或服务状态');
}
});
// 处理菜单点击
function handleMenuClick(menu) {
console.log('点击菜单:', menu);
console.log('当前activeMenu:', activeMenu.value);
activeMenu.value = menu;
console.log('更新后activeMenu:', activeMenu.value);
// 更新菜单激活状态
const menuItems = document.querySelectorAll('.menu-item');
menuItems.forEach(item => {
item.classList.remove('active');
if (item.textContent.trim() === menu) {
item.classList.add('active');
}
});
// 如果点击套餐设置,默认显示套餐设置界面
if (menu === '套餐设置') {
packageView.value = 'settings'
packageMode.value = 'add'
currentPackageData.value = null
console.log('显示套餐设置界面')
} else {
loadMenuData(menu);
}
}
// 从套餐设置切换到套餐管理界面
function handleSwitchToManagement() {
console.log('切换到套餐管理界面')
packageView.value = 'management'
}
// 从套餐管理切换到套餐设置界面(新增/编辑/查看)
function handleSwitchToSettings(params) {
console.log('切换到套餐设置界面:', params)
packageView.value = 'settings'
packageMode.value = params.mode
currentPackageData.value = params.data
}
// 保存成功后保持在套餐设置界面
function handleSaveSuccess() {
console.log('保存成功')
// 保存成功后保持在套餐设置界面,可以继续编辑或返回管理界面
ElMessage.success('保存成功')
}
// 根据菜单加载对应数据
async function loadMenuData(menu) {
try {
tableData.splice(0, tableData.length);
switch(menu) {
case '检查类型':
const typeResponse = await listCheckType();
if (typeResponse && typeResponse.data) {
// 获取所有不重复的检查类型值
checkTypes.value = [...new Set(typeResponse.data.map(item => item.type))];
typeResponse.data.forEach((item, index) => {
// 直接使用数据库中的department值不进行转换
tableData.push({
id: item.id, // 保存id字段用于判断是新增还是修改
row: (index + 1).toString(),
code: item.code,
name: item.name,
type: item.type,
selected: true,
department: item.department || '',
number: item.number || '999999',
remark: item.remark || '',
actions: true
});
});
}
break;
case '检查方法':
const methodResponse = await listCheckMethod();
if (methodResponse && methodResponse.data) {
methodResponse.data.forEach((item, index) => {
tableData.push({
id: item.id, // 保存id字段用于判断是新增还是修改
row: (index + 1).toString(),
code: item.code,
name: item.name,
type: item.type || '',
department: item.department || '',
amount: item.amount || '0.00',
number: item.number || '999999',
remark: item.remark || '',
actions: true
});
});
}
break;
case '检查部位':
// 构建检查部位的搜索参数
const partSearchParams = {
code: searchParams.checkPartCode,
name: searchParams.checkPartName,
visible: searchParams.visible
};
const partResponse = await listCheckPart(partSearchParams);
if (partResponse && partResponse.data) {
partResponse.data.forEach((item, index) => {
tableData.push({
id: item.id, // 保存id字段用于判断是新增还是修改
row: (index + 1).toString(),
code: item.code,
name: item.name,
priority: item.priority || '1',
visible: item.visible !== undefined ? String(item.visible) : '1',
number: item.number || '999999',
remark: item.remark || '',
actions: true
});
});
}
break;
case '套餐设置':
const packageResponse = await listCheckPackage();
if (packageResponse && packageResponse.data) {
}
break;
}
} catch (error) {
console.error('加载菜单数据失败:', error);
ElMessage.error(`加载${menu}数据失败,请检查网络或服务状态`);
}
}
// 处理行点击,进入编辑状态
function handleRowClick(item) {
if (!item.editing) {
item.editing = true;
}
}
// 处理确认按钮点击
async function handleConfirm(index) {
const item = tableData[index];
try {
// 根据是否有id判断是新增还是修改
if (item.id) {
// 修改操作
await updateCheckType(item);
} else {
// 新增操作
const newItem = await addCheckType(item);
// 将新增的id赋值给本地数据
item.id = newItem.id;
}
// 退出编辑状态
tableData[index].editing = false;
// 显示保存成功提示
alert(`${item.row} 行数据已保存`);
} catch (error) {
console.error('保存失败:', error);
alert('保存失败,请稍后重试');
}
}
// 处理删除按钮点击
async function handleDelete(index) {
if (confirm('确定要删除这一行吗?')) {
const item = tableData[index];
try {
// 如果有id调用API删除数据库中的数据
if (item.id) {
await delCheckType(item.id);
}
// 从数组中删除该行数据
tableData.splice(index, 1);
alert('删除成功!');
} catch (error) {
console.error('删除失败:', error);
alert('删除失败,请稍后重试');
}
}
}
// 处理添加新行按钮点击
function handleAddNewRow() {
// 获取当前最大行号,为新建行生成行号
const maxRowNum = Math.max(
0,
...tableData.map(item => {
// 处理子行编号,如"1.1"只取主行号"1"
const rowParts = item.row.split('.');
return parseInt(rowParts[0]) || 0;
})
);
let newRow;
// 根据当前激活的菜单生成不同的初始数据结构
if (activeMenu.value === '检查类型') {
newRow = {
row: String(maxRowNum + 1),
code: '',
name: '',
type: '',
selected: true,
department: '',
number: '999999',
remark: '',
editing: true, // 新行默认进入编辑状态
isNew: true, // 标记为新增行
actions: true
};
} else if (activeMenu.value === '检查方法') {
newRow = {
row: String(maxRowNum + 1),
code: '',
name: '',
type: '',
department: '',
amount: '0.00',
number: '999999',
remark: '',
editing: true, // 新行默认进入编辑状态
isNew: true, // 标记为新增行
actions: true
};
} else if (activeMenu.value === '检查部位') {
newRow = {
row: String(maxRowNum + 1),
code: '',
name: '',
priority: '1',
visible: '1',
number: '999999',
remark: '',
editing: true, // 新行默认进入编辑状态
isNew: true, // 标记为新增行
actions: true
};
} else {
// 默认数据结构
newRow = {
row: String(maxRowNum + 1),
code: '',
name: '',
type: '',
selected: true,
department: '',
number: '999999',
remark: '',
editing: true, // 新行默认进入编辑状态
isNew: true, // 标记为新增行
actions: true
};
}
tableData.push(newRow);
}
// 处理添加按钮点击
function handleAdd(index) {
const parentRow = tableData[index];
// 创建子行数据,继承父行的编码
const childRow = {
row: parentRow.row + '.1', // 子行编号
code: parentRow.code, // 继承父行编码
name: '',
type: '',
selected: false,
department: '',
number: '',
remark: '',
editing: true,
actions: false
};
// 在父行后插入子行
tableData.splice(index + 1, 0, childRow);
}
// 处理搜索功能
function handleSearch() {
console.log('搜索条件:', searchParams);
// 这里可以根据activeMenu和searchParams实现不同的搜索逻辑
ElMessage.info(`正在搜索${activeMenu.value}数据...`);
// 模拟搜索延迟
setTimeout(() => {
// 根据activeMenu执行相应的搜索逻辑
loadMenuData(activeMenu.value);
}, 300);
}
// 处理重置功能
function handleReset() {
// 重置所有搜索条件
searchParams.checkMethod = '';
searchParams.name = '';
searchParams.packageId = '';
searchParams.checkPartCode = '';
searchParams.checkPartName = '';
searchParams.visible = '';
ElMessage.info('搜索条件已重置');
}
// 处理导出表格功能
function handleExport() {
console.log('导出表格:', activeMenu.value);
ElMessage.success(`正在导出${activeMenu.value}数据,请稍候...`);
// 这里可以实现实际的导出逻辑
// 例如调用API或使用前端库生成Excel文件
}
</script>
<style scoped>
select {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right 8px center;
background-size: 14px;
padding-right: 28px;
}
.check-project-settings {
display: flex;
min-height: 100vh;
background-color: #f5f7fa;
color: #000000;
}
/* 左侧导航栏样式 */
.sidebar {
width: 160px;
background-color: #FFFFFF;
height: 100vh;
position: fixed;
left: 0;
top: 0;
padding: 16px 8px;
box-shadow: 1px 0 3px rgba(0, 0, 0, 0.05);
z-index: 10;
overflow-y: auto;
}
.menu-item {
display: block;
width: 100%;
padding: 8px 12px;
margin-bottom: 8px;
background-color: #FFFFFF;
color: #000000;
border-radius: 4px;
text-decoration: none;
font-size: 14px;
font-weight: 400;
line-height: 24px;
border: none;
cursor: pointer;
text-align: left;
transition: all 0.2s ease;
}
.menu-item:hover {
background-color: rgba(24, 144, 255, 0.1);
}
.menu-item.active {
background-color: #1890FF;
color: #FFFFFF;
}
/* 主内容区样式 */
.content {
flex: 1;
margin-left: 160px;
padding: 24px;
width: calc(100% - 160px);
height: 100vh;
overflow-x: auto;
overflow-y: auto;
box-sizing: border-box;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.header h1 {
font-size: 20px;
font-weight: 500;
color: #000000;
margin: 0;
}
/* 搜索栏样式 */
.search-bar {
background-color: #FFFFFF;
padding: 16px;
border-radius: 8px;
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
border: 1px solid #D9D9D9;
display: flex;
align-items: center;
gap: 16px;
}
.search-item {
display: flex;
align-items: center;
gap: 8px;
}
.search-item label {
font-size: 14px;
color: #000000;
white-space: nowrap;
}
.search-item select,
.search-item input {
width: 150px;
height: 32px;
padding: 0 8px;
border: 1px solid #D9D9D9;
border-radius: 4px;
font-size: 14px;
}
.search-actions {
margin-left: auto;
display: flex;
gap: 8px;
}
.search-actions .btn {
width: auto;
height: 32px;
padding: 0 16px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
border: none;
transition: all 0.2s ease;
}
.btn-purple {
background-color: #722ED1;
color: white;
}
.btn-blue {
background-color: #1890FF;
color: white;
}
.btn-default {
background-color: #FFFFFF;
color: #000000;
border: 1px solid #D9D9D9;
}
.btn-green {
background-color: #52C41A;
color: white;
}
.search-actions .btn:hover {
opacity: 0.85;
}
.header-actions {
display: flex;
gap: 10px;
}
.btn-add-new {
background-color: #409eff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s;
}
.btn-add-new:hover {
background-color: #66b1ff;
}
/* 表格样式 */
.table-container {
width: 100%;
overflow-x: auto;
background: #FFFFFF;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
border: 1px solid #D9D9D9;
}
table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
table-layout: fixed;
min-width: 1200px;
}
th {
background-color: #fafafa;
height: 40px;
padding: 8px 16px;
font-size: 14px;
font-weight: 500;
line-height: 24px;
text-align: left;
border-bottom: 1px solid #D9D9D9;
}
td {
padding: 8px 16px;
height: 40px;
font-size: 14px;
font-weight: 400;
line-height: 24px;
border-bottom: 1px solid #e8e8e8;
}
/* 操作按钮样式 */
.actions {
display: flex;
justify-content: flex-end;
gap: 8px;
}
.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;
}
.btn-confirm {
background-color: #1890FF;
color: white;
}
.btn-add {
background-color: #1890FF;
color: white;
}
.btn-delete {
background-color: #FF4D4F;
color: white;
font-size: 14px;
}
/* 特殊状态样式 */
.editing-row {
background-color: #E6F7FF;
cursor: text;
}
tr:not(.editing-row):hover {
background-color: rgba(24, 144, 255, 0.05);
cursor: pointer;
}
.child-row {
background-color: #f9f9f9;
}
.child-row td:first-child {
padding-left: 32px;
}
.checkbox-container {
display: flex;
justify-content: center;
}
input[type="checkbox"] {
width: 16px;
height: 16px;
}
input[type="text"], select {
height: 30px;
padding: 0 8px;
width: 100%;
border: 1px solid #D9D9D9;
border-radius: 4px;
font-size: 14px;
background-color: white;
color: #333;
}
input[type="text"]::placeholder {
color: #C0C4CC;
}
/* 分页样式 */
.pagination {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 16px 0;
margin-top: 8px;
}
.pagination span {
font-size: 14px;
margin: 0 16px;
}
.pagination-btn {
background: none;
border: 1px solid #D9D9D9;
border-radius: 4px;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s ease;
}
.pagination-btn:hover {
border-color: #1890FF;
color: #1890FF;
}
/* 禁用状态样式 */
.placeholder-text {
color: #C0C4CC;
}
/* 响应式设计 */
@media (max-width: 768px) {
.sidebar {
width: 60px;
}
.menu-item span {
display: none;
}
.content {
margin-left: 60px;
padding: 16px;
}
}
</style>