修改树形展示

This commit is contained in:
Euni4U 2025-03-28 16:50:00 +08:00
parent 19c47c79a0
commit ae8b5756c3
3 changed files with 284 additions and 98 deletions

View File

@ -1,45 +1,55 @@
import request from '@/config/axios'
// 汇总模板 VO
export interface TemplateVO {
id: number // 主键id
type: string // 类型
status: string // 状态
content: string // 模板内容
orderNum: number // 排序
createId: string // 创建人
contentName: string // 模板名称
}
// 汇总模板 API
export const TemplateApi = {
// 查询汇总模板分页
getTemplatePage: async (params: any) => {
return await request.get({ url: `/inspect/template/page`, params })
},
// 查询汇总模板详情
getTemplate: async (id: number) => {
return await request.get({ url: `/inspect/template/get?id=` + id })
},
// 新增汇总模板
createTemplate: async (data: TemplateVO) => {
return await request.post({ url: `/inspect/template/create`, data })
},
// 修改汇总模板
updateTemplate: async (data: TemplateVO) => {
return await request.put({ url: `/inspect/template/update`, data })
},
// 删除汇总模板
deleteTemplate: async (id: number) => {
return await request.delete({ url: `/inspect/template/delete?id=` + id })
},
// 导出汇总模板 Excel
exportTemplate: async (params) => {
return await request.download({ url: `/inspect/template/export-excel`, params })
},
}
import request from '@/config/axios'
// 汇总模板 VO
export interface TemplateVO {
id: number // 主键id
type: string // 类型
status: string // 状态
content: string // 模板内容
orderNum: number // 排序
createId: string // 创建人
contentName: string // 模板名称
category: string // 模板类别
}
// 汇总模板 API
export const TemplateApi = {
// 查询汇总模板分页
getTemplatePage: async (params: any) => {
return await request.get({ url: `/inspect/template/page`, params })
},
// 查询汇总模板详情
getTemplate: async (id: number) => {
return await request.get({ url: `/inspect/template/get?id=` + id })
},
// 新增汇总模板
createTemplate: async (data: TemplateVO) => {
return await request.post({ url: `/inspect/template/create`, data })
},
// 修改汇总模板
updateTemplate: async (data: TemplateVO) => {
return await request.put({ url: `/inspect/template/update`, data })
},
// 删除汇总模板
deleteTemplate: async (id: number) => {
return await request.delete({ url: `/inspect/template/delete?id=` + id })
},
// 导出汇总模板 Excel
exportTemplate: async (params) => {
return await request.download({ url: `/inspect/template/export-excel`, params })
},
//根据模版类型获取所属模版类别
getCategory: async (type: string) => {
return await request.get({ url: `/inspect/template/getcategory?type=` + type })
},
// 获取所有模板类别
getAllCategories: async () => {
return await request.get({ url: `/inspect/template/getAllCategories` })
},
}

View File

@ -7,11 +7,8 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="模板名称" prop="contentName">
<el-input v-model="formData.contentName" placeholder="请输入模板名称" />
</el-form-item>
<el-form-item label="模板类型" prop="type">
<el-select v-model="formData.type" placeholder="请选择模板类型">
<el-form-item label="模板类型" prop="type">
<el-select v-model="formData.type" placeholder="请选择模板类型" clearable>
<el-option label="一般检查" value="一般检查" />
<el-option label="超声" value="超声" />
<el-option label="心电图" value="心电图" />
@ -22,6 +19,15 @@
<el-option label="汇总" value="汇总" />
</el-select>
</el-form-item>
<el-form-item label="模板类别" prop="category">
<el-select v-model="formData.category" placeholder="请选择模板类别" clearable :loading="loadingCategories">
<el-option v-for="item in categoryOptions" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="模板名称" prop="contentName">
<el-input v-model="formData.contentName" placeholder="请输入模板名称" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio-button label="启用" value="1" />
@ -48,6 +54,7 @@
</template>
<script setup lang="ts">
import { TemplateApi, TemplateVO } from '@/api/inspect/inspecttemplate'
import { watch } from 'vue'
/** 汇总模板 表单 */
defineOptions({ name: 'TemplateForm' })
@ -67,22 +74,66 @@ const formData = ref({
orderNum: undefined,
createId: undefined,
contentName: undefined,
category: undefined,
})
const formRules = reactive({
})
const formRef = ref() // Ref
//
const categoryOptions = ref([])
//
const loadingCategories = ref(false)
//
watch(() => formData.value.type, async (newType) => {
if (newType) {
await loadCategoryOptions(newType)
} else {
//
categoryOptions.value = []
formData.value.category = undefined
}
})
//
const loadCategoryOptions = async (type) => {
if (!type) return
loadingCategories.value = true
//
// formData.value.category = undefined
try {
//
categoryOptions.value = await TemplateApi.getCategory(type)
} catch (error) {
console.error('加载类别选项失败', error)
message.error('加载类别选项失败')
categoryOptions.value = []
} finally {
loadingCategories.value = false
}
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await TemplateApi.getTemplate(id)
const templateData = await TemplateApi.getTemplate(id)
//
if (templateData.type) {
await loadCategoryOptions(templateData.type)
}
//
formData.value = templateData
} finally {
formLoading.value = false
}
@ -124,6 +175,7 @@ const resetForm = () => {
orderNum: undefined,
createId: undefined,
contentName: undefined,
category: undefined,
}
formRef.value?.resetFields()
}

View File

@ -28,6 +28,23 @@
class="!w-240px"
/>
</el-form-item>
<el-form-item label="模板类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择模板类型" clearable class="!w-240px">
<el-option label="一般检查" value="一般检查" />
<el-option label="超声" value="超声" />
<el-option label="心电图" value="心电图" />
<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="模板类别" prop="category">
<el-select v-model="queryParams.category" placeholder="请选择模板类别" clearable class="!w-240px">
<el-option v-for="item in categoryOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@ -51,53 +68,50 @@
</el-form>
</ContentWrap>
<!-- 列表 -->
<!-- 树形结构展示 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
:header-cell-style="{ background: 'rgb(235, 241, 250)', height: '56px',color:'#333333' }"
:row-style="{ height: '56px' }"
>
<el-table-column label="主键" align="center" prop="id" v-if="false" />
<el-table-column label="模板名称" align="center" prop="contentName" />
<el-table-column label="模板内容" align="center" prop="content" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<el-tag :type="scope.row.status === '1' ? 'success' : 'danger'">
{{ scope.row.status === '1' ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="模板类型" align="center" prop="type" />
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<el-card>
<el-table
:data="treeTableData"
style="width: 100%"
row-key="id"
border
default-expand-all
:tree-props="{ children: 'children' }"
>
<el-table-column prop="type" label="模板类型" width="180" />
<el-table-column prop="category" label="模板类别" width="180" />
<el-table-column prop="contentName" label="模板名称" />
<el-table-column prop="content" label="模板内容" />
<el-table-column label="状态" align="center" width="100">
<template #default="scope">
<el-tag v-if="scope.row.status" :type="scope.row.status === '1' ? 'success' : 'danger'">
{{ scope.row.status === '1' ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="150">
<template #default="scope">
<el-button
v-if="scope.row.isLeaf"
link
type="primary"
@click="openForm('update', scope.row.id)"
>
编辑
</el-button>
<el-button
v-if="scope.row.isLeaf"
link
type="danger"
@click="handleDelete(scope.row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
@ -118,6 +132,7 @@ const { t } = useI18n() // 国际化
const loading = ref(true) //
const list = ref<TemplateVO[]>([]) //
const total = ref(0) //
const categoryOptions = ref<any[]>([]) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
@ -127,10 +142,14 @@ const queryParams = reactive({
content: undefined,
orderNum: undefined,
contentName: undefined,
category: undefined,
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
//
const treeTableData = ref<any[]>([])
/** 查询列表 */
const getList = async () => {
loading.value = true
@ -138,11 +157,27 @@ const getList = async () => {
const data = await TemplateApi.getTemplatePage(queryParams)
list.value = data.list
total.value = data.total
//
treeTableData.value = convertToTreeTableData(data.list)
} finally {
loading.value = false
}
}
/** 获取所有模板类别 */
const getCategoryOptions = async () => {
try {
const categories = await TemplateApi.getAllCategories()
categoryOptions.value = categories.map(category => ({
label: category,
value: category
}))
} catch (error) {
console.error('获取模板类别失败:', error)
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
@ -189,8 +224,97 @@ const handleExport = async () => {
}
}
/** 转换列表数据为树形表格数据 */
const convertToTreeTableData = (listData: TemplateVO[]) => {
const typeMap = new Map()
let uniqueId = 1000 // ID
//
listData.forEach(item => {
if (!typeMap.has(item.type)) {
typeMap.set(item.type, {
id: uniqueId++,
type: item.type,
category: '',
contentName: '',
content: '',
children: new Map(),
isLeaf: false
})
}
const typeNode = typeMap.get(item.type)
const categoryMap = typeNode.children
//
if (!categoryMap.has(item.category)) {
categoryMap.set(item.category, {
id: uniqueId++,
type: '',
category: item.category,
contentName: '',
content: '',
children: [],
isLeaf: false
})
}
//
categoryMap.get(item.category).children.push({
id: item.id,
type: '',
category: '',
contentName: item.contentName,
content: item.content,
status: item.status,
isLeaf: true
})
})
//
const result: any[] = []
typeMap.forEach(typeNode => {
const typeItem = {
id: typeNode.id,
type: typeNode.type,
category: typeNode.category,
contentName: typeNode.contentName,
content: typeNode.content,
isLeaf: typeNode.isLeaf,
children: [] as any[]
}
typeNode.children.forEach(categoryNode => {
const categoryItem = {
id: categoryNode.id,
type: categoryNode.type,
category: categoryNode.category,
contentName: categoryNode.contentName,
content: categoryNode.content,
isLeaf: categoryNode.isLeaf,
children: categoryNode.children
}
typeItem.children.push(categoryItem)
})
result.push(typeItem)
})
return result
}
/** 初始化 **/
onMounted(() => {
getList()
getCategoryOptions() //
})
</script>
</script>
<style scoped>
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>