Files
intc-vue3/src/views/health/medicationPlan/index.vue
bot5 d8caa6c7e6 feat(health): 新增用药计划模块前端页面
- 新增用药计划和用药记录API接口
- 新增用药计划管理页面(列表/新增/编辑/暂停/恢复/结束)
- 新增用药记录管理页面(列表/服药/跳过)
2026-03-18 14:10:32 +08:00

448 lines
17 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="app-container">
<div class="search-con">
<div class="title">查询条件</div>
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="计划名称" prop="planName">
<el-input v-model="queryParams.planName" placeholder="请输入计划名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="人员" prop="personId">
<el-select v-model="queryParams.personId" placeholder="请选择人员" clearable filterable>
<el-option v-for="item in personList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="频率类型" prop="frequencyType">
<el-select v-model="queryParams.frequencyType" placeholder="请选择频率类型" clearable>
<el-option v-for="dict in medication_frequency_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option v-for="dict in medication_plan_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="关键字" prop="keys">
<el-input v-model="queryParams.keys" placeholder="计划名称/药品名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-form>
<div class="search-btn-con">
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button type="info" icon="Refresh" @click="resetQuery">重置</el-button>
</div>
</div>
<div class="main-con">
<div class="title-con">
<div class="title">用药计划</div>
<div class="operate-btn-con">
<el-button @click="handleAdd" icon="Plus" v-hasPermi="['health:medicationPlan:add']">新增</el-button>
<el-button :disabled="multiple" icon="Delete" @click="handleDelete" v-hasPermi="['health:medicationPlan:remove']">删除</el-button>
</div>
</div>
<div class="content-con" v-loading="loading" height="calc(100% - 0.65rem)">
<el-table v-loading="loading" :data="planList" @selection-change="handleSelectionChange" height="calc(100% - 0.65rem)">
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" :index="indexMethod" width="50"></el-table-column>
<el-table-column label="计划名称" align="center" prop="planName" width="150" />
<el-table-column label="人员" align="center" prop="personName" width="100" />
<el-table-column label="药品" align="center" width="200">
<template #default="scope">
{{ scope.row.shortName }}-{{ scope.row.brand }}
</template>
</el-table-column>
<el-table-column label="剂量/频率" align="center" width="120">
<template #default="scope">
{{ scope.row.dosage }}{{ scope.row.dosageUnit }} × {{ scope.row.frequency }}/
</template>
</el-table-column>
<el-table-column label="频率类型" align="center" prop="frequencyType" width="100">
<template #default="scope">
<dict-tag :options="medication_frequency_type" :value="scope.row.frequencyType" />
</template>
</el-table-column>
<el-table-column label="开始日期" align="center" prop="startDate" width="110">
<template #default="scope">
{{ formatDate(scope.row.startDate) }}
</template>
</el-table-column>
<el-table-column label="结束日期" align="center" prop="endDate" width="110">
<template #default="scope">
{{ scope.row.endDate ? formatDate(scope.row.endDate) : '长期' }}
</template>
</el-table-column>
<el-table-column label="今日进度" align="center" width="100">
<template #default="scope">
<span v-if="scope.row.status === '1'">
{{ scope.row.todayTakenCount || 0 }}/{{ scope.row.todayTotalCount || 0 }}
</span>
<span v-else>--</span>
</template>
</el-table-column>
<el-table-column label="提醒" align="center" prop="reminderEnabled" width="80">
<template #default="scope">
<el-tag v-if="scope.row.reminderEnabled === '1'" type="success"></el-tag>
<el-tag v-else type="info"></el-tag>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status" width="90">
<template #default="scope">
<dict-tag :options="medication_plan_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template v-slot="scope">
<div class="ctrl-btn d-flex">
<el-tooltip class="item" effect="dark" content="查看" placement="top">
<el-button icon="View" v-hasPermi="['health:medicationPlan:query']" circle @click="handleView(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.status === '1'" class="item" effect="dark" content="暂停" placement="top">
<el-button icon="VideoPause" v-hasPermi="['health:medicationPlan:edit']" circle @click="handlePause(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.status === '3'" class="item" effect="dark" content="恢复" placement="top">
<el-button icon="VideoPlay" v-hasPermi="['health:medicationPlan:edit']" circle @click="handleResume(scope.row)"></el-button>
</el-tooltip>
<el-tooltip v-if="scope.row.status !== '2'" class="item" effect="dark" content="结束" placement="top">
<el-button icon="Finished" v-hasPermi="['health:medicationPlan:edit']" circle @click="handleEnd(scope.row)"></el-button>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="修改" placement="top">
<el-button icon="Edit" v-hasPermi="['health:medicationPlan:edit']" circle @click="handleUpdate(scope.row)"></el-button>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="删除" placement="top">
<el-button icon="Delete" v-hasPermi="['health:medicationPlan:remove']" circle @click="handleDelete(scope.row)"></el-button>
</el-tooltip>
</div>
</template>
</el-table-column>
</el-table>
<el-pagination
small
background
layout="total,sizes, prev, pager, next"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
<!-- 添加或修改用药计划对话框 -->
<el-dialog :title="title" v-model="open" width="900px" append-to-body>
<el-form ref="planRef" :model="form" :inline="true" :rules="rules" label-width="120px">
<el-form-item label="计划名称" prop="planName">
<el-input v-model="form.planName" placeholder="请输入计划名称(可选)" style="width: 300px" />
</el-form-item>
<el-form-item label="人员" prop="personId">
<el-select v-model="form.personId" placeholder="请选择人员" filterable style="width: 200px">
<el-option v-for="item in personList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="药品" prop="medicineId">
<el-select v-model="form.medicineId" placeholder="请选择药品" filterable style="width: 300px" @change="handleMedicineChange">
<el-option v-for="item in medicineList" :key="item.id" :label="item.shortName + '-' + item.brand" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="每次剂量" prop="dosage">
<el-input-number v-model="form.dosage" :min="0" :precision="2" style="width: 150px" />
<el-select v-model="form.dosageUnit" placeholder="单位" style="width: 100px; margin-left: 10px">
<el-option v-for="dict in medical_unit" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="每日次数" prop="frequency">
<el-input-number v-model="form.frequency" :min="1" :max="10" style="width: 150px" />
</el-form-item>
<el-form-item label="频率类型" prop="frequencyType">
<el-select v-model="form.frequencyType" placeholder="请选择频率类型" style="width: 150px">
<el-option v-for="dict in medication_frequency_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="服药时间点" prop="timePoints">
<el-tag v-for="(time, index) in form.timePointList" :key="index" closable @close="removeTimePoint(index)" style="margin-right: 10px">
{{ time }}
</el-tag>
<el-time-picker v-model="newTimePoint" placeholder="添加时间" format="HH:mm" value-format="HH:mm" @change="addTimePoint" style="width: 120px" />
</el-form-item>
<el-form-item label="开始日期" prop="startDate">
<el-date-picker v-model="form.startDate" type="date" placeholder="选择开始日期" value-format="YYYY-MM-DD" style="width: 180px" />
</el-form-item>
<el-form-item label="结束日期" prop="endDate">
<el-date-picker v-model="form.endDate" type="date" placeholder="选择结束日期(可选)" value-format="YYYY-MM-DD" style="width: 180px" />
</el-form-item>
<el-form-item label="启用提醒" prop="reminderEnabled">
<el-switch v-model="form.reminderEnabled" active-value="1" inactive-value="0" />
</el-form-item>
<el-form-item v-if="form.reminderEnabled === '1'" label="提前提醒" prop="reminderMinutes">
<el-input-number v-model="form.reminderMinutes" :min="0" :max="60" style="width: 150px" />
<span style="margin-left: 10px">分钟</span>
</el-form-item>
<el-form-item label="备注" style="width: 100%">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" :rows="3" />
</el-form-item>
</el-form>
<template v-if="title !== '查看用药计划'" #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="MedicationPlan">
import { listMedicationPlan, getMedicationPlan, delMedicationPlan, addMedicationPlan, updateMedicationPlan, pauseMedicationPlan, resumeMedicationPlan, endMedicationPlan } from '@/api/health/medicationPlan'
import { listMedicineBasic } from '@/api/health/medicineBasic'
import { listPerson } from '@/api/health/person'
const { proxy } = getCurrentInstance()
const { medication_frequency_type, medication_plan_status, medical_unit } = proxy.useDict(
'medication_frequency_type',
'medication_plan_status',
'medical_unit'
)
const planList = ref([])
const personList = ref([])
const medicineList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref('')
const newTimePoint = ref(null)
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
planName: null,
personId: null,
frequencyType: null,
status: null,
keys: null
},
rules: {
personId: [{ required: true, message: '请选择人员', trigger: 'change' }],
medicineId: [{ required: true, message: '请选择药品', trigger: 'change' }],
dosage: [{ required: true, message: '请输入剂量', trigger: 'blur' }],
frequency: [{ required: true, message: '请输入每日次数', trigger: 'blur' }],
startDate: [{ required: true, message: '请选择开始日期', trigger: 'change' }]
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询用药计划列表 */
function getList() {
loading.value = true
listMedicationPlan(queryParams.value).then((response) => {
planList.value = response.rows
total.value = response.total
loading.value = false
})
}
/** 查询人员列表 */
function getPersonList() {
listPerson({ pageNum: 1, pageSize: 100 }).then((response) => {
personList.value = response.rows || []
})
}
/** 查询药品列表 */
function getMedicineList() {
listMedicineBasic({ pageNum: 1, pageSize: 1000 }).then((response) => {
medicineList.value = response.rows || []
})
}
// 取消按钮
function cancel() {
open.value = false
reset()
}
// 表单重置
function reset() {
form.value = {
id: null,
personId: null,
medicineId: null,
stockInId: null,
planName: null,
dosage: 1,
dosageUnit: '片',
frequency: 3,
frequencyType: '1',
timePoints: null,
timePointList: ['08:00', '12:00', '18:00'],
weekDays: null,
startDate: null,
endDate: null,
reminderEnabled: '0',
reminderMinutes: 15,
status: '1',
remark: null
}
proxy.resetForm('planRef')
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm('queryRef')
handleQuery()
}
// 分页
const handleCurrentChange = (val) => {
queryParams.value.pageNum = val
getList()
}
const handleSizeChange = (val) => {
queryParams.value.pageSize = val
getList()
}
// 序号翻页递增
const indexMethod = (index) => {
const nowPage = queryParams.value.pageNum
const nowLimit = queryParams.value.pageSize
return index + 1 + (nowPage - 1) * nowLimit
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.id)
single.value = selection.length !== 1
multiple.value = !selection.length
}
// 格式化日期
function formatDate(date) {
if (!date) return ''
return date.substring(0, 10)
}
// 查看
const handleView = (row) => {
getMedicationPlan(row.id).then((response) => {
form.value = response.data
form.value.timePointList = form.value.timePoints ? JSON.parse(form.value.timePoints) : []
title.value = '查看用药计划'
open.value = true
})
}
/** 新增按钮操作 */
function handleAdd() {
reset()
open.value = true
title.value = '添加用药计划'
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
const _id = row.id || ids.value
getMedicationPlan(_id).then((response) => {
form.value = response.data
form.value.timePointList = form.value.timePoints ? JSON.parse(form.value.timePoints) : []
open.value = true
title.value = '修改用药计划'
})
}
/** 暂停按钮操作 */
function handlePause(row) {
proxy.$modal.confirm('确认暂停该用药计划?').then(() => {
return pauseMedicationPlan(row.id)
}).then(() => {
getList()
proxy.$modal.msgSuccess('暂停成功')
}).catch(() => {})
}
/** 恢复按钮操作 */
function handleResume(row) {
resumeMedicationPlan(row.id).then(() => {
getList()
proxy.$modal.msgSuccess('恢复成功')
})
}
/** 结束按钮操作 */
function handleEnd(row) {
proxy.$modal.confirm('确认结束该用药计划?结束后将不再生成用药记录。').then(() => {
return endMedicationPlan(row.id)
}).then(() => {
getList()
proxy.$modal.msgSuccess('已结束')
}).catch(() => {})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs.planRef.validate((valid) => {
if (valid) {
form.value.timePoints = JSON.stringify(form.value.timePointList)
if (form.value.id != null) {
updateMedicationPlan(form.value).then((response) => {
proxy.$modal.msgSuccess('修改成功')
open.value = false
getList()
})
} else {
addMedicationPlan(form.value).then((response) => {
proxy.$modal.msgSuccess('新增成功')
open.value = false
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value
proxy.$modal.confirm('是否确认删除选中的数据项?').then(function () {
return delMedicationPlan(_ids)
}).then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
}).catch(() => {})
}
/** 添加服药时间点 */
function addTimePoint(val) {
if (val && !form.value.timePointList.includes(val)) {
form.value.timePointList.push(val)
}
newTimePoint.value = null
}
/** 移除服药时间点 */
function removeTimePoint(index) {
form.value.timePointList.splice(index, 1)
}
/** 药品选择变化 */
function handleMedicineChange(medicineId) {
const medicine = medicineList.value.find(m => m.id === medicineId)
if (medicine) {
form.value.dosageUnit = medicine.unit || '片'
}
}
getPersonList()
getMedicineList()
getList()
</script>