医生端-前端项目搭建

1.使用vite构建vue3

1.1.执行命令

npm create vite

输入项目名字 xixin-doctor-frontend



选择框架-vue



选择js标准-JavaScript

1.2.项目初始化安装

进入项目目录,安装默认依赖及vue-router,axios,element-plus,@element-plus/icons-vue,vue-echarts
Element-Plus: 官网

npm i
npm i vue-router
npm i axios
npm i element-plus
npm i @element-plus/icons-vue

2.项目初始化

2.1.删除默认生成的代码

1.修改App.vue

<template>
  <router-view></router-view>
</template>

2.修改style.css

html,body,div,span,h1,h2,h3,h4,h5,h6,ul,ol,li,p {
    margin: 0;
    padding: 0;
    font-family: "微软雅黑";
}
html,body,#app {
    width: 100%;
    height: 100%;
}
ul,ol {
    list-style: none;
}
a {
    text-decoration: none;
}

3.修改index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <link  rel="icon" type="image/x-icon" href="https://www.xikang.com/favicon.ico">
    <title>熙心健康</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

2.2.创建路由文件

router/index.js

import {createRouter,createWebHashHistory} from 'vue-router'

const routes = [

]
//创建路由实例
const router = createRouter({
    history: createWebHashHistory(),
    routes
  });
//路由守卫
router.beforeEach( (to, from, next) => {
  // 检查 sessionStorage 中是否有登录信息
  const doctor= sessionStorage.getItem('doctor')
  // 如果目标路由需要认证且用户未登录
  if ( !doctor&& to.meta.isAuth ) {
    router.push('/') // 重定向到登录页
  } else {
    next() // 继续导航
  }
})  
export default router;

2.3.创建 axios 实例并封装,配置拦截器

新建api/index.js

import axios from 'axios';
// 创建 axios 实例
const request = axios.create({
    baseURL: 'http://127.0.0.1:1234/backend',
    timeout: 3000 // 请求超时时间
});

// 响应拦截器
request.interceptors.response.use(
    response => {
        // 获取响应数据
        const res = response.data;
        //直接返回响应数据
        return res;
    },
    error => {
        // 处理响应错误
        console.log('响应错误:' + error); // 打印错误信息
    }
);
export default request;

2.4.修改main.js

main.js

import { createApp } from 'vue'
//引入element-plus
import ElementPlus from 'element-plus'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import App from './App.vue'
import './style.css'
import 'element-plus/dist/index.css'
import router from './router'


const app = createApp(App)
app.use(router)
app.use(ElementPlus)
//注册所有ElementPlus图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}
app.mount('#app')

2.5.修改启动端口号

修改vite.config.js

server:{
    port: 7777//启动端口号
  }

3.组件开发

3.1.登录组件 Login.vue

新建: views/Login.vue

<template>
  <div class="wrapper">
    <el-card style="width: 480px">
        <h2 class="login-title">系统登录</h2>
        <el-form ref="form" :model="admin" :rules="rules" label-width="auto" style="max-width: 400px">
            <el-form-item label="登录名" prop="loginName">
                <el-input :prefix-icon="User" v-model="admin.loginName" placeholder="请输入登录名"/>
            </el-form-item>
            <el-form-item label="密码" prop="password">
                <el-input :prefix-icon="Lock" v-model="admin.password" type="password" placeholder="请输入密码" show-password/>
            </el-form-item>    
            <el-button @click="login" :loading="loading" type="primary" class="login-button">
                登录
            </el-button>
        </el-form>    
    </el-card>
  </div>
</template>

<script setup>
 import {ref,reactive} from 'vue'
 import {User,Lock} from '@element-plus/icons-vue'
 import { ElMessage } from 'element-plus'
 import axios from '../api'
 import { useRouter } from 'vue-router'
 let admin = reactive({
    loginName:'',
    password: ''
 })

 let loading = ref(false) //加载
 const rules = reactive( {
  loginName: [
     { required: true, message: '请输入登录名', trigger: 'blur' },
  ],
  password: [
     { required: true, message: '请输入密码', trigger: 'blur' },
  ],})

 const form = ref(null);
 let router = useRouter()
 let login = ()=>{
    form.value.validate(  valid => {
    if (valid) {
      loading.value = true
      axios.get(`/admin/${admin.loginName}/${admin.password}`)
      .then( reponse => {
        loading.value = false
        if (reponse.code==200) {
            ElMessage.success('登录成功')
            sessionStorage.setItem('admin',JSON.stringify(reponse.data) )
            router.push('/index')
        } else{
             ElMessage.error(reponse.msg)
        }
      })
    } 
  });

 }
</script>
<style scoped>
.wrapper{
    background: linear-gradient(120deg, #a1c4fd, #c2e9fb);
    height: 100%;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
}
.el-card{
    width: 400px;
    background-color: #fff;
    border-radius: 10px;
    box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
    padding: 40px;
    box-sizing: border-box;
}
.login-title{
    text-align: center;
    margin-bottom: 30px;
    color: #303133;
    font-weight: 500;
    font-size: 24px;
}

.login-button{
    width: 100%;
    margin-top: 10px;
    background: linear-gradient(45deg, #409EFF, #64b5ff);
    border: none;
    height: 45px;
    font-size: 16px;
}
</style>

3.2.首页组件 Index.vue

<template>
    <el-container>
        <el-header>
            <div>
                <h3>熙心体检管理系统</h3>
            </div>
            <div>
                <el-avatar :size="50" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" />
                <span>{{ admin.loginName }}</span>
            </div>
        </el-header>
        <el-container>
          <el-aside>
            <el-menu
                active-text-color="#ffd04b"
                background-color="#545c64"
                class="el-menu-vertical-demo"
                text-color="#fff"
                router
            >
                <el-sub-menu index="sub1">
                    <template #title>
                        <el-icon><Position /></el-icon>
                        <span>基础数据管理</span>
                    </template>
                    <el-menu-item index="1">医院数据管理</el-menu-item>
                    <el-menu-item index="2">医生数据管理</el-menu-item>
                </el-sub-menu>
                <el-sub-menu index="sub2">
                    <template #title>
                        <el-icon><Histogram /></el-icon>
                        <span>统计分析</span>
                    </template>
                    <el-menu-item index="1">XXX</el-menu-item>
                    <el-menu-item index="2">YYY</el-menu-item>
                </el-sub-menu>
            </el-menu>
          </el-aside>
          <el-main>
            <router-view></router-view>
          </el-main>
        </el-container>
    </el-container>
</template>

<script setup>
 import { ref,reactive } from 'vue'

 const admin = JSON.parse(  sessionStorage.getItem('admin')   )
</script>
<style scoped>
.el-container{
    width: 100%;
    height: 100%;
}
.el-header{
    width: 100%;
    height: 100px;
    background-color: #409eff;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #fff;
}

.el-avatar{
    vertical-align: middle;
    margin-right: 10px;
}

.el-aside{
    width: 200px;
    height: 100%;
}

.el-menu{
    height: 100%;
}

.el-main{
    background-color: #f5f7fa;
}
</style>

3.3.控制台组件 Console.vue

<template>
<div class="page-title">
    <div>
        <div>控制台</div>
        <div class="welcome-text">欢迎回来,管理员!今天是 {{ currentDate }}</div>
    </div>
</div>
<div class="stat-cards">
    <div class="stat-card">
        <div class="card-title">
            <el-icon><User/></el-icon> 
            用户总数
        </div>
        <div class="card-value">12,586</div>
        <div class="card-trend trend-up">
            <el-icon><Top /></el-icon> 同比增长 12.5%
        </div>
    </div>
    
    <div class="stat-card">
        <div class="card-title">
            <i class="el-icon-shopping-bag-1"></i> 订单总数
        </div>
        <div class="card-value">8,742</div>
        <div class="card-trend trend-up">
            <el-icon><ShoppingBag /></el-icon>
             同比增长 8.2%
        </div>
    </div>
    
    <div class="stat-card">
        <div class="card-title">
           <el-icon><Money /></el-icon>
           销售额
        </div>
        <div class="card-value">¥ 1,254,689</div>
        <div class="card-trend trend-up">
            <el-icon><Top /></el-icon> 
            同比增长 15.3%
        </div>
    </div>
    
    <div class="stat-card">
        <div class="card-title">
            <el-icon><Timer /></el-icon> 
            平均响应时间
        </div>
        <div class="card-value">126 ms</div>
        <div class="card-trend trend-down">
            <el-icon><Bottom /></el-icon>
             同比下降 5.2%
        </div>
    </div>
</div>
</template>

<script setup>
 import {ref,reactive } from 'vue'
 import {User,ShoppingBag,Top,Bottom,Timer,Money} from '@element-plus/icons-vue'
const currentDate = new Date().toLocaleDateString('zh-CN', {
                    year: 'numeric',
                    month: 'long',
                    day: 'numeric',
                    weekday: 'long'
                })
                
</script>
<style scoped>
.page-title {
    margin-bottom: 20px;
    font-size: 12px;
    font-weight: 500;
    color: #303133;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.stat-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 20px;
    margin-bottom: 20px;
}
        
.stat-card {
    background: white;
    border-radius: 4px;
    padding: 20px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    transition: transform 0.3s;
}

.stat-card:hover {
    transform: translateY(-5px);
}

.card-title {
    color: #909399;
    font-size: 14px;
    margin-bottom: 12px;
    display: flex;
    align-items: center;
}

.card-title i {
    margin-right: 6px;
}

.card-value {
    font-size: 26px;
    font-weight: bold;
    color: #303133;
    margin-bottom: 8px;
}

.card-trend {
    font-size: 14px;
    display: flex;
    align-items: center;
}

.trend-up {
    color: #f56c6c;
}

.trend-down {
    color: #67c23a;
}
</style>

3.4.医院数据管理组件

1.Hospital.vue

<template>
   <el-card >
    <el-form :inline="true" :model="hospital" class="demo-form-inline">
         <el-form-item label="医院名称">
            <el-input v-model="hospital.name" clearable />
         </el-form-item>
         <el-form-item label="医院地址">
            <el-input v-model="hospital.address"  clearable />
         </el-form-item>
         <el-form-item >
            <el-button @click="query" type="primary" title="查询" :icon="Search" circle />
            <el-button @click="$router.push('/index/hospitaladd')" type="warning" title="新增" :icon="CirclePlus" circle />
         </el-form-item>
    </el-form>    
   
   <el-table :data="tableData" border  stripe>
    <el-table-column prop="hpId" label="医院编号" width="100"/>
    <el-table-column prop="name" label="医院名称" />
    <el-table-column label="医院图片" width="100">
        <template #default="scope">
             <el-image style="width: 50px; height: 50px" :src="scope.row.img"  />
        </template>
    </el-table-column>
    <el-table-column prop="telephone" label="医院电话" />
    <el-table-column prop="address" label="医院地址"/>
    <el-table-column prop="businessHours" label="营业时间" />
    <el-table-column prop="deadline" label="采血截止时间" />
     <el-table-column label="修改" width="80">
        <template #default="scope">
            <el-button @click="toUpdate(scope.row)" type="success"  :icon="Edit" circle />
        </template>
    </el-table-column>
   </el-table>
   </el-card>
</template>

<script setup>
 import { ref,reactive } from 'vue'
 import {Search,CirclePlus,Edit} from '@element-plus/icons-vue'
 import axios from '../api'
 import { useRouter } from 'vue-router'
 
 const hospital = reactive(
    {
        name: '',
        address: '',
    }
 )
 
 //
 const tableData = ref([])

 const query = ()=>{
   axios.post('/hospital/query',hospital)
   .then( response=>{
      tableData.value = response.data
   } ) 
 }

 const router = useRouter()
 const toUpdate = hospital=>{
   router.push({
      path: '/index/hospitalupdate',
      query: hospital
   })
 }
</script>
<style scoped>
.el-card{
   width: 90%;
   margin: 0 auto;
}
.el-form{
  
   margin: 0 auto;
}
.el-table{
  
   margin: 0 auto;
}
.el-pagination{
   
   margin: 0 auto;
}
</style>

2.HospitalAdd.vue

<template>
   <el-icon @click="$router.back"><DArrowLeft /></el-icon>
   <el-card>
      <template #header>
         <h4>医院信息增加</h4>
      </template>
      <el-form ref="form" :rules="rules" :model="hospital"  label-width="auto" style="width: 90%;margin: 0 auto;">
         <el-form-item label="医院名称" prop="name">
            <el-input v-model="hospital.name" />
         </el-form-item>
         <el-form-item label="医院地址" prop="address">
            <el-input v-model="hospital.address" />
         </el-form-item>
         <el-form-item label="医院电话" prop="telephone">
            <el-input v-model="hospital.telephone" />
         </el-form-item>
         <el-form-item label="营业时间" prop="businessHours">
            <el-input v-model="hospital.businessHours" />
         </el-form-item>
         <el-form-item label="采血截止时间" prop="deadline">
            <el-input v-model="hospital.deadline" />
         </el-form-item>
         <el-form-item  label="医院图片" prop="img">
            <el-input  v-model="hospital.img" type="textarea" />
         </el-form-item>
         <el-button class="submit-btn" type="primary" @click="onSubmit">提交</el-button>
      </el-form>
   </el-card>
</template>

<script setup>
 import { ref,reactive } from 'vue'
 import axios from '../api'
 import { ElMessage } from 'element-plus'
 
 const hospital = reactive(
    {
        name: '',
        address: '',
        img: '',
        telephone: '',
        address: '',
        businessHours: '',
        deadline: ''
    }
 )
 
const rules = reactive( {
name: [
   { required: true, message: '请输入医院名称', trigger: 'blur' },
],
address: [
   { required: true, message: '请输入医院地址', trigger: 'blur' },
],
telephone: [
   { required: true, message: '请输入医院电话', trigger: 'blur' },
],
businessHours:[
   { required: true,message: '请输入营业时间',trigger: 'blur'}
],
deadline:[
   { required: true,message: '请输入采血截止时间',trigger: 'blur'}
],
img:[
   { required: true,message: '请输入医院图片',trigger: 'blur'}
],
})

const form = ref(null)
const onSubmit = ()=>{
   form.value.validate( validate=>{
      if (validate) {
         axios.post('/hospital',hospital)
         .then( response=>{
            ElMessage.success(response.data)
         }  )
        
      }
   } )
}
</script>
<style scoped>
.el-card{
   width: 60%;
   margin: 0 auto;
   padding: 20px;
}
.submit-btn{
   width: 100%;
}
</style>

3.HospitalUpdate.vue

<template>
   <el-icon @click="$router.back"><DArrowLeft /></el-icon>
   <el-card>
       <template #header>
         <h4>医院信息修改</h4>
      </template>
      <el-form ref="form" :rules="rules" :model="hospital"  label-width="auto" style="width: 90%;margin: 0 auto;">
         <el-form-item label="医院编号" >
            <el-input readonly v-model="hospital.hpId" />
         </el-form-item>
         <el-form-item label="医院名称" prop="name">
            <el-input v-model="hospital.name" />
         </el-form-item>
         <el-form-item label="医院地址" prop="address">
            <el-input v-model="hospital.address" />
         </el-form-item>
         <el-form-item label="医院电话" prop="telephone">
            <el-input v-model="hospital.telephone" />
         </el-form-item>
         <el-form-item label="营业时间" prop="businessHours">
            <el-input v-model="hospital.businessHours" />
         </el-form-item>
         <el-form-item label="采血截止时间" prop="deadline">
            <el-input v-model="hospital.deadline" />
         </el-form-item>
         <el-form-item  label="医院图片" prop="img">
            <el-input  v-model="hospital.img" type="textarea" />
         </el-form-item>
         <el-button class="submit-btn" type="primary" @click="onSubmit">提交</el-button>
      </el-form>
   </el-card>
</template>

<script setup>
 import { ref,reactive } from 'vue'
 import axios from '../api'
 import { ElMessage } from 'element-plus'
 import { useRoute } from 'vue-router' 
 
 const route = useRoute()
 const hospital = reactive( route.query )
 
const rules = reactive( {
name: [
   { required: true, message: '请输入医院名称', trigger: 'blur' },
],
address: [
   { required: true, message: '请输入医院地址', trigger: 'blur' },
],
telephone: [
   { required: true, message: '请输入医院电话', trigger: 'blur' },
],
businessHours:[
   { required: true,message: '请输入营业时间',trigger: 'blur'}
],
deadline:[
   { required: true,message: '请输入采血截止时间',trigger: 'blur'}
],
img:[
   { required: true,message: '请输入医院图片',trigger: 'blur'}
],
})

const form = ref(null)
const onSubmit = ()=>{
   form.value.validate( validate=>{
      if (validate) {
         axios.put('/hospital',hospital)
         .then( response=>{
            ElMessage.success(response.data)
         }  )
        
      }
   } )
}
</script>
<style scoped>
.el-card{
   width: 60%;
   margin: 0 auto;
   padding: 20px;
}
.submit-btn{
   width: 100%;
}
</style>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容