From 9a1b67ca181efe8ca990f1c482b586b991425e23 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 5 Mar 2026 11:19:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DOCTOR_FIELDS_INSTALLATION.md | 114 +++++ admin/src/components/video-call/index.vue | 4 +- admin/src/views/consumer/doctor/edit.vue | 434 ++++++++++++++++++ admin/src/views/consumer/doctor/index.vue | 164 +++++++ .../components/prescription-drawer.vue | 255 ++++++++++ admin/src/views/tcm/appointment/list.vue | 248 +++++++++- admin/src/views/tcm/diagnosis/edit.vue | 195 ++++++-- install_doctor_fields.bat | 98 ++++ install_doctor_fields.sh | 100 ++++ ps/管理密码.txt | 6 +- server/app/adminapi/lists/auth/AdminLists.php | 4 +- .../lists/doctor/AppointmentLists.php | 104 ++++- .../app/adminapi/lists/tcm/DiagnosisLists.php | 27 +- server/app/adminapi/logic/auth/AdminLogic.php | 24 +- .../logic/doctor/AppointmentLogic.php | 6 +- .../migrations/add_doctor_fields_to_admin.sql | 24 + .../rollback_doctor_fields_from_admin.sql | 18 + 17 files changed, 1736 insertions(+), 89 deletions(-) create mode 100644 DOCTOR_FIELDS_INSTALLATION.md create mode 100644 admin/src/views/consumer/doctor/edit.vue create mode 100644 admin/src/views/consumer/doctor/index.vue create mode 100644 admin/src/views/tcm/appointment/components/prescription-drawer.vue create mode 100644 install_doctor_fields.bat create mode 100644 install_doctor_fields.sh create mode 100644 server/database/migrations/add_doctor_fields_to_admin.sql create mode 100644 server/database/migrations/rollback_doctor_fields_from_admin.sql diff --git a/DOCTOR_FIELDS_INSTALLATION.md b/DOCTOR_FIELDS_INSTALLATION.md new file mode 100644 index 00000000..6da37915 --- /dev/null +++ b/DOCTOR_FIELDS_INSTALLATION.md @@ -0,0 +1,114 @@ +# 医生字段安装说明 + +## 概述 +此文档说明如何为医生管理功能添加必要的数据库字段。 + +## 新增字段列表 + +### 基本信息 +- `gender` - 性别(1=男,2=女) +- `age` - 年龄 +- `phone` - 手机号 + +### 专业信息 +- `title` - 职称(如:主任医师、副主任医师) +- `department` - 所属科室(如:中医科、内科) +- `specialty` - 擅长领域(文本) + +### 履历信息 +- `education` - 教育背景(文本) +- `experience` - 工作经历(文本) +- `honors` - 荣誉资质(文本) + +## 安装步骤 + +### 1. 备份数据库 +在执行任何数据库修改之前,请先备份数据库: + +```bash +mysqldump -u root -p zyt > zyt_backup_$(date +%Y%m%d_%H%M%S).sql +``` + +### 2. 执行迁移脚本 + +#### 方法一:使用MySQL命令行 +```bash +mysql -u root -p zyt < server/database/migrations/add_doctor_fields_to_admin.sql +``` + +#### 方法二:使用数据库管理工具 +1. 打开 Navicat、phpMyAdmin 或其他数据库管理工具 +2. 连接到数据库 +3. 打开 `server/database/migrations/add_doctor_fields_to_admin.sql` 文件 +4. 执行SQL脚本 + +### 3. 验证安装 + +执行以下SQL查询验证字段是否添加成功: + +```sql +DESCRIBE zyt_admin; +``` + +应该能看到新增的字段: +- gender +- age +- phone +- title +- department +- specialty +- education +- experience +- honors + +### 4. 测试功能 + +1. 登录管理后台 +2. 进入"医生管理"页面 +3. 点击"新增医生" +4. 填写所有字段并保存 +5. 验证数据是否正确保存 + +## 回滚说明 + +如果需要撤销这些更改,可以执行回滚脚本: + +```bash +mysql -u root -p zyt < server/database/migrations/rollback_doctor_fields_from_admin.sql +``` + +**警告:** 回滚操作将删除这些字段的所有数据,请谨慎操作! + +## 注意事项 + +1. **数据兼容性**:现有的管理员记录不会受到影响,新字段默认为NULL +2. **索引优化**:为`phone`和`gender`字段添加了索引以提高查询性能 +3. **字段长度**: + - `phone`: varchar(20) - 支持国际号码格式 + - `title`: varchar(50) - 职称名称 + - `department`: varchar(100) - 科室名称 + - `specialty`, `education`, `experience`, `honors`: text - 支持长文本 + +## 常见问题 + +### Q: 执行脚本时报错"字段已存在" +A: 说明字段已经添加过了,可以跳过此步骤或先执行回滚脚本。 + +### Q: 现有管理员数据会丢失吗? +A: 不会,新增字段不会影响现有数据。 + +### Q: 如何批量更新现有医生的信息? +A: 可以通过管理后台逐个编辑,或编写SQL脚本批量更新。 + +## 相关文件 + +- 迁移脚本:`server/database/migrations/add_doctor_fields_to_admin.sql` +- 回滚脚本:`server/database/migrations/rollback_doctor_fields_from_admin.sql` +- 前端页面:`admin/src/views/consumer/doctor/edit.vue` + +## 技术支持 + +如有问题,请检查: +1. 数据库连接是否正常 +2. 用户是否有ALTER TABLE权限 +3. 表名是否正确(默认为`zyt_admin`) diff --git a/admin/src/components/video-call/index.vue b/admin/src/components/video-call/index.vue index 85988a6a..5482ee0e 100644 --- a/admin/src/components/video-call/index.vue +++ b/admin/src/components/video-call/index.vue @@ -126,11 +126,11 @@ const callInfo = ref({ // 窗口位置和大小 const windowRef = ref() const windowPosition = ref({ x: 100, y: 100 }) -const windowSize = ref({ width: 800, height: 600 }) +const windowSize = ref({ width: 300, height: 750 }) // 拖拽相关 const isDragging = ref(false) -const dragStart = ref({ x: 0, y: 0 }) +const dragStart = ref({ x: 10, y: 0 }) // 调整大小相关 const isResizing = ref(false) diff --git a/admin/src/views/consumer/doctor/edit.vue b/admin/src/views/consumer/doctor/edit.vue new file mode 100644 index 00000000..e5337c94 --- /dev/null +++ b/admin/src/views/consumer/doctor/edit.vue @@ -0,0 +1,434 @@ + + + + + diff --git a/admin/src/views/consumer/doctor/index.vue b/admin/src/views/consumer/doctor/index.vue new file mode 100644 index 00000000..90b967ee --- /dev/null +++ b/admin/src/views/consumer/doctor/index.vue @@ -0,0 +1,164 @@ + + + + + + diff --git a/admin/src/views/tcm/appointment/components/prescription-drawer.vue b/admin/src/views/tcm/appointment/components/prescription-drawer.vue new file mode 100644 index 00000000..67bb021f --- /dev/null +++ b/admin/src/views/tcm/appointment/components/prescription-drawer.vue @@ -0,0 +1,255 @@ + + + + + diff --git a/admin/src/views/tcm/appointment/list.vue b/admin/src/views/tcm/appointment/list.vue index 8f53bd06..6e54a056 100644 --- a/admin/src/views/tcm/appointment/list.vue +++ b/admin/src/views/tcm/appointment/list.vue @@ -8,16 +8,16 @@ v-model="formData.patient_name" placeholder="请输入患者姓名" clearable - @keyup.enter="resetPage" + @keyup.enter="handleSearch" /> - + @@ -26,6 +26,7 @@ + @@ -37,14 +38,43 @@ - 查询 - 重置 + 查询 + 重置 - + + + + + + + + + + + + + + + + + + - + - + @@ -155,7 +218,7 @@ {{ detailData.status_desc }} @@ -190,6 +253,15 @@ + + + + + + + + + @@ -197,22 +269,101 @@ import { usePaging } from '@/hooks/usePaging' import { appointmentLists, cancelAppointment, completeAppointment, appointmentDetail } from '@/api/doctor' import feedback from '@/utils/feedback' +import EditPopup from '../diagnosis/edit.vue' +import VideoCall from '@/components/video-call/index.vue' +import PrescriptionDrawer from './components/prescription-drawer.vue' +import useUserStore from '@/stores/modules/user' + +const userStore = useUserStore() +const userInfo = computed(() => userStore.userInfo) + +// 判断是否为管理员(非医生、非医助) +const isAdmin = computed(() => { + const roleId = userInfo.value.role_id + // 如果role_id是数组,检查是否包含医生(1)或医助(2) + if (Array.isArray(roleId)) { + return !roleId.includes(1) && !roleId.includes(2) + } + // 如果role_id是单个值,检查是否不是医生或医助 + return roleId !== 1 && roleId !== 2 +}) const formData = reactive({ patient_name: '', doctor_name: '', - status: '', + status: '' as string | number, start_date: '', end_date: '' }) +const activeTab = ref('all') +const statusCount = ref>({ + 1: 0, + 2: 0, + 3: 0, + 4: 0 +}) + const { pager, getLists, resetPage, resetParams } = usePaging({ fetchFun: appointmentLists, params: formData }) +// 获取各状态数量 +const getStatusCount = async () => { + try { + // 获取各状态的数量 + const promises = [1, 2, 3, 4].map(async (status) => { + const res = await appointmentLists({ + ...formData, + status, + page_no: 1, + page_size: 1 + }) + return { status, count: res.count || 0 } + }) + + const results = await Promise.all(promises) + results.forEach(({ status, count }) => { + statusCount.value[status] = count + }) + } catch (error) { + console.error('获取状态数量失败:', error) + } +} + +// 切换选项卡 +const handleTabChange = (tabName: string | number) => { + if (tabName === 'all') { + formData.status = '' + } else { + formData.status = Number(tabName) + } + resetPage() +} + +// 重写getLists,同时更新状态数量 +const loadData = async () => { + await getLists() + await getStatusCount() +} + +// 搜索 +const handleSearch = () => { + resetPage() +} + +// 重置 +const handleReset = () => { + activeTab.value = 'all' + resetParams() +} + const detailVisible = ref(false) const detailData = ref(null) +const editRef = ref() +const videoCallRef = ref() +const prescriptionDrawerRef = ref() // 查看详情 const handleDetail = async (row: any) => { @@ -231,7 +382,7 @@ const handleCancel = async (row: any) => { await feedback.confirm('确定要取消该挂号吗?') await cancelAppointment({ id: row.id }) feedback.msgSuccess('取消成功') - getLists() + loadData() } catch (error) { // 用户取消操作 } @@ -243,13 +394,78 @@ const handleComplete = async (row: any) => { await feedback.confirm('确认患者已就诊完成?') await completeAppointment({ id: row.id }) feedback.msgSuccess('操作成功') - getLists() + loadData() } catch (error) { // 用户取消操作 } } -getLists() +// 编辑患者资料 +const handleEditPatient = (row: any) => { + console.log() + if (!row.patient_id) { + feedback.msgWarning('该预约没有关联诊单信息') + return + } + editRef.value?.open('edit', row.patient_id) +} + +// 1v1视频通话 +const handleVideoCall = (row: any) => { + if (!row.patient_id) { + feedback.msgWarning('患者信息不完整') + return + } + + videoCallRef.value?.open({ + diagnosisId: row.diagnosis_id || row.id, + patientId: row.patient_id, + patientName: row.patient_name, + userId: `patient_${row.patient_id}`, + isGroup: false + }) +} + +// 群组视频通话 +const handleGroupVideoCall = (row: any) => { + if (!row.patient_id) { + feedback.msgWarning('患者信息不完整') + return + } + + if (!row.doctor_id) { + feedback.msgWarning('该预约没有医生信息,无法发起群组通话') + return + } + + // 群组通话参与者:患者和医生 + const userIds = [ + `patient_${row.patient_id}`, + `doctor_${row.doctor_id}` + ] + + videoCallRef.value?.open({ + diagnosisId: row.diagnosis_id || row.id, + patientId: row.patient_id, + patientName: row.patient_name, + doctorId: row.doctor_id, + userIds: userIds, + isGroup: true + }) +} + +// 创建处方单 +const handleCreatePrescription = async (row: any) => { + try { + // 获取详细信息 + const detail = await appointmentDetail({ id: row.id }) + prescriptionDrawerRef.value?.open(detail) + } catch (error) { + feedback.msgError('获取患者信息失败') + } +} + +loadData() diff --git a/install_doctor_fields.bat b/install_doctor_fields.bat new file mode 100644 index 00000000..349699b5 --- /dev/null +++ b/install_doctor_fields.bat @@ -0,0 +1,98 @@ +@echo off +chcp 65001 >nul +setlocal enabledelayedexpansion + +REM 医生字段安装脚本 (Windows版本) +REM 用法: install_doctor_fields.bat + +echo ========================================== +echo 医生字段安装脚本 +echo ========================================== +echo. + +REM 数据库配置 +set DB_HOST=localhost +set DB_PORT=3306 +set DB_NAME=zyt +set DB_USER=root + +REM 提示输入数据库密码 +set /p DB_PASS=请输入数据库密码: +echo. + +REM 检查MySQL是否可用 +echo 检查MySQL连接... +mysql -h%DB_HOST% -P%DB_PORT% -u%DB_USER% -p%DB_PASS% -e "SELECT 1;" >nul 2>&1 + +if errorlevel 1 ( + echo [错误] 无法连接到MySQL数据库 + echo 请检查数据库配置和密码是否正确 + pause + exit /b 1 +) + +echo [成功] 数据库连接成功 +echo. + +REM 备份数据库 +set BACKUP_FILE=zyt_backup_%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2%.sql +set BACKUP_FILE=%BACKUP_FILE: =0% +echo 正在备份数据库到: %BACKUP_FILE% +mysqldump -h%DB_HOST% -P%DB_PORT% -u%DB_USER% -p%DB_PASS% %DB_NAME% > %BACKUP_FILE% 2>nul + +if errorlevel 1 ( + echo [警告] 数据库备份失败 + set /p continue=是否继续安装? (y/n): + if /i not "!continue!"=="y" exit /b 1 +) else ( + echo [成功] 数据库备份成功 +) +echo. + +REM 执行迁移脚本 +echo 正在执行数据库迁移... +mysql -h%DB_HOST% -P%DB_PORT% -u%DB_USER% -p%DB_PASS% %DB_NAME% < server\database\migrations\add_doctor_fields_to_admin.sql 2>&1 + +if errorlevel 1 ( + echo [错误] 数据库迁移失败 + echo 请检查错误信息,可能字段已经存在 + pause + exit /b 1 +) + +echo [成功] 数据库迁移成功 +echo. + +REM 验证安装 +echo 验证字段是否添加成功... +mysql -h%DB_HOST% -P%DB_PORT% -u%DB_USER% -p%DB_PASS% %DB_NAME% -e "SHOW COLUMNS FROM zyt_admin LIKE 'gender';" 2>nul | find "gender" >nul + +if errorlevel 1 ( + echo [错误] 字段验证失败 + pause + exit /b 1 +) + +echo [成功] 字段验证成功 +echo. + +echo ========================================== +echo 安装完成! +echo ========================================== +echo. +echo 新增字段列表: +echo - gender (性别) +echo - age (年龄) +echo - phone (手机号) +echo - title (职称) +echo - department (所属科室) +echo - specialty (擅长领域) +echo - education (教育背景) +echo - experience (工作经历) +echo - honors (荣誉资质) +echo. +echo 备份文件: %BACKUP_FILE% +echo. +echo 现在可以使用医生管理功能了! +echo. +pause diff --git a/install_doctor_fields.sh b/install_doctor_fields.sh new file mode 100644 index 00000000..6af70e0b --- /dev/null +++ b/install_doctor_fields.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +# 医生字段安装脚本 +# 用法: ./install_doctor_fields.sh + +echo "==========================================" +echo "医生字段安装脚本" +echo "==========================================" +echo "" + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# 数据库配置 +DB_HOST="localhost" +DB_PORT="3306" +DB_NAME="zyt" +DB_USER="root" + +# 提示输入数据库密码 +echo -e "${YELLOW}请输入数据库密码:${NC}" +read -s DB_PASS +echo "" + +# 检查MySQL是否可用 +echo "检查MySQL连接..." +mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" -e "SELECT 1;" > /dev/null 2>&1 + +if [ $? -ne 0 ]; then + echo -e "${RED}错误: 无法连接到MySQL数据库${NC}" + echo "请检查数据库配置和密码是否正确" + exit 1 +fi + +echo -e "${GREEN}✓ 数据库连接成功${NC}" +echo "" + +# 备份数据库 +BACKUP_FILE="zyt_backup_$(date +%Y%m%d_%H%M%S).sql" +echo "正在备份数据库到: $BACKUP_FILE" +mysqldump -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$BACKUP_FILE" 2>/dev/null + +if [ $? -eq 0 ]; then + echo -e "${GREEN}✓ 数据库备份成功${NC}" +else + echo -e "${RED}✗ 数据库备份失败${NC}" + echo "是否继续安装? (y/n)" + read -r response + if [[ ! "$response" =~ ^[Yy]$ ]]; then + exit 1 + fi +fi +echo "" + +# 执行迁移脚本 +echo "正在执行数据库迁移..." +mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" < server/database/migrations/add_doctor_fields_to_admin.sql 2>&1 + +if [ $? -eq 0 ]; then + echo -e "${GREEN}✓ 数据库迁移成功${NC}" +else + echo -e "${RED}✗ 数据库迁移失败${NC}" + echo "请检查错误信息,可能字段已经存在" + exit 1 +fi +echo "" + +# 验证安装 +echo "验证字段是否添加成功..." +RESULT=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "SHOW COLUMNS FROM zyt_admin LIKE 'gender';" 2>/dev/null | grep -c "gender") + +if [ "$RESULT" -eq 1 ]; then + echo -e "${GREEN}✓ 字段验证成功${NC}" +else + echo -e "${RED}✗ 字段验证失败${NC}" + exit 1 +fi +echo "" + +echo "==========================================" +echo -e "${GREEN}安装完成!${NC}" +echo "==========================================" +echo "" +echo "新增字段列表:" +echo " - gender (性别)" +echo " - age (年龄)" +echo " - phone (手机号)" +echo " - title (职称)" +echo " - department (所属科室)" +echo " - specialty (擅长领域)" +echo " - education (教育背景)" +echo " - experience (工作经历)" +echo " - honors (荣誉资质)" +echo "" +echo "备份文件: $BACKUP_FILE" +echo "" +echo "现在可以使用医生管理功能了!" diff --git a/ps/管理密码.txt b/ps/管理密码.txt index d4f57030..b761b2c3 100644 --- a/ps/管理密码.txt +++ b/ps/管理密码.txt @@ -6,4 +6,8 @@ admin Zyt123456 外网面板地址: https://139.196.37.14:30296/2a7ef99b 内网面板地址: https://172.27.15.98:30296/2a7ef99b username: i6rjat7k - password: 0ccb31ec \ No newline at end of file + password: 0ccb31ec + +http://%E6%88%91%E6%8A%8A%E7%BB%84%E4%BB%B6%E6%94%B9%E6%88%90%E8%BF%99%E4%B8%AA%E4%BA%86@tencentcloud/call-uikit-vue%22:%20%22%5E4.0.12%22, + +我把视频组件从"@tencentcloud/call-uikit-vue": "^4.0.12", 改成了最新版,现在需要你更新所有视频通话组件逻辑代码 \ No newline at end of file diff --git a/server/app/adminapi/lists/auth/AdminLists.php b/server/app/adminapi/lists/auth/AdminLists.php index 6ba8430b..bd5f6369 100644 --- a/server/app/adminapi/lists/auth/AdminLists.php +++ b/server/app/adminapi/lists/auth/AdminLists.php @@ -135,7 +135,9 @@ class AdminLists extends BaseAdminDataLists implements ListsExtendInterface, Lis { $field = [ 'id', 'name', 'account', 'create_time', 'disable', 'root', - 'login_time', 'login_ip', 'multipoint_login', 'avatar' + 'login_time', 'login_ip', 'multipoint_login', 'avatar', + 'gender', 'age', 'phone', 'title', 'department', + 'specialty', 'education', 'experience', 'honors' ]; $adminLists = Admin::field($field) diff --git a/server/app/adminapi/lists/doctor/AppointmentLists.php b/server/app/adminapi/lists/doctor/AppointmentLists.php index 2c089e11..cf111ef0 100644 --- a/server/app/adminapi/lists/doctor/AppointmentLists.php +++ b/server/app/adminapi/lists/doctor/AppointmentLists.php @@ -4,6 +4,7 @@ namespace app\adminapi\lists\doctor; use app\adminapi\lists\BaseAdminDataLists; use app\common\model\doctor\Appointment; +use app\common\model\auth\AdminRole; use app\common\lists\ListsSearchInterface; /** @@ -19,15 +20,18 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac */ public function setSearch(): array { - $allowSearch = [ - '=' => ['a.patient_id', 'a.doctor_id', 'a.status', 'a.appointment_date'], - ]; - - // 处理日期范围搜索 - if (!empty($this->params['start_date']) && !empty($this->params['end_date'])) { - $this->searchWhere[] = ['a.appointment_date', 'between', [$this->params['start_date'], $this->params['end_date']]]; - } + return []; + } + /** + * @notes 获取列表 + * @return array + */ + public function lists(): array + { + // 获取当前管理员的角色ID + $roleIds = AdminRole::where('admin_id', $this->adminId)->column('role_id'); + // 处理患者姓名搜索 if (!empty($this->params['patient_name'])) { $this->searchWhere[] = ['u.patient_name', 'like', '%' . $this->params['patient_name'] . '%']; @@ -38,22 +42,41 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac $this->searchWhere[] = ['ad.name', 'like', '%' . $this->params['doctor_name'] . '%']; } - return $allowSearch; - } + // 处理状态搜索 + if (isset($this->params['status']) && $this->params['status'] !== '') { + $this->searchWhere[] = ['a.status', '=', $this->params['status']]; + } - /** - * @notes 获取列表 - * @return array - */ - public function lists(): array - { - - $lists = Appointment::alias('a') + // 处理日期范围搜索 + if (!empty($this->params['start_date']) && !empty($this->params['end_date'])) { + $this->searchWhere[] = ['a.appointment_date', 'between', [$this->params['start_date'], $this->params['end_date']]]; + } elseif (!empty($this->params['start_date'])) { + $this->searchWhere[] = ['a.appointment_date', '>=', $this->params['start_date']]; + } elseif (!empty($this->params['end_date'])) { + $this->searchWhere[] = ['a.appointment_date', '<=', $this->params['end_date']]; + } + + // 构建查询 + $query = Appointment::alias('a') ->leftJoin('tcm_diagnosis u', 'a.patient_id = u.id') ->leftJoin('admin ad', 'a.doctor_id = ad.id') - ->field('a.*, u.patient_name as patient_name, u.phone as patient_phone, ad.name as doctor_name') - ->where($this->searchWhere) - ->order('a.id', 'desc') + ->field('a.*, u.patient_name as patient_name, u.phone as patient_phone, ad.name as doctor_name, u.id as diagnosis_id') + ->where($this->searchWhere); + + // 如果是医生角色(role_id=1),只显示挂自己号的预约 + if (in_array(1, $roleIds)) { + $query->where('a.doctor_id', $this->adminId); + } + + // 如果是医助角色(role_id=2),只显示自己添加的患者的预约 + if (in_array(2, $roleIds)) { + $query->where('u.assistant_id', $this->adminId); + } + + $lists = $query + ->order('a.status', 'asc') + ->order('a.appointment_date', 'asc') + ->order('a.appointment_time', 'asc') ->limit($this->limitOffset, $this->limitLength) ->select() ->toArray(); @@ -64,6 +87,7 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac 1 => '已预约', 2 => '已取消', 3 => '已完成', + 4 => '已过号', ]; $item['status_desc'] = $statusMap[$item['status']] ?? '未知'; @@ -92,10 +116,48 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac */ public function count(): int { + // 获取当前管理员的角色ID + $roleIds = AdminRole::where('admin_id', $this->adminId)->column('role_id'); + + // 处理患者姓名搜索 + if (!empty($this->params['patient_name'])) { + $this->searchWhere[] = ['u.patient_name', 'like', '%' . $this->params['patient_name'] . '%']; + } + + // 处理医生姓名搜索 + if (!empty($this->params['doctor_name'])) { + $this->searchWhere[] = ['ad.name', 'like', '%' . $this->params['doctor_name'] . '%']; + } + + // 处理状态搜索 + if (isset($this->params['status']) && $this->params['status'] !== '') { + $this->searchWhere[] = ['a.status', '=', $this->params['status']]; + } + + // 处理日期范围搜索 + if (!empty($this->params['start_date']) && !empty($this->params['end_date'])) { + $this->searchWhere[] = ['a.appointment_date', 'between', [$this->params['start_date'], $this->params['end_date']]]; + } elseif (!empty($this->params['start_date'])) { + $this->searchWhere[] = ['a.appointment_date', '>=', $this->params['start_date']]; + } elseif (!empty($this->params['end_date'])) { + $this->searchWhere[] = ['a.appointment_date', '<=', $this->params['end_date']]; + } + + // 构建查询 $query = Appointment::alias('a') ->leftJoin('tcm_diagnosis u', 'a.patient_id = u.id') ->leftJoin('admin ad', 'a.doctor_id = ad.id') ->where($this->searchWhere); + + // 如果是医生角色(role_id=1),只显示挂自己号的预约 + if (in_array(1, $roleIds)) { + $query->where('a.doctor_id', $this->adminId); + } + + // 如果是医助角色(role_id=2),只显示自己添加的患者的预约 + if (in_array(2, $roleIds)) { + $query->where('u.assistant_id', $this->adminId); + } return $query->count(); } diff --git a/server/app/adminapi/lists/tcm/DiagnosisLists.php b/server/app/adminapi/lists/tcm/DiagnosisLists.php index 446c7b39..84bc644b 100644 --- a/server/app/adminapi/lists/tcm/DiagnosisLists.php +++ b/server/app/adminapi/lists/tcm/DiagnosisLists.php @@ -16,6 +16,7 @@ namespace app\adminapi\lists\tcm; use app\adminapi\lists\BaseAdminDataLists; use app\common\model\tcm\Diagnosis; +use app\common\model\auth\AdminRole; use app\common\lists\ListsSearchInterface; /** @@ -47,7 +48,18 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface */ public function lists(): array { - $lists = Diagnosis::where($this->searchWhere) + // 获取当前管理员的角色ID + $roleIds = AdminRole::where('admin_id', $this->adminId)->column('role_id'); + + // 构建查询 + $query = Diagnosis::where($this->searchWhere); + + // 如果是医助角色(role_id=2),只显示自己添加的患者 + if (in_array(2, $roleIds)) { + $query->where('assistant_id', $this->adminId); + } + + $lists = $query ->field(['id', 'patient_id', 'patient_name', 'id_card', 'phone', 'gender', 'age', 'diagnosis_date', 'diagnosis_type', 'syndrome_type', 'assistant_id', 'status', 'create_time', 'update_time']) ->append(['gender_desc', 'status_desc', 'diagnosis_date_text']) ->order(['id' => 'desc']) @@ -64,6 +76,17 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface */ public function count(): int { - return Diagnosis::where($this->searchWhere)->count(); + // 获取当前管理员的角色ID + $roleIds = AdminRole::where('admin_id', $this->adminId)->column('role_id'); + + // 构建查询 + $query = Diagnosis::where($this->searchWhere); + + // 如果是医助角色(role_id=2),只显示自己添加的患者 + if (in_array(2, $roleIds)) { + $query->where('assistant_id', $this->adminId); + } + + return $query->count(); } } diff --git a/server/app/adminapi/logic/auth/AdminLogic.php b/server/app/adminapi/logic/auth/AdminLogic.php index a522284b..8c32ebcf 100644 --- a/server/app/adminapi/logic/auth/AdminLogic.php +++ b/server/app/adminapi/logic/auth/AdminLogic.php @@ -60,6 +60,16 @@ class AdminLogic extends BaseLogic 'create_time' => time(), 'disable' => $params['disable'], 'multipoint_login' => $params['multipoint_login'], + // 新增字段 + 'gender' => $params['gender'] ?? 1, + 'age' => $params['age'] ?? null, + 'phone' => $params['phone'] ?? null, + 'title' => $params['title'] ?? null, + 'department' => $params['department'] ?? null, + 'specialty' => $params['specialty'] ?? null, + 'education' => $params['education'] ?? null, + 'experience' => $params['experience'] ?? null, + 'honors' => $params['honors'] ?? null, ]); // 角色 @@ -99,7 +109,17 @@ class AdminLogic extends BaseLogic 'name' => $params['name'], 'account' => $params['account'], 'disable' => $params['disable'], - 'multipoint_login' => $params['multipoint_login'] + 'multipoint_login' => $params['multipoint_login'], + // 新增字段 + 'gender' => $params['gender'] ?? 1, + 'age' => $params['age'] ?? null, + 'phone' => $params['phone'] ?? null, + 'title' => $params['title'] ?? null, + 'department' => $params['department'] ?? null, + 'specialty' => $params['specialty'] ?? null, + 'education' => $params['education'] ?? null, + 'experience' => $params['experience'] ?? null, + 'honors' => $params['honors'] ?? null, ]; // 头像 @@ -232,6 +252,8 @@ class AdminLogic extends BaseLogic $admin = Admin::field([ 'id', 'account', 'name', 'disable', 'root', 'multipoint_login', 'avatar', + 'gender', 'age', 'phone', 'title', 'department', + 'specialty', 'education', 'experience', 'honors' ])->findOrEmpty($params['id'])->toArray(); if ($action == 'detail') { diff --git a/server/app/adminapi/logic/doctor/AppointmentLogic.php b/server/app/adminapi/logic/doctor/AppointmentLogic.php index 8dd0f0e1..79b68488 100644 --- a/server/app/adminapi/logic/doctor/AppointmentLogic.php +++ b/server/app/adminapi/logic/doctor/AppointmentLogic.php @@ -290,9 +290,9 @@ class AppointmentLogic extends BaseLogic public static function detail(array $params) { $appointment = Appointment::alias('a') - ->leftJoin('la_user u', 'a.patient_id = u.id') - ->leftJoin('la_admin ad', 'a.doctor_id = ad.id') - ->field('a.*, u.nickname as patient_name, u.mobile as patient_phone, ad.name as doctor_name') + ->leftJoin('zyt_tcm_diagnosis u', 'a.patient_id = u.id') + ->leftJoin('zyt_admin ad', 'a.doctor_id = ad.id') + ->field('a.*, u.patient_name as patient_name, u.phone as patient_phone, ad.name as doctor_name') ->where('a.id', $params['id']) ->findOrEmpty() ->toArray(); diff --git a/server/database/migrations/add_doctor_fields_to_admin.sql b/server/database/migrations/add_doctor_fields_to_admin.sql new file mode 100644 index 00000000..6fea873d --- /dev/null +++ b/server/database/migrations/add_doctor_fields_to_admin.sql @@ -0,0 +1,24 @@ +-- 为管理员表添加医生相关字段 +-- 执行时间:请根据实际情况修改 + +-- 添加基本信息字段 +ALTER TABLE `zyt_admin` +ADD COLUMN `gender` tinyint(1) DEFAULT 1 COMMENT '性别:1=男,2=女' AFTER `name`, +ADD COLUMN `age` int(3) DEFAULT NULL COMMENT '年龄' AFTER `gender`, +ADD COLUMN `phone` varchar(20) DEFAULT NULL COMMENT '手机号' AFTER `age`; + +-- 添加专业信息字段 +ALTER TABLE `zyt_admin` +ADD COLUMN `title` varchar(50) DEFAULT NULL COMMENT '职称' AFTER `phone`, +ADD COLUMN `department` varchar(100) DEFAULT NULL COMMENT '所属科室' AFTER `title`, +ADD COLUMN `specialty` text DEFAULT NULL COMMENT '擅长领域' AFTER `department`; + +-- 添加履历信息字段 +ALTER TABLE `zyt_admin` +ADD COLUMN `education` text DEFAULT NULL COMMENT '教育背景' AFTER `specialty`, +ADD COLUMN `experience` text DEFAULT NULL COMMENT '工作经历' AFTER `education`, +ADD COLUMN `honors` text DEFAULT NULL COMMENT '荣誉资质' AFTER `experience`; + +-- 添加索引 +ALTER TABLE `zyt_admin` ADD INDEX `idx_phone` (`phone`); +ALTER TABLE `zyt_admin` ADD INDEX `idx_gender` (`gender`); diff --git a/server/database/migrations/rollback_doctor_fields_from_admin.sql b/server/database/migrations/rollback_doctor_fields_from_admin.sql new file mode 100644 index 00000000..945d4950 --- /dev/null +++ b/server/database/migrations/rollback_doctor_fields_from_admin.sql @@ -0,0 +1,18 @@ +-- 回滚:删除管理员表的医生相关字段 +-- 警告:执行此脚本将删除这些字段的所有数据 + +-- 删除索引 +ALTER TABLE `zyt_admin` DROP INDEX `idx_phone`; +ALTER TABLE `zyt_admin` DROP INDEX `idx_gender`; + +-- 删除字段 +ALTER TABLE `zyt_admin` +DROP COLUMN `gender`, +DROP COLUMN `age`, +DROP COLUMN `phone`, +DROP COLUMN `title`, +DROP COLUMN `department`, +DROP COLUMN `specialty`, +DROP COLUMN `education`, +DROP COLUMN `experience`, +DROP COLUMN `honors`;