尚医通 (三十) --------- 前端 (非逆向) 搭建 与 首页


一、尚医通平台前端搭建

1. 服务端渲染

A、什么是服务端渲染

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

服务器端渲染的优势主要在于:更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。

如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再进行页面内容的抓取。也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。

另外,使用服务器端渲染,我们可以获得更快的内容到达时间 (time-to-content),无需等待所有的 JavaScript 都完成下载并执行,产生更好的用户体验,对于那些内容到达时间 (time-to-content) 与转化率直接相关的应用程序而言,服务器端渲染 (SSR) 至关重要。

B、什么是 NUXT

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

官网网站:https://zh.nuxtjs.org/

2. NUXT 环境初始化

A、下载压缩包

https://github.com/nuxt-community/starter-template/archive/master.zip

B、解压

在这里插入图片描述

在 yygh-parent 目录中新建 yygh-site 目录,将 template 中的内容复制到此目录中

C、修改 package.json

name、description、author (必须修改这里,否则项目无法安装)
{
	"name": "yygh-site",
	"version": "1.0.0",
	"description": "尚医通",
	"author": "fancy",
	"private": true,
	"scripts": {
		"dev": "nuxt",
		"build": "nuxt build",
		"start": "nuxt start",
		"generate": "nuxt generate",
		"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
		"precommit": "npm run lint"
	},
	...
}

在这里插入图片描述

D、修改 nuxt.config.js

修改

title: '{{ name }}', content: '{{escape description }}'

这里的设置最后会显示在页面标题栏和meta数据中

module.exports = {
  /*
  ** Headers of the page
  */
  head: {
    title: 'yygh-site',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '尚医通' }
    ],

在这里插入图片描述

E、终端中进入项目目录安装依赖

npm install

在这里插入图片描述

F、引入 element-ui

下载 element-ui

npm  install  element-ui

在这里插入图片描述

在 plugins 文件夹下创建 myPlugin.js 文件

在这里插入图片描述

在 myPlugin.js 文件引入 element-ui

import Vue from 'vue'
import ElementUI from 'element-ui' //element-ui的全部组件
import 'element-ui/lib/theme-chalk/index.css'//element-ui的css
Vue.use(ElementUI) //使用elementUI

在这里插入图片描述

在 nuxt.config.js 文件中使用 myPlugin.js

在 build 下面添加内容:

plugins: [
   { src: '~/plugins/myPlugin.js', ssr: false }
]

G、测试运行

npm run dev

访问项目:http://localhost:3000/

H、NUXT目录结构

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

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

  • 布局目录 layouts
    用于组织应用的布局组件。

  • 页面目录 pages
    用于组织应用的路由及视图。Nuxt.js 框架读取该目录下所有的 .vue 文件并自动生成对应的路由配置。

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

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

3. 封装 axios

A、安装 axios

执行安装命令

npm install axios

B、封装 axios

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

import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
// 创建axios实例
const service = axios.create({
    baseURL: 'http://localhost',
    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 !== 200) {
            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. 公共处理

① 添加静态资源

将静态资源下面的 css、images 文件夹添加到 assets 目录,如图:

在这里插入图片描述

② 定义布局

A、修改默认布局

参考静态资源文件首页,我们可以把页头和页尾提取出来,形成布局页。

在 layouts 目录下修改默认布局文件default.vue,将主内容区域的内容替换成 <nuxt />

修改 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'
export default {
}
</script>

B、提取头文件

创建 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="search-wrapper">
            <div class="hospital-search animation-show">
                <el-autocomplete
                    class="search-input small"
                    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 class="right-wrapper">
        <span class="v-link clickable">帮助中心</span>
        <!--        <el-dropdown >-->
        <!--              <span class="el-dropdown-link">-->
        <!--                晴天<i class="el-icon-arrow-down el-icon&#45;&#45;right"></i>-->
        <!--              </span>-->
        <!--            <el-dropdown-menu class="user-name-wrapper" slot="dropdown">-->
        <!--                <el-dropdown-item>挂号订单</el-dropdown-item>-->
        <!--                <el-dropdown-item>就诊人管理</el-dropdown-item>-->
        <!--                <el-dropdown-item divided>退出登录</el-dropdown-item>-->
        <!--            </el-dropdown-menu>-->
        <!--        </el-dropdown>-->
        <span class="v-link clickable" @click="dialogUserFormVisible = true">登录/注册</span>
        </div>
        </div>
    </div>
</template>
<script>
export default {
}
</script>

C、提取尾文件

创建 layouts/myfooter.vue 文件

<template>
    <div class="footer-container">
        <div class="wrapper">
            <div><span class="record">京ICP备13018369号</span><span
            class="phone">电话挂号010-56253825</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>

D、默认布局引入头尾文件

修改 layouts/default.vue 文件

<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
    }
  }
</script>

启动项目:npm run dev
访问项目:http://localhost:3000/

2. 首页引入

① 引入首页静态页面
修改 pages/inde.vue 文件

<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、获取医院等级(根据数据字典编码获取)
2、获取地区(根据数据字典编码获取)
3、医院分页列表
4、根据医院名称关键字搜索医院列表

3. 首页数据 api 接口

① 医院分页列表

A、service 接口与实现

在管理平台医院分页列表时已经提供,目前我们可以直接使用

B、添加 controller 接口

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

    @Autowired
    private HospitalService hospitalService;

    @ApiOperation(value = "获取分页列表")
    @GetMapping("{page}/{limit}")
    public Result index(
            @PathVariable Integer page,
            @PathVariable Integer limit,
            HospitalQueryVo hospitalQueryVo) {
        //显示上线的医院
        //hospitalQueryVo.setStatus(1);
        Page<Hospital> pageModel = hospitalService.selectHospPage(page, limit, hospitalQueryVo);
        return Result.ok(pageModel);
    }
}

② 根据医院名称关键字搜索医院列表

A、service接口与实现

在 HospitalService 类添加接口

/**
 * 根据医院名称获取医院列表
*/
List<Hospital> findByHosname(String hosname);

在 HospitalService 类添加接口实现

@Override
public List<Hospital> findByHosname(String hosname) {
    return hospitalRepository.findHospitalByHosnameLike(hosname);
}

B、repository 添加接口

在 HospitalRepository 类添加接口

List<Hospital> findHospitalByHosnameLike(String hosname);

C、添加 controller 接口

在 HospitalApiController 类添加方法

@ApiOperation(value = "根据医院名称获取医院列表")
@GetMapping("findByHosname/{hosname}")
public Result findByHosname(
        @ApiParam(name = "hosname", value = "医院名称", required = true)
        @PathVariable String hosname) {
    return Result.ok(hospitalService.findByHosname(hosname));
}

4. 首页前端实现

① 封装 api 请求

创建 api 文件夹,创建 /api/hosp/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
    })
  },

 getByHosname(hosname) {
    return request({
        url: `${api_name}/findByHosname/${hosname}`,
        method: 'get'
    })
  }
}

创建 /api/cmn/dict.js

import request from '@/utils/request'

const api_name = '/admin/cmn/dict'

export default {
	findByDictCode(dictCode) {
	return request({
		url: `${api_name}/findByDictCode/${dictCode}`,
		method: 'get'
	})
},

findByParentId(parentId) {
    return request({
        url: `${api_name}/findChildData/${parentId}`,
        method: 'get'
    })
  }
}

2. 添加组件

修改 pages/index.vue 组件

<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 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>

import hospApi from '@/api/hosp'
import dictApi from '@/api/dict'

export default {
  //服务端渲染异步,显示医院列表
  asyncData({ params, error }) {
    //调用
    return hospApi.getPageList(1,10,null)
      .then(response => {
        return {
          list: response.data.content,
          pages: response.data.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 => {
          //hostypeList清空
          this.hostypeList = []
          //向hostypeList添加全部值
          this.hostypeList.push({"name":"全部","value":""})
          //把接口返回数据,添加到hostypeList
          for(var i=0;i<response.data.length;i++) {
              this.hostypeList.push(response.data[i])
          }
      })

      //查询地区数据
      dictApi.findByDictCode('Beijing')
        .then(response => {
          this.districtList = []
          this.districtList.push({"name":"全部","value":""})
          for(let i in response.data) {
            this.districtList.push(response.data[i])
          }
        })
    },

    //查询医院列表
    getList() {
      hospApi.getPageList(this.page,this.limit,this.searchObj)
        .then(response => {
          for(let i in response.data.content) {
            this.list.push(response.data.content[i])
          }
          this.page = response.data.totalPages
        })
    },

    //根据医院等级查询
    hostypeSelect(hostype,index) {
      //准备数据
      this.list = []
      this.page = 1
      this.hostypeActiveIndex = index
      this.searchObj.hostype = hostype
      //调用查询医院列表方法
      this.getList()
	},

    //根据地区查询医院
    districtSelect(districtCode, index) {
      this.list = []
      this.page = 1
      this.provinceActiveIndex = index
      this.searchObj.districtCode = districtCode
      this.getList();
	},

    //在输入框输入值,弹出下拉框,显示相关内容
    querySearchAsync(queryString, cb) {
      this.searchObj = []
      if(queryString == '') return
      hospApi.getByHosname(queryString).then(response => {
        for (let i = 0, len = response.data.length; i <len; i++) {
          response.data[i].value = response.data[i].hosname
        }
        cb(response.data)
      })
	},

    //在下拉框选择某一个内容,执行下面方法,跳转到详情页面中
    handleSelect(item) {
      window.location.href = '/hospital/' + item.hoscode
    },

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

三、医院详情

1. 预约挂号

在这里插入图片描述
说明:需要获取医院信息(医院基本信息、预约信息)和科室信息

api 接口

① 添加service接口与实现

在 HospitalService 类添加接口

/**
 * 医院预约挂号详情
*/
Map<String, Object> item(String hoscode);

在 HospitalServiceImpl 类实现接口

@Autowired
private DepartmentService departmentService;
@Override
public Map<String, Object> item(String hoscode) {
    Map<String, Object> result = new HashMap<>();
    //医院详情
    Hospital hospital = this.setHospitalHosType(this.getByHoscode(hoscode));
    result.put("hospital", hospital);
    //预约规则
    result.put("bookingRule", hospital.getBookingRule());
    //不需要重复返回
    hospital.setBookingRule(null);
    return result;
}

② 添加 controller 接口

在 HospitalApiController 类添加方法

@ApiOperation(value = "获取科室列表")
@GetMapping("department/{hoscode}")
public Result index(
        @ApiParam(name = "hoscode", value = "医院code", required = true)
        @PathVariable String hoscode) {
    return Result.ok(departmentService.findTree(hoscode));
}

@ApiOperation(value = "医院预约挂号详情")
@GetMapping("{hoscode}")
public Result item(
        @ApiParam(name = "hoscode", value = "医院code", required = true)
        @PathVariable String hoscode) {
    return Result.ok(hospitalService.item(hoscode));
}

预约挂号前端

① 封装 api 请求

在 /api/hosp.js 文件添加方法

show(hoscode) {
    return request({
        url: `${api_name}/${hoscode}`,
        method: 'get'
    })
},
findDepartment(hoscode) {
    return request({
        url: `${api_name}/department/${hoscode}`,
        method: 'get'
    })
}

② 页面布局

创建 /pages/hospital/_hoscode.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>

<script>
import '~/assets/css/hospital_personal.css'
import '~/assets/css/hospital.css'

import hospitalApi from '@/api/hosp'

export default {
  data() {
    return {
      hoscode: null,
      activeIndex: 0,

      hospital: {
        param: {}
      },
      bookingRule : {},
      departmentVoList : []
    }
  },
  created() {
    this.hoscode = this.$route.params.hoscode
    this.init()
  },

  methods: {
    init() {
      hospitalApi.show(this.hoscode).then(response => {
        this.hospital = response.data.hospital
        this.bookingRule = response.data.bookingRule
      })

      hospitalApi.findDepartment(this.hoscode).then(response => {
        this.departmentVoList = response.data
      })
    },

    move(index, depcode) {
      this.activeIndex = index
      document.getElementById(depcode).scrollIntoView();
    },

    schedule(depcode) {
      window.location.href = '/hospital/schedule?hoscode=' + this.hoscode + "&depcode="+ depcode
    }
  }
}
</script>

2. 医院详情

页面布局:

创建 /pages/hospital/detail/_hoscode.vue 组件

<template>
  <!-- header -->
  <div class="nav-container page-component">
    <!--左侧导航 #start -->
    <div class="nav left-nav">
      <div class="nav-item ">
        <span class="v-link clickable dark" :onclick="'javascript:window.location=\'/hosp/'+hospital.hoscode+'\''">预约挂号 </span>
      </div>
      <div class="nav-item selected">
        <span class="v-link selected dark" :onclick="'javascript:window.location=\'/hosp/detail/'+hospital.hoscode+'\''"> 医院详情 </span>
      </div>
      <div class="nav-item">
        <span class="v-link clickable dark" :onclick="'javascript:window.location=\'/hosp/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-detail">
        <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 :src="'data:image/jpeg;base64,'+hospital.logoData" :alt="hospital.hosname" style="width: 80px; height: 80px;">
          <div class="content-wrapper">
            <div></div>
            <div></div>
            <div></div>
            <div>
              <div class="icon-text-wrapper"><span class="iconfont prefix-icon"></span>
                <span class="text"><p>{{ hospital.route }}</p>
              </span><span class="iconfont right-icon"></span></div>
            </div>
          </div>
        </div>
        <div class="title mt40"> 医院介绍</div>
        <div class="detail-content mt40"><p>{{ hospital.intro }}</p></div>
      </div>
    </div>
    <!-- 右侧内容 #end -->
  </div>
  <!-- footer -->
</template>

<script>
import '~/assets/css/hospital_personal.css'
import '~/assets/css/hospital.css'

import hospitalApi from '@/api/hosp'
export default {
  data() {
    return {
      hoscode: null,
      hospital: {
        param: {}
      }
    }
  },

  created() {
    this.hoscode = this.$route.params.hoscode

    this.init()
  },

  methods: {
    init() {
      hospitalApi.show(this.hoscode).then(response => {
        this.hospital = response.data.hospital
      })

    }
  }
}
</script>
<style>
  .hospital-detail .info-wrapper {
    width: 100%;
    padding-left: 0;
    padding-top: 0;
    margin-top: 0;
    flex-direction: inherit;
  }

  .hospital-detail .info-wrapper .text {
    font-size: 14px;

  }

  .hospital-detail .content-wrapper p {
    text-indent: 0;
  }
</style>

3. 预约须知

页面布局:

创建/pages/hospital/notice/_hoscode.vue组件

<template>
  <!-- header -->
  <div class="nav-container page-component">
    <!--左侧导航 #start -->
    <div class="nav left-nav">
      <div class="nav-item ">
        <span class="v-link clickable dark" :onclick="'javascript:window.location=\'/hosp/'+hospital.hoscode+'\''">预约挂号 </span>
      </div>
      <div class="nav-item ">
        <span class="v-link clickable dark" :onclick="'javascript:window.location=\'/hosp/detail/'+hospital.hoscode+'\''"> 医院详情 </span>
      </div>
      <div class="nav-item selected">
        <span class="v-link selected dark" :onclick="'javascript:window.location=\'/hosp/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-notice">
        <div class="content"><h2>{{ hospital.hosname }}预约挂号须知</h2>
          <p>为方便您早日就医康复,请您认真阅读预约挂号须知:</p>
          <h4 id="一、预约实名制:">一、预约实名制:</h4>
          <p>统一平台电话预约和网上预约挂号均采取实名制注册预约,请您如实提供就诊人员的真实姓名、有效证件号(身份证、护照)、性别、手机号码、社保卡号等基本信息。</p>
          <h4 id="二、预约挂号:">二、预约挂号:</h4>
          <p>按照北京市卫健委统一平台要求,预约挂号规则如下:</p>
          <ul>
            <li>在同一自然日,同一医院,同一科室,同一就诊单元,同一就诊人,可以预约最多1个号源;</li>
            <li>在同一自然周,同一就诊人,可以预约最多8个号源;</li>
            <li>在同一自然月,同一就诊人,可以预约最多12个号源;</li>
            <li>在同一自然季度,同一就诊人,可以预约最多24个号源。</li>
          </ul>
          <h4 id="三、取消预约:">三、取消预约:</h4>
          <p>已完成预约的号源,如需办理退号,至少在就诊前一工作日14:00前通过网站、微信公众号、114电话等平台预约渠道进行取消预约。</p>
          <h4 id="四、爽约处理:">四、爽约处理:</h4>
          <p>如预约成功后患者未能按时就诊且不办理取消预约号视为爽约,同一患者在自然年内爽约规则如下:</p>
          <ul>
            <li>累计爽约3次,自3次爽约日起,90天内不允许通过114平台进行预约挂号;</li>
            <li>累计爽约6次,自6次爽约日起,180天内不允许通过114平台进行预约挂号。</li>
          </ul>
        </div>

      </div>
    </div>
    <!-- 右侧内容 #end -->
  </div>
  <!-- footer -->
</template>

<script>
import '~/assets/css/hospital_personal.css'
import '~/assets/css/hospital.css'

import hospitalApi from '@/api/hosp'
export default {
  data() {
    return {
      hoscode: null,
      hospital: {
        param: {}
      }
    }
  },

  created() {
    this.hoscode = this.$route.params.hoscode

    this.init()
  },

  methods: {
    init() {
      hospitalApi.show(this.hoscode).then(response => {
        this.hospital = response.data.hospital
      })
    }
  }
}
</script>
<style>
  .hospital-detail .info-wrapper {
    width: 100%;
    padding-left: 0;
    padding-top: 0;
    margin-top: 0;
    flex-direction: inherit;
  }

  .hospital-detail .info-wrapper .text {
    font-size: 14px;

  }

  .hospital-detail .content-wrapper p {
    text-indent: 0;
  }
</style>
一个简单的医院挂号系统本采用ACCESS+ASP开发,系统经过多年应用并且持续不断改进,系统各部功能已基本完善,常适合大型医疗集团,当然小型医院或科室就更适合了。 (注:如果你觉的功能太多而不想用其他功能,你可以只用挂号登记) 系统功能说明 1.账号权限 (系统可以任设账号,然后给账号赋予权限,比如导医账户,你可以只给他到院与否的设置,其他一概无法操作和查看,咨询账户只允许填写登记而不能修改和删除以确保登记信息不会被随意更改) 2.咨询内容 (可将咨询内容填入患者资料,以方便查询回访) 3.医院(科室)添加 (可无限动态添加科室或医院) 4.回访 (实时回访标注功能,让你对回访记录一目了然) 5.同比数据对比 (让您时时刻刻了解同期数据对比情况,以了解广告投入和同期回报率) 6.数据明细 (竞价广告、电视广告等等全部综合和单独统计到院和预约量实时掌握成本控制) 7.预约人员评比 (实时查看咨询人员到诊数与预约数,以便了解每位咨询人员的咨询质量和能力,更能促进咨询人员的竞争心理) 8.咨询内容记录 (以方便记录每位患者的详细情况,并了解他为何没有到院以便更好的回访) 9、到院跟踪 (运营部、网络部、医院组、导医组、咨询组完美解决医院内部沟通之间的问题) 还有更多更能您可登陆查看
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在森林中麋了鹿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值