新增体检套餐界面相关,修改基础项目界面查询字段

This commit is contained in:
Euni4U 2025-02-17 17:59:16 +08:00
parent f0dd8d7e3b
commit c0b99c2ba2
8 changed files with 642 additions and 40 deletions

View File

@ -0,0 +1,42 @@
import request from '@/config/axios'
// 体检套餐 VO
export interface ExammoduleVO {
id: number // 主键
examModuleName: string // 套餐名称
examModuleID: number // 套餐ID
itemCode: string // 项目ID
}
// 体检套餐 API
export const ExammoduleApi = {
// 查询体检套餐分页
getExammodulePage: async (params: any) => {
return await request.get({ url: `/inspect/exammodule/page`, params })
},
// 查询体检套餐详情
getExammodule: async (id: number) => {
return await request.get({ url: `/inspect/exammodule/get?id=` + id })
},
// 新增体检套餐
createExammodule: async (data: ExammoduleVO) => {
return await request.post({ url: `/inspect/exammodule/create`, data })
},
// 修改体检套餐
updateExammodule: async (data: ExammoduleVO) => {
return await request.put({ url: `/inspect/exammodule/update`, data })
},
// 删除体检套餐
deleteExammodule: async (id: number) => {
return await request.delete({ url: `/inspect/exammodule/delete?id=` + id })
},
// 导出体检套餐 Excel
exportExammodule: async (params) => {
return await request.download({ url: `/inspect/exammodule/export-excel`, params })
},
}

View File

@ -12,7 +12,7 @@ export interface DepartmentVO {
deletePerson: string // 删除操作人
deleteDate: Date // 删除时间
departmentAddress: string // 科室具体位置
orgId: string // 机构ID
sectionID: string // 科室ID
}
export interface InspectDepartmentRespVO {

View File

@ -17,6 +17,7 @@ export interface itemsVO {
createTime: Date // 创建时间
moduleID: number // 模块ID体检单元ID 模块名称ID
moduleName: string // 模块名称:体检单元
sectionID: string // 科室ID
}
// 检查项目 API

View File

@ -22,7 +22,7 @@
v-for="item in departmentOptions"
:key="item.value"
:label="item.label"
:value="item.value"
:value="item.value + '|' + item.label"
/>
</el-select>
</el-form-item>
@ -139,7 +139,8 @@ const formData = ref<Partial<itemsVO>>({
moduleName: '',
highValue: undefined,
lowValue: undefined,
moduleID: undefined
moduleID: undefined,
sectionID: ''
})
//
@ -176,6 +177,11 @@ const handleSubmit = async () => {
formData.value.moduleName = moduleName.split('|')[0]
formData.value.moduleID = parseInt(moduleName.split('|')[1])
}
if (formData.value.section) {
const section = formData.value.section
formData.value.section = section.split('|')[0]
formData.value.sectionID = section.split('|')[1]
}
await itemsApi.createitems(formData.value as itemsVO)
ElMessage.success('添加成功')
handleClose()

View File

@ -14,7 +14,7 @@
v-for="item in departmentOptions"
:key="item.value"
:label="item.label"
:value="item.value"
:value="item.label + '|' + item.value"
/>
</el-select>
</el-form-item>
@ -137,7 +137,7 @@ const getDepartmentList = async () => {
try {
const data = await DepartmentApi.getListDepartment()
departmentOptions.value = data.map((item: DepartmentVO) => ({
value: item.departmentName,
value: item.departmentCode,
label: item.departmentName
}))
} catch (error) {
@ -158,6 +158,13 @@ const handleSubmit = async () => {
formData.value.moduleName = moduleName.split('|')[0]
formData.value.moduleID = parseInt(moduleName.split('|')[1])
}
if (formData.value.section) {
const section = formData.value.section
formData.value.section = section.split('|')[0]
formData.value.sectionID = section.split('|')[1]
}
console.log('section', formData.value.sectionID)
await itemsApi.updateitems(formData.value as itemsVO)
ElMessage.success('修改成功')
handleClose()

View File

@ -0,0 +1,243 @@
<template>
<div class="search-item">
<span class="label">项目名称</span>
<el-input
v-model="searchForm.keyword"
placeholder="请输入项目名称"
clearable
filterable
/>
</div>
<div class="search-item">
<span class="label">所属科室</span>
<el-select
v-model="searchForm.department"
placeholder="请选择科室"
clearable
filterable
>
<el-option
v-for="item in departmentOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button type="primary" @click="save">保存</el-button>
<el-button type="danger" @click="handleDelete">删除选中</el-button>
<el-button type="danger" @click="handleClear">清空列表</el-button>
</div>
<el-table
:data="tableData"
border
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55"/>
<el-table-column prop="itemName" label="项目名称"/>
<el-table-column prop="price" label="销售价(元)"/>
<el-table-column prop="discountedPrice" label="折扣价(元)"/>
<el-table-column prop="discounted" label="折扣百分比"/>
<el-table-column prop="unit" label="单位"/>
<el-table-column prop="moduleName" label="模块单元"/>
</el-table>
<!-- 分页 -->
<div class="pagination-container">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 30, 50]"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script setup lang="ts">
import { ExammoduleApi } from '@/api/inspect/exammodule'
import { DepartmentApi, DepartmentVO } from '@/api/inspect/inspectdepartment/index'
import { ElMessage, ElMessageBox } from 'element-plus'
import { itemsApi } from '@/api/inspect/inspectitems/index'
//
async function handleSearch() {
const queryParams: any = {
pageNum: currentPage.value,
pageSize: pageSize.value
}
//
const keyword = searchForm.keyword?.trim()
if (keyword) {
queryParams.itemName = keyword // 使itemName
}
if (searchForm.department) {
queryParams.sectionID = searchForm.department // 使section
}
console.log('查询参数:', queryParams) //
try {
const res = await itemsApi.getitemsPage(queryParams)
console.log('查询结果:', res)
if (res) {
tableData.value = res.list || []
total.value = res.total || 0
}
} catch (error) {
console.error('查询失败:', error)
ElMessage.error('查询失败')
tableData.value = []
total.value = 0
}
}
const searchForm = reactive({
keyword: '',
department: ''
})
const tableData = ref([])
const departmentOptions = ref()
const getDepartmentList = async () => {
try {
const data = await DepartmentApi.getListDepartment()
departmentOptions.value = data.map((item: DepartmentVO) => ({
value: item.departmentCode,
label: item.departmentName
}))
} catch (error) {
console.error('获取科室列表失败:', error)
ElMessage.error('获取科室列表失败')
}
}
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
//
const save = () => {
console.log(tableData.value)
}
const handleSizeChange = (val: number) => {
pageSize.value = val
handleSearch()
}
const handleCurrentChange = (val: number) => {
currentPage.value = val
handleSearch()
}
//
const selectedRows = ref([])
//
const handleSelectionChange = (selection: any[]) => {
selectedRows.value = selection
}
//
const handleDelete = () => {
if (selectedRows.value.length === 0) {
ElMessage.warning('请选择要删除的数据')
return
}
ElMessageBox.confirm('确认从列表中移除选中的数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//
const selectedIndices = selectedRows.value.map(row =>
tableData.value.findIndex(item => item === row)
)
//
selectedIndices.sort((a, b) => b - a).forEach(index => {
if (index !== -1) {
tableData.value.splice(index, 1)
}
})
ElMessage.success('移除成功')
}).catch(() => {})
}
const handleClear = () => {
ElMessageBox.confirm('确认清空列表数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
tableData.value = []
total.value = 0
ElMessage.success('清空成功')
}).catch(() => {})
}
onMounted(() => {
getDepartmentList()
})
</script>
<style lang="scss" scoped>
.exam-package-content {
background: #fff;
height: 100%;
display: flex;
flex-direction: column;
.search-item {
margin-bottom: 10px;
display: flex;
align-items: center;
.label {
width: 80px;
text-align: right;
margin-right: 10px;
}
.el-input,
.el-select {
flex: 1;
}
.el-button {
margin-left: 10px; /* 添加按钮间距 */
}
}
.el-table {
flex: 1;
padding: 0 20px;
}
.pagination-area {
padding: 10px 20px;
text-align: right;
position: absolute;
bottom: 70px;
right: 0;
width: 100%;
}
.footer {
padding: 20px;
text-align: right;
background: #fff;
border-top: 1px solid #e8e8e8;
position: absolute;
bottom: 0;
width: 100%;
}
}
</style>

View File

@ -8,8 +8,21 @@
v-model="searchKeyword"
placeholder="请输入关键字"
:prefix-icon="Search"
@input="handleSearch"
/>
</div>
<!-- 添加套餐列表展示 -->
<div class="package-list">
<div
v-for="item in filteredPackageList"
:key="item.id"
class="package-item"
:class="{ active: selectedPackage?.id === item.id }"
@click="handleSelectPackage(item)"
>
<div class="package-name">{{ item.examModuleName }}</div>
</div>
</div>
</div>
<!-- 原有的右侧内容 -->
@ -21,7 +34,7 @@
<el-button type="primary" @click="handleDelete">
<el-icon><Delete /></el-icon>
</el-button>
<el-button type="primary" @click="handleAddItem">
<el-button type="primary" @click="openDrawer">
<el-icon><Plus /></el-icon>
</el-button>
<el-button type="primary" @click="handleSubmit">
@ -31,36 +44,18 @@
<div class="search-form">
<el-form :inline="true" :model="searchForm">
<el-form-item label="套餐类别" required>
<el-select v-model="searchForm.packageType" placeholder="请选择" style="width: 200px">
<el-option label="全部" value="" />
<el-option label="职业体检" value="职业"/>
<el-option label="健康体检" value="健康"/>
<el-option label="从业体检" value="从业"/>
<el-option label="放射体检" value="放射"/>
</el-select>
</el-form-item>
<el-form-item label="适合性别" required>
<el-select v-model="searchForm.gender" placeholder="请选择" style="width: 200px">
<el-option label="全部" value="" />
<el-option label="男" value="男"/>
<el-option label="女" value="女"/>
</el-select>
<el-form-item label="套餐编号" required>
<el-input v-model="searchForm.name" placeholder="请输入" style="width: 200px" />
</el-form-item>
<el-form-item label="套餐名称" required>
<el-input v-model="searchForm.name" placeholder="请输入" style="width: 200px"/>
</el-form-item>
<el-form-item label="简拼" required>
<el-input v-model="searchForm.pinyin" placeholder="请输入" style="width: 200px"/>
<el-input v-model="searchForm.name" placeholder="请输入" style="width: 200px" />
</el-form-item>
</el-form>
</div>
<el-table :data="tableData" border style="width: 100%">
<el-table-column type="selection" width="55" />
<el-table-column label="#" type="index" width="50" />
<el-table-column prop="name" label="名称" />
<el-table-column prop="pinyin" label="简拼" />
<el-table-column prop="price" label="销售价(元)" />
<el-table-column prop="discount" label="折扣(%)" />
<el-table-column prop="discountPrice" label="折扣价(元)" />
@ -86,20 +81,35 @@
background
/>
</div>
<NewPackage ref="newPackageRef" @refresh-list="refreshList" />
<el-drawer
v-model="drawer"
title="套餐项目"
size="30%"
:destroy-on-close="true"
>
<Drawer/>
</el-drawer>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { Plus, Delete, Upload, Search } from '@element-plus/icons-vue'
<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
import { Plus, Delete, Upload, Search, Picture, PictureFilled } from '@element-plus/icons-vue'
import NewPackage from './new.vue'
import { ExammoduleApi } from '@/api/inspect/exammodule'
import { ElMessage } from 'element-plus'
import Drawer from './drawer.vue'
//
const searchKeyword = ref('')
// type
const searchForm = reactive({
type: '', //
type: '', //
packageType: '',
gender: '',
name: '',
@ -114,9 +124,67 @@ const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
const newPackageRef = ref(null) //
//
const packageList = ref([])
const selectedPackage = ref(null)
//
const filteredPackageList = computed(() => {
if (!searchKeyword.value) return packageList.value
return packageList.value.filter(item =>
item.examModuleID.toString().includes(searchKeyword.value) ||
item.examModuleName.includes(searchKeyword.value)
)
})
//
const getPackageList = async () => {
try {
const res = await ExammoduleApi.getExammodulePage({
pageNo: 1,
pageSize: 100
})
// res.list
if (res?.list) {
packageList.value = res.list
} else {
packageList.value = []
console.warn('获取套餐列表数据结构异常:', res)
}
} catch (error) {
console.error('获取套餐列表失败:', error)
packageList.value = []
}
}
//
const handleSelectPackage = (item) => {
selectedPackage.value = item
//
}
//
const handleSearch = () => {
// filteredPackageList
}
//
onMounted(() => {
getPackageList()
})
//
const handleAdd = () => {
//
const handleAdd = async () => {
await newPackageRef.value.open()
await getPackageList() //
}
//
const refreshList = async () => {
await getPackageList() //
}
const handleDelete = (row) => {
@ -138,12 +206,18 @@ const handleEdit = (row) => {
//
const handleSizeChange = (val) => {
pageSize.value = val
//
getPackageList()
}
const handleCurrentChange = (val) => {
currentPage.value = val
//
getPackageList()
}
const drawer = ref(false)
const openDrawer = () => {
drawer.value = true
}
</script>
@ -220,13 +294,13 @@ const handleCurrentChange = (val) => {
.pagination-container {
margin-top: 20px;
display: flex;
justify-content: flex-end; /* 内容靠右对齐 */
padding: 15px 20px; /* 增加左右内边距 */
justify-content: flex-end; /* 内容靠右对齐 */
padding: 15px 20px; /* 增加左右内边距 */
background-color: #fff;
}
.el-pagination {
justify-content: flex-end; /* 分页组件内部靠右对齐 */
justify-content: flex-end; /* 分页组件内部靠右对齐 */
}
/* 可选:美化分页样式 */
@ -240,4 +314,81 @@ const handleCurrentChange = (val) => {
flex: 1;
overflow-y: auto;
}
/* 添加套餐列表样式 */
.package-list {
margin-top: 10px;
}
.package-item {
padding: 10px;
border-bottom: 1px solid #eee;
cursor: pointer;
transition: background-color 0.3s;
}
.package-item:hover {
background-color: #f5f7fa;
}
.package-item.active {
background-color: #ecf5ff;
}
.package-code {
font-size: 14px;
color: #666;
margin-bottom: 5px;
}
.package-name {
font-size: 14px;
color: #333;
}
.drawer-content {
padding: 20px;
}
.image-container {
width: 100%;
height: 60vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #f5f7fa;
border-radius: 8px;
overflow: hidden;
}
.el-image {
max-width: 100%;
max-height: 100%;
}
.image-slot {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
color: #909399;
}
.description {
margin-top: 20px;
padding: 20px;
background-color: #f5f7fa;
border-radius: 8px;
}
.description h3 {
margin-bottom: 10px;
color: #303133;
}
.description p {
color: #606266;
line-height: 1.6;
}
</style>

View File

@ -0,0 +1,152 @@
<template>
<el-dialog v-model="visible" title="新增套餐" width="25%">
<el-form :model="formData" :rules="rules" ref="newPackageRef" label-width="80px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="套餐编号" prop="packageCode" required>
<el-input
v-model="formData.packageCode"
placeholder="请输入整数"
@input="handlePackageCodeInput"
maxlength="20"
>
<template #suffix>
<el-tooltip
content="只能输入整数"
placement="top"
effect="light"
>
<el-icon><InfoFilled /></el-icon>
</el-tooltip>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="套餐名称" prop="packageName" required>
<el-input v-model="formData.packageName" placeholder="请输入" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'
import { ExammoduleApi } from '@/api/inspect/exammodule/index'
import { InfoFilled } from '@element-plus/icons-vue'
const newPackageRef = ref(null)
const visible = ref(false)
const formData = reactive({
packageType: '',
suitableGender: '',
packageCode: '',
packageName: '',
examModuleName: '',
examModuleID: 0,
itemCode: ''
})
const handlePackageCodeInput = (value) => {
//
formData.packageCode = value.replace(/[^\d]/g, '')
}
const rules = {
packageCode: [
{ required: true, message: '请输入套餐编号', trigger: 'blur' },
{
validator: (rule, value, callback) => {
if (value && (!Number.isInteger(Number(value)) || isNaN(Number(value)))) {
callback(new Error('套餐编号必须为整数'))
} else {
callback()
}
},
trigger: 'blur'
},
{
validator: async (rule, value, callback) => {
if (!value) return callback()
const result = await ExammoduleApi.createExammodule({
examModuleName: formData.packageName,
examModuleID: Number(value),
itemCode: value,
})
if (result === 999) {
callback(new Error('套餐编号已存在'))
} else {
callback()
}
},
trigger: 'blur'
}
],
packageName: [{ required: true, message: '请输入套餐名称', trigger: 'blur' }]
}
const open = async () => {
//
Object.keys(formData).forEach(key => {
formData[key] = ''
})
// undefined
formData.examModuleID = undefined
//
if (newPackageRef.value) {
newPackageRef.value.resetFields()
}
visible.value = true
}
const handleSubmit = async () => {
if (!newPackageRef.value) return
try {
await newPackageRef.value.validate()
ElMessage.success('新增套餐成功')
visible.value = false
emit('refresh-list')
} catch (error) {
console.error('提交失败', error)
ElMessage.error('新增套餐失败')
}
}
// emit
const emit = defineEmits(['refresh-list'])
defineExpose({ open })
</script>
<style scoped>
.exam-form {
padding: 20px;
}
:deep(.el-form-item) {
margin-bottom: 18px;
}
:deep(.el-input),
:deep(.el-select) {
width: 240px;
}
.dialog-footer {
text-align: right;
}
</style>