feat(sprint12): 床位管理模块 — 全栈CRUD+状态流转+Flyway迁移
- 后端: Bed Entity/Mapper/Service/Controller (6个文件) - Flyway: V12__bed_management.sql (sys_bed表+索引) - 前端: bedspace页面完整CRUD (搜索/表格/新增编辑弹窗/状态流转/分页) - 状态: 空闲(0)→占用(1)→清洁(2)→空闲(0), 维修(3)独立 - 编译: BUILD SUCCESS
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package com.healthlink.his.web.basicmanage.controller;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.healthlink.his.basicmanage.domain.Bed;
|
||||
import com.healthlink.his.basicmanage.service.IBedService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
@RestController
|
||||
@RequestMapping("/basic-manage/bed")
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class BedController {
|
||||
private final IBedService bedService;
|
||||
@GetMapping("/page")
|
||||
public R<?> getPage(@RequestParam(value = "bedNo", required = false) String bedNo,
|
||||
@RequestParam(value = "wardId", required = false) Long wardId,
|
||||
@RequestParam(value = "status", required = false) Integer status,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
|
||||
LambdaQueryWrapper<Bed> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.like(StringUtils.hasText(bedNo), Bed::getBedNo, bedNo)
|
||||
.eq(wardId != null, Bed::getWardId, wardId)
|
||||
.eq(status != null, Bed::getStatus, status)
|
||||
.orderByDesc(Bed::getCreateTime);
|
||||
return R.ok(bedService.page(new Page<>(pageNo, pageSize), wrapper));
|
||||
}
|
||||
@GetMapping("/list")
|
||||
public R<List<Bed>> getList(@RequestParam(value = "status", required = false) Integer status) {
|
||||
LambdaQueryWrapper<Bed> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(status != null, Bed::getStatus, status).orderByAsc(Bed::getBedNo);
|
||||
return R.ok(bedService.list(wrapper));
|
||||
}
|
||||
@PostMapping("/add")
|
||||
public R<?> add(@RequestBody Bed bed) {
|
||||
return bedService.save(bed) ? R.ok("新增成功") : R.fail("新增失败");
|
||||
}
|
||||
@PutMapping("/update")
|
||||
public R<?> update(@RequestBody Bed bed) {
|
||||
return bedService.updateById(bed) ? R.ok("修改成功") : R.fail("修改失败");
|
||||
}
|
||||
@DeleteMapping("/delete")
|
||||
public R<?> delete(@RequestParam Long id) {
|
||||
return bedService.removeById(id) ? R.ok("删除成功") : R.fail("删除失败");
|
||||
}
|
||||
@PutMapping("/status")
|
||||
public R<?> updateStatus(@RequestParam Long id, @RequestParam Integer status) {
|
||||
Bed bed = new Bed(); bed.setId(id); bed.setStatus(status);
|
||||
return bedService.updateById(bed) ? R.ok("状态更新成功") : R.fail("状态更新失败");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
CREATE TABLE IF NOT EXISTS sys_bed (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
bed_no VARCHAR(20) NOT NULL,
|
||||
bed_name VARCHAR(50),
|
||||
ward_id BIGINT,
|
||||
ward_name VARCHAR(100),
|
||||
dept_id BIGINT,
|
||||
dept_name VARCHAR(100),
|
||||
bed_type INT DEFAULT 1,
|
||||
status INT DEFAULT 0,
|
||||
remark TEXT,
|
||||
create_by VARCHAR(64),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64),
|
||||
update_time TIMESTAMP,
|
||||
tenant_id INT DEFAULT 0
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_bed_ward ON sys_bed(ward_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_bed_dept ON sys_bed(dept_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_bed_status ON sys_bed(status);
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.healthlink.his.basicmanage.domain;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.core.common.core.domain.HisBaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@Data
|
||||
@TableName("sys_bed")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Bed extends HisBaseEntity {
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private String bedNo;
|
||||
private String bedName;
|
||||
private Long wardId;
|
||||
private String wardName;
|
||||
private Long deptId;
|
||||
private String deptName;
|
||||
private Integer bedType;
|
||||
private Integer status;
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.healthlink.his.basicmanage.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.healthlink.his.basicmanage.domain.Bed;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper
|
||||
public interface BedMapper extends BaseMapper<Bed> {}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.healthlink.his.basicmanage.service;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.healthlink.his.basicmanage.domain.Bed;
|
||||
public interface IBedService extends IService<Bed> {}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.healthlink.his.basicmanage.service.impl;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.healthlink.his.basicmanage.domain.Bed;
|
||||
import com.healthlink.his.basicmanage.mapper.BedMapper;
|
||||
import com.healthlink.his.basicmanage.service.IBedService;
|
||||
import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class BedServiceImpl extends ServiceImpl<BedMapper, Bed> implements IBedService {}
|
||||
@@ -0,0 +1,6 @@
|
||||
import request from '@/utils/request'
|
||||
export function getBedPage(params) { return request({ url: '/basic-manage/bed/page', method: 'get', params }) }
|
||||
export function addBed(data) { return request({ url: '/basic-manage/bed/add', method: 'post', data }) }
|
||||
export function updateBed(data) { return request({ url: '/basic-manage/bed/update', method: 'put', data }) }
|
||||
export function deleteBed(id) { return request({ url: '/basic-manage/bed/delete', method: 'delete', params: { id } }) }
|
||||
export function updateBedStatus(id, status) { return request({ url: '/basic-manage/bed/status', method: 'put', params: { id, status } }) }
|
||||
@@ -1,42 +1,108 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-card shadow="never">
|
||||
<template #header><span class="card-title">床位管理</span></template>
|
||||
<el-form :inline="true" :model="queryParams">
|
||||
<el-form-item label="搜索">
|
||||
<el-input v-model="queryParams.searchKey" placeholder="搜索" clearable @keyup.enter="handleQuery" />
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">床位管理</span>
|
||||
<el-button type="primary" icon="Plus" @click="handleAdd">新增床位</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-form :inline="true" :model="queryParams" label-width="80px">
|
||||
<el-form-item label="床号">
|
||||
<el-input v-model="queryParams.bedNo" placeholder="床号" clearable @keyup.enter="handleQuery" style="width: 140px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="queryParams.status" placeholder="全部" clearable style="width: 120px">
|
||||
<el-option label="空闲" :value="0" /><el-option label="占用" :value="1" />
|
||||
<el-option label="清洁" :value="2" /><el-option label="维修" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button type="success" icon="Plus" @click="handleAdd">新增</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<vxe-table :data="tableData" border height="calc(100vh - 280px)">
|
||||
<vxe-table :data="tableData" border height="calc(100vh - 320px)" v-loading="loading">
|
||||
<vxe-column type="seq" title="序号" width="60" />
|
||||
<vxe-column field="name" title="名称" />
|
||||
<vxe-column field="code" title="编码" />
|
||||
<vxe-column field="status" title="状态">
|
||||
<template #default="{ row }"><el-tag :type="row.status === '0' ? 'success' : 'info'">{{ row.status === '0' ? '正常' : '停用' }}</el-tag></template>
|
||||
</vxe-column>
|
||||
<vxe-column title="操作" width="150">
|
||||
<vxe-column field="bedNo" title="床号" width="100" />
|
||||
<vxe-column field="bedName" title="床位名" width="120" />
|
||||
<vxe-column field="wardName" title="病区" width="120" />
|
||||
<vxe-column field="deptName" title="科室" width="120" />
|
||||
<vxe-column field="bedType" title="类型" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
|
||||
<el-tag :type="row.bedType === 2 ? 'danger' : row.bedType === 3 ? 'warning' : 'info'" size="small">
|
||||
{{ { 1: '普通', 2: 'ICU', 3: '急诊' }[row.bedType] || '普通' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="status" title="状态" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="statusType(row.status)" size="small">{{ statusText(row.status) }}</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="操作" width="220" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link icon="Edit" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button v-if="row.status === 0" type="warning" link @click="changeStatus(row, 1)">占用</el-button>
|
||||
<el-button v-if="row.status === 1" type="success" link @click="changeStatus(row, 2)">清洁</el-button>
|
||||
<el-button v-if="row.status === 2" type="info" link @click="changeStatus(row, 0)">空闲</el-button>
|
||||
<el-button v-if="row.status !== 3" type="danger" link @click="changeStatus(row, 3)">维修</el-button>
|
||||
<el-button type="danger" link icon="Delete" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<pagination v-show="total > 0" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
|
||||
</el-card>
|
||||
<el-dialog v-model="formVisible" :title="formTitle" width="550px" append-to-body>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="床号" prop="bedNo"><el-input v-model="form.bedNo" placeholder="床号" /></el-form-item>
|
||||
<el-form-item label="床位名"><el-input v-model="form.bedName" placeholder="床位名" /></el-form-item>
|
||||
<el-form-item label="病区"><el-input v-model="form.wardName" placeholder="病区" /></el-form-item>
|
||||
<el-form-item label="科室"><el-input v-model="form.deptName" placeholder="科室" /></el-form-item>
|
||||
<el-form-item label="类型">
|
||||
<el-select v-model="form.bedType" style="width:100%">
|
||||
<el-option label="普通" :value="1" /><el-option label="ICU" :value="2" /><el-option label="急诊" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注"><el-input v-model="form.remark" type="textarea" :rows="2" /></el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="formVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
const queryParams = ref({ searchKey: '', pageNum: 1, pageSize: 20 })
|
||||
const tableData = ref([])
|
||||
const handleQuery = () => { tableData.value = [] }
|
||||
const handleAdd = () => { ElMessage.info('新增功能开发中') }
|
||||
const handleEdit = (row) => { ElMessage.info('编辑功能开发中') }
|
||||
const handleDelete = (row) => { ElMessage.info('删除功能开发中') }
|
||||
onMounted(() => handleQuery())
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getBedPage, addBed, updateBed, deleteBed, updateBedStatus } from './components/api'
|
||||
const loading = ref(false); const tableData = ref([]); const total = ref(0)
|
||||
const queryParams = ref({ bedNo: '', status: undefined, pageNo: 1, pageSize: 20 })
|
||||
const formVisible = ref(false); const formTitle = ref('新增床位'); const isEdit = ref(false); const formRef = ref()
|
||||
const form = ref({ id: null, bedNo: '', bedName: '', wardName: '', deptName: '', bedType: 1, remark: '' })
|
||||
const rules = { bedNo: [{ required: true, message: '请输入床号', trigger: 'blur' }] }
|
||||
const statusText = (s) => ({ 0: '空闲', 1: '占用', 2: '清洁', 3: '维修' }[s] || '未知')
|
||||
const statusType = (s) => ({ 0: 'success', 1: 'danger', 2: 'info', 3: 'warning' }[s] || 'info')
|
||||
function getList() {
|
||||
loading.value = true
|
||||
getBedPage(queryParams.value).then(res => { tableData.value = res.data?.records || []; total.value = res.data?.total || 0 }).finally(() => { loading.value = false })
|
||||
}
|
||||
function handleQuery() { queryParams.value.pageNo = 1; getList() }
|
||||
function resetQuery() { queryParams.value = { bedNo: '', status: undefined, pageNo: 1, pageSize: 20 }; getList() }
|
||||
function handleAdd() { isEdit.value = false; formTitle.value = '新增床位'; form.value = { id: null, bedNo: '', bedName: '', wardName: '', deptName: '', bedType: 1, remark: '' }; formVisible.value = true }
|
||||
function handleEdit(row) { isEdit.value = true; formTitle.value = '编辑床位'; form.value = { ...row }; formVisible.value = true }
|
||||
function submitForm() {
|
||||
formRef.value.validate(valid => { if (!valid) return
|
||||
const action = isEdit.value ? updateBed(form.value) : addBed(form.value)
|
||||
action.then(res => { if (res.code === 200) { ElMessage.success(isEdit.value ? '修改成功' : '新增成功'); formVisible.value = false; getList() } else ElMessage.error(res.msg || '操作失败') })
|
||||
})
|
||||
}
|
||||
function handleDelete(row) { ElMessageBox.confirm('确认删除该床位?', '提示', { type: 'warning' }).then(() => { deleteBed(row.id).then(res => { if (res.code === 200) { ElMessage.success('删除成功'); getList() } }) }).catch(() => {}) }
|
||||
function changeStatus(row, status) { updateBedStatus(row.id, status).then(res => { if (res.code === 200) { ElMessage.success('状态已更新'); getList() } }) }
|
||||
onMounted(() => getList())
|
||||
</script>
|
||||
<style scoped>.card-title { font-weight: bold; font-size: 16px; }</style>
|
||||
<style lang="scss" scoped>
|
||||
.card-header { display: flex; justify-content: space-between; align-items: center; }
|
||||
.card-title { font-weight: bold; font-size: 16px; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user