增加发票号码维护界面

This commit is contained in:
2025-12-17 10:39:19 +08:00
parent d85a8684a6
commit 19ecb65183
3 changed files with 261 additions and 111 deletions

View File

@@ -1,15 +1,43 @@
@import './variables.module.scss';
// Element Plus风格的颜色按钮样式
@mixin colorBtn($color) {
background: $color;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8px 16px;
font-size: 14px;
font-weight: 400;
line-height: 1;
white-space: nowrap;
text-align: center;
background-image: none;
border: 1px solid $color;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
box-sizing: border-box;
color: #fff;
background-color: $color;
&:hover {
color: $color;
&:hover,
&:focus {
background-color: lighten($color, 10%);
border-color: lighten($color, 10%);
color: #fff;
}
&:before,
&:after {
background: $color;
}
&:active {
background-color: darken($color, 5%);
border-color: darken($color, 5%);
color: #fff;
}
&:disabled {
color: #c0c4cc;
background-color: #f5f7fa;
border-color: #e4e7ed;
cursor: not-allowed;
}
}
@@ -42,42 +70,110 @@
}
.pan-btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8px 16px;
font-size: 14px;
color: #fff;
padding: 14px 36px;
border-radius: 8px;
font-weight: 400;
line-height: 1;
white-space: nowrap;
text-align: center;
background-image: none;
border: 1px solid #dcdfe6;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
box-sizing: border-box;
color: #606266;
background-color: #fff;
&:hover,
&:focus {
color: #409eff;
border-color: #c6e2ff;
background-color: #ecf5ff;
}
&:active {
color: #3a8ee6;
border-color: #3a8ee6;
background-color: #ecf5ff;
}
&:disabled {
color: #c0c4cc;
background-color: #f5f7fa;
border-color: #e4e7ed;
cursor: not-allowed;
}
}
// Element Plus风格的链接按钮样式
.pan-btn-link {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8px 16px;
font-size: 14px;
font-weight: 400;
line-height: 1;
white-space: nowrap;
text-align: center;
background-image: none;
border: none;
border-radius: 4px;
cursor: pointer;
transition: color 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
box-sizing: border-box;
background-color: transparent;
text-decoration: none;
outline: none;
transition: 600ms ease all;
position: relative;
display: inline-block;
&:hover {
background: #fff;
&:before,
&:after {
width: 100%;
transition: 600ms ease all;
}
&:hover,
&:focus {
text-decoration: underline;
}
&:before,
&:after {
content: '';
position: absolute;
top: 0;
right: 0;
height: 2px;
width: 0;
transition: 400ms ease all;
&:active {
opacity: 0.8;
}
&:disabled {
color: #c0c4cc;
cursor: not-allowed;
text-decoration: none;
}
}
&::after {
right: inherit;
top: inherit;
left: 0;
bottom: 0;
// 不同颜色的链接按钮
.blue-btn-link {
@extend .pan-btn-link;
color: #409eff;
&:hover,
&:focus {
color: #66b1ff;
}
}
.red-btn-link {
@extend .pan-btn-link;
color: #f56c6c;
&:hover,
&:focus {
color: #f78989;
}
}
.info-btn-link {
@extend .pan-btn-link;
color: #909399;
&:hover,
&:focus {
color: #a6a9ad;
}
}

View File

@@ -8,12 +8,12 @@
<!-- 操作按钮区域 -->
<div class="button-group">
<button @click="addNewRow" class="btn btn-primary">
<i class="icon-plus"></i> 添加新行
</button>
<button @click="saveData" class="btn btn-success" :disabled="saveButtonText === '保存中...'">
{{ saveButtonText }}
</button>
<button @click="addNewRow" class="pan-btn blue-btn">
<i class="icon-plus"></i> 添加新行
</button>
<button @click="saveData" class="pan-btn green-btn" :disabled="saveButtonText === '保存中...'">
{{ saveButtonText }}
</button>
</div>
<!-- 错误提示区域 -->
@@ -119,7 +119,7 @@
<button
v-if="!item.isActive"
@click="toggleEdit(item.keyId)"
class="btn btn-primary btn-sm mr-1"
class="pan-btn-link blue-btn-link"
title="编辑"
>
<i class="icon-edit"></i> 编辑
@@ -127,14 +127,14 @@
<button
v-if="item.isActive"
@click="toggleEdit(item.keyId)"
class="btn btn-secondary btn-sm mr-1"
class="pan-btn-link info-btn-link"
title="取消"
>
<i class="icon-cancel"></i> 取消
</button>
<button
@click="deleteRow(item)"
class="btn btn-danger btn-sm"
class="pan-btn-link red-btn-link"
title="删除"
>
<i class="icon-delete"></i> 删除
@@ -1262,6 +1262,7 @@ export default {
</script>
<style scoped>
@import '@/assets/styles/btn.scss';
.invoice-management {
padding: 20px;
min-height: 100vh;
@@ -1330,18 +1331,14 @@ export default {
flex-wrap: wrap;
}
.button-group .btn {
.button-group .pan-btn {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 6px 12px;
font-size: 14px;
font-weight: 500;
border-radius: 4px;
transition: all 0.2s ease;
}
.button-group .btn:hover {
.button-group .pan-btn:hover {
transform: translateY(-1px);
}
@@ -1472,9 +1469,7 @@ export default {
white-space: nowrap;
}
.action-buttons .btn {
padding: 4px 8px;
font-size: 12px;
.action-buttons .pan-btn {
margin-right: 4px;
}
@@ -1550,11 +1545,10 @@ export default {
gap: 6px;
}
.button-group .btn {
.button-group .pan-btn {
flex: 1;
justify-content: center;
min-width: 80px;
padding: 8px 12px;
}
.table-container {
@@ -1578,10 +1572,8 @@ export default {
gap: 4px;
}
.action-buttons .btn {
.action-buttons .pan-btn {
margin-right: 0;
padding: 4px 8px;
font-size: 11px;
}
.no-data-row {

View File

@@ -35,8 +35,10 @@
<thead>
<tr>
<th></th>
<th>*大类编码</th>
<th>*大类项目名称</th>
<th>*编码</th>
<th>*名称</th>
<th>*检查类型</th>
<th>选择部位</th>
<th>*执行科室</th>
<th>序号</th>
<th>备注</th>
@@ -66,6 +68,32 @@
{{ row.name }}
</template>
</td>
<td>
<template v-if="editingRowId === row.id">
<select v-model="row.type" :style="inputStyle">
<option value="">请选择检查类型</option>
<option value="超声">超声</option>
<option value="放射">放射</option>
<option value="病理">病理</option>
<option value="内镜">内镜</option>
<option value="心电图">心电图</option>
<option value="计算机断层扫描">计算机断层扫描</option>
<option value="数字放射成像">数字放射成像</option>
<option value="骨密度测定">骨密度测定</option>
<option value="动态血压">动态血压</option>
<option value="磁共振">磁共振</option>
<option value="胃肠镜">胃肠镜</option>
<option value="普放">普放</option>
<option value="内镜检查">内镜检查</option>
</select>
</template>
<template v-else>
{{ row.type || '-' }}
</template>
</td>
<td>
<input type="checkbox" v-model="row.selected" :disabled="editingRowId !== row.id">
</td>
<td>
<template v-if="editingRowId === row.id">
<el-tree-select
@@ -163,7 +191,7 @@
<!-- 检验项目页面 -->
<template v-else-if="activeNav === 1">
<div class="page-header">
<h2>项目管理</h2>
<h2>项目管理</h2>
</div>
<div class="header-actions">
<button class="add-new-btn" @click="addNewItem">
@@ -171,7 +199,7 @@
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
新增检项目
新增检项目
</button>
</div>
<div class="table-container">
@@ -181,7 +209,7 @@
<th></th>
<th>*项目编码</th>
<th>*项目名称</th>
<th>*类型</th>
<th>*类型</th>
<th>*执行科室</th>
<th>单位</th>
<th>价格</th>
@@ -330,14 +358,14 @@
<div class="form-item">
<span class="form-label">套餐类别</span>
<select class="form-control form-select">
<option value="1" selected>套餐</option>
<option value="1" selected>套餐</option>
</select>
</div>
<div class="form-item">
<span class="form-label">套餐类别</span>
<select class="form-control form-select" v-model="packageCategory" disabled>
<option value="检套餐">套餐</option>
<option value="检套餐">套餐</option>
</select>
</div>
<div class="form-item">
@@ -706,7 +734,19 @@ const navItems = ref(['检验类型', '检验项目', '套餐设置']);
const activeNav = ref(0);
// 检验类型数据
const tableData = ref([]);
const tableData = ref([
{ id: 1, code: '01', name: '彩超', type: '超声', selected: false, department: 'B超', sortOrder: 999999, remark: '' },
{ id: 2, code: '02', name: 'CT', type: '计算机断层扫描', selected: false, department: '放射科', sortOrder: 999999, remark: '' },
{ id: 3, code: '03', name: 'DR', type: '数字放射成像', selected: false, department: '放射科', sortOrder: 999999, remark: '' },
{ id: 4, code: '04', name: '心电图', type: '心电图', selected: false, department: '心电图室', sortOrder: 999999, remark: '' },
{ id: 5, code: '05', name: '骨密度测定', type: '超声', selected: false, department: '放射科', sortOrder: 999999, remark: '' },
{ id: 6, code: '06', name: '动态血压', type: '超声', selected: false, department: '心电图室', sortOrder: 999999, remark: '' },
{ id: 7, code: '07', name: '磁共', type: '磁共振', selected: false, department: '放射科', sortOrder: 999999, remark: '' },
{ id: 8, code: '08', name: '胃肠镜', type: '胃肠镜', selected: false, department: '内窥镜科室', sortOrder: 999999, remark: '' },
{ id: 9, code: '09', name: 'MR', type: '磁共振', selected: false, department: '放射科', sortOrder: 999999, remark: '' },
{ id: 10, code: '10', name: 'OT', type: '普放', selected: false, department: '放射科', sortOrder: 999999, remark: '' },
{ id: 11, code: '16', name: '妇科', type: '内镜检查', selected: false, department: '内窥镜科室', sortOrder: 9999, remark: '' }
]);
// 获取检验类型列表 - 从后端API获取
const getInspectionTypeList = () => {
@@ -726,7 +766,7 @@ const getInspectionTypeList = () => {
});
};
const editingRowId = ref(null);
const inputStyle = { width: '100%', height: '28px', padding: '0 4px', border: '1px solid #d9d9d9', borderRadius: '2px' };
const inputStyle = { width: '100%', height: '30px', padding: '0 4px', border: '1px solid #d9d9d9', borderRadius: '4px' };
const departments = ref([]);
/** 查询就诊科室 - 与门诊挂号页面保持一致 */
@@ -1101,7 +1141,7 @@ const handleSelectPackage = (item) => {
// 检验类型相关方法
const addNewRow = () => {
const newRow = { id: Date.now(), code: '', name: '', department: departments.value[0], sortOrder: tableData.value.length + 1, remark: '' };
const newRow = { id: Date.now(), code: '', name: '', type: '', selected: false, department: departments.value[0], sortOrder: tableData.value.length + 1, remark: '' };
tableData.value.push(newRow);
editingRowId.value = newRow.id;
};
@@ -1132,6 +1172,11 @@ const handleConfirm = (row) => {
return;
}
if (!submitData.type || submitData.type.trim() === '') {
alert('检查类型不能为空');
return;
}
if (!submitData.department || submitData.department.trim() === '') {
alert('执行科室不能为空');
return;
@@ -1190,7 +1235,8 @@ const handleConfirm = (row) => {
};
const handleAdd = (row, index) => {
const newRow = { id: Date.now(), code: '', name: '', department: row.department, sortOrder: row.sortOrder + 0.5, remark: '' };
// 子行继承主行编码,并添加子序号
const newRow = { id: Date.now(), code: row.code, name: '', type: row.type, selected: false, department: row.department, sortOrder: row.sortOrder + 0.5, remark: '' };
tableData.value.splice(index + 1, 0, newRow);
editingRowId.value = newRow.id;
};
@@ -1198,38 +1244,48 @@ const handleAdd = (row, index) => {
const handleDelete = (id) => {
console.log('删除按钮被点击原始ID:', id, '类型:', typeof id);
// 确保ID是数字类型
const numericId = Number(id);
console.log('转换后的ID:', numericId, '类型:', typeof numericId);
// 判断是否为临时ID临时ID是通过Date.now()生成的值很大通常大于2000000000000
const isTemporaryId = numericId > 2e12;
console.log('是否为临时ID:', isTemporaryId, '判断阈值:', 2e12);
if (!isTemporaryId) { // 真实数据库ID
console.log('调用删除APIID:', numericId, 'API路径:', `/system/inspection-type/${numericId}`);
delInspectionType(numericId).then(response => {
console.log('删除成功,响应:', response);
// 二次确认对话框
ElMessageBox.confirm('确定要删除该检查类型吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 确保ID是数字类型
const numericId = Number(id);
console.log('转换后的ID:', numericId, '类型:', typeof numericId);
// 判断是否为临时ID临时ID是通过Date.now()生成的值很大通常大于2000000000000
const isTemporaryId = numericId > 2e12;
console.log('是否为临时ID:', isTemporaryId, '判断阈值:', 2e12);
if (!isTemporaryId) { // 真实数据库ID
console.log('调用删除APIID:', numericId, 'API路径:', `/system/inspection-type/${numericId}`);
delInspectionType(numericId).then(response => {
console.log('删除成功,响应:', response);
ElMessage.success('删除成功');
getInspectionTypeList();
}).catch(error => {
console.error('删除检验类型失败:', error);
ElMessage.error('删除失败: ' + (error.response?.data?.msg || '未知错误'));
if (error.response) {
console.error('响应状态:', error.response.status);
console.error('响应数据:', error.response.data);
} else if (error.request) {
console.error('请求发送但未收到响应:', error.request);
} else {
console.error('请求配置错误:', error.message);
}
});
} else {
// 删除临时新增的行
console.log('删除临时行ID:', numericId);
tableData.value = tableData.value.filter(row => Number(row.id) !== numericId);
ElMessage.success('删除成功');
getInspectionTypeList();
}).catch(error => {
console.error('删除检验类型失败:', error);
ElMessage.error('删除失败: ' + (error.response?.data?.msg || '未知错误'));
if (error.response) {
console.error('响应状态:', error.response.status);
console.error('响应数据:', error.response.data);
} else if (error.request) {
console.error('请求发送但未收到响应:', error.request);
} else {
console.error('请求配置错误:', error.message);
}
});
} else {
// 删除临时新增的行
console.log('删除临时行ID:', numericId);
tableData.value = tableData.value.filter(row => Number(row.id) !== numericId);
ElMessage.success('删除成功');
}
}
}).catch(() => {
// 取消删除操作
console.log('用户取消删除');
});
};
// 检验项目相关方法
@@ -1331,7 +1387,7 @@ watch(packageItems, (newVal) => {
/* 左侧导航 */
.side-nav {
width: 200px;
width: 160px;
background-color: #fff;
box-shadow: 1px 0 5px rgba(0, 0, 0, 0.05);
padding: 20px 0;
@@ -1366,12 +1422,12 @@ watch(packageItems, (newVal) => {
/* 页面标题 */
.page-header {
margin-bottom: 20px;
margin-bottom: 24px;
}
.page-header h2 {
font-size: 18px;
font-weight: 600;
font-size: 20px;
font-weight: 500;
color: #333;
}
@@ -1421,6 +1477,8 @@ watch(packageItems, (newVal) => {
padding: 0 12px;
text-align: left;
border-bottom: 1px solid #f0f0f0;
font-size: 14px;
line-height: 24px;
}
.data-table th {
@@ -1449,7 +1507,7 @@ watch(packageItems, (newVal) => {
.action-btn {
width: 24px;
height: 24px;
border-radius: 4px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
@@ -1486,14 +1544,18 @@ watch(packageItems, (newVal) => {
/* 分页 */
.pagination {
display: flex;
justify-content: center;
justify-content: flex-end;
align-items: center;
gap: 8px;
margin-top: 20px;
}
.page-btn {
padding: 6px 12px;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #d9d9d9;
border-radius: 4px;
cursor: pointer;
@@ -1670,11 +1732,11 @@ watch(packageItems, (newVal) => {
.data-table input,
.data-table select {
width: 100%;
height: 28px;
height: 30px;
padding: 0 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 12px;
font-size: 14px;
box-sizing: border-box;
}