Files
his/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/index.vue
2025-11-24 16:19:46 +08:00

697 lines
18 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">
<div class="header">
<h1>检查类型管理</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>
{{ item.type || '<span 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>
{{ item.department || '<span 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>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { getDicts } from '@/api/system/dict/data';
import { listCheckType, listCheckMethod, listCheckPart, listCheckPackage, addCheckType, updateCheckType, delCheckType } from '@/api/system/checkType';
// 菜单数据
const menus = ['检查类型', '检查方法', '检查部位', '套餐设置'];
const activeMenu = ref('检查类型');
// 检查类型和科室选项
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) {
activeMenu.value = menu;
// 根据菜单切换,重新加载对应数据
loadMenuData(menu);
}
// 根据菜单加载对应数据
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>