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

772 lines
20 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-else>
<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>
<!-- 分页区域 -->
<div class="pagination">
<button class="pagination-btn"></button>
<span>1</span>
<button class="pagination-btn"></button>
</div>
</template>
</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([]);
// 从数据库获取所有检查相关数据
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({
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) {
}
break;
case '检查部位':
const partResponse = await listCheckPart();
if (partResponse && partResponse.data) {
}
break;
case '套餐设置':
const packageResponse = await listCheckPackage();
if (packageResponse && packageResponse.data) {
}
break;
}
} catch (error) {
console.error('加载菜单数据失败:', error);
alert(`加载${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 newRowNumber = tableData.length + 1;
// 添加新行数据
tableData.push({
row: newRowNumber.toString(),
code: '',
name: '',
type: '',
selected: true,
department: '',
number: '999999',
remark: '',
actions: true,
editing: true, // 新行默认进入编辑状态
isNew: true // 标记为新增行
});
}
// 处理添加按钮点击
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);
}
</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;
}
.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;
}
.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>