Day111.尚医通:集成NUXT框架、前台页面首页数据、医院详情页

目录

 

一、服务端渲染技术NUXT

集成

二、静态资源改造

三、首页数据展示

1、后端接口

1. 根据分页条件查询 查询医院信息

2. 根据医院名称模糊查询医院信息 

2、前台页面

四、医院详情页

1、后端

2、前端页面


一、服务端渲染技术NUXT

1、服务端渲染

服务端渲染又称SSR (Server Side Render)是在服务端完成页面的内容,而不是在客户端通过AJAX获取数据。

服务器端渲染(SSR)的优势主要在于:更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。根据关键字搜索,关键字出现越多越靠前(倒排索引),因此不能用差值表达式。

2、什么是NUXT

Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。

官网:Nuxt - The Intuitive Vue Framework

集成

1、解压

2、解压到工程目录,修改名称 

 

3、修改配置文件

3、下载配置 npm install

4、快捷步骤:找到下载好依赖的工程包,解压,直接启动 npm run dev 

5、目录结构介绍

(1)assets 资源目录

 用于组织未编译的静态资源如 LESS、SASS 或 JavaScript。

(2)components  组件目录 

用于组织应用的 Vue.js 组件。Nuxt.js 不会扩展增强该目录下 Vue.js 组件,即这些组件不会像页面组件那样有 asyncData 方法的特性。

(3)layouts  布局目录 用于组织应用的布局组件。

(4)pages  页面目录 存放所有前端页面,和layouts布局进行组合 组成完整页面

(5)插件目录 plugins

用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。

(6)nuxt.config.js 文件

nuxt.config.js 文件用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置。

6、封装axios

1. 导入依赖

npm install axios

2. 创建utils文件夹,创建request.js

import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
// 创建axios实例
const service = axios.create({
    baseURL: 'http://localhost:8222',  //注意这里!
    timeout: 15000 // 请求超时时间
})
// http request 拦截器
service.interceptors.request.use(
    config => {
    // token 先不处理,后续使用时在完善
    return config
},
  err => {
    return Promise.reject(err)
})
// http response 拦截器
service.interceptors.response.use(
    response => {
        if (response.data.code !== 20000) { //注意这里!
            Message({
                message: response.data.message,
                type: 'error',
                duration: 5 * 1000
            })
            return Promise.reject(response.data)
        } else {
            return response.data
        }
    },
    error => {
        return Promise.reject(error.response)
})
export default service

二、静态资源改造

1. 首页静态数据整合

复制即可

2、布局

3、布局改造

提取头文件

创建layouts/myheader.vue文件

<template>
    <div class="header-container">
        <div class="wrapper">
            <!-- logo -->
            <div class="left-wrapper v-link selected">
                <img style="width: 50px" width="50" height="50" src="~assets/images/logo.png">
                <span class="text">尚医通 预约挂号统一平台</span>
            </div>
            <!-- 右侧 -->
            <div class="right-wrapper">
                <span class="v-link clickable">帮助中心</span>
                <span class="v-link clickable" @click="dialogUserFormVisible = true">登录/注册</span>
            </div>
        </div>
    </div>
</template>
<script>
export default {
}
</script>

提取尾文件 

创建layouts/myfooter.vue文件

<template>
  <div class="footer-container">
    <div class="wrapper">
      <div><span class="record">京ICP备atguigu号</span><span
        class="phone">www.atguigu.com</span></div>
      <div class="right"><span
        class="v-link clickable"> 联系我们 </span><span
        class="v-link clickable"> 合作伙伴 </span><span
        class="v-link clickable"> 用户协议 </span><span
        class="v-link clickable"> 隐私协议 </span></div>
    </div>
  </div>
</template>

<script>
export default {

}
</script>

修改默认布局

修改layouts/default.vue文件

<template>
  <div class="app-container">
    <div id="main">
      <!-- 公共头 -->
      <myheader/>
      <div class="main-container">
        <el-scrollbar class='page-component__scroll'>
          <!-- 内容区域 -->
          <nuxt/>
        </el-scrollbar>
      </div>
      <!-- 公共底 -->
      <myfooter/>
    </div>
  </div>
</template>
<script>
import '~/assets/css/app.css'
import '~/assets/css/chunk.css'
import '~/assets/css/iconfont.css'
import '~/assets/css/main.css'

import myheader from './myheader'
import myfooter from './myfooter'

export default {

  components: {
    myheader,myfooter
  },

  mounted() {
    window.document.getElementById("__nuxt").classList.add("app-container")
    window.document.getElementById("__layout").classList.add("app-container")
  }
}
</script>

4、修改首页面内容

<template>
  <div class="home page-component">
    <el-carousel indicator-position="outside">
      <el-carousel-item v-for="item in 2" :key="item">
        <img src="~assets/images/web-banner1.png" alt="">
      </el-carousel-item>
    </el-carousel>
    <!-- 搜索 -->
    <div class="search-container">
      <div class="search-wrapper">
        <div class="hospital-search">
          <el-autocomplete class="search-input" prefix-icon="el-icon-search" v-model="state"
            :fetch-suggestions="querySearchAsync" placeholder="点击输入医院名称" @select="handleSelect">
            <span slot="suffix" class="search-btn v-link highlight clickable selected">搜索 </span>
          </el-autocomplete>
        </div>
      </div>
    </div>
    <!-- bottom -->
    <div class="bottom">
      <div class="left">
        <div class="home-filter-wrapper">
          <div class="title"> 医院</div>
          <div>
            <div class="filter-wrapper">
              <span class="label">等级:</span>
              <div class="condition-wrapper"><span class="item v-link highlight clickable selected">
                  全部 </span><span class="item v-link clickable">
                  三级医院 </span><span class="item v-link clickable">
                  二级医院 </span><span class="item v-link clickable">
                  一级医院 </span></div>
            </div>
            <div class="filter-wrapper">
              <span class="label">地区:</span>
              <div class="condition-wrapper"><span class="item v-link highlight clickable selected">
                  全部 </span><span class="item v-link clickable">
                  东城区 </span><span class="item v-link clickable">
                  西城区 </span><span class="item v-link clickable">
                  朝阳区 </span><span class="item v-link clickable">
                  丰台区 </span><span class="item v-link clickable">
                  石景山区 </span><span class="item v-link clickable">
                  海淀区 </span><span class="item v-link clickable">
                  门头沟区 </span><span class="item v-link clickable">
                  房山区 </span><span class="item v-link clickable">
                  通州区 </span><span class="item v-link clickable">
                  顺义区 </span><span class="item v-link clickable">
                  昌平区 </span><span class="item v-link clickable">
                  大兴区 </span><span class="item v-link clickable">
                  怀柔区 </span><span class="item v-link clickable">
                  平谷区 </span><span class="item v-link clickable">
                  密云区 </span><span class="item v-link clickable">
                  延庆区 </span></div>
            </div>
          </div>
        </div>
        <div class="v-scroll-list hospital-list">
          <div class="v-card clickable list-item">
            <div class="">
              <div class="hospital-list-item hos-item" index="0">
                <div class="wrapper">
                  <div class="hospital-title"> 北京协和医院
                  </div>
                  <div class="bottom-container">
                    <div class="icon-wrapper"><span class="iconfont"></span>
                      三级甲等
                    </div>
                    <div class="icon-wrapper"><span class="iconfont"></span>
                      每天8:30放号
                    </div>
                  </div>
                </div>
                <img src="images/23176337663806575.png" alt="北京协和医院" class="hospital-img">
              </div>
            </div>
          </div>
          <div class="v-card clickable list-item space">
            <div class="">
              <div class="hospital-list-item hos-item" index="0">
                <div class="wrapper">
                  <div class="hospital-title"> 北京协和医院
                  </div>
                  <div class="bottom-container">
                    <div class="icon-wrapper"><span class="iconfont"></span>
                      三级甲等
                    </div>
                    <div class="icon-wrapper"><span class="iconfont"></span>
                      每天8:30放号
                    </div>
                  </div>
                </div>
                <img src="images/23176337663806575.png" alt="北京协和医院" class="hospital-img">
              </div>
            </div>
          </div>
          <div class="v-card clickable list-item">
            <div class="">
              <div class="hospital-list-item hos-item" index="0">
                <div class="wrapper">
                  <div class="hospital-title"> 北京协和医院
                  </div>
                  <div class="bottom-container">
                    <div class="icon-wrapper"><span class="iconfont"></span>
                      三级甲等
                    </div>
                    <div class="icon-wrapper"><span class="iconfont"></span>
                      每天8:30放号
                    </div>
                  </div>
                </div>
                <img src="images/23176337663806575.png" alt="北京协和医院" class="hospital-img">
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="right">
        <div class="common-dept">
          <div class="header-wrapper">
            <div class="title"> 常见科室</div>
            <div class="all-wrapper"><span>全部</span>
              <span class="iconfont icon"></span>
            </div>
          </div>
          <div class="content-wrapper">
            <span class="item v-link clickable dark">神经内科 </span>
            <span class="item v-link clickable dark">消化内科 </span>
            <span class="item v-link clickable dark">呼吸内科 </span>
            <span class="item v-link clickable dark">内科 </span>
            <span class="item v-link clickable dark">神经外科 </span>
            <span class="item v-link clickable dark">妇科 </span>
            <span class="item v-link clickable dark"> 产科 </span>
            <span class="item v-link clickable dark">儿科 </span>
          </div>
        </div>
        <div class="space">
          <div class="header-wrapper">
            <div class="title-wrapper">
              <div class="icon-wrapper"><span class="iconfont title-icon"></span>
              </div>
              <span class="title">平台公告</span>
            </div>
            <div class="all-wrapper">
              <span>全部</span>
              <span class="iconfont icon"></span>
            </div>
          </div>
          <div class="content-wrapper">
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark">关于延长北京大学国际医院放假的通知 </span>
            </div>
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark">北京中医药大学东方医院部分科室医生门诊医 </span>
            </div>
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark"> 武警总医院号源暂停更新通知 </span>
            </div>
          </div>
        </div>
        <div class="suspend-notice-list space">
          <div class="header-wrapper">
            <div class="title-wrapper">
              <div class="icon-wrapper">
                <span class="iconfont title-icon"></span>
              </div>
              <span class="title">停诊公告</span>
            </div>
            <div class="all-wrapper">
              <span>全部</span>
              <span class="iconfont icon"></span>
            </div>
          </div>
          <div class="content-wrapper">
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark"> 中国人民解放军总医院第六医学中心(原海军总医院)呼吸内科门诊停诊公告 </span>
            </div>
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark"> 首都医科大学附属北京潞河医院老年医学科门诊停诊公告 </span>
            </div>
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark">中日友好医院中西医结合心内科门诊停诊公告 </span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  export default {
  }
</script>

测试: 

三、首页数据展示

1、后端接口

1. 根据分页条件查询 查询医院信息

根据搜索框 医院名称模糊查询

1. 接口分析

参数:page、limit、HospitalQueryVo

返回值:R (Page)

2. 实现 controller

修改swagger2 api文档,扫描位置

创建 api/HospitalApiController

@Api(tags = "医院显示接口")
@RestController
@RequestMapping("/api/hosp/hospital")
public class HospitalApiController {

    @Autowired
    private HospitalService hospitalService;

    @ApiOperation(value = "条件分页查询 获取医院分页列表")
    @GetMapping("{page}/{limit}")
    public R index(
            @PathVariable Integer page,
            @PathVariable Integer limit,
            HospitalQueryVo hospitalQueryVo) {
        //方法写过,接口复用即可
        Page<Hospital> pageModel = hospitalService.selectPage(page, limit, hospitalQueryVo);
        return R.ok().data("pageModel",pageModel);
    }

2. 根据医院名称模糊查询医院信息 

根据分页条件查询医院信息 

1. 接口分析

参数:hosname

返回值:R ( List<Hospital> )

2. 实现 controller

    @ApiOperation(value = "根据医院名称获取医院列表")
    @GetMapping("findByHosname/{hosname}")
    public R findByHosname(
            @PathVariable String hosname) {

        List<Hospital> list = hospitalService.findByHosnameLike(hosname);
        return R.ok().data("list",list);
    }

3. 实现 service

    //根据医院名称获取医院列表
    @Override
    public List<Hospital> findByHosnameLike(String hosname) {
        List<Hospital> list = 
                hospitalRepository.getByHosnameLike(hosname);
        return list;
    }

4. 测试: 

2、前台页面

1. 创建 API 接口方法

创建 /api/hospital.js

import request from '@/utils/request'
//提取请求路径
const api_name = '/api/hosp/hospital'

export default {

    //带条件带分页获取医院列表
    getPageList(page, limit, searchObj) {
        return request({
            url: `${api_name}/${page}/${limit}`,
            method: 'get',
            params: searchObj
        })
    },
    //根据医院名称获取医院列表
    findByHosname(hosname) {
        return request({
            url: `${api_name}/findByHosname/${hosname}`,
            method: 'get'
        })
    },
}

dict.js,从后台工程复制即可

2. 改造页面动态元素

<template>
  <div class="home page-component">
    <el-carousel indicator-position="outside">
      <el-carousel-item v-for="item in 2" :key="item">
        <img src="~assets/images/web-banner1.png" alt="">
      </el-carousel-item>
    </el-carousel>
    <!-- 搜索 自动搜索输入框 -->
    <div class="search-container">
      <div class="search-wrapper">
        <div class="hospital-search">
          <el-autocomplete class="search-input" prefix-icon="el-icon-search" v-model="hosname"
            :fetch-suggestions="querySearchAsync" placeholder="点击输入医院名称" @select="handleSelect">
            <span slot="suffix" class="search-btn v-link highlight clickable selected">搜索 </span>
          </el-autocomplete>
        </div>
      </div>
    </div>
    <!-- bottom -->
    <div class="bottom">
      <div class="left">
        <div class="home-filter-wrapper">
          <div class="title"> 医院</div>
          <div>
            <div class="filter-wrapper">
              <span class="label">等级:</span>
              <div class="condition-wrapper">
                <span class="item v-link clickable" :class="hostypeActiveIndex == index ? 'selected' : ''"
                  v-for="(item,index) in hostypeList" :key="item.id" @click="hostypeSelect(item.value, index)">{{
                  item.name }}</span>
              </div>
            </div>
            <div class="filter-wrapper">
              <span class="label">地区:</span>
              <div class="condition-wrapper">
                <span class="item v-link clickable" :class="provinceActiveIndex == index ? 'selected' : ''"
                  v-for="(item,index) in districtList" :key="item.id" @click="districtSelect(item.value, index)">{{
                  item.name }}</span>
              </div>
            </div>
          </div>
        </div>
        <div class="v-scroll-list hospital-list">
          <div class="v-card clickable list-item" v-for="item in list" :key="item.id">
            <div class="">
              <div class="hospital-list-item hos-item" index="0" @click="show(item.hoscode)">
                <div class="wrapper">
                  <div class="hospital-title"> {{ item.hosname }}</div>
                  <div class="bottom-container">
                    <div class="icon-wrapper">
                      <span class="iconfont"></span>{{ item.param.hostypeString }}
                    </div>
                    <div class="icon-wrapper">
                      <span class="iconfont"></span>每天{{ item.bookingRule.releaseTime }}放号
                    </div>
                  </div>
                </div>
                <img :src="'data:image/jpeg;base64,'+item.logoData" :alt="item.hosname" class="hospital-img">
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="right">
        <div class="common-dept">
          <div class="header-wrapper">
            <div class="title"> 常见科室</div>
            <div class="all-wrapper"><span>全部</span>
              <span class="iconfont icon"></span>
            </div>
          </div>
          <div class="content-wrapper">
            <span class="item v-link clickable dark">神经内科 </span>
            <span class="item v-link clickable dark">消化内科 </span>
            <span class="item v-link clickable dark">呼吸内科 </span>
            <span class="item v-link clickable dark">内科 </span>
            <span class="item v-link clickable dark">神经外科 </span>
            <span class="item v-link clickable dark">妇科 </span>
            <span class="item v-link clickable dark"> 产科 </span>
            <span class="item v-link clickable dark">儿科 </span>
          </div>
        </div>
        <div class="space">
          <div class="header-wrapper">
            <div class="title-wrapper">
              <div class="icon-wrapper"><span class="iconfont title-icon"></span>
              </div>
              <span class="title">平台公告</span>
            </div>
            <div class="all-wrapper">
              <span>全部</span>
              <span class="iconfont icon"></span>
            </div>
          </div>
          <div class="content-wrapper">
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark">关于延长北京大学国际医院放假的通知 </span>
            </div>
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark">北京中医药大学东方医院部分科室医生门诊医 </span>
            </div>
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark"> 武警总医院号源暂停更新通知 </span>
            </div>
          </div>
        </div>
        <div class="suspend-notice-list space">
          <div class="header-wrapper">
            <div class="title-wrapper">
              <div class="icon-wrapper">
                <span class="iconfont title-icon"></span>
              </div>
              <span class="title">停诊公告</span>
            </div>
            <div class="all-wrapper">
              <span>全部</span>
              <span class="iconfont icon"></span>
            </div>
          </div>
          <div class="content-wrapper">
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark"> 中国人民解放军总医院第六医学中心(原海军总医院)呼吸内科门诊停诊公告 </span>
            </div>
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark"> 首都医科大学附属北京潞河医院老年医学科门诊停诊公告 </span>
            </div>
            <div class="notice-wrapper">
              <div class="point"></div>
              <span class="notice v-link clickable dark">中日友好医院中西医结合心内科门诊停诊公告 </span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    
  }
</script>

3. 添加JS方法

<script>
  import hospApi from '@/api/hospital.js'
  import dictApi from '@/api/dict.js'
  export default {
    //服务端渲染异步,显示医院列表
    asyncData({ params, error }) {
      //调用
      return hospApi.getPageList(1, 10, null)
        .then(response => {
          return {
            list: response.data.pageModel.content,
            pages: response.data.pageModel.totalPages
          }
        })
    },
    data() {
      return {
        searchObj: {},
        page: 1,
        limit: 10,

        hosname: '', //医院名称
        hostypeList: [], //医院等级集合
        districtList: [], //地区集合

        hostypeActiveIndex: 0,
        provinceActiveIndex: 0
      }
    },
    created() {
      //调用初始化方法
      this.init()
    },
    methods: {
      //初始化方法
      init() {
        //查询医院等级信息
        dictApi.findByDictCode("Hostype").then(response => {
          //1.清空hostypeList集合数据
          this.hostypeList = []
          //2.存入"全部" 数据
          this.hostypeList.push({ name: "全部", value: "" })
          //3.遍历返回结果 存入hostypeList
          for (let i = 0; i < response.data.list.length; i++) {
            this.hostypeList.push(response.data.list[i])
          }
        })
        //查询地区数据
        dictApi.findByDictCode("Beijin").then(response => {
          //1.清空districtList集合数据
          this.districtList = []
          //2.存入"全部" 数据
          this.districtList.push({ name: "全部", value: "" })
          //3.遍历返回结果 存入hostypeList
          for (let i in response.data.list) {
            this.districtList.push(response.data.list[i])
          }
        })
      },
      //根据医院等级查询
      hostypeSelect(hostype, index) {
        this.list = []
        //1.准备数据
        this.page = 1
        this.hostypeActiveIndex = index
        //2.选中样式
        this.searchObj.hostype = hostype
        //3.调用查询医院列表方法
        this.getList()
      },
      //根据地区查询医院信息
      districtSelect(districtCode, index) {
        this.list = []
        //1.准备参数
        this.page = 1
        //2.选中样式
        this.provinceActiveIndex = index
        //3.调用方法查询
        this.searchObj.districtCode = districtCode
        this.getList();
      },
      //查询医院方法
      getList() {
        hospApi.getPageList(this.page, this.limit, this.searchObj)
          .then(response => {
            console.log(response);
            this.list = response.data.pageModel.content
            this.pages = response.data.pageModel.totalPages
          })
      },
    }
  }
</script>

根据关键字搜索

<script>
  import hospApi from '@/api/hospital.js'
  import dictApi from '@/api/dict.js'
  export default {
    //服务端渲染异步,显示医院列表
    asyncData({ params, error }) {
      //调用
      return hospApi.getPageList(1, 10, null)
        .then(response => {
          return {
            list: response.data.pageModel.content,
            pages: response.data.pageModel.totalPages
          }
        })
    },
    data() {
      return {
        searchObj: {},
        page: 1,
        limit: 10,

        hosname: '', //医院名称
        hostypeList: [], //医院等级集合
        districtList: [], //地区集合

        hostypeActiveIndex: 0,
        provinceActiveIndex: 0
      }
    },
    created() {
      //调用初始化方法
      this.init()
    },
    methods: {
      //初始化方法
      init() {
        //查询医院等级信息
        dictApi.findByDictCode("Hostype").then(response => {
          //1.清空hostypeList集合数据
          this.hostypeList = []
          //2.存入"全部" 数据
          this.hostypeList.push({ name: "全部", value: "" })
          //3.遍历返回结果 存入hostypeList
          for (let i = 0; i < response.data.list.length; i++) {
            this.hostypeList.push(response.data.list[i])
          }
        })
        //查询地区数据
        dictApi.findByDictCode("Beijin").then(response => {
          //1.清空districtList集合数据
          this.districtList = []
          //2.存入"全部" 数据
          this.districtList.push({ name: "全部", value: "" })
          //3.遍历返回结果 存入hostypeList
          for (let i in response.data.list) {
            this.districtList.push(response.data.list[i])
          }
        })
      },
      //根据医院等级查询
      hostypeSelect(hostype, index) {
        this.list = []
        //1.准备数据
        this.page = 1
        this.hostypeActiveIndex = index
        //2.选中样式
        this.searchObj.hostype = hostype
        //3.调用查询医院列表方法
        this.getList()
      },
      //根据地区查询医院信息
      districtSelect(districtCode, index) {
        this.list = []
        //1.准备参数
        this.page = 1
        //2.选中样式
        this.provinceActiveIndex = index
        //3.调用方法查询
        this.searchObj.districtCode = districtCode
        this.getList();
      },
      //查询医院列表(下拉时加载下一页,添加数据而不是覆盖)
      getList() {
        hospApi.getPageList(this.page, this.limit, this.searchObj)
          .then(response => {
            for (let i in response.data.pageModel.content) {
              this.list.push(response.data.pageModel.content[i])
            }
            this.page = response.data.pageModel.totalPages
          })
      },
      //自动搜索方法
      querySearchAsync(queryString, cb) {
        //1.非空校验
        if (queryString == '') return
        //2.调接口查询数据
        hospApi.findByHosname(queryString).then(response => {
          //3.遍历集合添加value字段=hosname
          for (let i in response.data.list) {
            response.data.list[i].value = response.data.list[i].hosname;
          }
          //4.调用cd加载集合数据
          cb(response.data.list)
        })
      },
      //在下拉框选择某一个内容,执行下面方法,跳转到详情页面中
      handleSelect(item) {
        window.location.href = '/hospital/' + item.hoscode
      },

      //点击某个医院名称,跳转到详情页面中
      show(hoscode) {
        window.location.href = '/hospital/' + hoscode
      }
    }
  }
</script>

四、医院详情页

1、后端

1.需求分析

a. 根据医院编码查询医院信息+预约规则

b. 根据医院编码查询所有科室信息

2. 分析接口

参数:hoscode

返回值:map (医院信息+预约规则)

参数:hoscode

返回值:list

3. 实现controller

    @ApiOperation(value = "医院预约挂号详情(预约规则)")
    @GetMapping("{hoscode}")
    public R getHospInfo(
            @PathVariable String hoscode) {
        Map<String,Object> map
                =hospitalService.getHospByHoscode(hoscode);
        return R.ok().data(map);
    }

    @ApiOperation(value = "获取科室列表")
    @GetMapping("department/{hoscode}")
    public R getDepartment(
            @PathVariable String hoscode) {
        //接口复用
        List<DepartmentVo> list = departmentService.findDeptTree(hoscode);
        return R.ok().data("list",list);
    }

4. 实现 service 

    //根据医院名称获取医院列表
    @Override
    public List<Hospital> findByHosnameLike(String hosname) {
        List<Hospital> list =
                hospitalRepository.getByHosnameLike(hosname);
        return list;
    }
    //医院预约挂号详情(预约规则)
    @Override
    public Map<String, Object> getHospByHoscode(String hoscode) {
        //1.根据hoscode查询医院信息
        Hospital hospital = hospitalRepository.getByHoscode(hoscode);
        //2.翻译字段
        hospital = this.packHospital(hospital);
        //3.取出预约规则
        BookingRule bookingRule = hospital.getBookingRule();
        hospital.setBookingRule(null);
        //4.封装数据,返回
        Map<String, Object> map  = new HashMap<>();
        map.put("hospital",hospital);
        map.put("bookingRule",bookingRule);
        return map;
    }

2、前端页面

固定路由(静态路由)

访问的url是固定不变的,例如 url/yygh/hosp

对应页面:/pages/yygh/hosp.vue、 /pages/yygh/index.vue

动态路由

请求url可变 (后面拼接了参数),对应页面是以 _ 开头

一个目录下,只能创建一个动态路由页面

1. 添加 API接口

    //医院预约挂号详情
    show(hoscode) {
        return request({
            url: `${api_name}/${hoscode}`,
            method: 'get'
        })
    },
    //查看科室列表
    findDepartment(hoscode) {
        return request({
            url: `${api_name}/department/${hoscode}`,
            method: 'get'
        })
    }

2. 创建 hospital/_hospital.vue,添加页面元素

 

<template>
  <!-- header -->
  <div class="nav-container page-component">
    <!--左侧导航 #start -->
    <div class="nav left-nav">
      <div class="nav-item selected">
        <span class="v-link selected dark"
          :onclick="'javascript:window.location=\'/hospital/'+hospital.hoscode+'\''">预约挂号</span>
      </div>
      <div class="nav-item">
        <span class="v-link clickable dark"
          :onclick="'javascript:window.location=\'/hospital/detail/'+hospital.hoscode+'\''">医院详情</span>
      </div>
      <div class="nav-item">
        <span class="v-link clickable dark"
          :onclick="'javascript:window.location=\'/hospital/notice/'+hospital.hoscode+'\''">预约须知</span>
      </div>
      <div class="nav-item">
        <span class="v-link clickable dark">停诊信息</span>
      </div>
      <div class="nav-item">
        <span class="v-link clickable dark">查询/取消</span>
      </div>
    </div>
    <!-- 左侧导航 #end -->
    <!-- 右侧内容 #start -->
    <div class="page-container">
      <div class="hospital-home">
        <div class="common-header">
          <div class="title-wrapper">
            <span class="hospital-title">{{ hospital.hosname }}</span>
            <div class="icon-wrapper">
              <span class="iconfont"></span>
              {{ hospital.param.hostypeString }}
            </div>
          </div>
        </div>
        <div class="info-wrapper">
          <img class="hospital-img" :src="'data:image/jpeg;base64,'+hospital.logoData" :alt="hospital.hosname">
          <div class="content-wrapper">
            <div>挂号规则</div>
            <div class="line">
              <div>
                <span class="label">预约周期:</span>
                <span>{{ bookingRule.cycle }}天</span>
              </div>
              <div class="space">
                <span class="label">放号时间:</span>
                <span>{{ bookingRule.releaseTime }}</span>
              </div>
              <div class="space">
                <span class="label">停挂时间:</span>
                <span>{{ bookingRule.stopTime }}</span>
              </div>
            </div>
            <div class="line">
              <span class="label">退号时间:</span>
              <span v-if="bookingRule.quitDay == -1">就诊前一工作日{{ bookingRule.quitTime }}前取消</span>
              <span v-if="bookingRule.quitDay == 0">就诊前当天{{ bookingRule.quitTime }}前取消</span>
            </div>
            <div style="margin-top:20px">医院预约规则</div>
            <div class="rule-wrapper">
              <ol>
                <li v-for="item in bookingRule.rule" :key="item">{{ item }}</li>
              </ol>
            </div>
          </div>
        </div>
        <div class="title select-title">选择科室</div>
        <div class="select-dept-wrapper">
          <div class="department-wrapper">
            <div class="hospital-department">
              <div class="dept-list-wrapper el-scrollbar" style="height: 100%;">
                <div class="dept-list el-scrollbar__wrap" style="margin-bottom: -17px; margin-right: -17px;">
                  <div class="el-scrollbar__view">
                    <div class="sub-item" v-for="(item,index) in departmentVoList" :key="item.id"
                      :class="index == activeIndex ? 'selected' : ''" @click="move(index,item.depcode)">{{ item.depname
                      }}</div>
                  </div>
                </div>
                <div class="el-scrollbar__bar is-horizontal">
                  <div class="el-scrollbar__thumb" style="transform: translateX(0%);"></div>
                </div>
                <div class="el-scrollbar__bar is-vertical">
                  <div class="el-scrollbar__thumb" style="transform: translateY(0%); height: 91.4761%;"></div>
                </div>
              </div>
            </div>
          </div>
          <div class="sub-dept-container">
            <div v-for="(item,index) in departmentVoList" :key="item.id" :class="index == 0 ? 'selected' : ''"
              class="sub-dept-wrapper" :id="item.depcode">
              <div class="sub-title">
                <div class="block selected"></div>
                {{ item.depname }}
              </div>
              <div class="sub-item-wrapper">
                <div v-for="it in item.children" :key="it.id" class="sub-item" @click="schedule(it.depcode)">
                  <span class="v-link clickable">{{ it.depname }}</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!-- 右侧内容 #end -->
  </div>
  <!-- footer -->
</template>

JS 实现

<script>
  import "~/assets/css/hospital_personal.css";
  import "~/assets/css/hospital.css";
  import hospApi from "@/api/hospital";

  export default {
    data() {
      return {
        hoscode: null, //医院编码
        activeIndex: 0, //选中索引
        hospital: {
          param: {} //初始化对象
        },
        bookingRule: {}, //预约规则
        departmentVoList: []  //科室信息
      };
    },
    created() {
      //1获取参数
      this.hoscode = this.$route.params.hoscode;
      //2初始化查询
      this.init();
    },
    methods: {
      //初始化查询
      init() {
        //查询医院信息
        hospApi.show(this.hoscode).then(response => {
          this.hospital = response.data.hospital;
          this.bookingRule = response.data.bookingRule;
        });

        //查询相关科室信息
        hospApi.findDepartment(this.hoscode).then(response => {
          this.departmentVoList = response.data.list;
        });
      },
      schedule(depcode) {
        //?传参 还是静态请求
        //   window.location.href =
        //     "/hospital/schedule?hoscode=" + this.hoscode + "&depcode=" + depcode;
      }
    }
  };
</script>

详情和预约,详见课件

如果访问很慢,换个浏览器试试!

原因未知

手机验证码登录

实现方式:弹出对话框

登录注册方式:手机号验证码注册登录、微信扫码登录

1、手机号验证码注册登录

注册没有单独步骤 和登录一起实现

在同一位置动态实现发送验证码、登录注册相关功能

2、微信扫码登陆

判断扫码登录是否是第一次,如果第一次需要绑定手机号

如果不是第一次直接登录

3、部分页面校验是否登录,未登录弹出登录对话框

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值