This commit is contained in:
Hoshinasuzu 2024-12-24 21:44:26 +08:00
parent 7d7422aa15
commit 3eb0692a99
21 changed files with 3925 additions and 530 deletions

View File

@ -11,9 +11,6 @@
padding: 0;
box-sizing: border-box;
}
li {
list-style: none;
}
</style>
</head>
<body>

3583
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
"element-plus": "^2.7.6",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"pnpm": "^9.15.0",
"vue": "^3.5.10",
"vue-router": "^4.3.3"
},

View File

@ -26,6 +26,9 @@ importers:
pinia-plugin-persistedstate:
specifier: ^3.2.1
version: 3.2.1(pinia@2.1.7(vue@3.5.10))
pnpm:
specifier: ^9.15.0
version: 9.15.0
vue:
specifier: ^3.5.10
version: 3.5.10
@ -1096,6 +1099,11 @@ packages:
pkg-types@1.1.3:
resolution: {integrity: sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==}
pnpm@9.15.0:
resolution: {integrity: sha512-duI3l2CkMo7EQVgVvNZije5yevN3mqpMkU45RBVsQpmSGon5djge4QfUHxLPpLZmgcqccY8GaPoIMe1MbYulbA==}
engines: {node: '>=18.12'}
hasBin: true
postcss-selector-parser@6.1.0:
resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==}
engines: {node: '>=4'}
@ -2357,6 +2365,8 @@ snapshots:
mlly: 1.7.1
pathe: 1.1.2
pnpm@9.15.0: {}
postcss-selector-parser@6.1.0:
dependencies:
cssesc: 3.0.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,4 +1,5 @@
import instance from '@/utils/request'
import warning from '@/utils/warning'
export const getDoctor = ({ current, size, name }) =>
instance({
@ -19,7 +20,7 @@ export const saveOrUpdateDoctor = (doctor) =>
})
export const deleteDoctorApi = (id) =>
instance({
warning({
url: '/doctor/deleteDoctor',
method: 'post',
data: id

View File

@ -1,4 +1,5 @@
import instance from '@/utils/request'
import warning from '@/utils/warning'
export const getHospitalApi = ({ current, size, name, districtName }) =>
instance({
@ -20,7 +21,7 @@ export const saveOrUpdateHospital = (hospital) =>
})
export const deleteHospitalApi = (id) =>
instance({
warning({
url: '/hospital/deleteHospital',
method: 'post',
data: id

View File

@ -8,4 +8,4 @@ export const userLoginService = ({ username, password, captchaKey, captchaCode }
instance.post('/login', { username, password, captchaKey, captchaCode })
// 获取用户信息
export const userGetInfoService = () => instance.get('/info')
export const userGetInfoService = (name) => instance.post('/info?name=' + name)

View File

@ -1,4 +1,5 @@
import instance from '@/utils/request'
import warning from '@/utils/warning'
export const getUserInfoApi = ({current, size, name}) => instance({
url: '/user/getUserInfoPageItem',
@ -13,4 +14,4 @@ export const getUserInfoApi = ({current, size, name}) => instance({
export const getUserStateApi = ({id, state}) =>
instance.post('/user/updateUserInfoState?id=' + id + '&state=' + state)
export const deleteUserApi = (id) => instance.post('/user/deleteUserInfo?id=' + id)
export const deleteUserApi = (id) => warning.post('/user/deleteUserInfo?id=' + id)

View File

@ -5,11 +5,11 @@ const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/login',
path: '/',
component: () => import('../views/1_login/LoginPage.vue')
},
{
path: '/',
path: '/home',
component: () => import('../views/2_layout/Layout.vue'),
redirect: '/hospital',
children: [

View File

@ -8,4 +8,3 @@ export default pinia
// 统一导出
export * from './modules/user'
export * from './modules/counter'

View File

@ -5,7 +5,8 @@ import { userGetInfoService } from '@/api/user'
export const useUserStore = defineStore(
'big-user',
() => {
const token = ref('eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NTg4ODQxMzAsInN1YiI6IkxPR0lOX1VTRVIiLCJ1c2VySWQiOjgsInVzZXJOYW1lIjoiMTU2NzQ2NzU2NjcifQ.SzXVzIX5hk1trTyTTasnpLOGJQKhnjk56KCM5P5kVGo')
// const token = ref('eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NTg4ODQxMzAsInN1YiI6IkxPR0lOX1VTRVIiLCJ1c2VySWQiOjgsInVzZXJOYW1lIjoiMTU2NzQ2NzU2NjcifQ.SzXVzIX5hk1trTyTTasnpLOGJQKhnjk56KCM5P5kVGo')
const token = ref('')
const setToken = (newToken) => {
token.value = newToken
}
@ -13,9 +14,9 @@ export const useUserStore = defineStore(
token.value = ''
}
const user = ref({})
const getUser = async() => {
// const res = await userGetInfoService()
// user.value = res.data.data
const getUser = async(name) => {
const res = await userGetInfoService(name)
user.value = res.data.data
}
const setUser = (newUser) => {
user.value = newUser

View File

@ -7,7 +7,6 @@ import { useUserStore } from '@/stores'
const baseURL = '/admin'
const instance = axios.create({
baseURL,
timeout: 5000,
headers: {
token: ''
}

43
src/utils/warning.js Normal file
View File

@ -0,0 +1,43 @@
import axios from 'axios'
import { ElMessage } from 'element-plus'
import router from '@/router'
import { useUserStore } from '@/stores'
// 基本配置
const baseURL = '/admin'
const warning = axios.create({
baseURL,
headers: {
token: ''
}
})
// 请求拦截器,发送给数据之前
warning.interceptors.request.use(
(config) => {
// 添加token
const userStore = useUserStore()
const token = userStore.token
if (token) {
config.headers.token = token
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器,获取数据之前
warning.interceptors.response.use(
(response) => {
if (response.data.status === 200) {
return response
}
},
(error) => {
ElMessage.warning('请先删除子集')
return Promise.reject(error)
}
)
export default warning

View File

@ -46,8 +46,9 @@ const login = async () => {
const res = await userLoginService(formModle.value)
// token
userStore.setToken(res.data.data)
userStore.getUser(formModle.value.username)
ElMessage.success('登录成功')
router.push('/')
router.push('/home')
}
const getVerification = async () => {
@ -63,7 +64,7 @@ const getVerification = async () => {
<div class="logo"></div>
<el-form :model="formModle" :rules="rules" ref="form" size="large" class="forms">
<el-form-item>
<h1 style="margin-bottom: 8px">欢迎来到后台管理</h1>
<h1 style="margin-bottom: 8px">欢迎来到后台管理系统</h1>
</el-form-item>
<el-form-item prop="username">
<el-input
@ -85,6 +86,7 @@ const getVerification = async () => {
v-model="formModle.captchaCode"
:prefix-icon="Lock"
type="captchaCode"
@keyup.enter="login"
placeholder="请输入验证码"
>
</el-input>

View File

@ -31,62 +31,70 @@ window.addEventListener('resize', handleResize)
//
onMounted(() => {
userStore.getUser()
handleResize()
})
</script>
<template>
<el-container class="layout-container">
<el-menu
class="el-menu el-menu-vertical-demo"
:collapse="isCollapse"
:default-active="$route.path"
active-text-color="#409EFF"
background-color="#444"
text-color="#fff"
router
>
<el-menu class="el-menu el-menu-vertical-demo" :collapse="isCollapse" :default-active="$route.path"
active-text-color="#409EFF" background-color="#444" text-color="#fff" router>
<div class="logo"></div>
<el-menu-item index="/hospital">
<el-icon><CirclePlusFilled /></el-icon>
<el-icon>
<CirclePlusFilled />
</el-icon>
<span>医院管理</span>
</el-menu-item>
<el-menu-item index="/doctor">
<el-icon><Avatar /></el-icon>
<el-icon>
<Avatar />
</el-icon>
<span>医生管理</span>
</el-menu-item>
<el-menu-item index="/article">
<el-icon><Management /></el-icon>
<el-icon>
<Management />
</el-icon>
<span>医说管理</span>
</el-menu-item>
<el-menu-item index="/appoint">
<el-icon><List /></el-icon>
<el-icon>
<List />
</el-icon>
<span>预约管理</span>
</el-menu-item>
<el-menu-item index="/userInfo">
<el-icon><UserFilled /></el-icon>
<el-icon>
<UserFilled />
</el-icon>
<span>用户信息管理</span>
</el-menu-item>
</el-menu>
<el-container>
<el-header>
<div style="display: flex; font-size: 20px">
<span
@click="isCollapse = !isCollapse"
style="
<div style="display: flex; font-size: 16px">
<span @click="isCollapse = !isCollapse" style="
display: flex;
align-items: center;
margin-right: 16px;
cursor: pointer;
"
>
<el-icon v-if="!isCollapse" size="24"><Fold /></el-icon>
<el-icon v-else size="24"><Expand /></el-icon>
">
<el-icon v-if="!isCollapse" size="24">
<Fold />
</el-icon>
<el-icon v-else size="24">
<Expand />
</el-icon>
</span>
<strong>后台管理员{{ userStore.user.name || 'admin' }}</strong>
<div style="display: flex; align-items: center">
<el-avatar :src="userStore.user.avatarUrl || avatar" style="width: 60px; height: 60px; margin-right: 8px;"
fit="cover;" />
<strong>{{ userStore.user.name || 'admin' }}</strong>
</div>
</div>
<el-avatar :src="userStore.user.avatarUrl || avatar" />
<h2 style="font-size: 30px; position: absolute; left: 45%">医路无忧后台管理系统</h2>
</el-header>
<el-main>
<el-config-provider :locale="zhCn">
@ -104,25 +112,35 @@ onMounted(() => {
<style lang="scss" scoped>
.layout-container {
height: 100vh;
.logo {
height: 100px;
margin-top: 16px;
margin-bottom: 4px;
background: url('/logo.png') no-repeat center / 50%;
}
:deep() .el-menu {
width: auto;
.el-menu-item {
padding-left: 30px !important;
padding-right: 30px !important;
}
}
.el-header {
background-color: #fff;
display: flex;
align-items: center;
height: 100px;
justify-content: space-between;
}
.el-main {
padding-top: 0;
}
.el-footer {
display: flex;
align-items: center;
@ -136,6 +154,7 @@ onMounted(() => {
.scale-leave-active {
transition: all 0.3s ease;
}
.scale-enter-from,
.scale-leave-to {
opacity: 0;

View File

@ -330,6 +330,34 @@ const options = ref([
label: '肝胆外科'
}
]
},
{
value: '妇产科',
label: '妇产科',
children: [
{
value: '妇科',
label: '妇科'
},
{
value: '产科',
label: '产科'
}
]
},
{
value: '中医科',
label: '中医科',
children: [
{
value: '针灸推拿科',
label: '针灸推拿科'
},
{
value: '中医科',
label: '中医科'
}
]
}
])
const getDepartmentVo = async (id) => {
@ -337,9 +365,8 @@ const getDepartmentVo = async (id) => {
departmentList.value = res.data.data
}
///
const deletedoctorDepartment = async (row) => {
console.log(hospitalId.value, row.id)
await deleteDepartment({ hospitalId: row.id, departmentId: row.id })
const deleteHospitalDepartment = async (row) => {
await deleteDepartment({ hospitalId: hospitalId.value, departmentId: row.id })
ElMessage.success('删除成功')
getDepartmentVo(hospitalId.value)
}
@ -422,138 +449,55 @@ onMounted(async () => {
<el-button @click="deletehospitals" type="danger"> 批量删除 </el-button>
</template>
<template #search>
<el-cascader
@change="cityFilter"
placeholder="请选择辖区"
filterable
clearable
style="width: fit-content; margin-right: 16px"
:options="cityChoose"
/>
<el-input
v-model="params.name"
placeholder="搜索医院名称"
clearable
@keyup.enter="getHospital"
style="width: 220px"
>
<el-cascader @change="cityFilter" placeholder="请选择辖区" filterable clearable
style="width: fit-content; margin-right: 16px" :options="cityChoose" />
<el-input v-model="params.name" placeholder="搜索医院名称" clearable @keyup.enter="getHospital" style="width: 220px">
</el-input>
</template>
<el-drawer
v-model="drawerVisible"
title="编辑或增加"
size="50%"
@closed="show = true"
>
<el-form
ref="hospitalFormRef"
:model="hospitalForm"
label-width="auto"
inline
label-position="left"
style="padding: 0 24px"
>
<el-form-item
label="医院名称"
:rules="[
{ required: true, message: '请输入医院名称', trigger: 'blur' }
]"
prop="hospitalName"
>
<el-input
placeholder="请输入医院名称"
v-model="hospitalForm.hospitalName"
/>
<el-drawer v-model="drawerVisible" title="编辑或增加" size="50%" @closed="show = true">
<el-form ref="hospitalFormRef" :model="hospitalForm" label-width="auto" inline label-position="left"
style="padding: 0 24px">
<el-form-item label="医院名称" :rules="[
{ required: true, message: '请输入医院名称', trigger: 'blur' }
]" prop="hospitalName">
<el-input placeholder="请输入医院名称" v-model="hospitalForm.hospitalName" />
</el-form-item>
<el-form-item label="&nbsp;&nbsp;所在辖区" prop="cityInfo">
<el-select
v-if="hospitalForm.cityInfo && show"
v-model="hospitalForm.cityInfo"
@click="show = false"
/>
<el-cascader
v-else
@change="cityChange"
placeholder="请选择辖区"
filterable
style="width: fit-content"
:options="cityChoose"
/>
<el-select v-if="hospitalForm.cityInfo && show" v-model="hospitalForm.cityInfo" @click="show = false" />
<el-cascader v-else @change="cityChange" placeholder="请选择辖区" filterable style="width: fit-content"
:options="cityChoose" />
</el-form-item>
<el-form-item
label="医院地址"
:rules="[
{ required: true, message: '请输入医院地址', trigger: 'blur' }
]"
prop="address"
>
<el-input
placeholder="请输入医院地址"
v-model="hospitalForm.address"
/>
<el-form-item label="医院地址" :rules="[
{ required: true, message: '请输入医院地址', trigger: 'blur' }
]" prop="address">
<el-input placeholder="请输入医院地址" v-model="hospitalForm.address" />
</el-form-item>
<el-form-item
label="等&emsp;&emsp;级"
:rules="[
{ required: true, message: '请选择医院等级', trigger: 'blur' }
]"
prop="level"
>
<el-select
v-model="hospitalForm.level"
placeholder="请选择医院等级"
@change="levelChange"
>
<el-option
v-for="item in levelList"
:key="item.value"
:value="item.value"
/>
<el-form-item label="等&emsp;&emsp;级" :rules="[
{ required: true, message: '请选择医院等级', trigger: 'blur' }
]" prop="level">
<el-select v-model="hospitalForm.level" placeholder="请选择医院等级" @change="levelChange">
<el-option v-for="item in levelList" :key="item.value" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item
label="医院电话"
prop="phone"
:rules="[
{ required: true, message: '请输入医院电话', trigger: 'blur' }
]"
>
<el-form-item label="医院电话" prop="phone" :rules="[
{ required: true, message: '请输入医院电话', trigger: 'blur' }
]">
<el-input placeholder="请输入医院电话" v-model="hospitalForm.phone" />
</el-form-item>
<el-form-item
label="医院照片"
:rules="[{ required: true, message: '请上传图片', trigger: 'blur' }]"
prop="url"
style="width: 100%"
>
<el-upload
:show-file-list="false"
:auto-upload="false"
:on-change="onSelectFile"
class="avatar-uploader"
>
<img
v-if="imageUrl || hospitalForm.url"
:src="imageUrl || hospitalForm.url"
class="avatar"
/>
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
<el-form-item label="医院照片" :rules="[{ required: true, message: '请上传图片', trigger: 'blur' }]" prop="url"
style="width: 100%">
<el-upload :show-file-list="false" :auto-upload="false" :on-change="onSelectFile" class="avatar-uploader">
<img v-if="imageUrl || hospitalForm.url" :src="imageUrl || hospitalForm.url" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item
label="医院简介"
style="width: 100%"
:rules="[
{ required: true, message: '请输入医院简介', trigger: 'blur' }
]"
>
<el-input
placeholder="请输入医院简介"
type="textarea"
:rows="10"
v-model="hospitalForm.introduction"
/>
<el-form-item label="医院简介" style="width: 100%" :rules="[
{ required: true, message: '请输入医院简介', trigger: 'blur' }
]">
<el-input placeholder="请输入医院简介" type="textarea" :rows="10" v-model="hospitalForm.introduction" />
</el-form-item>
</el-form>
<template #footer>
@ -565,11 +509,7 @@ onMounted(async () => {
</el-drawer>
<el-dialog v-model="dialogVisible" title="增加" width="400">
<el-cascader-panel
@change="departmentChange"
style="width: fit-content"
:options="options"
/>
<el-cascader-panel @change="departmentChange" style="width: fit-content" :options="options" />
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false"> 取消 </el-button>
@ -578,49 +518,27 @@ onMounted(async () => {
</template>
</el-dialog>
<el-table
stripe
:data="hospital.records"
height="100%"
:default-sort="{ prop: 'id', order: 'ascending' }"
@expand-change="expandChange"
@selection-change="select"
>
<el-table stripe :data="hospital.records" height="100%" :default-sort="{ prop: 'id', order: 'ascending' }"
@expand-change="expandChange" @selection-change="select">
<el-table-column type="selection" width="50" />
<el-table-column type="expand">
<template #default="{ row }">
<div class="expand-content">
<div>
<h3 style="margin-bottom: 8px">医院简介</h3>
<p
v-html="
row.introduction
.replace(/\n/g, '<br/>')
.replace(/\t/g, '&emsp;')
"
></p>
<p v-html="row.introduction
.replace(/\n/g, '<br/>')
.replace(/\t/g, '&emsp;')
"></p>
</div>
<div style="display: flex">
<h3 style="margin-bottom: 20px">标签</h3>
<el-tag
v-for="tag in dynamicTags"
:key="tag"
closable
style="margin-right: 8px"
:disable-transitions="false"
@close="handleClose(tag)"
>
<el-tag v-for="tag in dynamicTags" :key="tag" closable style="margin-right: 8px"
:disable-transitions="false" @close="handleClose(tag)">
{{ tag }}
</el-tag>
<el-input
v-if="inputVisible"
ref="InputRef"
v-model="inputValue"
size="small"
style="height: 100%; width: 82px"
@keyup.enter="handleInputConfirm"
@blur="handleInputConfirm"
/>
<el-input v-if="inputVisible" ref="InputRef" v-model="inputValue" size="small"
style="height: 100%; width: 82px" @keyup.enter="handleInputConfirm" @blur="handleInputConfirm" />
<el-button v-else size="small" @click="showInput">
+ 添加标签
</el-button>
@ -631,31 +549,16 @@ onMounted(async () => {
添加科室
</el-button>
</div>
<el-table
:data="departmentList"
max-height="300"
:default-sort="{ prop: 'id', order: 'ascending' }"
>
<el-table :data="departmentList" max-height="300" :default-sort="{ prop: 'id', order: 'ascending' }">
<el-table-column prop="id" label="id" show-overflow-tooltip />
<el-table-column
prop="belong"
label="科室"
show-overflow-tooltip
/>
<el-table-column
prop="name"
label="具体科室"
show-overflow-tooltip
/>
<el-table-column prop="belong" label="科室" show-overflow-tooltip />
<el-table-column prop="name" label="具体科室" show-overflow-tooltip />
<el-table-column label="删除" width="108">
<template #default="{ row }">
<el-button
plain
type="danger"
size="small"
@click="deletedoctorDepartment(row)"
>
<el-icon><Delete /></el-icon>
<el-button plain type="danger" size="small" @click="deleteHospitalDepartment(row)">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-table-column>
@ -666,32 +569,17 @@ onMounted(async () => {
</div>
</template>
</el-table-column>
<el-table-column
prop="id"
label="id"
show-overflow-tooltip
width="60px"
/>
<el-table-column width="100px" label="图片">
<el-table-column prop="id" label="id" show-overflow-tooltip width="60px" />
<el-table-column width="80px" label="图片">
<template #default="{ row }">
<el-image :src="row.url || '/logo.png'" />
<el-image :src="row.url || '/logo.png'" style="width: 80px; height: 80px" fit="cover" />
</template>
</el-table-column>
<el-table-column
prop="hospitalName"
label="医院名称"
show-overflow-tooltip
/>
<el-table-column prop="hospitalName" label="医院名称" show-overflow-tooltip />
<el-table-column prop="cityName" label="所在市" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="address" label="地址" show-overflow-tooltip />
<el-table-column
prop="level"
label="等级"
:filters="levelList"
:filter-method="levelFilter"
show-overflow-tooltip
>
<el-table-column prop="level" label="等级" :filters="levelList" :filter-method="levelFilter" show-overflow-tooltip>
<template #default="scope">
<span>{{ scope.row.level }}</span>
</template>
@ -699,21 +587,15 @@ onMounted(async () => {
<el-table-column prop="phone" label="电话" show-overflow-tooltip />
<el-table-column label="编辑/删除" width="108" fixed="right">
<template #default="{ row }">
<el-button
plain
type="primary"
size="small"
@click="saveOrUpdate(row)"
>
<el-icon><Edit /></el-icon>
<el-button plain type="primary" size="small" @click="saveOrUpdate(row)">
<el-icon>
<Edit />
</el-icon>
</el-button>
<el-button
plain
type="danger"
size="small"
@click="deletehospital(row)"
>
<el-icon><Delete /></el-icon>
<el-button plain type="danger" size="small" @click="deletehospital(row)">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-table-column>
@ -722,14 +604,9 @@ onMounted(async () => {
</template>
</el-table>
<el-pagination
v-model:page-size="pageSize"
layout="total, prev, pager, next"
:total="+hospital.total"
style="height: 48px; justify-content: center"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
/>
<el-pagination v-model:page-size="pageSize" layout="total, prev, pager, next" :total="+hospital.total"
style="height: 48px; justify-content: center" @current-change="handleCurrentChange"
@size-change="handleSizeChange" />
</page-container>
</template>
@ -743,6 +620,7 @@ onMounted(async () => {
width: 100%;
flex-direction: column;
padding: 16px;
p {
border-radius: 12px;
line-height: 1.5;
@ -750,6 +628,7 @@ onMounted(async () => {
padding: 24px;
margin-bottom: 24px;
}
.el-table {
width: 50%;
}
@ -764,6 +643,7 @@ onMounted(async () => {
display: block;
object-fit: contain;
}
.el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
@ -772,9 +652,11 @@ onMounted(async () => {
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;

View File

@ -40,7 +40,7 @@ const doctor = ref({
})
//
const pageSize = ref(2)
const pageSize = ref(10)
const currentPage = ref(1)
const handleCurrentChange = async (val) => {
currentPage.value = val
@ -169,7 +169,7 @@ const appoint = async () => {
dialogVisible.value = false
ElMessage.success('添加成功')
appointAdd.value = false
getAppoint()
getAppoint(appointForm.value)
}
//
@ -208,122 +208,53 @@ onUnmounted(() => {
<el-button @click="deletedoctors" type="danger"> 批量删除 </el-button>
</template>
<template #search>
<el-input
v-model="params.name"
placeholder="请输入医生名称"
clearable
@keyup.enter="getDoctorList"
style="width: 250px"
>
<el-input v-model="params.name" placeholder="请输入医生名称" clearable @keyup.enter="getDoctorList" style="width: 250px">
</el-input>
</template>
<!-- 医生弹出层 -->
<el-drawer v-model="drawerVisible" title="编辑或增加" size="50%">
<el-form
ref="doctorFormRef"
:model="doctorForm"
label-width="auto"
inline
label-position="left"
style="padding: 0 24px"
>
<el-form-item
label="医生姓名"
:rules="[
{ required: true, message: '请输入医生姓名', trigger: 'blur' }
]"
prop="doctorName"
>
<el-input
placeholder="请输入医生姓名"
v-model="doctorForm.doctorName"
/>
<el-form ref="doctorFormRef" :model="doctorForm" label-width="auto" inline label-position="left"
style="padding: 0 24px">
<el-form-item label="医生姓名" :rules="[
{ required: true, message: '请输入医生姓名', trigger: 'blur' }
]" prop="doctorName">
<el-input placeholder="请输入医生姓名" v-model="doctorForm.doctorName" />
</el-form-item>
<el-form-item
label="职&emsp;&emsp;称"
:rules="[
{ required: true, message: '请输入医生职称', trigger: 'blur' }
]"
prop="level"
>
<el-form-item label="职&emsp;&emsp;称" :rules="[
{ required: true, message: '请输入医生职称', trigger: 'blur' }
]" prop="level">
<el-input placeholder="请输入医生职称" v-model="doctorForm.level" />
</el-form-item>
<el-form-item label="&nbsp;&nbsp;头&emsp;&emsp;衔" prop="source">
<el-input placeholder="请输入医生学历" v-model="doctorForm.source" />
</el-form-item>
<el-form-item label="&nbsp;&nbsp;擅长领域" prop="expertise">
<el-input
placeholder="请输入医生头衔"
v-model="doctorForm.expertise"
/>
<el-input placeholder="请输入医生头衔" v-model="doctorForm.expertise" />
</el-form-item>
<el-form-item
label="所属科室"
:rules="[{ required: true, message: '请选择医生', trigger: 'blur' }]"
prop="departmentName"
>
<el-select
v-model="doctorForm.departmentName"
placeholder="请选择科室"
@change="departmentChange"
>
<el-option
v-for="item in departmentList"
:key="item.value"
:value="item.value"
/>
<el-form-item label="所属科室" :rules="[{ required: true, message: '请选择医生', trigger: 'blur' }]"
prop="departmentName">
<el-select v-model="doctorForm.departmentName" placeholder="请选择科室" @change="departmentChange">
<el-option v-for="item in departmentList" :key="item.value" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item
label="所属医院"
:rules="[{ required: true, message: '请选择医院', trigger: 'blur' }]"
prop="hospitalName"
>
<el-select
v-model="doctorForm.hospitalName"
placeholder="请选择医院"
@change="hospitalChange"
>
<el-option
v-for="item in hospitalList"
:key="item.value"
:value="item.value"
/>
<el-form-item label="所属医院" :rules="[{ required: true, message: '请选择医院', trigger: 'blur' }]" prop="hospitalName">
<el-select v-model="doctorForm.hospitalName" placeholder="请选择医院" @change="hospitalChange">
<el-option v-for="item in hospitalList" :key="item.value" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item
label="医生照片"
:rules="[{ required: true, message: '请上传图片', trigger: 'blur' }]"
prop="url"
>
<el-upload
:show-file-list="false"
:auto-upload="false"
:on-change="onSelectFile"
class="avatar-uploader"
>
<img
v-if="imageUrl || doctorForm.url"
:src="imageUrl || doctorForm.url"
class="avatar"
/>
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
<el-form-item label="医生照片" :rules="[{ required: true, message: '请上传图片', trigger: 'blur' }]" prop="url">
<el-upload :show-file-list="false" :auto-upload="false" :on-change="onSelectFile" class="avatar-uploader">
<img v-if="imageUrl || doctorForm.url" :src="imageUrl || doctorForm.url" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item
label="医生简介"
style="width: 100%"
:rules="[
{ required: true, message: '请输入医生简介', trigger: 'blur' }
]"
>
<el-input
placeholder="请输入医生简介"
type="textarea"
:rows="3"
v-model="doctorForm.briefly"
/>
<el-form-item label="医生简介" style="width: 100%" :rules="[
{ required: true, message: '请输入医生简介', trigger: 'blur' }
]">
<el-input placeholder="请输入医生简介" type="textarea" :rows="3" v-model="doctorForm.briefly" />
</el-form-item>
</el-form>
<template #footer>
@ -336,27 +267,12 @@ onUnmounted(() => {
<!-- 预约弹出框 -->
<el-dialog v-model="dialogVisible" title="编辑或增加" width="400">
<el-form
ref="appointRef"
:model="appointForm"
label-width="100px"
style="width: 350px"
>
<el-form-item
label="日期"
prop="appointmentDate"
:rules="{ required: true, message: '请输入日期', trigger: 'blur' }"
>
<el-input
placeholder="请输入日期"
v-model="appointForm.appointmentDate"
/>
<el-form ref="appointRef" :model="appointForm" label-width="100px" style="width: 350px">
<el-form-item label="日期" prop="appointmentDate" :rules="{ required: true, message: '请选择日期', trigger: 'blur' }">
<el-date-picker v-model="appointForm.appointmentDate" type="date" placeholder="请选择日期" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" />
</el-form-item>
<el-form-item
label="费用"
prop="fees"
:rules="{ required: true, message: '请输入费用', trigger: 'blur' }"
>
<el-form-item label="费用" prop="fees" :rules="{ required: true, message: '请输入费用', trigger: 'blur' }">
<el-input placeholder="请输入费用" v-model="appointForm.fees" />
</el-form-item>
</el-form>
@ -368,52 +284,32 @@ onUnmounted(() => {
</template>
</el-dialog>
<el-table
stripe
:data="doctor.records"
height="100%"
:default-sort="{ prop: 'id', order: 'ascending' }"
@expand-change="expandChange"
@selection-change="select"
>
<el-table stripe :data="doctor.records" height="100%" :default-sort="{ prop: 'id', order: 'ascending' }"
@expand-change="expandChange" @selection-change="select">
<el-table-column type="selection" width="50" />
<el-table-column type="expand">
<template #default="{ row }">
<div class="expand-content">
<h3 style="margin-bottom: 8px">医生简介</h3>
<p
v-html="
row.briefly.replace(/\n/g, '<br/>').replace(/\t/g, '&emsp;')
"
></p>
<p v-html="row.briefly.replace(/\n/g, '<br/>').replace(/\t/g, '&emsp;')
"></p>
<!-- 预约列表 -->
<div style="display: flex">
<h3 style="margin-bottom: 8px">预约列表</h3>
<el-button
size="small"
@click="saveOrUpdateAppoint(null)"
type="primary"
>
<el-button size="small" @click="saveOrUpdateAppoint(null)" type="primary">
添加预约
</el-button>
</div>
<el-table :data="appointmentTimeList" max-height="300">
<el-table :data="appointmentTimeList" max-height="300" :default-sort="{ prop: 'appointmentDate', order: 'ascending' }">
<el-table-column type="index" />
<el-table-column
prop="appointmentDate"
label="日期"
show-overflow-tooltip
/>
<el-table-column prop="appointmentDate" label="日期" show-overflow-tooltip />
<el-table-column prop="fees" label="费用" show-overflow-tooltip />
<el-table-column label="删除" width="68">
<template #default="{ row }">
<el-button
plain
type="danger"
size="small"
@click="deletedoctorAppoint(row)"
>
<el-icon><Delete /></el-icon>
<el-button plain type="danger" size="small" @click="deletedoctorAppoint(row)">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-table-column>
@ -424,68 +320,39 @@ onUnmounted(() => {
</div>
</template>
</el-table-column>
<el-table-column
prop="id"
label="id"
show-overflow-tooltip
width="60px"
/>
<el-table-column prop="url" width="100px" label="图片">
<el-table-column prop="id" label="id" show-overflow-tooltip width="60px" />
<el-table-column prop="url" width="80px" label="图片">
<template #default="{ row }">
<el-image :src="row.url || '/logo.png'" />
<el-image :src="row.url || '/logo.png'" style="width: 80px; height: 80px" fit="cover" />
</template>
</el-table-column>
<el-table-column
prop="doctorName"
label="医生姓名"
show-overflow-tooltip
/>
<el-table-column prop="doctorName" label="医生姓名" show-overflow-tooltip />
<el-table-column prop="level" label="职称" show-overflow-tooltip />
<el-table-column prop="source" label="头衔" show-overflow-tooltip />
<el-table-column
prop="expertise"
label="擅长领域"
show-overflow-tooltip
/>
<el-table-column
prop="departmentName"
label="所属科室"
:filters="departmentList"
:filter-method="departmentFilter"
show-overflow-tooltip
>
<el-table-column prop="expertise" label="擅长领域" show-overflow-tooltip />
<el-table-column prop="departmentName" label="所属科室" :filters="departmentList" :filter-method="departmentFilter"
show-overflow-tooltip>
<template #default="scope">
<span>{{ scope.row.departmentName }}</span>
</template>
</el-table-column>
<el-table-column
prop="hospitalName"
label="所属医院"
:filters="hospitalList"
:filter-method="hospitalFilter"
show-overflow-tooltip
>
<el-table-column prop="hospitalName" label="所属医院" :filters="hospitalList" :filter-method="hospitalFilter"
show-overflow-tooltip>
<template #default="scope">
<span>{{ scope.row.hospitalName }}</span>
</template>
</el-table-column>
<el-table-column label="编辑/删除" width="108" fixed="right">
<template #default="{ row }">
<el-button
plain
type="primary"
size="small"
@click="saveOrUpdate(row)"
>
<el-icon><Edit /></el-icon>
<el-button plain type="primary" size="small" @click="saveOrUpdate(row)">
<el-icon>
<Edit />
</el-icon>
</el-button>
<el-button
plain
type="danger"
size="small"
@click="deletedoctor(row)"
>
<el-icon><Delete /></el-icon>
<el-button plain type="danger" size="small" @click="deletedoctor(row)">
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-table-column>
@ -494,14 +361,9 @@ onUnmounted(() => {
</template>
</el-table>
<el-pagination
v-model:page-size="pageSize"
layout="total, prev, pager, next"
:total="+doctor.total"
style="height: 48px; justify-content: center"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
/>
<el-pagination v-model:page-size="pageSize" layout="total, prev, pager, next" :total="+doctor.total"
style="height: 48px; justify-content: center" @current-change="handleCurrentChange"
@size-change="handleSizeChange" />
</page-container>
</template>
@ -515,6 +377,7 @@ onUnmounted(() => {
width: 100%;
flex-direction: column;
padding: 16px;
p {
border-radius: 12px;
line-height: 1.5;
@ -522,6 +385,7 @@ onUnmounted(() => {
padding: 24px;
margin-bottom: 24px;
}
.el-table {
width: 50%;
}
@ -536,6 +400,7 @@ onUnmounted(() => {
display: block;
object-fit: contain;
}
.el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
@ -544,9 +409,11 @@ onUnmounted(() => {
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;

View File

@ -36,7 +36,7 @@ const article = ref({
})
//
const pageSize = ref(5)
const pageSize = ref(10)
const currentPage = ref(1)
const handleCurrentChange = async (val) => {
currentPage.value = val
@ -135,7 +135,7 @@ const params = reactive({
const getArticleList = async () => {
const res = await getArticle(params)
article.value = res.data.data
params.title = ''
// params.title =
}
onMounted(async () => {
await getArticleList()
@ -296,9 +296,9 @@ onUnmounted(() => {
show-overflow-tooltip
width="60px"
/>
<el-table-column prop="url" width="100px" label="图片">
<el-table-column prop="url" width="80px" label="图片">
<template #default="{ row }">
<el-image :src="row.url || '/src/assets/default.png'" />
<el-image :src="row.url || '/src/assets/default.png'" style="width: 80px; height: 80px" fit="cover"/>
</template>
</el-table-column>
<el-table-column prop="titleBig" label="标题" show-overflow-tooltip />

View File

@ -21,12 +21,12 @@ const userInfo = ref({
})
//
const pageSize = ref(5)
const pageSize = ref(10)
const currentPage = ref(1)
const handleCurrentChange = async(val) => {
const handleCurrentChange = async (val) => {
currentPage.value = val
params.current = val
const res = await getUserInfoApi({current: val, size: pageSize.value})
const res = await getUserInfoApi({ current: val, size: pageSize.value })
userInfo.value = res.data.data
}
const handleSizeChange = (val) => {
@ -45,15 +45,19 @@ const forbiddenUser = async (row) => {
getUserInfo()
}
const deleteUser = async(row) => {
const deleteUser = async (row) => {
await ElMessageBox.confirm('确定要删除该用户吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
await deleteUserApi(row.id)
ElMessage.success('删除成功')
getUserInfo()
if (row.state === 1) {
ElMessage.warning('该用户未禁用,无法删除')
} else {
await deleteUserApi(row.id)
ElMessage.success('删除成功')
getUserInfo()
}
}
const params = reactive({
@ -64,6 +68,7 @@ const params = reactive({
const getUserInfo = async () => {
const res = await getUserInfoApi(params)
userInfo.value = res.data.data
console.log(userInfo.value);
}
onMounted(() => {
getUserInfo()
@ -73,47 +78,34 @@ onMounted(() => {
<template>
<page-container>
<template #extra>
<el-input
v-model="params.name"
placeholder="请输入用户昵称"
clearable
@keyup.enter="getUserInfo"
style="width: 250px"
>
<el-input v-model="params.name" placeholder="请输入用户昵称" clearable @keyup.enter="getUserInfo" style="width: 250px">
</el-input>
</template>
<el-table stripe :data="userInfo.records" height="100%">
<el-table stripe :data="userInfo.records" :default-sort="{ prop: 'id', order: 'ascending' }" height="100%">
<el-table-column prop="id" label="id" width="60"></el-table-column>
<el-table-column prop="url" label="头像">
<template #default="{ row }">
<el-avatar :size="40" :src="row.url || './src/assets/default.png'" />
<el-avatar :size="40" :src="row.url || './src/assets/default.png'" style="width: 50px; height: 50px" fit="cover"/>
</template>
</el-table-column>
<el-table-column
prop="nickname"
label="昵称"
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="phone"
label="手机号"
show-overflow-tooltip
></el-table-column>
<el-table-column prop="appointNum" label="预约次数"></el-table-column>
<el-table-column prop="nickname" label="昵称" show-overflow-tooltip></el-table-column>
<el-table-column prop="phone" label="手机号" show-overflow-tooltip></el-table-column>
<el-table-column prop="consultationNumber" label="预约次数"></el-table-column>
<el-table-column label="禁用/删除" width="108" fixed="right">
<template #default="{ row }">
<el-button
plain
:type="row.state === 1 ? 'success' : 'warning'"
size="small"
@click="forbiddenUser(row)"
>
<el-icon v-if="row.state === 0"><Close /></el-icon>
<el-icon v-else><Check /></el-icon>
<el-button plain :type="row.state === 1 ? 'success' : 'warning'" size="small" @click="forbiddenUser(row)">
<el-icon v-if="row.state === 0">
<Close />
</el-icon>
<el-icon v-else>
<Check />
</el-icon>
</el-button>
<el-button plain type="danger" size="small" @click="deleteUser(row)">
<el-icon><Delete /></el-icon>
<el-icon>
<Delete />
</el-icon>
</el-button>
</template>
</el-table-column>
@ -122,14 +114,9 @@ onMounted(() => {
</template>
</el-table>
<el-pagination
v-model:page-size="pageSize"
layout="total, prev, pager, next"
:total="+userInfo.total"
style="height: 48px; justify-content: center"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
/>
<el-pagination v-model:page-size="pageSize" layout="total, prev, pager, next" :total="+userInfo.total"
style="height: 48px; justify-content: center" @current-change="handleCurrentChange"
@size-change="handleSizeChange" />
</page-container>
</template>

View File

@ -22,7 +22,7 @@ const appoint = ref({
})
//
const pageSize = ref(5)
const pageSize = ref(10)
const currentPage = ref(1)
const handleCurrentChange = async(val) => {
currentPage.value = val
@ -43,11 +43,11 @@ const deleteUser = async(row) => {
}
const userFilters = ref([
{ text: '王五-5667', value: '王五-5667' },
{ text: '王五-5667', value: '王五-5667' }
{ text: '用户-5667', value: '用户-5667' },
{ text: '用户-8888', value: '用户-8888' }
])
const userFilterTag = (value, row) => {
return row.state === value
return row.nickname === value
}
const filters = ref([
{ text: '未就诊', value: 1 },
@ -73,6 +73,8 @@ const params = reactive({
const getAppoint = async () => {
const res = await getAppointApi(params)
appoint.value = res.data.data
console.log(res.data.data);
}
onMounted(() => {
getAppoint()
@ -92,14 +94,14 @@ onMounted(() => {
</el-input>
</template>
<el-table stripe :data="appoint.records" height="100%">
<el-table stripe :data="appoint.records" :default-sort="{ prop: 'id', order: 'ascending' }" height="100%">
<el-table-column type="expand">
<template #default="{ row }">
<div class="expand-content">
<h3 style="margin-bottom: 8px">备注</h3>
<p
v-html="
row.meno.replace(/\n/g, '<br/>').replace(/\t/g, '&emsp;')
row.memo?.replace(/\n/g, '<br/>').replace(/\t/g, '&emsp;')
"
></p>
</div>
@ -112,17 +114,17 @@ onMounted(() => {
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="appointHospital"
prop="hospitalName"
label="预约医院"
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="appointDoctor"
prop="doctorName"
label="预约医生"
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="appointTime"
prop="appointmentDate"
label="预约时间"
show-overflow-tooltip
></el-table-column>
@ -132,19 +134,19 @@ onMounted(() => {
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="fee"
prop="fees"
label="费用"
show-overflow-tooltip
></el-table-column>
<el-table-column
prop="appointUser"
prop="nickname"
label="预约用户"
show-overflow-tooltip
:filters="userFilters"
:filter-method="userFilterTag"
>
<template #default="{ row }">
{{ row.appointUser }}
{{ row.nickname }}
</template>
</el-table-column>
<el-table-column