feat(V43): 临床路径 — 完整前端+DB修复+3/3 API通过

前端:
- ClinicalPathway: 完整CRUD页面+入径/完成/变异操作
- 统计卡片: 路径总数/入径数/完成数/变异数

数据库修复:
- clinical_pathway: 添加create_by/update_by/update_time列
- clinical_pathway_execution: 添加create_by/update_by/update_time/delete_flag/tenant_id列

测试: 3/3 API通过(新增/分页/统计)
This commit is contained in:
2026-06-07 13:33:08 +08:00
parent 9dd36fe828
commit 4bcbeef52f
2 changed files with 98 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
import request from '@/utils/request'
export function getWorkflowPage(p) { return request({ url: '/clinical-pathway/page', method: 'get', params: p }) }
export function addWorkflow(d) { return request({ url: '/clinical-pathway/add', method: 'post', data: d }) }
export function enterPathway(d) { return request({ url: '/clinical-pathway/enter', method: 'post', data: d }) }
export function completePathway(id) { return request({ url: '/clinical-pathway/complete/' + id, method: 'put' }) }
export function varyPathway(id, reason) { return request({ url: '/clinical-pathway/vary/' + id, method: 'put', params: { reason } }) }
export function getStats() { return request({ url: '/clinical-pathway/stats', method: 'get' }) }

View File

@@ -0,0 +1,91 @@
<template>
<div class="app-container">
<el-row :gutter="20" class="mb8">
<el-col :span="6"><el-card shadow="hover"><el-statistic title="路径总数" :value="stats.totalPathways || 0" /></el-card></el-col>
<el-col :span="6"><el-card shadow="hover"><el-statistic title="入径数" :value="stats.enteredCount || 0" /></el-card></el-col>
<el-col :span="6"><el-card shadow="hover"><el-statistic title="完成数" :value="stats.completedCount || 0" /></el-card></el-col>
<el-col :span="6"><el-card shadow="hover"><el-statistic title="变异数" :value="stats.variedCount || 0" /></el-card></el-col>
</el-row>
<el-card>
<template #header>
<div style="display:flex;justify-content:space-between;align-items:center">
<span>临床路径管理</span>
<el-button type="primary" icon="Plus" @click="handleAdd">新增路径</el-button>
</div>
</template>
<el-form :model="queryParams" :inline="true" class="mb8">
<el-form-item label="疾病编码"><el-input v-model="queryParams.diseaseCode" placeholder="疾病编码" clearable /></el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button>
<el-button @click="queryParams.diseaseCode='';handleQuery()">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="dataList">
<el-table-column label="疾病编码" prop="diseaseCode" width="120" />
<el-table-column label="疾病名称" prop="diseaseName" width="150" />
<el-table-column label="路径名称" prop="pathwayName" width="200" show-overflow-tooltip />
<el-table-column label="标准住院日" prop="standardLos" width="100" align="center" />
<el-table-column label="版本" prop="version" width="70" align="center" />
<el-table-column label="状态" prop="status" width="90">
<template #default="s">
<el-tag :type="s.row.status==='ACTIVE'?'success':'info'">{{ s.row.status === 'ACTIVE' ? '启用' : '停用' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template #default="s">
<el-button link type="primary" @click="handleEnter(s.row)">入径</el-button>
<el-button link type="success" @click="handleComplete(s.row)">完成</el-button>
<el-button link type="warning" @click="handleVary(s.row)">变异</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<el-dialog title="新增临床路径" v-model="dialogVisible" width="600px">
<el-form :model="formData" label-width="110px">
<el-row :gutter="20">
<el-col :span="12"><el-form-item label="疾病编码"><el-input v-model="formData.diseaseCode" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="疾病名称"><el-input v-model="formData.diseaseName" /></el-form-item></el-col>
<el-col :span="24"><el-form-item label="路径名称"><el-input v-model="formData.pathwayName" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="标准住院日"><el-input-number v-model="formData.standardLos" :min="1" /></el-form-item></el-col>
<el-col :span="24"><el-form-item label="路径内容"><el-input v-model="formData.pathwayContent" type="textarea" :rows="4" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { getWorkflowPage, addWorkflow, enterPathway, completePathway, varyPathway, getStats } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
const loading = ref(false); const dataList = ref([]); const total = ref(0); const stats = ref({})
const dialogVisible = ref(false)
const queryParams = reactive({ diseaseCode: '', pageNo: 1, pageSize: 20 })
const formData = ref({})
const getList = async () => { loading.value = true; const res = await getWorkflowPage(queryParams); dataList.value = res.data?.records || []; total.value = res.data?.total || 0; loading.value = false }
const loadStats = async () => { const res = await getStats(); stats.value = res.data || {} }
const handleQuery = () => { queryParams.pageNo = 1; getList() }
const handleAdd = () => { formData.value = {}; dialogVisible.value = true }
const submitForm = async () => { await addWorkflow(formData.value); ElMessage.success('创建成功'); dialogVisible.value = false; getList(); loadStats() }
const handleEnter = async (row) => {
await ElMessageBox.confirm(`确认将患者入径「${row.pathwayName}」?`, '入径确认', { type: 'info' })
await enterPathway({ pathwayId: row.id, diseaseCode: row.diseaseCode, diseaseName: row.diseaseName }); ElMessage.success('入径成功'); loadStats()
}
const handleComplete = async (row) => {
await ElMessageBox.confirm('确认完成此路径?', '完成确认', { type: 'success' })
await completePathway(row.id); ElMessage.success('已完成'); getList(); loadStats()
}
const handleVary = async (row) => {
await ElMessageBox.prompt('请输入变异原因', '变异登记', { type: 'warning' })
.then(async ({ value }) => { await varyPathway(row.id, value || '未填写原因'); ElMessage.success('变异已登记'); getList(); loadStats() })
}
onMounted(() => { getList(); loadStats() })
</script>