粤嵌实训医疗项目(小组开发)--day05

news2024/11/26 0:23:25

目录

一、医生功能模块

------------前端实现------------

------------后端接口------------

功能一:分页查询医生基础信息(介绍MybatisPlus如何使用分页)

功能二:根据搜索栏名称查找对应医生(讲解自定义查询集)

功能三: 实现获取医生的详细信息

功能四:实现预约功能

功能五:根据医生科室查询医生

收获与反思


一、医生功能模块

模块需求:

本模块设计,我负责后端接口开发,另一位成员负责前端开发。

------------前端实现------------

<template>
    <div>
        <div style="margin: 20px 0px;">
            <el-row>
                <el-col :span="10" class="center">
                    
                    <!-- 输入标签组件 -->
                    <el-input v-model="search" @focus="focus" @blur="blur" @keyup.enter.native="searchHandler"
                        placeholder="搜索医生名称" clearable>
                        <el-button slot="append" icon="el-icon-search" id="search" @click="searchHandler"></el-button>
                    </el-input>


                    <!---设置z-index优先级,防止被走马灯效果遮挡-->
                    <el-card @mouseenter="enterSearchBoxHanlder" v-if="isSearch" class="box-card" id="search-box"
                        style="position:absolute;z-index:15">
                        <dl v-if="isHistorySearch">
                            <dt class="search-title" v-show="history">历史搜索</dt>
                            <dt class="remove-history" v-show="history" @click="removeAllHistory">
                                <i class="el-icon-delete"></i>清空历史记录
                            </dt>
                            <el-tag v-for="search in historySearchList" :key="search.id" closable :type="search.type"
                                @close="closeHandler(search)" @click="searchistory(search)"
                                style="margin-right:5px; margin-bottom:5px;">{{ search.name }}</el-tag>
                            <dt class="search-title">热门搜索</dt>
                            <dd v-for="search in hotSearchList" :key="search.id">{{ search }}</dd>
                        </dl>
                        <dl v-if="isSearchList">
                            <dd v-for="search in searchList" :key="search.id">{{ search }}</dd>
                        </dl>
                    </el-card>
                </el-col>
            </el-row>
            <el-dialog title="简介" :visible.sync="introductionDialog" width="30%">
                <el-form ref="form" :model="form" label-width="80px">
                    <el-form-item label="头像">
                        <!-- action表示为上传文件的url   -->
                        <el-upload class="avatar-uploader">
                            <img v-if="imageUrl" :src="imageUrl" class="avatar" />
                            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                        </el-upload>
                    </el-form-item>
                    <el-form-item label="姓名">
                        <h2>{{ form.name }}</h2>
                    </el-form-item>
                    <el-form-item label="个人简介">
                        <p>{{ form.introduction }}</p>
                    </el-form-item>
                </el-form>
            </el-dialog>
            <el-dialog title="预约" :visible.sync="appointmentDialog1" width="40%">
                <el-calendar v-model="value">
                    <div slot="dateCell" slot-scope="{ data }" @click="allcalendar(data)" class="temp">
                        <span>{{ data.day.split("-")[2] }}</span>
                    </div>
                </el-calendar>
            </el-dialog>
            <el-dialog title="预约" :visible.sync="appointmentDialog2" width="40%">
                    <el-table :data="bookTime" style="width: 100%">
                        <el-table-column label="日期" width="180">
                            <template slot-scope="scope">
                                <i class="el-icon-time"></i>
                                <span style="margin-left: 10px">{{ scope.row.time }}</span>
                            </template>
                        </el-table-column>
                        <el-table-column label="剩余" width="180">
                            <template slot-scope="scope">
                                <el-popover trigger="hover" placement="top">
                                    <p>人数: {{ scope.row.Remain }}</p>
                                    <div slot="reference" class="name-wrapper">
                                        <el-tag size="medium">{{ scope.row.Remain }}</el-tag>
                                    </div>
                                </el-popover>
                            </template>
                        </el-table-column>
                        <el-table-column label="操作">
                            <template slot-scope="scope">
                                <el-button size="mini" @click="handleBooktime(scope.$index, scope.row)">预约</el-button>
                            </template>
                        </el-table-column>
                    </el-table>
            </el-dialog>
        </div>
        <el-table :data="tableData" border style="width: 100%">
            <el-table-column prop="major" label="科室" sortable width="180" column-key="date" :filters="[{ text: '内科', value: '内科' },
            { text: '妇科', value: '妇科专业' },
            { text: '儿科', value: '儿科' },
            { text: '外科', value: '外科手术' }]" :filter-method="filterHandler">
            </el-table-column>
            <el-table-column prop="host_id" label="医生编号" width="120">
            </el-table-column>
            <el-table-column prop="name" label="医生名称" width="120">
            </el-table-column>
            <el-table-column prop="image" label="医生帅照" width="120">
            </el-table-column>
            <el-table-column prop="phone" label="电话" width="300">
 

            </el-table-column>
            <el-table-column fixed="right" label="操作" width="100">
                <template slot-scope="scope">
                    <el-button @click="handleCheck(scope.row)" type="text" size="small">查看</el-button>
                    <el-button @click="handleBook(scope.row)" type="text" size="small">预约</el-button>
                </template>
            </el-table-column>
        </el-table>
        <!-- 定义一个分页标签 -->
        <div>
            <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageNum"
                :page-sizes="[3, 8, 15, 30]" :page-size="3" layout="total, sizes, prev, pager, next, jumper" :total="total">
            </el-pagination>
        </div>
    </div>
</template>
  
<script>
import RandomUtil from "../utils/randomUtil";
import Store from "../utils/store";
//导入request工具
import request from "@/utils/request";
export default {
    data() {
        return {
            search: "", //当前输入框的值
            isFocus: false, //是否聚焦
            hotSearchList: ["暂无热门搜索"], //热门搜索数据
            historySearchList: [], //历史搜索数据
            searchList: ["暂无数据"], //搜索返回数据,
            history: false,
            bookDoctor: '',
            bookTime: [
                {
                    time: "8:00~9:00",
                    Remain: 3,
                },
            ],
            introductionDialog: false,
            appointmentDialog1: false,
            appointmentDialog2: false,
            total: 0,
            pageNum: 1,
            pageSize: 3,
            value: new Date(),
            imageUrl: 'https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg',
            types: ["", "success", "info", "warning", "danger"], //搜索历史tag式样
            tableData: [
            ],
            form: {
                doctorId: '',
                department: '',
                name: '',
                province: '',
                city: '',
                address: '',
                culture: '',
                phone: '',
                image: '',
                sex: '',
                age: '',
                introduction: '',
            },
        };
    },
    // 通过在生命周期创建时候就使用查询方法
    created() {
        this.query();
    },
    methods: {
        focus() {
            this.isFocus = true;
            this.historySearchList =
                Store.loadHistory() == null ? [] : Store.loadHistory();
            this.history = this.historySearchList.length == 0 ? false : true;
        },
        blur() {
            var self = this;
            this.searchBoxTimeout = setTimeout(function () {
                self.isFocus = false;
            }, 300);
        },
        enterSearchBoxHanlder() {
            clearTimeout(this.searchBoxTimeout);
        },
        searchHandler() {
            //随机生成搜索历史tag式样
            let n = RandomUtil.getRandomNumber(0, 5);
            //发起一个异步请求,查询分类的数据
            request
                // get表示指定请求地址 和 请求参数
                .get("/vaccinum/doctor/SerchByName", {
                    params: {
                        pageNum: this.pageNum,
                        pageSize: this.pageSize,
                        name: this.search,
                    },
                })
                // then表示请求后的回调函数
                .then((res) => {
                    console.log(res);
                    // 把后台的响应的数据赋值给data中的tableData
                    this.tableData = res.list;
                    this.form = res.list;
                    this.total = res.total;
                });
            let exist =
                this.historySearchList.filter(value => {
                    return value.name == this.search;
                }).length == 0
                    ? false
                    : true;
            if (!exist) {
                this.historySearchList.push({ name: this.search, type: this.types[n] });
                Store.saveHistory(this.historySearchList);
            }
            this.history = this.historySearchList.length == 0 ? false : true;
        },
        closeHandler(search) {
            this.historySearchList.splice(this.historySearchList.indexOf(search), 1);
            Store.saveHistory(this.historySearchList);
            clearTimeout(this.searchBoxTimeout);
            if (this.historySearchList.length == 0) {
                this.history = false;
            }
        },
        searchistory(search) {
            this.search = search.name;
        },
        removeAllHistory() {
            Store.removeAllHistory();
        },





        // 执行搜索函数,将后端数据展示出来
        query() {
            //发起一个异步请求,查询分类的数据
            request
                // get表示指定请求地址 和 请求参数
                .get("/vaccinum/doctor/list", {
                    params: {
                        pageNum: this.pageNum,
                        pageSize: this.pageSize,
                    },
                })
                // then表示请求后的回调函数
                .then((res) => {
                    console.log(res);
                    // 把后台的响应的数据赋值给data中的tableData
                    this.tableData = res.list;
                    this.form = res.list;
                    this.total = res.total;
                });

        },


        
        handleCheck(row) {
            console.log(row);
            this.introductionDialog = true;
            this.doctorId = row.doctorId;
            this.form.department = row.department;
            this.form.name = row.name;
            this.form.province = row.province;
            this.form.city = row.city;
            this.form.address = row.address;
            this.form.culture = row.culture;
            this.form.phone = row.phone;
            this.form.image = row.image;
            this.form.introduction = row.introduction;
        },
        handleBook(row) {
            console.log(row);
            this.bookDoctor = row.name;
            this.appointmentDialog1 = true;
        },
        handleBooktime(index,row){
            // TODO 向后端发送用户提交的预约信息
            console.log(row.time);
            this.bookTime[index].Remain=this.bookTime[index].Remain-1;

        },
        //筛选功能实现函数
        resetDateFilter() {
            this.$refs.filterTable.clearFilter('date');
        },
        clearFilter() {
            this.$refs.filterTable.clearFilter();
        },
        formatter(row, column) {
            return row.address;
        },
        filterTag(value, row) {
            return row.tag === value;
        },
        filterHandler(value, row, column) {
            const property = column['property'];
            return row[property] === value;
        },
        //修改单页数据数量
        handleSizeChange(val) {

            this.pageSize = val;
            this.query();
        },
        //跳转页码
        handleCurrentChange(val) {
            console.log(val);
            this.pageNum = val;
            this.query();
        },
        // 日历触发事件
        allcalendar(data) {
            const loading = this.$loading({
                // lock: true,  //加上这个 页面点击日历的时候会莫名其妙抖动一下 因为我界面上有滚动条,所以我注释了
                text: "Loading",
                spinner: "el-icon-loading",
                background: "rgba(0, 0, 0, 0.7)",
            });
            setTimeout(() => {
                this.value = data.day; //取到你需要的日期data.day
                //需要用到这日期做啥事,比如做为调接口的参数
                request
                    // get表示指定请求地址 和 请求参数
                    .get("/doctor/freetime", {
                        params: {
                            name: this.bookDoctor,
                            date: data.day,
                        },
                    })
                    // then表示请求后的回调函数
                    .then((res) => {
                        console.log(res);
                    });
                this.appointmentDialog1 = false;
                this.appointmentDialog2 = true;
                loading.close();
            }, 500);
        },
    },
    computed: {
        isHistorySearch() {
            return this.isFocus && !this.search;
        },
        isSearchList() {
            return this.isFocus && this.search;
        },
        isSearch() {
            return this.isFocus;
        }
    },
   
};
    
</script>
  
<style>
.left {
    margin-left: 200px;
}

.center {
    margin-top: 15px;
    margin-left: 200px;
}

#search {
    background-color: #616cee;
    border-radius: 0%;
}

.search-title {
    color: #bdbaba;
    font-size: 15px;
    margin-bottom: 5px;
}

.remove-history {
    color: #bdbaba;
    font-size: 15px;
    float: right;
    margin-top: -22px;
}

#search-box {
    width: 555px;
    height: 300px;
    margin-top: 0px;
    padding-bottom: 20px;
}

.avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
}

.avatar-uploader .el-upload:hover {
    border-color: #409eff;
}

.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
}

.avatar {
    width: 178px;
    height: 178px;
    display: block;
}

.temp {
    padding: 20px;
}
</style>

------------后端接口------------

功能一:分页查询医生基础信息(介绍MybatisPlus如何使用分页)

//    接口
//    TODO:接口功能:查询医生一般信息
@RequestMapping("/list")
public String query(@RequestParam(defaultValue = "1") Integer pageNum,
                    @RequestParam(defaultValue = "2") Integer pageSize) throws JsonProcessingException {

    // 创建分页对象
    Page<Doctor> page = new Page<>(pageNum, pageSize);

    // 执行分页查询
    IPage<Doctor> doctorIPage = doctorService.page(page);

    // 从分页对象中获取分页数据和总记录数
    List<Doctor> pageInfoList = doctorIPage.getRecords();
    long total = doctorIPage.getTotal();

    // 构造返回的医生信息列表
    List<DoctorSummary> doctorSummaryList = new ArrayList<>();
    for (Doctor doctor:pageInfoList){
        doctorSummaryList.add(new DoctorSummary(doctor.getHostId(),doctor.getName(),doctor.getPhone(),doctor.getImage(),doctor.getMajor()));
    }

    // 返回医生不敏感信息的信息
    return JsonTool.writeValueAsString(doctorSummaryList);
}

收获:MyBatis-Plus的分页插件与MyBatis的PageHelper的区别和使用。

区别:

  • 使用范围:

    • MyBatis-Plus 是一个全面的持久层框架,提供了更多的 CRUD 操作和通用的数据库操作,同时包含了一些方便的工具类和增强功能。
    • PageHelper 是一个简单且专注于分页功能的插件,主要用于处理基本的分页查询需求,不包含其他复杂的数据库操作。
  • 使用方式:

    • MyBatis-Plus 的分页插件是内置在框架中的,无需额外引入依赖,可以直接使用其中的 Page 类进行分页查询,并且提供了丰富的分页查询方法。
    • PageHelper 需要单独引入依赖,根据具体的项目和需求选择相应的版本。使用 PageHelper 需要在 MyBatis 的配置文件中进行配置,并通过拦截器实现分页功能。
  • API 和功能支持:

    • MyBatis-Plus 提供了更多的 API 和功能,如分页查询、排序、条件查询、自定义查询等。同时也支持 Lambda 表达式来简化条件查询的编写。
    • PageHelper 的功能相对较为简单,主要提供了基本的分页功能,可以通过设置分页参数进行分页查询。

使用MyBatisPlus的方法,如下:
1.引入mybatis-plus依赖

        <!--mybatis-plus插件-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>

2.进行配置,在config包下写对应配置类,按照如下代码进行配置

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        // 创建 MybatisPlusInterceptor 对象
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 创建并添加 PaginationInnerInterceptor 分页拦截器
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        interceptor.addInnerInterceptor(paginationInnerInterceptor);

        // 返回 MybatisPlusInterceptor 对象,作为一个 Bean 注入到 Spring 容器中
        return interceptor;
    }
}

 3.在控制层使用插件(通过案例代码解析插件使用步骤)

  1. 创建分页对象 Page<Doctor> page = new Page<>(pageNum, pageSize);

    • pageNum 表示当前页码,指定要查询的页数。
    • pageSize 表示每页显示的记录数,指定每页要展示多少条数据。通过这两个参数,可以确定分页查询的起始位置和返回的记录数量。
  2. 执行分页查询 IPage<Doctor> doctorIPage = doctorService.page(page);

    • doctorService.page(page) 是调用 doctorService 中的 page 方法来执行分页查询操作。
    • IPage<Doctor> 是 MyBatis-Plus 框架提供的分页结果对象,其中包含了分页查询的结果数据和总记录数。
  3. 从分页对象中获取分页数据和总记录数:

    • List<Doctor> pageInfoList = doctorIPage.getRecords(); 获取当前页的数据列表。
    • long total = doctorIPage.getTotal(); 获取查询结果的总记录数。

总结:

  • Page<Doctor> 对象是 MyBatis-Plus 提供的分页对象,用于指定当前页码和每页显示的记录数。
  • IPage<Doctor> 对象是分页查询的结果对象,包含了分页查询的数据列表和总记录数。
  • 通过 getRecords() 方法可以获取当前页的数据列表。
  • 通过 getTotal() 方法可以获取查询结果的总记录数。

下面介绍IPage的常用方法获取分页信息:

方法描述
long getTotal()获取查询结果的总记录数。
List<T> getRecords()获取当前页的数据列表。
int getCurrent()获取当前页码。
int getSize()获取每页显示的记录数。
int getPages()获取总页数。
default boolean hasPrevious()判断是否有上一页。
default boolean hasNext()判断是否有下一页。
List<OrderItem> orders()获取排序的字段和排序方式。可以用于在分页查询时设置排序规则。

Api接口测试结果:

前端功能显示:

3条每页展示

8条每页展示


功能二:根据搜索栏名称查找对应医生(讲解自定义查询集)

//  TODO:根据搜索栏查找对应医生
    @RequestMapping("/SerchByName")
    public String SerchByName(@RequestParam("name")String name,
                              @RequestParam(defaultValue = "1") Integer pageNum,
                              @RequestParam(defaultValue = "8") Integer pageSize) throws JsonProcessingException {
//        创建分页对象
        Page<Doctor> page = new Page<>(pageNum,pageSize);
//        自定义查询
        QueryWrapper<Doctor> wrapper = new QueryWrapper<>();
        wrapper.eq("name",name);

//        创建分页结果对象
        IPage<Doctor> iPage = doctorService.page(page,wrapper);
        List<Doctor> list = iPage.getRecords();

        List<DoctorSummary> doctorSummaryList = new ArrayList<>();
        for (Doctor doctor:list){
            doctorSummaryList.add(new DoctorSummary(doctor.getHostId(),doctor.getName(),doctor.getPhone(),doctor.getImage(),doctor.getMajor()));
        }
        return JsonTool.writeValueAsString(doctorSummaryList);
    }

收获:学习查询模块的使用(QueryWrapper)

使用步骤(三层框架)

1.首先创建QueryWrapper对象

2.通过调用对象内部方法完善自定义查询的条件,以下是常用的方法

方法名说明
eq设置等于条件
ne设置不等于条件
gt设置大于条件
ge设置大于等于条件
lt设置小于条件
le设置小于等于条件
between设置范围条件
like设置模糊查询条件
in设置包含在列表中的条件
orderByAsc设置升序排序字段
orderByDesc设置降序排序字段
and设置并且连接的条件
or设置或者连接的条件
last直接拼接在 SQL 语句的最后
select设置要查询的字段
groupBy设置分组字段
having设置聚合条件

3.通过自动注入对应的service层,实现对应的操作

MyBatisPlus扩展下service层的所有快捷方法:

方法名作用
save保存实体对象到数据库
saveBatch批量保存实体对象到数据库
removeById根据ID删除数据库中的记录
removeByMap根据条件删除数据库中的记录
remove根据条件删除数据库中的记录
removeByIds根据ID列表批量删除数据库中的记录
updateById根据ID更新数据库中的记录
update根据条件更新数据库中的记录
updateBatchById根据ID列表批量更新数据库中的记录
saveOrUpdate如果存在则更新,否则保存实体对象到数据库
getById根据ID从数据库中查询对应的记录
listByIds根据ID列表从数据库中查询对应的记录
listByMap根据条件从数据库中查询对应的记录
getOne根据条件从数据库中查询一条记录
getMap根据条件从数据库中查询一条记录,并返回Map形式的结果
getObj根据条件从数据库中查询一条记录,并通过自定义函数进行映射转换
count计算数据库中符合条件的记录数量
list根据条件从数据库中查询多条记录
page根据条件从数据库中分页查询记录
listMaps根据条件从数据库中查询多条记录,并以Map形式返回结果
listObjs根据条件从数据库中查询多条记录,并返回Object类型的结果列表
pageMaps根据条件从数据库中分页查询记录,并以Map形式返回结果
getBaseMapper获取基础的Mapper接口,用于执行底层的数据库操作
getEntityClass获取实体类的Class对象
query创建一个QueryChainWrapper对象,用于构建查询条件
lambdaQuery创建一个LambdaQueryChainWrapper对象,用于构建Lambda表达式查询条件
ktQuery创建一个KtQueryChainWrapper对象,用于构建Kotlin DSL查询条件
ktUpdate创建一个KtUpdateChainWrapper对象,用于构建Kotlin DSL更新条件
update创建一个UpdateChainWrapper对象,用于构建更新条件
lambdaUpdate创建一个LambdaUpdateChainWrapper对象,用于构建Lambda表达式更新条件
saveOrUpdate如果存在则根据条件更新数据库中的记录,否则保存实体对象到数据库

api调试结果:

前端功能显示:


功能三: 实现获取医生的详细信息

代码如下:

//    TODO:获取医生的详细信息
    @RequestMapping("/getDetail")
    public String getDetail(@RequestParam("id") Integer id) throws JsonProcessingException {

        QueryWrapper<Doctor> wrapper = new QueryWrapper<>();
        wrapper.eq("id",id);

        Doctor doctorServiceById = doctorService.getOne(wrapper);
        DoctorDetailSummary doctorDetailSummary =
                new DoctorDetailSummary(doctorServiceById.getHostId(),
                                        doctorServiceById.getName(),
                                        doctorServiceById.getPhone(),
                                        doctorServiceById.getImage(),
                                        doctorServiceById.getMajor(),
                                        doctorServiceById.getSchool());
        return JsonTool.writeValueAsString(doctorDetailSummary);
    }

这个功能需要前端在展示医生基础数据时候,还能进行查看更多详细但是不敏感的信息。

api测试结果:

前端功能实现展示:
 


功能四:实现预约功能

@RestController
@RequestMapping("/vaccinum/registration")
public class RegistrationController {
    @Autowired
    IRegistrationService registrationService;
    ObjectMapper JSon_Tool = new ObjectMapper();

    @RequestMapping("/insert")
    public String register(Registration registration) throws JsonProcessingException {
        HashMap map = new HashMap();
        boolean save = registrationService.save(registration);
        map.put("flag",save);
        return JSon_Tool.writeValueAsString(map);
    }
}


功能五:根据医生科室查询医生

//  TODO:根据医院的科室查询对应医生
    @RequestMapping("/SerchByMajor")
    public String SerchByMajor(@RequestParam("major") String major,
                               @RequestParam(defaultValue = "1") Integer pageNum,
                               @RequestParam(defaultValue = "8") Integer pageSize) throws JsonProcessingException {

        HashMap map = new HashMap<>();
        Page<Doctor> page = new Page<>(pageNum,pageSize);

        QueryWrapper<Doctor> wrapper = new QueryWrapper<>();
        wrapper.eq("major",major);

        IPage<Doctor> iPage = doctorService.page(page,wrapper);
        List<Doctor> list = iPage.getRecords();

//        获取信息
        List<DoctorSummary> doctorSummaryList = new ArrayList<>();
        for (Doctor doctor:list){
            doctorSummaryList.add(new DoctorSummary(doctor.getHostId(),doctor.getName(),doctor.getPhone(),doctor.getImage(),doctor.getMajor()));
        }

        map.put("list",doctorSummaryList);
        map.put("total",iPage.getTotal());
        return JsonTool.writeValueAsString(doctorSummaryList);
    }

 Apifox测试:

注意:

由于这里没有和前端沟通好,前端直接使用了elementUi中自带的种类查询,这样会导致一个问题,那就是后端给的数据在前端筛选,导致分页功能无法正常使用。

如图:

3条每页的数据只有两条,甚至一条或者空,这是因为,在前端访问后端并返回数据时候,这个页面是固定数据的3条每一页。而elementUi在此基础上进行筛选,三条数据中major==外科手术的只有两条,那么就保留两条。


收获与反思

收获:

本次我负责后端的接口开发,这次的模块功能开发,

1.让我了解了MybatisPlus的分页是如何实现的,与一般的MyBatis的区别之处。

2.然后就是自定义结果集(QueryWrapper)的基本使用。

3.MyBatisPlus提供的快速方法,进行一些基本的了解

反思:

  • 第一,代码需要规范,与前端交接时候,前端代码应该有条理性,前端模块开发中函数设计分区块,即前端自行处理的区块,和后端交互的函数区块需要分开。并且注意在函数前加上注释。否则若只给后端前端的代码,后端只能看到一坨捆绑的线团。不知所云。
  • 第二,并且需要基于事实实现对应的功能。根据数据库实际的列去实现,这里前端做的预约功能虽然看似合理,但是缺少了对应的信息填写表格。
  • 第三, 后端方面的问题,第一,返回的格式类型应该以map形式传递,这样能保证传输格式的灵活性。这里一开始就仅仅传递一个链表返回,并未考虑可能有其它参数需要返回。
  • 第四,如果写好了开发文档,请前端务必按照开发文档中来做,这里我后端其实还实现一个功能,根据科室进行查找对应的医生,但是前端中使用组件的方式,
  • 最后,在前后端的开发中一定一定要保持交流,任何的改动都需要跟对方谈好,否则会给双方带来极大的困扰!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1190937.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SRRC认证的必要性:保障电子产品质量安全的重要措施

随着电子产品的普及和应用&#xff0c;对电子产品的质量安全要求也越来越高。为了保障消费者的权益和安全&#xff0c;国家对电子产品进行了严格的监管和管理。其中&#xff0c;SRRC认证是保障电子产品质量安全的重要措施之一。 SRRC认证是指在我国境内生产、销售、使用的无线电…

(动手学习深度学习)第13章 计算机视觉---图像增广与微调

13.1 图像增广 总结 数据增广通过变形数据来获取多样性从而使得模型泛化性能更好常见图片增广包裹翻转、切割、变色。 图像增广代码实现

简单剖析程序的翻译过程!

本文旨在讲解一段源程序如何翻译成机器所能识别的二进制的命令的&#xff0c;希望通过本文&#xff0c;能使读者对一段程序的翻译过程有进一步的认识&#xff01; 这里首先要介绍的是一段程序从编写完成到执行需要经过以下几个步骤&#xff01; 1.预处理 首先讲到的是预处理&…

十八章总结

一.Swing概述 二.Swing常用窗体 1.JFrame窗体 创建一个不可见、具有标题的窗体&#xff0c;关键代码&#xff1a; JFrame jfnew JFrame("登陆系统"); Container containerjf.getContentPane(); 删除容器中的按钮&#xff0c;关键代码&#xff1a; container.remo…

Ubuntu22.04配置Go环境

Ubuntu上配置Go环境biCentOS简单多了&#xff0c;有两种方案&#xff0c;一种直接使用apt进行安装&#xff0c;一种自己从官网下载安装包进行安装。 1、使用apt直接安装 更新apt安装包&#xff0c;常规操作 apt update 然后看看apt自带的Go版本是多少 apt list golang 是1…

【C++】复杂的多继承及其缺陷(菱形继承)

本篇要分享的内容是C中多继承的缺陷&#xff1a;菱形继承。 以下为本篇目录 目录 1.多继承的缺陷与解决方法 2.虚继承的底层原理 3.虚继承底层原理的设计原因 1.多继承的缺陷与解决方法 首先观察下面的图片判断它是否为多继承 这实际上是一个单继承&#xff0c;单继承的特…

对象序列化

介绍 作用&#xff1a;以内存为基准&#xff0c;把内存中的对象存储到磁盘文件中去&#xff0c;称为对象序列化。 使用到的流是对象字节输出流&#xff1a;ObjectOutputStream。 ObjectOutputStream序列化方法 序列化对象的要求是对象必须实现序列化接口。 示例&#xff1…

面试算法常考题之-------逆波兰式合集

逆波兰式背景介绍 逆波兰式是一种特殊的数学表达式表示法&#xff0c;它的诞生背景可以追溯到20世纪30年代。当时&#xff0c;波兰数学家Jan Wjtowicz和Wacław Sierpiński提出了一种新的数学表达式表示法&#xff0c;这种表示法将运算符放在操作数之后&#xff0c;而不是传统…

Stable Diffusion webui 源码调试(二)

Stable Diffusion webui 源码调试&#xff08;二&#xff09; 个人模型主页&#xff1a;LibLibai stable-diffusion-webui 版本&#xff1a;v1.4.1 内容更新随机&#xff0c;看心情调试代码~ 分析StableDiffusionProcessingTxt2Img类中的sample函数 Sampler /work/stable-d…

xxx升学助考网登录参数跟栈分析

逆向参数分析&#xff1a; 思路&#xff1a; ​ 如果参数出现的次数比较少&#xff0c;完全可以使用全局搜索 ​ 如果参数出现比较多&#xff0c;建议使用跟栈 网站&#xff1a; 下面运行结果 import base64 # 解密 result base64.b64decode(aHR0cHM6Ly93ZWIuZXd0MzYwLm…

【经验模态分解】3.EMD模态分解算法设计与准备工作

/*** poject 经验模态分解及其衍生算法的研究及其在语音信号处理中的应用* file EMD模态分解算法设计与准备工作* author jUicE_g2R(qq:3406291309)* * language MATLAB* EDA Base on matlabR2022b* editor Obsidian&#xff08;黑曜石笔记软…

Day25力扣打卡

打卡记录 寻找旋转排序数组中的最小值&#xff08;二分&#xff09; 链接 由于是旋转排序数组&#xff0c;所以整个数组有两部分是递增的&#xff0c;选取右侧最后元素&#xff0c;即可将整个数组分为大于该元素和小于该元素&#xff0c;碰头地段即为最小值。 class Solutio…

Effective C++ 系列和 C++ Core Guidelines 如何选择?

Effective C 系列和 C Core Guidelines 如何选择&#xff1f; 如果一定要二选一&#xff0c;我会选择C Core Guidelines。因为它是开源的&#xff0c;有300多个贡献者&#xff0c;而且还在不断更新&#xff0c;意味着它归纳总结了最新的C实践经验。最近很多小伙伴找我&#xff…

系列二、Shiro的核心组件

一、核心组件 # 1、UsernamePasswordToken 封装了用户的登录信息&#xff0c;使用用户的登录信息来创建Token # 2、SecurityManager Shiro的核心组件&#xff0c;负责安全认证和授权 # 3、Subject Shiro的一个抽象概念&#xff0c;包含了用户信息 # 4、Realm 开发者自定义的模块…

AcWing99. 激光炸弹

题目 地图上有 N N N 个目标&#xff0c;用整数 X i , Y i X_i,Y_i Xi​,Yi​ 表示目标在地图上的位置&#xff0c;每个目标都有一个价值 W i W_i Wi​。 注意&#xff1a;不同目标可能在同一位置。 现在有一种新型的激光炸弹&#xff0c;可以摧毁一个包含 R R RR RR 个…

SpringBoot自动配置的原理篇,剖析自动配置原理;实现自定义启动类!附有代码及截图详细讲解

SpringBoot 自动配置 Condition Condition 是在Spring 4.0 增加的条件判断功能&#xff0c;通过这个可以功能可以实现选择性的创建 Bean 操作 思考&#xff1a;SpringBoot是如何知道要创建哪个Bean的&#xff1f;比如SpringBoot是如何知道要创建RedisTemplate的&#xff1f;…

前端-第一部分-HTML

一.初识HTML 1.1 HTML 简介 HTML 全称为 HyperText Mark-up Language&#xff0c;翻译为超文本标签语言&#xff0c;标签也称作标记或者元素。HTML 是目前网络上应用最为广泛的技术之一&#xff0c;也是构成网页文档的主要基石之一。HTML文本是由 HTML 标签组成的描述性文本&a…

在Rust中使用多线程并发运行代码

1.Rust线程实现理念 在大部分现代操作系统中&#xff0c;已执行程序的代码在一个 进程&#xff08;process&#xff09;中运行&#xff0c;操作系统则会负责管理多个进程。在程序内部&#xff0c;也可以拥有多个同时运行的独立部分。这些运行这些独立部分的功能被称为 线程&am…

【js逆向实战】某sakura动漫视频逆向

写在前面 再写一个逆向实战&#xff0c;后面写点爬虫程序来实现一下。 网站简介与逆向目标 经典的一个视频网站&#xff0c;大多数视频网站走的是M3U8协议&#xff0c;就是一个分段传输&#xff0c;其实这里就有两个分支。 通过传统的m3u8协议&#xff0c;我们可以直接进行分…

千万别对女项目经理抱有幻想

大家好&#xff0c;我是老原。 前段时间&#xff0c;有一个粉丝朋友来咨询我一个问题&#xff0c;多少是有点把老原我问蒙圈 现在职场上女PM并不少见&#xff0c;也有很多优秀的女PM。 我也有不少和女PM合作的经历&#xff0c;不得不说&#xff0c;和她们沟通/合作可以说是很…