This commit is contained in:
wucongxing8150 2025-08-11 17:32:15 +08:00
parent 449bd0c09d
commit cd6dd3d202
8 changed files with 594 additions and 300 deletions

118
HOME_PAGE_CHANGE_README.md Normal file
View File

@ -0,0 +1,118 @@
# 首页修改说明
## 🎯 修改目标
将系统首页从原来的"首页"改为"文章病例库管理",用户登录后直接进入文章病例库管理页面。
## 🔧 修改内容
### 1. 修改常量配置
#### `src/constants/system/home-const.js`
- **HOME_PAGE_NAME**: 从 `'Home'` 改为 `'CaseClinicalArticleList'`
- **HOME_PAGE_PATH**: 从 `'/home'` 改为 `'/case-clinical-article/list'`
#### `src/constants/common-const.js`
- **HOME_PAGE_PATH**: 从 `'/home'` 改为 `'/case-clinical-article/list'`
### 2. 修改路由配置
#### `src/router/system/home.js`
- **路径**: 从 `/home` 改为 `/case-clinical-article/list`
- **标题**: 从"首页"改为"文章病例库管理"
- **图标**: 从 `HomeOutlined` 改为 `FileTextOutlined`
- **组件**: 从首页组件改为文章病例库列表组件
#### 新增 `src/router/system/case-clinical-article.js`
- 创建完整的文章病例库管理路由配置
- 包含列表页和表单页两个子路由
#### `src/router/routers.js`
- 引入文章病例库管理路由配置
- 将新路由添加到主路由数组中
## 📁 文件结构
```
src/
├── constants/
│ ├── system/
│ │ └── home-const.js # 首页常量配置
│ └── common-const.js # 通用常量配置
├── router/
│ ├── system/
│ │ ├── home.js # 首页路由配置
│ │ └── case-clinical-article.js # 文章病例库路由配置
│ └── routers.js # 主路由配置
└── views/
└── business/
└── case-clinical-article/
├── case-clinical-article-list.vue # 列表页面
└── case-clinical-article-form.vue # 表单页面
```
## 🚀 使用方法
### 1. 用户登录后
- 系统自动跳转到 `/case-clinical-article/list`
- 显示文章病例库管理列表页面
### 2. 访问路径
- **首页**: `/case-clinical-article/list`
- **新增**: `/case-clinical-article/form?type=add`
- **编辑**: `/case-clinical-article/form?type=edit&id=xxx`
### 3. 菜单显示
- 主菜单显示"文章病例库管理"
- 子菜单显示"文章病例库列表"
- 表单页面在菜单中隐藏hideInMenu: true
## 🎨 界面变化
### 修改前
- 首页显示系统概览信息
- 图标:🏠 HomeOutlined
- 标题:首页
### 修改后
- 首页显示文章病例库管理列表
- 图标:📄 FileTextOutlined
- 标题:文章病例库管理
## ⚠️ 注意事项
1. **路由重定向**: 根路径 `/` 会自动重定向到文章病例库管理页面
2. **权限控制**: 确保用户有访问文章病例库管理的权限
3. **面包屑导航**: 面包屑会显示"文章病例库管理 > 文章病例库列表"
4. **页面缓存**: 如果启用了keepAlive文章病例库列表页面会被缓存
## 🔍 验证方法
### 1. 登录测试
- 用户登录后应该直接进入文章病例库管理页面
- URL应该是 `/case-clinical-article/list`
### 2. 菜单测试
- 主菜单应该显示"文章病例库管理"
- 点击应该能正常跳转
### 3. 路由测试
- 访问根路径 `/` 应该重定向到文章病例库管理
- 直接访问 `/case-clinical-article/list` 应该正常显示
## 📝 后续优化
1. **添加首页统计**: 在文章病例库列表页面添加统计信息
2. **优化加载性能**: 考虑使用懒加载优化页面加载
3. **添加快捷操作**: 在首页添加常用的快捷操作按钮
4. **个性化配置**: 允许用户自定义首页显示内容
## ✅ 完成状态
- [x] 修改首页常量配置
- [x] 修改首页路由配置
- [x] 创建文章病例库路由配置
- [x] 更新主路由配置
- [x] 创建说明文档
**首页修改已完成!** 用户登录后将直接进入文章病例库管理页面。

View File

@ -15,7 +15,7 @@ export const PAGE_SIZE_OPTIONS = ['5', '10', '15', '20', '30', '40', '50', '75',
//登录页面名字 //登录页面名字
export const PAGE_PATH_LOGIN = '/login'; export const PAGE_PATH_LOGIN = '/login';
//首页页面名字 //首页页面名字
export const HOME_PAGE_PATH = '/home'; export const HOME_PAGE_PATH = '/case-clinical-article/list';
//404页面名字 //404页面名字
export const PAGE_PATH_404 = '/404'; export const PAGE_PATH_404 = '/404';

View File

@ -9,7 +9,7 @@
*/ */
//首页页面名字 //首页页面名字
export const HOME_PAGE_NAME = 'Home'; export const HOME_PAGE_NAME = 'CaseClinicalArticleList';
//首页页面路径 //首页页面路径
export const HOME_PAGE_PATH = '/home'; export const HOME_PAGE_PATH = '/case-clinical-article/list';

View File

@ -8,6 +8,7 @@
* @Copyright 1024创新实验室 https://1024lab.net Since 2012 * @Copyright 1024创新实验室 https://1024lab.net Since 2012
*/ */
import { homeRouters } from './system/home'; import { homeRouters } from './system/home';
import { caseClinicalArticleRouters } from './system/case-clinical-article';
import { loginRouters } from './system/login'; import { loginRouters } from './system/login';
import { helpDocRouters } from './support/help-doc'; import { helpDocRouters } from './support/help-doc';
import NotFound from '/@/views/system/40X/404.vue'; import NotFound from '/@/views/system/40X/404.vue';
@ -15,7 +16,8 @@ import NoPrivilege from '/@/views/system/40X/403.vue';
export const routerArray = [ export const routerArray = [
...loginRouters, ...loginRouters,
...homeRouters, ...homeRouters,
...caseClinicalArticleRouters,
...helpDocRouters, ...helpDocRouters,
{ path: '/:pathMatch(.*)*', name: '404', component: NotFound }, { path: '/:pathMatch(.*)*', name: '404', component: NotFound },
{ path: '/403', name: '403', component: NoPrivilege } { path: '/403', name: '403', component: NoPrivilege }

View File

@ -0,0 +1,47 @@
/*
* 文章病例库管理路由
*
* @Author: xing
* @Date: 2025-01-27
* @Copyright gdxz
*/
import { MENU_TYPE_ENUM } from '/@/constants/system/menu-const';
import SmartLayout from '/@/layout/index.vue';
export const caseClinicalArticleRouters = [
{
path: '/case-clinical-article',
name: 'CaseClinicalArticle',
component: SmartLayout,
meta: {
title: '文章病例库管理',
menuType: MENU_TYPE_ENUM.CATALOG.value,
icon: 'FileTextOutlined',
},
children: [
{
path: '/case-clinical-article/list',
name: 'CaseClinicalArticleList',
meta: {
title: '文章病例库列表',
menuType: MENU_TYPE_ENUM.MENU.value,
icon: 'FileTextOutlined',
parentMenuList: [{ name: 'CaseClinicalArticle', title: '文章病例库管理' }],
},
component: () => import('/@/views/business/case-clinical-article/case-clinical-article-list.vue'),
},
{
path: '/case-clinical-article/form',
name: 'CaseClinicalArticleForm',
meta: {
title: '文章病例库表单',
menuType: MENU_TYPE_ENUM.MENU.value,
icon: 'FileTextOutlined',
hideInMenu: true,
parentMenuList: [{ name: 'CaseClinicalArticle', title: '文章病例库管理' }],
},
component: () => import('/@/views/business/case-clinical-article/case-clinical-article-form.vue'),
},
],
},
];

View File

@ -18,21 +18,21 @@ export const homeRouters = [
redirect: { name: HOME_PAGE_NAME }, redirect: { name: HOME_PAGE_NAME },
component: SmartLayout, component: SmartLayout,
meta: { meta: {
title: '首页', title: '文章病例库管理',
menuType: MENU_TYPE_ENUM.CATALOG.value, menuType: MENU_TYPE_ENUM.CATALOG.value,
icon: 'HomeOutlined', icon: 'FileTextOutlined',
}, },
children: [ children: [
{ {
path: '/home', path: '/case-clinical-article/list',
name: HOME_PAGE_NAME, name: HOME_PAGE_NAME,
meta: { meta: {
title: '首页', title: '文章病例库管理',
menuType: MENU_TYPE_ENUM.MENU.value, menuType: MENU_TYPE_ENUM.MENU.value,
icon: 'HomeOutlined', icon: 'FileTextOutlined',
parentMenuList: [{ name: '_home', title: '首页' }], parentMenuList: [{ name: '_home', title: '文章病例库管理' }],
}, },
component: () => import('/@/views/system/home/index.vue'), component: () => import('/@/views/business/case-clinical-article/case-clinical-article-list.vue'),
}, },
{ {
path: '/account', path: '/account',

View File

@ -7,84 +7,116 @@
--> -->
<template> <template>
<a-modal <a-modal
:title="form.doctorId ? '编辑' : '添加'" :title="form.doctorId ? '编辑医生' : '添加医生'"
:width="1000" :width="800"
:open="visibleFlag" :open="visibleFlag"
@cancel="onClose" @cancel="onClose"
:maskClosable="false" :maskClosable="false"
:destroyOnClose="true" :destroyOnClose="true"
> >
<a-form ref="formRef" :model="form" :rules="rules" :label-col="{ span: 5 }" > <a-form ref="formRef" :model="form" :rules="rules" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
<a-form-item label="用户名称" name="doctorName"> <!-- 医生姓名 -->
<a-input-group compact> <a-form-item label="医生姓名" name="doctorName">
<a-input <a-input-group compact>
style="calc(100% - 80px)" <a-input
v-model:value="form.doctorName" v-model:value="form.doctorName"
placeholder="请输入医生姓名" placeholder="请输入医生姓名"
:disabled="!!form.doctorId"
@pressEnter="searchAppDoctor"
/>
<a-button
v-if="!form.doctorId"
type="primary"
style="width: 80px"
@click="searchAppDoctor"
:loading="searchLoading"
>
搜索
</a-button>
</a-input-group>
<!-- 搜索到的APP医生信息提示 -->
<div v-if="appDoctorInfo && !form.doctorId" style="margin-top: 8px;">
<a-alert
:message="`找到APP医生${appDoctorInfo.doctorName}`"
:description="`手机号:${appDoctorInfo.phone || '未知'} | 省份:${appDoctorInfo.province || '未知'}`"
type="info"
show-icon
closable
@close="clearAppDoctorInfo"
>
<template #action>
<a-button size="small" type="primary" @click="useAppDoctorInfo">
使用此信息
</a-button>
</template>
</a-alert>
</div>
</a-form-item>
<a-form-item label="所属医院" name="hospitalId">
<a-select
v-model:value="form.hospitalId"
placeholder="请选择医院"
style="width: 100%"
:options="hospitalOptions"
:field-names="{ label: 'hospitalName', value: 'hospitalId' }"
:loading="hospitalLoading"
:disabled="!!form.doctorId" :disabled="!!form.doctorId"
@focus="onHospitalFocus" style="width: calc(100% - 80px)"
@search="onHospitalSearch" @pressEnter="searchDoctor"
show-search
allowClear
/> />
</a-form-item> <a-button
<!-- 编辑时显示状态 --> v-if="!form.doctorId"
<a-form-item v-if="form.doctorId" label="状态" name="status"> type="primary"
<a-radio-group v-model:value="form.status"> style="width: 80px"
<a-radio :value="1">正常</a-radio> @click="searchDoctor"
<a-radio :value="2">禁用</a-radio> :loading="searchLoading"
</a-radio-group> >
</a-form-item> 搜索
<!-- 编辑时显示头像 --> </a-button>
<a-form-item v-if="form.doctorId" label="头像" name="avatar"> </a-input-group>
<div v-if="form.avatar && typeof form.avatar === 'string' && form.avatar.trim()" class="avatar-display"> </a-form-item>
<img :src="form.avatar" alt="头像" style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover;" />
<!-- 医生搜索结果 -->
<a-form-item v-if="doctorList.length > 0 && !form.doctorId" label="搜索结果">
<div class="doctor-list">
<a-list
:data-source="doctorList"
item-layout="horizontal"
size="small"
>
<template #renderItem="{ item }">
<a-list-item>
<a-list-item-meta>
<template #title>
<div class="doctor-info">
<span class="doctor-name">{{ item.doctorName }}</span>
<span class="doctor-phone" v-if="item.phone">({{ item.phone }})</span>
</div>
</template>
<template #description>
<div class="doctor-details">
<span v-if="item.province">省份{{ item.province }}</span>
<span v-if="item.hospitalName" style="margin-left: 16px;">医院{{ item.hospitalName }}</span>
</div>
</template>
</a-list-item-meta>
<template #actions>
<a-button type="primary" size="small" @click="selectDoctor(item)">
选择此医生
</a-button>
</template>
</a-list-item>
</template>
</a-list>
</div>
</a-form-item>
<!-- 无搜索结果提示 -->
<a-form-item v-if="showNoResult && !form.doctorId" label="搜索结果">
<a-alert
message="未找到医生信息"
description="请手动填写医生信息"
type="info"
show-icon
/>
</a-form-item>
<!-- 所属医院 -->
<a-form-item label="所属医院" name="hospitalId">
<a-select
v-model:value="form.hospitalId"
placeholder="请选择医院"
style="width: 100%"
:options="hospitalOptions"
:loading="hospitalLoading"
@search="onHospitalSearch"
@change="onHospitalChange"
show-search
allowClear
:filter-option="false"
/>
</a-form-item>
<!-- 编辑时显示状态 -->
<a-form-item v-if="form.doctorId" label="状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="1">正常</a-radio>
<a-radio :value="2">禁用</a-radio>
</a-radio-group>
</a-form-item>
<!-- 编辑时显示头像 -->
<a-form-item v-if="form.doctorId" label="头像" name="avatar">
<div v-if="form.avatar && typeof form.avatar === 'string' && form.avatar.trim()" class="avatar-display">
<img :src="form.avatar" alt="头像" style="width: 80px; height: 80px; border-radius: 50%; object-fit: cover;" />
</div>
<div v-else class="avatar-placeholder">
<div style="width: 80px; height: 80px; border-radius: 50%; background-color: #f0f0f0; display: flex; align-items: center; justify-content: center; color: #999; font-size: 12px; border: 1px dashed #d9d9d9;">
默认头像
</div> </div>
<div v-else class="avatar-placeholder"> </div>
<div style="width: 80px; height: 80px; border-radius: 50%; background-color: #f0f0f0; display: flex; align-items: center; justify-content: center; color: #999; font-size: 12px; border: 1px dashed #d9d9d9;"> </a-form-item>
默认头像
</div>
</div>
</a-form-item>
</a-form> </a-form>
<template #footer> <template #footer>
@ -95,238 +127,332 @@
</template> </template>
</a-modal> </a-modal>
</template> </template>
<script setup> <script setup>
import { reactive, ref, nextTick } from 'vue'; import { reactive, ref, nextTick } from 'vue';
import _ from 'lodash'; import { message } from 'ant-design-vue';
import { message } from 'ant-design-vue'; import { SmartLoading } from '/@/components/framework/smart-loading';
import { SmartLoading } from '/@/components/framework/smart-loading'; import { caseClinicalDoctorApi } from '/@/api/business/case-clinical-doctor/case-clinical-doctor-api';
import { caseClinicalDoctorApi } from '/@/api/business/case-clinical-doctor/case-clinical-doctor-api'; import { basicHospitalApi } from '/@/api/business/basic-hospital/basic-hospital-api';
import { basicHospitalApi } from '/@/api/business/basic-hospital/basic-hospital-api'; import { smartSentry } from '/@/lib/smart-sentry';
import { smartSentry } from '/@/lib/smart-sentry';
import { debounce } from 'lodash';
// ------------------------ ------------------------ //
const emits = defineEmits(['reloadList']);
const emits = defineEmits(['reloadList']); //
const formRef = ref();
// ------------------------ ------------------------ //
// const visibleFlag = ref(false);
const visibleFlag = ref(false);
async function show(rowData) { //
Object.assign(form, formDefault); const searchLoading = ref(false);
hospitalOptions.value = []; const showNoResult = ref(false);
appDoctorInfo.value = null;
if (rowData && !_.isEmpty(rowData)) { // APP
if (rowData.doctorId) { const selectedFromApp = ref(false);
// //
try { const autoSaving = ref(false);
SmartLoading.show();
const result = await caseClinicalDoctorApi.getDetail(rowData.doctorId);
Object.assign(form, result.data);
// 便 //
if (result.data.hospitalId && result.data.hospitalName) { const doctorList = ref([]);
hospitalOptions.value = [{
hospitalId: result.data.hospitalId,
hospitalName: result.data.hospitalName
}];
}
} catch (e) {
smartSentry.captureError(e);
// 使
Object.assign(form, rowData);
} finally {
SmartLoading.hide();
}
} else {
// 使
Object.assign(form, rowData);
}
}
visibleFlag.value = true; //
nextTick(() => { const hospitalOptions = ref([]);
formRef.value.clearValidate(); const hospitalLoading = ref(false);
}); const hospitalSearchKeyword = ref('');
}
function onClose() { //
Object.assign(form, formDefault); const formDefault = {
hospitalOptions.value = []; doctorId: undefined,
appDoctorInfo.value = null; doctorName: undefined,
searchLoading.value = false; doctorIden: undefined,
visibleFlag.value = false; hospitalId: undefined,
} hospitalUuid: undefined,
hospitalName: undefined,
status: 1,
avatar: undefined,
};
// ------------------------ ------------------------ //
let form = reactive({ ...formDefault });
// APP //
async function searchAppDoctor() { const rules = {
// doctorName: [{ required: true, message: '医生姓名必填' }],
if (form.doctorId || !form.doctorName || form.doctorName.trim() === '') { hospitalId: [{ required: true, message: '所属医院必填' }],
message.warning('请输入医生姓名'); };
return;
}
searchLoading.value = true; //
async function show(rowData) {
//
Object.assign(form, formDefault);
doctorList.value = [];
hospitalOptions.value = [];
showNoResult.value = false;
searchLoading.value = false;
hospitalLoading.value = false;
hospitalSearchKeyword.value = '';
selectedFromApp.value = false;
autoSaving.value = false;
//
if (rowData && rowData.doctorId) {
try { try {
const result = await caseClinicalDoctorApi.getAppDoctor(form.doctorName); SmartLoading.show();
if (result.data) { const result = await caseClinicalDoctorApi.getDetail(rowData.doctorId);
// APP Object.assign(form, result.data);
appDoctorInfo.value = result.data;
message.info('找到APP医生信息请确认是否使用');
}
} catch (e) {
//
appDoctorInfo.value = null;
message.info('未找到APP医生信息请手动选择医院');
// //
if (hospitalOptions.value.length === 0) { if (result.data.hospitalId && result.data.hospitalName) {
loadHospitalOptions();
}
} finally {
searchLoading.value = false;
}
}
// 使APP
function useAppDoctorInfo() {
if (appDoctorInfo.value) {
form.doctorName = appDoctorInfo.value.doctorName;
form.doctorIden = appDoctorInfo.value.uuid; // app
form.hospitalUuid = appDoctorInfo.value.hospitalUuid; // UUID
// APP使
if (appDoctorInfo.value.hospitalId && appDoctorInfo.value.hospitalName) {
form.hospitalId = appDoctorInfo.value.hospitalId;
form.hospitalName = appDoctorInfo.value.hospitalName;
//
hospitalOptions.value = [{ hospitalOptions.value = [{
hospitalId: appDoctorInfo.value.hospitalId, label: result.data.hospitalName,
hospitalName: appDoctorInfo.value.hospitalName value: result.data.hospitalId,
hospitalId: result.data.hospitalId,
hospitalName: result.data.hospitalName,
hospitalUuid: result.data.hospitalUuid,
}]; }];
} else {
//
form.hospitalId = undefined;
form.hospitalName = undefined;
//
if (hospitalOptions.value.length === 0) {
loadHospitalOptions();
}
} }
// APP
appDoctorInfo.value = null;
message.success('已使用APP医生信息');
}
}
// APP
function clearAppDoctorInfo() {
appDoctorInfo.value = null;
}
// ------------------------ ------------------------
//
async function loadHospitalOptions() {
hospitalLoading.value = true;
try {
const result = await basicHospitalApi.queryList({
keywords: hospitalSearchKeyword.value
});
hospitalOptions.value = result.data || [];
} catch (e) { } catch (e) {
smartSentry.captureError(e); smartSentry.captureError(e);
hospitalOptions.value = []; Object.assign(form, rowData);
} finally {
hospitalLoading.value = false;
}
}
//
const debouncedSearch = debounce(() => {
loadHospitalOptions();
}, 300);
function onHospitalSearch(value) {
hospitalSearchKeyword.value = value;
debouncedSearch();
}
function onHospitalFocus() {
if (hospitalOptions.value.length === 0) {
loadHospitalOptions();
}
}
// ------------------------ ------------------------
// ref
const formRef = ref();
//
const hospitalOptions = ref([]);
const hospitalLoading = ref(false);
const hospitalSearchKeyword = ref('');
// APP
const appDoctorInfo = ref(null);
const searchLoading = ref(false);
const formDefault = {
doctorId: undefined, //ID
doctorName: undefined, //
doctorIden: undefined, //app
hospitalId: undefined, //
hospitalUuid: undefined, //UUID
hospitalName: undefined, //
status: 1, //1: 2:-
avatar: undefined, //
};
let form = reactive({ ...formDefault });
const rules = {
doctorName: [{ required: true, message: '用户名称 必填' }],
hospitalId: [{ required: true, message: '所属医院 必填' }],
};
//
async function onSubmit() {
try {
await formRef.value.validateFields();
save();
} catch (err) {
message.error('参数验证错误,请仔细填写表单数据!');
}
}
// API
async function save() {
SmartLoading.show();
try {
if (form.doctorId) {
await caseClinicalDoctorApi.update(form);
} else {
await caseClinicalDoctorApi.add(form);
}
message.success('操作成功');
emits('reloadList');
onClose();
} catch (err) {
smartSentry.captureError(err);
} finally { } finally {
SmartLoading.hide(); SmartLoading.hide();
} }
} }
defineExpose({ visibleFlag.value = true;
show,
nextTick(() => {
formRef.value?.clearValidate();
}); });
}
//
function onClose() {
visibleFlag.value = false;
selectedFromApp.value = false;
autoSaving.value = false;
}
//
async function searchDoctor() {
if (!form.doctorName || form.doctorName.trim() === '') {
message.warning('请输入医生姓名');
return;
}
searchLoading.value = true;
showNoResult.value = false;
doctorList.value = [];
try {
const result = await caseClinicalDoctorApi.getAppDoctor(form.doctorName.trim());
if (result.data && Array.isArray(result.data) && result.data.length > 0) {
if (result.data.length === 1) {
//
selectDoctor(result.data[0]);
} else {
//
doctorList.value = result.data;
message.info(`找到${result.data.length}个医生,请选择其中一个`);
}
} else {
//
showNoResult.value = true;
message.info('未找到医生信息,请手动填写');
}
} catch (e) {
smartSentry.captureError(e);
showNoResult.value = true;
message.info('搜索失败,请手动填写');
} finally {
searchLoading.value = false;
}
}
//
function selectDoctor(doctor) {
selectedFromApp.value = true;
form.doctorName = doctor.doctorName;
form.doctorIden = doctor.uuid;
form.hospitalUuid = doctor.hospitalUuid;
//
if (doctor.hospitalName) {
form.hospitalName = doctor.hospitalName;
form.hospitalId = doctor.hospitalId;
//
if (doctor.hospitalId) {
hospitalOptions.value = [{
label: doctor.hospitalName,
value: doctor.hospitalId,
hospitalId: doctor.hospitalId,
hospitalName: doctor.hospitalName,
hospitalUuid: doctor.hospitalUuid,
}];
}
message.success(`已选择医生:${doctor.doctorName},医院:${doctor.hospitalName}`);
} else {
form.hospitalName = undefined;
form.hospitalId = undefined;
message.success(`已选择医生:${doctor.doctorName},请选择医院`);
}
//
doctorList.value = [];
showNoResult.value = false;
}
//
async function loadHospitalOptions() {
hospitalLoading.value = true;
try {
const result = await basicHospitalApi.queryList({
keywords: hospitalSearchKeyword.value || ''
});
if (result.data && Array.isArray(result.data)) {
// {label, value}
const formattedData = result.data.map(item => {
const hospitalId = item.hospitalId || item.id;
const hospitalName = item.hospitalName || item.name || item.hospital_name;
const hospitalUuid = item.hospitalUuid || item.uuid;
return {
label: hospitalName,
value: hospitalId,
hospitalId,
hospitalName,
hospitalUuid,
};
});
hospitalOptions.value = formattedData;
} else {
hospitalOptions.value = [];
}
} catch (e) {
smartSentry.captureError(e);
hospitalOptions.value = [];
} finally {
hospitalLoading.value = false;
}
}
//
function onHospitalSearch(value) {
hospitalSearchKeyword.value = value;
if (value && value.trim()) {
loadHospitalOptions();
} else {
hospitalOptions.value = [];
}
}
//
async function onHospitalChange(value, option) {
if (!value || !option) {
form.hospitalId = undefined;
form.hospitalName = undefined;
form.hospitalUuid = undefined;
return;
}
form.hospitalId = option.hospitalId ?? value;
form.hospitalName = option.hospitalName ?? option.label;
form.hospitalUuid = option.hospitalUuid ?? option.uuid;
// APP
if (selectedFromApp.value && !form.doctorId) {
if (autoSaving.value) return;
autoSaving.value = true;
try {
await formRef.value.validateFields();
await save();
} catch (err) {
//
} finally {
autoSaving.value = false;
}
}
}
//
async function onSubmit() {
try {
await formRef.value.validateFields();
await save();
} catch (err) {
message.error('请检查表单填写是否正确');
}
}
//
async function save() {
SmartLoading.show();
try {
if (form.doctorId) {
await caseClinicalDoctorApi.update(form);
message.success('更新成功');
} else {
await caseClinicalDoctorApi.add(form);
message.success('添加成功');
}
emits('reloadList');
onClose();
} catch (err) {
smartSentry.captureError(err);
message.error('操作失败');
} finally {
SmartLoading.hide();
}
}
//
defineExpose({
show,
});
</script> </script>
<style scoped>
.doctor-list {
max-height: 300px;
overflow-y: auto;
border: 1px solid #d9d9d9;
border-radius: 6px;
padding: 8px;
}
.doctor-info {
display: flex;
align-items: center;
gap: 8px;
}
.doctor-name {
font-weight: 500;
color: #262626;
}
.doctor-phone {
color: #8c8c8c;
font-size: 12px;
}
.doctor-details {
color: #595959;
font-size: 12px;
}
.avatar-display img {
border: 2px solid #f0f0f0;
}
.avatar-placeholder {
display: flex;
align-items: center;
justify-content: center;
}
</style>

View File

@ -96,6 +96,7 @@
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js';
import { useDictStore } from '/@/store/modules/system/dict.js'; import { useDictStore } from '/@/store/modules/system/dict.js';
import { dictApi } from '/@/api/support/dict-api.js'; import { dictApi } from '/@/api/support/dict-api.js';
import { HOME_PAGE_PATH } from '/@/constants/common-const';
//--------------------- --------------------------------- //--------------------- ---------------------------------
@ -149,7 +150,7 @@
useDictStore().initData(dictRes.data); useDictStore().initData(dictRes.data);
// //
buildRoutes(); buildRoutes();
router.push('/home'); router.replace(HOME_PAGE_PATH);
} catch (e) { } catch (e) {
if (e.data && e.data.code !== 0) { if (e.data && e.data.code !== 0) {
loginForm.captchaCode = ''; loginForm.captchaCode = '';