Ashun's 技術駅 Ashun's 技術駅
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • Vue
  • 现代web布局
  • React
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 技术资源
  • 第一阶段

    • HTML
  • 第二阶段

    • JavaScript
  • 第三阶段

    • Vue
  • 第四阶段

    • 实战项目
  • 每周测试

    • 每周
  • 其他

    • Vue引入UI框架
    • Web前端面试
    • Vue3-resource
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 福利资源
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Ashun

前端界的小学生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • Vue
  • 现代web布局
  • React
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 技术资源
  • 第一阶段

    • HTML
  • 第二阶段

    • JavaScript
  • 第三阶段

    • Vue
  • 第四阶段

    • 实战项目
  • 每周测试

    • 每周
  • 其他

    • Vue引入UI框架
    • Web前端面试
    • Vue3-resource
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 福利资源
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 核心概念

  • 高级指引

  • Hook

  • 案例演示

  • 商医通项目

    • react基础笔记
    • typescript笔记
    • antd基本使用
    • react项目笔记
      • 1-1. 项目clone
      • 1-2. 目录结构
      • 1-3. final项目安装依赖并运行
      • 5-1. 创建路由组件
      • 5-2. 完成路由配置
      • 5-3. 医院设置静态布局完成
      • 5-4. 查看接口定义类型-api函数
      • 5-5. 调用api
      • 5-6. 渲染数据
      • 7-1. 查看接口
      • 7-2. 点击保存
      • 8-1. 查看接口
      • 8-2. 实现删除功能
      • 11-1. 省市区联动bug解决
      • 12-1. 接口相关类型封装
      • 12-2. api函数封装
      • 12-3. 渲染医院列表及分页
      • 12-4. 查询、清空功能
        • 12-4-1. 查询功能实现
        • 12-4-2. 清空功能实现
      • 13-1. 渲染科室列表
      • 13-2. 排班日期分页数据获取
        • 13-2-1. api类型及函数封装
        • 13-2-2. api函数调用时机及状态定义
      • 13-3. 医生列表渲染
        • 13-3-1. 医生列表api类型及api函数定义
      • 17-1. 学习:
      • 17-2. 找工作
      • 17-3. 工作前三个月
    • 课件-react路由-V6
    • 课件-redux-toolkit
    • 课件-国际化
    • 课件-其他hooks
    • 课件-虚拟dom和diff算法
  • 《React》笔记
  • 商医通项目
ashun
2024-01-22
目录

react项目笔记

# 1. 项目安装运行

# 1-1. 项目clone

git clone https://gitee.com/yuonly0528/react-project.git
1

# 1-2. 目录结构

06_React_project
   |- syt-admin_docs        项目开发文档
   |- syt-admin-final       完成的项目
   |- syt-admin-react-base  二次开发的项目
1
2
3
4

# 1-3. final项目安装依赖并运行

  1. 修改镜像源:

    # 腾讯
    npm config set registry http://mirrors.cloud.tencent.com/npm
    # 淘宝
    npm config set registry https://registry.npmmirror.com
    # npm 原镜像
    npm config set registry https://registry.npmjs.org
    
    1
    2
    3
    4
    5
    6
  2. 启动final项目:进入项目根目录,打开终端

    cd syt-admin-final
    npm i -f  # -f force 强制安装
    npm start 启动项目
    
    1
    2
    3
  3. 启动 base项目:进入base项目目录,打开终端

    cd syt-admin-react-base
    npm i -f
    npm start
    
    1
    2
    3
  4. 可能出现的错误及解决方案:

    1. 由于网络原因,导致包没下全。
      1. 删除node_modules : 切换源 重新 npm i -f安装
      2. 叉掉错误:对付用
    2. token异常:
      1. 删除本地存储的token,刷新页面重新登录

# 2. 接口地址

  • 医院接口地址:http://139.198.34.216:8201/swagger-ui.html#/
  • 数据字典接口地址:http://139.198.34.216:8202/swagger-ui.html#/259682545423383208563164929702
  • 登录接口地址:http://139.198.34.216:8212/swagger-ui.html

# 3. 项目目录文件介绍

├── public # 公共静态资源目录
│   ├── favicon.ico # 网站图标
│   ├── index.html # 主页面
├── src # 主目录
│   ├── api # 接口文件
│   ├── app # redux配置文件
│   ├── components # 公共组件
│   │   ├── Loading # loading组件
│   │   ├── Translation # 国际化组件
│   │   └── withAuthorization # 登陆权限校验组件
│   ├── layouts # 主要布局组件
│   ├── locales # i18n国际化配置
│   ├── pages # 路由组件
│   ├── routes # 路由配置
│   ├── styles # 全局/公共样式
│   ├── utils # 工具函数
│   │   └── http # 封装请求函数
│   ├── App.tsx # App组件
│   ├── index.ts # 主入口
│   ├── react-app-env.d.ts # 类型文件,在编译时会引入额外文件
├── .env.development # 开发环境加载的环境变量配置
├── .env.production # 生产环境加载的环境变量配置
├── .gitignore # git忽略文件
├── craco.config.js # react脚手架配置文件
├── package.json # 包文件
├── README.md # 项目说明文件
├── tsconfig.extend.json # 路径别名配置文件
├── tsconfig.json # ts配置文件
└── yarn.lock # yarn下载包的缓存文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 4. 实现功能的流程

  1. 创建路由组件
  2. 配置路由
  3. 创建组件的静态结构
  4. 查看接口
    1. 封装 interface
    2. 封装 api 函数
  5. 调用 api 函数
    1. 事件回调
    2. 钩子函数
  6. 声明状态

# 5. 医院设置功能实现

# 5-1. 创建路由组件

  • 文件创建路径:src/pages/hospital/hospitalSet/HospitalSet.tsx
import React from 'react'
export default function HospitalSet() {
    return (
        <div>HospitalSet</div>
    )
}
1
2
3
4
5
6

# 5-2. 完成路由配置

  1. 导入医院设置路由组件 [懒加载方式导入]
  2. src/routes/index.ts 进行路由配置
  • src/routes/index.ts
{
    path: "/syt",
    element: <Layout />,
    children: [
        {
            // 路由路径
            path: "/syt/dashboard",
            meta: {
                icon: <HomeOutlined />,
                title: '首页'
            },
            element: load(Dashboard),
        },
        {
            path:'/syt/hospital',
            meta:{
                title:'医院管理',
                icon:<ShopOutlined />
            },
            children:[
                {
                    path:'/syt/hospital/hospitalSet',
                    meta:{
                        title:'医院设置'
                    },
                    element:load(HospitalSet)
                }
            ]
        }
    ],
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 5-3. 医院设置静态布局完成

import { Button, Card, Form, Input, Space, Table } from 'antd'
import { ColumnsType } from 'antd/lib/table'
import React from 'react'
export default function HospitalSet() {
    const columns:ColumnsType<any> = [
        {
            title:'序号'
        },
        {
            title:'医院名称'
        },
        {
            title:'医院编号'
        },
        {
            title:'api基础路径'
        },
        {
            title:'签名'
        },
        {
            title:'联系人姓名'
        },
        {
            title:'联系人手机'
        },
        {
            title:'操作'
        }
    ]
    return (
        <Card>
            {/* 1. Form */}
            <Form
                layout='inline'
            >
                <Form.Item>
                    <Input placeholder='医院名称' />
                </Form.Item>
                <Form.Item>
                    <Input placeholder='医院编号' />
                </Form.Item>
                <Form.Item>
                    <Space>
                        <Button type='primary'>查询</Button>
                        <Button>清空</Button>
                    </Space>
                </Form.Item>
            </Form>
            {/* 2. button */}
            <Space className='mt'>
                <Button type='primary'>添加</Button>
                <Button disabled>批量删除</Button>
            </Space>
            {/* 3. Table */}
            <Table 
                className='mt'
                columns={columns}
            />
        </Card>
    )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

# 5-4. 查看接口定义类型-api函数

  1. 查看接口:【请求方式、url、参数、返回值】

  2. 封装interface: 返回值

  3. 封装api函数:

    1. path: request.请求方式<any,响应值类型>(url/参数1/参数2...)
    2. query: request.请求方式<any,响应值类型>(url, {params:参数key:参数值})
    
    1
    2

# 5-5. 调用api

  1. 事件回调
  2. 钩子函数

# 5-6. 渲染数据

  1. 定义状态
  2. 设置状态

# 6. 点击查询获取分页数据

描述: 做了什么,产生了什么结果?

​ 文本框输入内容,点击查询,重新获取分页数据!

拆分步骤:

  1. 获取文本框输入内容
    1. 参数:values
    2. form对象:
      1. const [form] = Form.useForm()
      2. 绑定form对象
      3. form.getFieldsValue获取
      4. Form.Item 要有name属性 hosname hoscode
  2. 给查询按钮绑定单击事件
    1. button htmlType='submit'
    2. Form onFinish ==> search 函数
  3. 根据文本框内容发送ajax请求
    1. 在useEffect 的监听中 监听 hosname hoscode
    2. 在 onFinish的事件回调中,重新设置 hosname 和 hoscode的状态

# 7. 添加医院

# 7-1. 查看接口

  1. 请求方式、url、参数、响应结果
  2. 封装 interface
  3. 封装api函数

# 7-2. 点击保存

描述:点击保存,将表单中的数据添加到医院列表

步骤:

  1. 绑定事件

    1. 给Form绑定 onFinish 事件
    2. Button组件 添加 htmlType='submit'
  2. 获取表单数据

    通过form获取

    1. Form.Item 组件需要有 name属性,并赋值

    2. 创建form: const [form] = Form.useForm()

    3. 给Form组件绑定form属性

    4. 通过form.getFieldsValue获取表单数据

  3. 发送ajax请求

    调用api函数,发送请求

# 8. 删除医院设置

# 8-1. 查看接口

# 8-2. 实现删除功能

  1. 描述:点击删除按钮,根据id删除当前记录

  2. 步骤:

    1. 给删除按钮绑定单击事件,事件回调中要传递当前记录的id
    2. 根据id,调用api函数,实现删除操作。
    3. 刷新列表
  3. 点击删除按钮弹出 confirm模态框

    1. 导入:

      1. import {Modal} from 'antd'
      2. 解构:const {confirm} = Modal
    2. 调用:

      confirm({
          title: '确定删除么?',
          icon: <ExclamationCircleFilled />,
          content: '删除当前记录',
          async onOk() {
              await deleteHospitalSetById(id)
              message.success('删除成功');
              // 刷新列表
              _getHospitalSetList();
          },
          onCancel() {
              console.log('Cancel');
          },
      });
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14

# 9. 批量删除

table 配置 rowSelection

rowSelection={{
    /**
     * onChange调用时机,列表复选框发生变化的时候
     * @param selectedKeys 选中条id组成的数组
     */
    onChange(selectedKeys: React.Key[]) {
        console.log('selectedKeys: ', selectedKeys)
        setSelectedKeys(selectedKeys);
    }
}}
1
2
3
4
5
6
7
8
9
10
  • 点击批量删除按钮
<Button disabled={selectedKeys.length === 0} onClick={() => {
    confirm({
        title: '确定批量删除么?',
        icon: <ExclamationCircleFilled />,
        content: '批量删除记录',
        async onOk() {
            await removeBatch(selectedKeys);
            // 将selectedKeys状态清空成空数组
            setSelectedKeys([]);
            message.success('批量删除成功');
            // 刷新列表
            _getHospitalSetList();
        },
        onCancel() {
            console.log('Cancel');
        },
    });
}}>批量删除</Button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 10. 编辑医院设置

编辑医院设置总共分两个大的步骤:

  1. 点击编辑按钮,跳转到编辑页面,并获取当前条医院设置数据渲染到表单中
  2. 点击表单的保存按钮,将用户最新修改的医院设置数据修改原数据

此处,我们将新增医院设置和编辑医院设置共用了同一个页面 AddOrUpdate.tsx ,通过路由参数id,来区分是编辑还是新增操作

# 11. 医院省市区列表

  1. 查看接口

  2. 封装interface

    /**
     * 省市区 返回数据 对象类型
     */
    export interface IDistrictItem {
        id: number;
        createTime: string;
        updateTime: string;
        name: string;
        value: string;
        hasChildren: boolean;
    }
    /**
     * 省市区列表类型,也是获取省市区列表接口的返回值类型
     */
    export type IDistrictList = IDistrictItem[]
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
  3. 封装api函数

    export const getDistrictList = (id: number) => {
        return request.get<any, IDistrictList>('/admin/cmn/dict/findByParentId/' + id)
    }
    
    1
    2
    3
  4. 调用api函数

    获取省列表在组件挂载完成后的声明周期钩子调用

    市列表是在 省选中后根据 省 id 发请求获取

    区列表时在 市选中后根据 市id 发请求获取

    • 省列表获取
    // 获取省列表
    const getProvinceList = async () => {
        const provinceList = await getDistrictList(86);
        // 设置省状态数据
        setProvinceList(provinceList);
    }
    useEffect(() => {
        getProvinceList();
    }, [])
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    • 获取市列表
    // 根据省id 获取是列表并渲染
    const getCityList = async (id: number) => {
        console.log('id: ', id);
        const cityList = await getDistrictList(id);
        setCityList(cityList);
    }
    
    1
    2
    3
    4
    5
    6
    • 获取区列表
     // 根据市id 获取区列表并渲染
    const getDictList = async (id: number) => {
        console.log('city id: ', id);
        const dictList = await getDistrictList(id);
        setDictList(dictList);
    }
    
    1
    2
    3
    4
    5
    6

# 11-1. 省市区联动bug解决

问题描述:当切换省时,应该将原来省的市、区表单的显示恢复成未选择状态,并且将区列表的状态设置为空数组。

设置表单值,需要使用 form对象更方便。

使用form对象的四个步骤:

  1. 给Form.Item 设置name属性

  2. 创建form: const [form] = Form.useForm()

  3. 绑定form

  4. 使用form的api操作form

    form.getFieldsValue() // 获取表单数据的全部的值
    form.setFieldsValue({key1:value1,key2:value2}) // 设置表单数据的值
    
    1
    2

解决联动bug

  1. 切换省列表,清空市、区的表单、重置区的状态为空数组

    const getCityList = async (id: number) => {
        console.log('id: ', id);
        // 将市、区的表单项赋值为undefined
        form.setFieldsValue({
            cityCode:undefined,
            districtCode:undefined
        })
        // 将区的状态数据设置为空数组
        setDictList([]);
        const cityList = await getDistrictList(id);
        setCityList(cityList);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  2. 切换市列表,清空区的表单

    const getDictList = async (id: number) => {
        console.log('city id: ', id);
        // 将区的表单值设置为undefined
        form.setFieldsValue({
            districtCode:undefined
        })
        const dictList = await getDistrictList(id);
        setDictList(dictList);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

# 12. 医院列表分页功能

# 12-1. 接口相关类型封装

/**
 * 医院列表参数类型
 */
export interface IHospitalListParams {
    page: number;
    limit: number;
    hoscode?: string;
    hosname?: string;
    hostype?: string;
    provinceCode?: string;
    cityCode?: string;
    districtCode?: string;
    status?: number;
}
/**
 * 医院列表每一项 类型
 */
export interface IHospitalItem {
    id: string;
    createTime: string; // 创建时间
    param: {
        hostypeString: string; // 医院等级
        fullAddress: string; // 医院地址
    },
    hoscode: string; // 医院编号
    hosname: string; // 医院名
    hostype: string; // 医院类型
    provinceCode: string; // 省
    cityCode: string; // 市
    districtCode: string; // 区
    address: string; // 地址
    logoData: string; // 医院logo base64URL
    route: string;  //乘车路线
    status: number; // 医院状态
    bookingRule: {
        cycle: number; // 预约周期
        releaseTime: string; // 放号时间
        stopTime: string;// 停止挂号时间
        quitDay: number; // 就诊结束日期
        quitTime: string; // 结束时间
        rule: string[]; //取号规则
    }
}
/**
 * 医院列表类型
 */
export type IHospitalList = IHospitalItem[]

/**
 *  请求医院列表响应对象类型
 */
export interface IHospitalListResponse {
    content:IHospitalList;
    totalElements:number;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# 12-2. api函数封装

/**
 * 获取医院列表分页数据api方法
 * @param param0 
 * @returns 
 */
export const getHospitalList = ({page,limit,hoscode,hosname,hostype,provinceCode,cityCode,districtCode,status}:IHospitalListParams)=>{
    return request.get<any, IHospitalListResponse>(`/admin/hosp/hospital/${page}/${limit}`, {
        params:{
            hoscode,
            hosname,
            hostype,
            provinceCode,
            cityCode,
            districtCode,
            status
        }
    })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 12-3. 渲染医院列表及分页

  1. 定义分页相关状态
  2. 定义获取医院分页列表的async函数
  3. 定义useEffect 生命周期钩子并调用
  4. 给Table组件添加 rowKey dataSource
  5. 给columns 数组中的对应列配置对象,定义 dataIndex或 render
  6. 给table定义 pagination,实现分页
  7. 给useEffect添加监听 current, pageSize
  8. 给请求方法中的固定值参数,替换成 状态数据

# 12-4. 查询、清空功能

查询实现原理:

  1. 点击查询按钮,获取表单中的数据,用来重置状态数据
  2. 在useEffect中监听 表单中对应状态数据的变化,触发重新发送请求
  3. 请求的方法参数,都换成状态数据

# 12-4-1. 查询功能实现

  • 定义form表单对应的状态
let [formFields, setFormFields] = useState<IFormFields>({
    hoscode: undefined,
    hosname: undefined,
    provinceCode: undefined,
    cityCode: undefined,
    districtCode: undefined,
    status: undefined,
    hostype: undefined
})
1
2
3
4
5
6
7
8
9
  • 给Form组件添加 onFinish方法,并绑定事件的回调函数
<Form onFinish={search}>
    
const search = () => {
    setFormFields(form.getFieldsValue());// 获取表单数据最新的值,设置到formFields状态数据中
    setCurrent(1);
}
1
2
3
4
5
6
  • 监听 formFields中每一个值的变化,如果有改变,重新发送ajax请求
useEffect(() => {
        console.log('重新发请求')
        _getHospitalList();
    }, [current, pageSize, formFields.hoscode, formFields.hosname, formFields.cityCode, formFields.provinceCode, formFields.districtCode, formFields.hostype, formFields.status])
1
2
3
4
  • 修改_getHospitalList() 函数中的参数,带上状态数据 formFields
const _getHospitalList = async () => {
    setLoading(true);
    let { content, totalElements } = await getHospitalList({ page: current, limit: pageSize, ...formFields });
    
    // 设置医院列表状态
    setHospitalList(content);
    setTotal(totalElements);
    setLoading(false);
}
1
2
3
4
5
6
7
8
9

# 12-4-2. 清空功能实现

  1. 设置清空按钮 disabled 的禁用条件
  2. 给清空按钮绑定事件回调函数 clear
  3. clear中的逻辑
    1. 重置表单数据为空
    2. 重置状态数据 formFields 各项值为undefined
    3. 设置为当前页
  • 按钮 disabled禁用条件
<Button disabled={Object.values(formFields).every(item => item === undefined)} onClick={clear}>清空</Button>
1
  • clear 实现逻辑
const clear = () => {
    // 清空form表单的数据
    // 清空 formFields 状态的值都为 undefined
    // 当前页设置为 1
    form.resetFields();
    setFormFields({
        hoscode: undefined,
        hosname: undefined,
        provinceCode: undefined,
        cityCode: undefined,
        districtCode: undefined,
        status: undefined,
        hostype: undefined
    })
    setCurrent(1);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 13. 排班管理

# 13-1. 渲染科室列表

科室列表的渲染,需要将请求回来的数据处理成符合tree组件使用的数据,需要做如下配置:

  1. fieldsName:设置 key code children的映射关系
  2. expandedKeys:设置要默认展开的树节点
  3. disabled:true => 设置禁用的节点
  4. selectedKeys: 这只默认被选中的树节点
  5. onSelected: 点击切换树节点切换科室
let [departmentList, setDepartmentList] = useState<IDepartmentList>([]);
let [expandedKeys, setExpandedKeys] = useState<string[]>([]);// 一级科室depcode组成的数组
let [depname, setDepname] = useState<string>();
let [depcode, setDepcode] = useState<string>();
const _getDepartmentList = async ()=>{
    let departmentList = await getDepartmentList(hoscode as string);
    console.log('departmentList: ', departmentList);

    // 禁用一级科室树节点,就是给所有的一级科室对象,添加一个disabled:true
    departmentList = departmentList.map(item=>{
        item.disabled = true;
        return item;
    })
    // 展开所有的一级科室
    // 1. 获取所有一级科室 depcode组成的数组
    let expandedKeys = departmentList.map(item=>item.depcode)
    console.log('expandedKeys', expandedKeys);
    setExpandedKeys(expandedKeys);
    setDepartmentList(departmentList);// 设置科室列表状态数据

    // 处理默认选中科室
    let depname = (departmentList[0].children as IDepartmentList)[0].depname;
    let depcode = (departmentList[0].children as IDepartmentList)[0].depcode;
    // console.log(depname);
    // console.log(depcode);
    // 设置科室名和科室code状态
    setDepname(depname);
    setDepcode(depcode);
}

useEffect(()=>{
    hoscode && _getDepartmentList();
}, [])

// tree组件
<Tree                      
    // onSelect={onSelect}
    // onCheck={onCheck}
    treeData={departmentList as []}
    fieldNames={{
        title:'depname',
        key:'depcode'
    }}
    expandedKeys={expandedKeys}
    selectedKeys={[depcode as string]}
    onSelect={(selectedKeys:any,info:any)=>{
        // console.log('selectedKeys: ', selectedKeys);
        // console.log('info:', info);
        // 重新设置depcode和depname
        setDepcode(info.node.depcode);
        setDepname(info.node.depname);
    }}
/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

# 13-2. 排班日期分页数据获取

排班日期分页数据,依赖于depcode,所以执行的时机是depcode如果发生改变,重新获取该科室的排班日期列表

# 13-2-1. api类型及函数封装

  • 类型封装:
/**
 * 排班日期每一项的类型
 */
export interface IBookingScheduleItem {
    workDate: string;// 排班日期
    dayOfWeek: string;//星期几
    docCount: number;// 已预约人数
    reservedNumber: number;//总预约数
    availableNumber: number;// 剩余预约数
}

export type IBookingScheduleList = IBookingScheduleItem[];

/**
 * 请求排班日期分页数据响应结果的类型
 */
export interface IScheduleResponse {
    total: number;
    bookingScheduleList: IBookingScheduleList;
    baseMap: {
        hosname: string;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  • api函数封装
/**
 * 获取医院科室排班日期分页列表数据
 * @param page     当前页
 * @param limit    每页几条
 * @param hoscode  医院编号
 * @param depcode  科室编号
 * @returns 
 */
export const getScheduleList = (page:number,limit:number,hoscode:string,depcode:string)=>{
    return request.get<any,IScheduleResponse>(`/admin/hosp/schedule/getScheduleRule/${page}/${limit}/${hoscode}/${depcode}`)
}
1
2
3
4
5
6
7
8
9
10
11

# 13-2-2. api函数调用时机及状态定义

  • 状态定义:
let [current, setCurrent] = useState<number>(1);
let [pageSize, setPageSize] = useState<number>(3);
let [total, setTotal] = useState<number>(10);
let [bookingScheduleList, setBookingScheduleList] = useState<IBookingScheduleList>([]);
1
2
3
4
  • 调用时机
//获取医院科室 排班日期数据
const _getScheduleList = async ()=>{
let res = await getScheduleList(current,pageSize,hoscode as string, depcode as string);
    console.log('res: ',res);
}

 useEffect(()=>{
    depcode && _getScheduleList();
},[depcode,current, pageSize]);
1
2
3
4
5
6
7
8
9

# 13-3. 医生列表渲染

# 13-3-1. 医生列表api类型及api函数定义

  • api类型
/**
 * 排班医生对象类型
 */
export interface IDoctorItem {
    id: string;
    createTime: string;
    param: {
        dayOfWeek: string;
        depname: string;
        hosname:string;
    },
    hoscode:string;
    depcode: string;
    title: string;
    skill: string;
    workDate: string;
    reservedNumber: number;
    availableNumber: number;
    amount: number;
    status: number;
}

//排班医生列表类型
export type IDoctorList = IDoctorItem[];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  • api函数封装
/**
 * 获取排班医生列表
 * @param hoscode 
 * @param depcode 
 * @param workDate 
 * @returns 
 */
export const getDoctorList = (hoscode: string, depcode: string, workDate: string) => {
    return request.get<any,IDoctorList>(`/admin/hosp/schedule/findScheduleList/${hoscode}/${depcode}/${workDate}`);
}
1
2
3
4
5
6
7
8
9
10
  • 调用时机
// 获取排班医生列表数据
const _getDoctorList = async ()=>{
    let doctorList = await getDoctorList(hoscode as string, depcode as string, workDate as string);
    // console.log('doctorList: ', doctorList);
    setDoctorList(doctorList);
}

useEffect(()=>{// 组件挂载完成之后执行 + workDate变化后执行
    workDate && _getDoctorList();
}, [workDate]);

1
2
3
4
5
6
7
8
9
10
11
  • 渲染:
<Table
    className='mt'
    pagination={false}
    columns={columns}
    dataSource={doctorList}
    rowKey={'id'}
/>
1
2
3
4
5
6
7

# 14. 项目完成打包上线部署

  1. 构建最终目录: npm run build ===> build
  2. 部署需要解决的问题:
    1. 404 ==》 index.html
    2. 配置静态资源目录
    3. 设置代理服务器完成跨域
const express = require('express');
const history = require('connect-history-api-fallback');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();

// 0. 所有404的相应,使用 index.html替换
app.use(history());
// 1. 配置当前目录为静态资源目录
app.use(express.static('./'));
// 2. 进行跨域配置
app.use('/prod-api', createProxyMiddleware(
    {
        target: "http://syt-api.atguigu.cn", // 目标服务器地址
        changeOrigin: true, // 允许跨域
        pathRewrite: {
            // 路径重写
            "^/prod-api": "",
        },
    }
));
app.listen(5000, () => {
    console.log('server run at 5000');
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 15. 复习

  1. 类组件

    • state:

    ​ 属性直接赋值:

    ​ 构造函数:

    • props:

    ​ this.props

    • 事件处理函数

      • this指向问题:
      1. 包裹箭头函数
      
      2. bind:
      
      3. 直接定义成箭头函数:
      
      • 怎么定义:<button onClick={事件处理函数}></button>

      • 事件处理函数调用者:window

      • 事件对象:

        1. 事件对象是一个合成的事件对象,做过兼容性处理。e.nativeEvent获取原生

        2. 如何得到事件对象? react会默认将第一个形参传事件对象

          const click1 = (e)=>{
              e 作为第一个形参,就可以接收到事件对象
          }
          <button onClick={click1}>点击</button>
          
          1
          2
          3
          4
    • 生命周期:

      // componentDidMount 组件挂载后执行, 只会执行一次
      	发送ajax请求,开启定时器,订阅消息,绑定自定义事件
      // componentDidUpdate 组件更新执行 render--》componentDidUpdate
      	newprops  setState forceUpdate ==> render
           有机会执行多次
           
      // componentWillUnmount 组件卸载前执行  只会执行一次
           取消定时器、取消订阅、解绑自定义事件
      
      1
      2
      3
      4
      5
      6
      7
      8

    插值表达式:

    // 条件渲染:  在jsx模板中,只能使用三元表达式、逻辑运算
    return (
        <>
    	 <div>三元表达式:{条件?<div>111</div>:</div>222</div>}</div>
          <div>逻辑运算:  {条件 && <div>222</div>}</div>
          <div>函数调用:  {fn()} </div>
        </>
    )
    
    1
    2
    3
    4
    5
    6
    7
    8
  2. 函数组件:

    • state:useState

    • props: 形参

      1. 传递:

        • 一个一个传:<Child count={count} msg={msg}/>

        • 使用扩展运算符一起传:

          let [user, setUser] = useState({
              count:1,
              msg:'atguigu'
          })
          
          <Child {...user}/>
          
          1
          2
          3
          4
          5
          6

    事件处理函数:没有this问题 this-> undefined

    ​

    生命周期:useEffect

    // 
    useEffect(()=>{// didMount 组件挂载调用一次
        return ()=>{ // willUnmount  调用一次
            
        }
    },[])
    
    //
    useEffect(()=>{
        
    })
    useEffect(()=>{
        
    },[count])
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    redux:

    <Provider store={}>
        
    </Provider>
    useSelector
    useDispatch
    
    useDispatch(actionCreator(payload))==> useDispatch(action对象)
    
    1
    2
    3
    4
    5
    6
    7

    路由:

    <BrowserRouter></BrowserRouter>
    <NavLink > 
    <Link>
    useNavigate 创建编程式导航
    路由表:     useRoutes(路由表数组)   path  element  children
    路由参数:
    1. useParams()        path
    2. useSearchParams()  query
    3. useLocation()      state
    
    BrowserRouter NavLink  Link Outlet  from  'react-router'
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

创建一个根节点

const root = ReactDOM.createRoot(dom元素)
1

ref:

  1. 绑定在dom元素身上,作用 获取该dom元素
  2. 单独模拟 componentDidUpdate
  3. 给类组件绑定,获取类组件的实例对象
  4. 给函数组件绑定, React.forwardRef, 作用,父组件获取子组件的dom元素

受控组件非受控组件:

  1. 受控:表单元素收到了组件状态的控制

    value、checked 赋值了状态就受控

    只读

    onChange 获取最新的用户输入 改变对应的状态

    获取值:直接通过状态数据回去

  2. 非受控:

    defaultValue、defaultChecked

    获取值:通过ref 获取真实dom .value获取

redux/toolkit

  1. 创建切片: createSlice

    name 属性==》切片名 必须的

    initalState

    reducer

  2. 配置仓库: configureStore

    configureStore({
        reducer:{
            count:countSlice.reducer
        }
    })
    
    1
    2
    3
    4
    5
  3. 获取仓库数据:store.getState()

  4. 改变仓库数据:

    store.dispatch(actionCreator(payload))
    ===>
    store.dispatch(action对象)
    
    1
    2
    3

# 16. 前端重要知识点

image-20230714172522980

# 17. 未来三年

# 17-1. 学习:

# 17-2. 找工作

跟编码水平无关、跟记忆力、脸皮、韧性、心态关系重大

心态:

# 17-3. 工作前三个月

心法:这里是尚硅谷带薪实训基地【60窝囊废 + 40 技术】

三个月:

  1. 行业经验:
  2. 真实的项目经验:
  3. 编码能力,同行同事:

# 17-4. 半年后

# 17-5. 必须进大厂

  1. 学历:本科 买一个 学信网可查的 成人教育 2-3年 2. 3 ==》 1
  2. 年终奖:

# 附件

13141403113

react 中的事件对象 onClick={(e)=>{}} react自己合成是事件对象 e 做过兼容 e.nativeEvent

react 中的事件处理函数,参数的默认值是 当前组件实例对象

function send(e){

}

=>{

​ this

}}

编辑 (opens new window)
antd基本使用
课件-react路由-V6

← antd基本使用 课件-react路由-V6→

最近更新
01
课件-react路由-V6
01-22
02
课件-国际化
01-22
03
课件-redux-toolkit
01-22
更多文章>
Theme by Vdoing | Copyright © 2019-2024 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式