Merge branch 'develop' of https://gitea.gentronhealth.com/wangyizhe/his into develop

This commit is contained in:
huabuweixin
2026-01-20 18:01:46 +08:00
65 changed files with 7243 additions and 1162 deletions

View File

@@ -1637,7 +1637,6 @@
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/lodash": "*"
}
@@ -1648,7 +1647,6 @@
"integrity": "sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~7.16.0"
}
@@ -3335,7 +3333,6 @@
"resolved": "https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"license": "ISC",
"peer": true,
"engines": {
"node": ">=12"
}
@@ -5578,15 +5575,13 @@
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/lodash-unified": {
"version": "1.0.3",
@@ -6539,7 +6534,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -6780,7 +6774,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -6793,7 +6786,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
@@ -7045,7 +7037,6 @@
"integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/estree": "1.0.8"
},
@@ -7224,7 +7215,6 @@
"integrity": "sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==",
"devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
@@ -7257,7 +7247,6 @@
"version": "2.0.3",
"resolved": "https://registry.npmmirror.com/segmentit/-/segmentit-2.0.3.tgz",
"integrity": "sha512-7mn2XL3OdTUQ+AhHz7SbgyxLTaQRzTWQNVwiK+UlTO8aePGbSwvKUzTwE4238+OUY9MoR6ksAg35zl8sfTunQQ==",
"peer": true,
"dependencies": {
"preval.macro": "^4.0.0"
}
@@ -8457,7 +8446,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -8819,7 +8807,6 @@
"integrity": "sha512-RzAr8LSvM8lmhB4tQ5OPcBhpjOZRZjuxv9zO5UcxeoY2bd3kP3Ticd40Qma9/BqZ8JS96Ll/jeBX9u+LJZrhVg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.19.3",
"postcss": "^8.4.31",
@@ -8924,7 +8911,6 @@
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.25.tgz",
"integrity": "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.25",
"@vue/compiler-sfc": "3.5.25",

View File

@@ -0,0 +1,33 @@
import request from '@/utils/request'
export function getLisConfigPage(query) {
return request({
url: '/inspection/lisConfig/init-page',
method: 'get',
params: query
})
}
export function getLisConfigDetail(id) {
return request({
url: '/inspection/lisConfig/info-detail',
method: 'get',
params: { id }
})
}
export function getLisConfigList(searchKey, type) {
return request({
url: '/inspection/lisConfig/init-list',
method: 'get',
params: { searchKey, type }
})
}
export function saveLisConfig(data) {
return request({
url: '/inspection/lisConfig/saveAll',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,48 @@
import request from '@/utils/request'
export function getObservationInit() {
return request({
url: '/inspection/observation/init',
method: 'get'
})
}
export function getObservationPage(query) {
return request({
url: '/inspection/observation/information-page',
method: 'get',
params: query
})
}
export function getObservationOne(id) {
return request({
url: '/inspection/observation/information-one',
method: 'get',
params: { id }
})
}
export function addObservation(data) {
return request({
url: '/inspection/observation/information',
method: 'post',
data: data
})
}
export function updateObservation(data) {
return request({
url: '/inspection/observation/information',
method: 'post',
data: data
})
}
export function deleteObservation(ids) {
return request({
url: '/inspection/observation/information-status',
method: 'post',
data: { ids, type: '停用' }
})
}

View File

@@ -1,4 +1,4 @@
import {createWebHistory, createRouter} from 'vue-router'
import { createWebHistory, createRouter } from 'vue-router'
/* Layout */
import Layout from '@/layout'
@@ -61,7 +61,7 @@ export const constantRoutes = [
path: '/index',
component: () => import('@/views/index'),
name: 'Index',
meta: {title: '首页', icon: 'dashboard', affix: true}
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
},
@@ -75,7 +75,21 @@ export const constantRoutes = [
path: 'profile',
component: () => import('@/views/system/user/profile/index'),
name: 'Profile',
meta: {title: '个人中心', icon: 'user'}
meta: { title: '个人中心', icon: 'user' }
}
]
},
// 添加套餐管理相关路由到公共路由,确保始终可用
{
path: '/maintainSystem/Inspection/PackageManagement',
component: Layout,
hidden: true,
children: [
{
path: '',
component: () => import('@/views/maintainSystem/Inspection/PackageManagement.vue'),
name: 'DirectPackageManagement',
meta: { title: '套餐管理' }
}
]
}
@@ -83,6 +97,162 @@ export const constantRoutes = [
// 动态路由,基于用户权限动态去加载
export const dynamicRoutes = [
{
path: '/basicmanage',
component: Layout,
redirect: '/basicmanage/invoice-management',
name: 'BasicManage',
meta: { title: '基础管理', icon: 'component' },
children: [
{
path: 'invoice-management',
component: () => import('@/views/basicmanage/InvoiceManagement/index.vue'),
name: 'invoice-management',
meta: { title: '发票管理' }
}
]
},
{
path: '/system/tenant-user',
component: Layout,
hidden: true,
permissions: ['*:*:*'],
children: [
{
path: 'set/:tenantId(\\d+)',
component: () => import('@/views/system/tenant/setUser'),
name: 'SetUser',
meta: { title: '所属用户', activeMenu: '/system/tenant' }
}
]
},
{
path: '/system/tenant-contract',
component: Layout,
hidden: true,
permissions: ['*:*:*'],
children: [
{
path: 'set/:tenantId(\\d+)',
component: () => import('@/views/system/tenant/setContract'),
name: 'SetContract',
meta: { title: '合同管理', activeMenu: '/system/tenant' }
}
]
},
{
path: '/system/user-auth',
component: Layout,
hidden: true,
permissions: ['system:user:edit'],
children: [
{
path: 'role/:userId(\\d+)',
component: () => import('@/views/system/user/authRole'),
name: 'AuthRole',
meta: { title: '分配角色', activeMenu: '/system/user' }
}
]
},
{
path: '/system/role-auth',
component: Layout,
hidden: true,
permissions: ['system:role:edit'],
children: [
{
path: 'user/:roleId(\\d+)',
component: () => import('@/views/system/role/authUser'),
name: 'AuthUser',
meta: { title: '分配用户', activeMenu: '/system/role' }
}
]
},
{
path: '/system/dict-data',
component: Layout,
hidden: true,
permissions: ['system:dict:list'],
children: [
{
path: 'index/:dictId(\\d+)',
component: () => import('@/views/system/dict/data'),
name: 'Data',
meta: { title: '字典数据', activeMenu: '/system/dict' }
}
]
},
{
path: '/monitor',
component: Layout,
redirect: '/monitor/operlog',
name: 'Monitor',
meta: { title: '系统监控', icon: 'monitor' },
children: [
{
path: 'operlog',
component: () => import('@/views/monitor/operlog/index.vue'),
name: 'Operlog',
meta: { title: '操作日志', icon: 'operlog', permissions: ['monitor:operlog:list'] }
},
{
path: 'logininfor',
component: () => import('@/views/monitor/logininfor/index.vue'),
name: 'Logininfor',
meta: { title: '登录日志', icon: 'logininfor', permissions: ['monitor:logininfor:list'] }
},
{
path: 'job',
component: () => import('@/views/monitor/job/index.vue'),
name: 'Job',
meta: { title: '定时任务', icon: 'job', permissions: ['monitor:job:list'] }
}
]
},
{
path: '/tool',
component: Layout,
redirect: '/tool/gen',
name: 'Tool',
meta: { title: '系统工具', icon: 'tool' },
children: [
{
path: 'gen',
component: () => import('@/views/tool/gen/index.vue'),
name: 'Gen',
meta: { title: '代码生成', icon: 'gen', permissions: ['tool:gen:list'] }
}
]
},
{
path: '/monitor/job-log',
component: Layout,
hidden: true,
permissions: ['monitor:job:list'],
children: [
{
path: 'index/:jobId(\\d+)',
component: () => import('@/views/monitor/job/log'),
name: 'JobLog',
meta: { title: '调度日志', activeMenu: '/monitor/job' }
}
]
},
{
path: '/tool/gen-edit',
component: Layout,
hidden: true,
permissions: ['tool:gen:edit'],
children: [
{
path: 'index/:tableId(\\d+)',
component: () => import('@/views/tool/gen/editTable'),
name: 'GenEdit',
meta: { title: '修改生成配置', activeMenu: '/tool/gen' }
}
]
},
{
path: '/help-center',
component: Layout,
@@ -92,10 +262,36 @@ export const dynamicRoutes = [
path: '',
component: () => import('@/views/helpcenter/index.vue'),
name: 'HelpCenter',
meta: {title: '帮助中心'},
meta: { title: '帮助中心'},
},
],
},
// 字典类型路由(直接复制这段)
{
path: '/system/dict',
component: Layout,
alwaysShow: true,
name: 'DictType',
meta: {
title: '字典类型管理',
icon: 'list' // 图标随便选一个比如list、dict不影响跳转
},
children: [
{
path: '',
component: () => import('@/views/system/dict/index.vue'),
name: 'DictTypeList',
meta: {title: '字典类型', noCache: false}
},
{
path: 'data/:dictId?', // 带字典ID参数?表示可选
component: () => import('@/views/system/dict/data.vue'), // 你的data.vue路径
name: 'DictData',
hidden: true, // 不在侧边栏显示(子页面)
meta: {title: '字典数据', activeMenu: '/system/dict'} // 保持侧边栏高亮
}
]
},
];
// 合并常量路由和动态路由,确保所有路由都能被访问
@@ -115,7 +311,7 @@ const router = createRouter({
if (savedPosition) {
return savedPosition
} else {
return {top: 0}
return { top: 0 }
}
},
});

View File

@@ -347,7 +347,7 @@ const printForm = () => {
};
function handleClick() {
console.log('112313413');
console.log('住院记录表单点击事件触发');
}
const resetFun = (data) => {

View File

@@ -81,15 +81,15 @@
v-model="scope.row.activityDefinitionId"
filterable
remote
reserve-keyword
placeholder="请选择"
remote-show-suffix
:remote-method="(query) => handleRemoteQuery(query, scope.row)"
:loading="scope.row.loading"
placeholder="请输入并搜索项目"
style="width: 400px; max-width: 500px"
:class="{ 'error-border': scope.row.error }"
clearable
>
<el-option
v-for="item in allImplementDepartmentList"
v-for="item in scope.row.filteredOptions || []"
:key="item.value"
:label="item.label"
:value="item.value"
@@ -236,15 +236,34 @@ const filterNode = (value, data) => {
};
// 所有诊疗项目列表
const allImplementDepartmentList = ref([]);
function getAllImplementDepartment() {
async function getAllImplementDepartment() {
loading.value = true;
getAllTreatmentList().then((res) => {
try {
const res = await getAllTreatmentList();
allImplementDepartmentList.value = res.data.map((item) => ({
value: item.activityDefinitionId,
label: item.activityDefinitionName,
}));
// 为所有现有行初始化过滤选项(使用防抖处理,避免频繁更新)
if (catagoryList.value && catagoryList.value.length > 0) {
// 使用 setTimeout 将 DOM 更新推迟到下一个事件循环,避免阻塞
setTimeout(() => {
catagoryList.value.forEach(row => {
if (!row.hasOwnProperty('filteredOptions')) {
row.filteredOptions = allImplementDepartmentList.value.slice(0, 100); // 限制为前100个
row.loading = false;
}
});
}, 0);
}
loading.value = false;
});
} catch (error) {
console.error('获取诊疗项目列表失败:', error);
loading.value = false;
proxy.$message.error('获取诊疗项目列表失败');
}
}
/** 选择条数 */
@@ -253,18 +272,63 @@ function handleSelectionChange(selection) {
single.value = selection.length != 1;
multiple.value = !selection.length;
}
// 远程搜索处理函数
function handleRemoteQuery(query, row) {
if (query !== '') {
// 设置加载状态
row.loading = true;
// 模拟异步延迟
setTimeout(() => {
// 确保数据已加载
if (!allImplementDepartmentList.value || allImplementDepartmentList.value.length === 0) {
row.filteredOptions = [];
row.loading = false;
return;
}
// 过滤选项,限制结果数量以提高性能
const filtered = allImplementDepartmentList.value.filter(item => {
return item.label.toLowerCase().includes(query.toLowerCase()) ||
item.value.toLowerCase().includes(query.toLowerCase());
});
// 限制返回结果数量,避免过多选项导致性能问题
row.filteredOptions = filtered.slice(0, 100); // 限制为前100个匹配项
row.loading = false;
}, 300); // 300ms 延迟,模拟网络请求
} else {
// 如果查询为空,显示所有选项(但限制数量以提高性能)
if (allImplementDepartmentList.value && allImplementDepartmentList.value.length > 0) {
row.filteredOptions = allImplementDepartmentList.value.slice(0, 100); // 限制为前100个
} else {
row.filteredOptions = [];
}
}
}
// 新增项目
function handleAddItem() {
if (data.isAdding) {
proxy.$message.warning('请先保存当前行后再新增!');
return;
}
// 确保 allImplementDepartmentList 已经初始化
if (!allImplementDepartmentList.value || allImplementDepartmentList.value.length === 0) {
proxy.$message.warning('正在加载数据,请稍后再试!');
// 如果数据还未加载完成,尝试重新加载
getAllImplementDepartment();
return;
}
const newRow = {
startTime: '00:00:00',
endTime: '23:59:59',
loading: false, // 添加加载状态
filteredOptions: allImplementDepartmentList.value.slice(0, 100), // 初始化过滤选项,限制数量
};
catagoryList.value.push(newRow);
total.value = organization.value.length;
total.value = catagoryList.value.length; // 修正:使用实际数据列表长度,而不是组织结构长度
data.isAdding = true; // 设置标志位为 true表示有未保存的
}
// 批量添加
@@ -272,6 +336,7 @@ function handleBacthAddItem() {
// 批量添加显示对话框
bacthAddItemDialogVisible.value = true;
}
// 检验 编辑或 保存数据
function handleBlur(row, index) {
let hasError = false;
@@ -344,15 +409,25 @@ function deleteSelectedRows(row) {
}
/** 节点单击事件 */
function handleNodeClick(res, node) {
// 新增按钮是否 disable
data.isAdding = false;
// 新增按钮是否 disable
if (node.parent === null || node.level === 1) {
isAddDisable.value = true;
// 检查是否有未保存的数据
if (data.isAdding) {
proxy.$modal.confirm('当前有未保存的数据,切换节点将丢失未保存的数据,是否继续?').then(() => {
// 确认切换,重置状态
data.isAdding = false;
continueHandleNodeClick(node);
}).catch(() => {
// 取消切换,保持当前状态
return;
});
} else {
isAddDisable.value = false;
continueHandleNodeClick(node);
}
}
// 实际的节点点击处理逻辑
function continueHandleNodeClick(node) {
// 新增按钮是否 disable
isAddDisable.value = false;
// 检查节点是否有子节点
if (node.data.children && node.data.children.length > 0) {
// proxy.$message.warning("不能选择父节点");
@@ -365,26 +440,28 @@ function handleNodeClick(res, node) {
}
/** 目录分类查询 */
function getDiseaseTreatmentList() {
async function getDiseaseTreatmentList() {
loading.value = true;
getDiseaseTreatmentInit().then(({ data }) => {
loading.value = false;
try {
const { data } = await getDiseaseTreatmentInit();
//分类目录初始化获取
// 分类目录初始化获取
catagoryDicts.value = data.diagnosisCategoryOptions.sort((a, b) => {
return parseInt(a.value) - parseInt(b.value);
});
});
// 诊疗目录分类查询下拉树结d构
loading.value = true;
// 诊疗目录分类查询下拉树结d构
getImplDepartList();
} catch (error) {
console.error('获取疾病治疗初始化数据失败:', error);
proxy.$message.error('获取分类目录失败');
}
// 诊疗目录分类查询下拉树结构
await getImplDepartList();
loading.value = false;
}
// 诊疗目录分类查询下拉树结d构
function getImplDepartList() {
loading.value = true;
getImplementDepartmentList().then((res) => {
loading.value = false;
async function getImplDepartList() {
try {
const res = await getImplementDepartmentList();
if (res.code === 200) {
if (res.data.records.length > 0) {
organization.value = res.data.records.map((res) => {
@@ -398,13 +475,24 @@ function getImplDepartList() {
organization.value = [];
}
} else {
this.$modal.msgError(res.code);
proxy.$modal.msgError(res.code);
}
});
} catch (error) {
console.error('获取实施部门列表失败:', error);
proxy.$message.error('获取科室信息失败');
}
}
onMounted(() => {
getAllImplementDepartment();
getDiseaseTreatmentList();
onMounted(async () => {
try {
// 并行加载数据,提高效率
await Promise.all([
getAllImplementDepartment(),
getDiseaseTreatmentList()
]);
} catch (error) {
console.error('初始化数据加载失败:', error);
proxy.$message.error('数据加载失败,请稍后重试');
}
});
</script>
<style scoped>

View File

@@ -582,7 +582,7 @@ function submitForm() {
console.log('params11========>', JSON.stringify(params));
orgRef.value.validate((valid) => {
if (valid) {
console.log('99999999');
console.log('表单验证通过,准备提交数据');
if (form.busNoParent) {
if (form.formEnum == 4) {

View File

@@ -424,7 +424,7 @@ function clickRow(row) {
// 初始化
onMounted(() => {
preloadData(); // 预加载数据
// preloadData(); // 预加载数据
getList(); // 获取初始数据
});

View File

@@ -7,183 +7,78 @@
<el-option label="科室" :value="2"></el-option>
<el-option label="全院" :value="3"></el-option>
</el-select>
<el-input
v-model="searchKeyword"
placeholder="请输入名称"
style="width: 240px; margin-left: 10px;"
@keyup.enter="handleSearch"
></el-input>
<el-button style="margin-left: 10px;" @click="handleSearch"><el-icon><Search /></el-icon> 查询</el-button>
<el-button style="margin-left: 10px;" @click="handleReset"><el-icon><Refresh /></el-icon> 重置</el-button>
<el-button type="primary" style="margin-left: 10px;" @click="showAddDialog"><el-icon><Plus /></el-icon> 增加</el-button>
<el-input v-model="searchKeyword" placeholder="请输入名称" style="width: 240px; margin-left: 10px;"
@keyup.enter="handleSearch"></el-input>
<el-button style="margin-left: 10px;" @click="handleSearch"><el-icon>
<Search />
</el-icon> 查询</el-button>
<el-button style="margin-left: 10px;" @click="handleReset"><el-icon>
<Refresh />
</el-icon> 重置</el-button>
<el-button type="primary" style="margin-left: 10px;" @click="showAddDialog"><el-icon>
<Plus />
</el-icon> 增加</el-button>
</div>
<!-- 表格 -->
<el-table :data="tableData" style="width: 100%; margin-top: 20px;">
<el-table-column prop="sortNo" label="排序号" width="200">
<template #default="scope">
<el-input-number
v-if="editingId === scope.row.id"
v-model="editForm.sortNo"
:min="1"
:step="1"
style="width: 100%"
/>
<span v-else>{{ scope.row.sortNo }}</span>
</template>
</el-table-column>
<el-table-column prop="phraseName" label="名称" width="250">
<template #default="scope">
<el-input
v-if="editingId === scope.row.id"
v-model="editForm.phraseName"
placeholder="请输入名称(不超过50字)"
maxlength="50"
show-word-limit
style="width: 100%"
/>
<span v-else>{{ scope.row.phraseName }}</span>
</template>
</el-table-column>
<el-table-column prop="phraseContent" label="内容">
<template #default="scope">
<el-input
v-if="editingId === scope.row.id"
v-model="editForm.phraseContent"
placeholder="请输入内容"
type="textarea"
:rows="3"
style="width: 100%"
/>
<span v-else>{{ scope.row.phraseContent }}</span>
</template>
</el-table-column>
<el-table-column label="范围" width="250">
<template #default="scope">
<el-select
v-if="editingId === scope.row.id"
v-model="editForm.phraseType"
placeholder="请选择范围"
style="width: 100%"
>
<el-option label="个人" :value="1"></el-option>
<el-option label="科室" :value="2"></el-option>
<el-option label="全院" :value="3"></el-option>
</el-select>
<span v-else>{{ getScopeName(scope.row.phraseType) }}</span>
{{ getScopeName(scope.row.phraseType) }}
</template>
</el-table-column>
<!-- 业务分类列使用枚举转换中文名称 -->
<el-table-column label="业务分类" width="200">
<template #default="scope">
<el-select
v-if="editingId === scope.row.id"
v-model="editForm.phraseCategory"
placeholder="请选择业务分类"
style="width: 100%"
>
<el-option label="病愈" value="12"></el-option>
<el-option
v-for="item in businessclassification"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
<span v-else>{{ getBusinessTypeName(scope.row.phraseCategory) }}</span>
{{ getBusinessTypeName(scope.row.phraseCategory) }}
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template #default="scope">
<!-- 编辑状态 -->
<template v-if="editingId === scope.row.id">
<el-button
type="success"
size="small"
@click="handleSave"
>
<el-icon><Check /></el-icon> 保存
</el-button>
<el-button
type="warning"
size="small"
style="margin-left: 5px;"
@click="handleCancel"
>
<el-icon><Close /></el-icon> 取消
</el-button>
</template>
<!-- 非编辑状态 -->
<template v-else>
<el-button
type="primary"
size="small"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
type="danger"
size="small"
style="margin-left: 5px;"
@click="handleDelete(scope.row)"
>
删除
</el-button>
</template>
<el-button type="primary" size="small" @click="showEditDialog(scope.row)">
编辑
</el-button>
<el-button type="danger" size="small" style="margin-left: 5px;" @click="handleDelete(scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-container">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[15, 30, 50]"
:page-size="pageSize"
layout="total, prev, pager, next, jumper, sizes"
:total="total"
></el-pagination>
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
:page-sizes="[15, 30, 50]" :page-size="pageSize" layout="total, prev, pager, next, jumper, sizes"
:total="total"></el-pagination>
</div>
<!-- 新增模态框 -->
<el-dialog
v-model="addDialogVisible"
title="新增医生常用语"
width="600px"
center
>
<el-form ref="addFormRef" :model="addForm" :rules="rules" label-width="100px" class="add-form">
<el-form-item label="名称" prop="phraseName" required>
<el-input v-model="addForm.phraseName" placeholder="请输入常用语名称(不超过50字)" maxlength="50" show-word-limit style="width: 100%;"></el-input>
<el-dialog v-model="addDialogVisible" title="新增医生常用语" width="600px" center>
<el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="100px" class="add-form">
<el-form-item label="名称" prop="phraseName">
<el-input v-model="addForm.phraseName" placeholder="请输入常用语名称(不超过50字)" maxlength="50" show-word-limit
style="width: 100%;"></el-input>
</el-form-item>
<el-form-item label="内容" prop="phraseContent" required>
<el-input
v-model="addForm.phraseContent"
placeholder="请输入常用语内容"
type="textarea"
:rows="4"
style="width: 100%;"
></el-input>
<el-form-item label="内容" prop="phraseContent">
<el-input v-model="addForm.phraseContent" placeholder="请输入常用语内容" type="textarea" :rows="4"
style="width: 100%;"></el-input>
</el-form-item>
<el-form-item label="排序号">
<el-input-number v-model="addForm.sortNo" :min="1" :step="1" style="width: 100%;"></el-input-number>
</el-form-item>
<el-form-item label="业务分类">
<el-form-item label="业务分类" prop="phraseCategory">
<el-select v-model="addForm.phraseCategory" placeholder="请选择业务分类" style="width: 100%;">
<!-- 默认添加"病愈"选项 -->
<el-option label="病愈" value="12"></el-option>
<!-- 从数据字典获取其他选项 -->
<el-option
v-for="item in businessclassification"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
<el-option v-for="item in businessTypeOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="范围">
<el-form-item label="范围" prop="phraseType">
<el-select v-model="addForm.phraseType" placeholder="请选择范围" style="width: 100%;">
<el-option label="个人" :value="1"></el-option>
<el-option label="科室" :value="2"></el-option>
@@ -198,12 +93,48 @@
</span>
</template>
</el-dialog>
<!-- 编辑模态框 -->
<el-dialog v-model="editDialogVisible" title="编辑医生常用语" width="600px" center>
<el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="100px" class="add-form">
<el-form-item label="名称" prop="phraseName">
<el-input v-model="editForm.phraseName" placeholder="请输入常用语名称(不超过50字)" maxlength="50" show-word-limit
style="width: 100%;"></el-input>
</el-form-item>
<el-form-item label="内容" prop="phraseContent">
<el-input v-model="editForm.phraseContent" placeholder="请输入常用语内容" type="textarea" :rows="4"
style="width: 100%;"></el-input>
</el-form-item>
<el-form-item label="排序号">
<el-input-number v-model="editForm.sortNo" :min="1" :step="1" style="width: 100%;"></el-input-number>
</el-form-item>
<el-form-item label="业务分类" prop="phraseCategory">
<el-select v-model="editForm.phraseCategory" placeholder="请选择业务分类" style="width: 100%;">
<el-option v-for="item in businessTypeOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="范围" prop="phraseType">
<el-select v-model="editForm.phraseType" placeholder="请选择范围" style="width: 100%;">
<el-option label="个人" :value="1"></el-option>
<el-option label="科室" :value="2"></el-option>
<el-option label="全院" :value="3"></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="editDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleEditSave">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import {onMounted, ref} from 'vue'
import {Check, Close, Plus, Refresh, Search} from '@element-plus/icons-vue'
import { onMounted, ref } from 'vue'
import { Check, Close, Plus, Refresh, Search } from '@element-plus/icons-vue'
import {
addDoctorPhrase,
deleteDoctorPhrase,
@@ -211,71 +142,98 @@ import {
searchDoctorPhraseList,
updateDoctorPhrase
} from './api'
import {ElMessage, ElMessageBox} from 'element-plus'
import {useDict} from '@/utils/dict'
import { ElMessage, ElMessageBox } from 'element-plus'
// 如果数据字典未对齐后端枚举暂时注释useDict改用固定枚举后续可替换为dict
// import { useDict } from '@/utils/dict'
// 核心配置定义和后端枚举对齐的业务分类选项替换原businessclassification
const businessTypeOptions = ref([
{ label: '主诉', value: 'MAIN_COMPLAINT' },
{ label: '现病史', value: 'PRESENT_HISTORY' },
{ label: '术前', value: 'PRE_OPERATION' },
{ label: '术后', value: 'POST_OPERATION' },
{ label: '既往史', value: 'PAST_HISTORY' }
])
// 搜索条件
const searchScope = ref(null) // null表示未选择数字类型1=个人2=科室3=全院
const searchKeyword = ref('')
const searchScope = ref(null) // null表示未选择数字类型1=个人2=科室3=全院
const searchKeyword = ref('')
// 表格数据
const tableData = ref([])
// 分页
// 分页参数配置
const currentPage = ref(1)
const pageSize = ref(15)
const total = ref(0)
// 新增模态框相关
// 新增模态框相关配置
const addDialogVisible = ref(false)
const addFormRef = ref()
// 新增表单默认值:业务分类默认空,强制用户选择
const addForm = ref({
phraseName: '',
phraseContent: '',
sortNo: 1,
phraseType: 1,
phraseCategory: '病愈'
phraseCategory: ''
})
// 表单验证规则
const rules = {
// 完善新增表单验证规则补充业务分类必填、名称50字限制
const addRules = {
phraseName: [
{ required: true, message: '请输入常用语名称', trigger: 'blur' }
{ required: true, message: '请输入常用语名称', trigger: 'blur' },
{ max: 50, message: '常用语名称不能超过50字', trigger: 'blur' }
],
phraseContent: [
{ required: true, message: '请输入常用语内容', trigger: 'blur' }
],
phraseType: [
{ required: true, message: '请选择范围', trigger: 'change' }
],
phraseCategory: [
{ required: true, message: '请选择业务分类', trigger: 'change' }
]
}
// 编辑状态管理
const editingId = ref(null)
const editForm = ref({})
// 编辑模态框相关配置
const editDialogVisible = ref(false)
const editFormRef = ref()
// 编辑表单默认值配置
const editForm = ref({
id: '',
phraseName: '',
phraseContent: '',
sortNo: 1,
phraseType: 1,
phraseCategory: ''
})
// 完善编辑表单验证规则(和新增一致,保证校验统一)
const editRules = {
phraseName: [
{ required: true, message: '请输入常用语名称', trigger: 'blur' }
{ required: true, message: '请输入常用语名称', trigger: 'blur' },
{ max: 50, message: '常用语名称不能超过50字', trigger: 'blur' }
],
phraseContent: [
{ required: true, message: '请输入常用语内容', trigger: 'blur' }
],
phraseType: [
{ required: true, message: '请选择范围', trigger: 'change' }
],
phraseCategory: [
{ required: true, message: '请选择业务分类', trigger: 'change' }
]
}
// 获取业务分类数据字典
const { businessclassification } = useDict('businessclassification')
// 获取业务分类名称
const getBusinessTypeName = (category) => {
// 直接返回后端返回的phrase_category字段值
// 从数据库截图看phrase_category已经是中文名称"主诉"、"现病史"、"术后"等
if (category) {
return category
}
return '未知类型'
// 重构业务分类名称转换方法(适配后端编码→中文展示)
const getBusinessTypeName = (code) => {
if (!code) return '未知类型'
const item = businessTypeOptions.value.find(item => item.value === code)
return item ? item.label : '未知类型'
}
// 获取范围名称
// 获取范围名称转换方法
const getScopeName = (scope) => {
const scopeMap = {
1: '个人',
@@ -285,46 +243,41 @@ const getScopeName = (scope) => {
return scopeMap[scope] || '未知范围'
}
// 名称唯一性校验函数
// 名称唯一性校验函数(新增/编辑通用编辑时排除自身ID
const validatePhraseName = (phraseName, excludeId = null) => {
if (!phraseName || !phraseName.trim()) {
return { valid: false, message: '请输入常用语名称' }
}
// 检查字数限制
// 检查字数限制严格控制50字
if (phraseName.trim().length > 50) {
return { valid: false, message: '常用语名称不能超过50字' }
}
// 检查名称是否已存在
// 检查名称是否已存在,编辑时排除当前记录
const existingPhrase = allData.value.find(item => {
// 排除自身(更新时)
if (excludeId && item.id === excludeId) {
return false
}
return item.phraseName === phraseName.trim()
return item.phraseName.trim() === phraseName.trim()
})
if (existingPhrase) {
return { valid: false, message: '常用语名称已存在,请输入不同的名称' }
}
return { valid: true, message: '' }
}
// 所有数据(用于客户端分页)
// 所有数据(用于客户端分页处理
const allData = ref([])
// 获取医生常用语列表
// 获取医生常用语列表数据
const fetchDoctorPhraseList = async () => {
try {
const response = await getDoctorPhraseList()
// 处理后端返回的数据结构data.data
if (response.code === 200 && response.data && response.data.data) {
// 按照sortNo由小到大排序
// 按照sortNo由小到大排序,保证列表顺序正确
allData.value = response.data.data.sort((a, b) => a.sortNo - b.sortNo)
total.value = response.data.data.length
// 执行客户端分页
total.value = allData.value.length
// 执行客户端分页逻辑
applyPagination()
} else {
ElMessage.error('获取数据失败: ' + (response.msg || '未知错误'))
@@ -332,56 +285,54 @@ const fetchDoctorPhraseList = async () => {
total.value = 0
}
} catch (error) {
console.error('获取列表失败:', error) // 增加控制台日志便于调试
ElMessage.error('获取数据失败: 网络请求错误')
allData.value = []
total.value = 0
}
}
// 重置功能
// 重置功能方法
const handleReset = () => {
// 重置搜索条件
searchScope.value = null
searchKeyword.value = ''
// 重置分页到第一页
currentPage.value = 1
// 重新加载所有数据
fetchDoctorPhraseList()
}
// 客户端分页处理
// 客户端分页处理核心方法
const applyPagination = () => {
const start = (currentPage.value - 1) * pageSize.value
const end = start + pageSize.value
tableData.value = allData.value.slice(start, end)
}
// 分页处理
// 分页条数改变事件
const handleSizeChange = (val) => {
pageSize.value = val
applyPagination()
}
// 分页页码改变事件
const handleCurrentChange = (val) => {
currentPage.value = val
applyPagination()
}
// 搜索功能
// 搜索功能核心方法
const handleSearch = async () => {
try {
// searchScope可能是null未选择、1=个人2=科室3=全院
const searchScopeValue = searchScope.value
const phraseType = searchScopeValue === null ? undefined : searchScopeValue
const phraseType = searchScope.value === null ? undefined : searchScope.value
// 调用搜索接口phraseName, phraseType
// 如果phraseType为undefined则后端不会按范围过滤查询所有数据
const response = await searchDoctorPhraseList(searchKeyword.value, phraseType)
// 处理后端返回的数据结构data.data
if (response.code === 200 && response.data && response.data.data) {
// 按照sortNo由小到大排序
allData.value = response.data.data.sort((a, b) => a.sortNo - b.sortNo)
total.value = response.data.data.length
total.value = allData.value.length
currentPage.value = 1 // 搜索后重置到第一页
applyPagination() // 应用分页
} else {
@@ -390,179 +341,157 @@ const handleSearch = async () => {
total.value = 0
}
} catch (error) {
console.error('搜索失败:', error)
ElMessage.error('搜索失败: 网络请求错误')
allData.value = []
total.value = 0
}
}
// 打开新增模态框
// 打开新增模态框方法
const showAddDialog = () => {
// 重置表单
addForm.value = {
phraseName: '',
phraseContent: '',
sortNo: 1,
phraseType: 1,
phraseCategory: '病愈'
}
// 重置表单数据
addForm.value = {
phraseName: '',
phraseContent: '',
sortNo: 1,
phraseType: 1,
phraseCategory: ''
}
// 重置表单验证状态
if (addFormRef.value) {
addFormRef.value.clearValidate()
}
// 打开模态框
addDialogVisible.value = true
}
// 提交新增表单
// 提交新增表单方法
const handleAdd = async () => {
try {
// 验证表单
await addFormRef.value.validate()
// 先执行表单验证
const validateResult = await addFormRef.value.validate()
if (!validateResult) return
// 名称唯一性校验
const nameValidation = validatePhraseName(addForm.value.phraseName)
if (!nameValidation.valid) {
ElMessage.error(nameValidation.message)
return
}
// 添加数据库要求的必填默认字段
const formData = {
...addForm.value,
phraseCode: 'PHR000',
phraseCode: 'PHR000', // 建议后端自动生成,前端可传空
enableFlag: 1,
staffId: 1001,
deptCode: 'DEPT001',
creatorId: 1001
staffId: 1001, // 建议从登录态获取,不要硬编码
deptCode: 'DEPT001', // 建议从登录态获取
creatorId: 1001 // 建议从登录态获取
}
// 调用新增接口
const response = await addDoctorPhrase(formData)
// 处理新增结果
if (response.code === 200) {
ElMessage.success('新增成功')
// 关闭模态框
addDialogVisible.value = false
// 将新数据添加到数组开头,使新增的数据在表格最上方显示
const newData = {
...formData,
id: response.data.id || Date.now() // 使用后端返回的id或当前时间戳作为临时id
}
allData.value.unshift(newData)
total.value = allData.value.length
// 重新应用分页
applyPagination()
// 重新拉取数据比手动unshift更可靠避免数据不一致
fetchDoctorPhraseList()
} else {
ElMessage.error('新增失败: ' + (response.msg || '未知错误'))
}
} catch (error) {
console.error('新增失败:', error)
// 表单验证失败或其他错误
if (error instanceof Error) {
ElMessage.error('请填写完整信息或网络请求错误')
} else {
// 表单验证失败的情况
ElMessage.error('请填写完整信息')
}
ElMessage.error('新增失败: 请填写完整信息或网络异常')
}
}
// 删除功能
// 删除功能方法
const handleDelete = async (row) => {
try {
// 弹出确认对话框
await ElMessageBox.confirm('确定要删除该常用语吗?', '删除确认', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
await ElMessageBox.confirm(
'确定要删除该常用语吗?删除后无法恢复!',
'删除确认',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
// 调用删除接口
const response = await deleteDoctorPhrase(row.id)
// 处理删除结果
if (response.code === 200) {
ElMessage.success('删除成功')
// 重新取数据以更新界面
// 重新取数据
fetchDoctorPhraseList()
} else {
ElMessage.error('删除失败: ' + (response.msg || '未知错误'))
}
} catch (error) {
// 如果用户取消删除,不显示错误信息
if (error !== 'cancel' && error !== undefined) {
if (error.msg) {
ElMessage.error('删除操作失败: ' + error.msg)
} else if (error instanceof Error) {
ElMessage.error('删除操作失败: 网络请求错误')
} else {
ElMessage.error('删除操作失败: 未知错误')
}
// 用户取消删除时不提示错误
if (error !== 'cancel') {
console.error('删除失败:', error)
ElMessage.error('删除操作失败: 网络异常或权限不足')
}
}
}
// 编辑按钮点击事件
const handleEdit = (row) => {
// 进入编辑状态
editingId.value = row.id
// 复制当前行数据到编辑表单
editForm.value = {
...row,
// 确保phraseCategory和phraseType类型正确
phraseCategory: row.phraseCategory,
phraseType: row.phraseType
// 打开编辑弹窗核心方法 - 点击表格编辑按钮触发
const showEditDialog = (row) => {
// 深拷贝当前行数据到编辑表单,避免原数据被修改
editForm.value = JSON.parse(JSON.stringify(row))
// 确保数字类型正确,防止表单赋值异常
editForm.value.sortNo = Number(editForm.value.sortNo) || 1
editForm.value.phraseType = Number(editForm.value.phraseType) || 1
// 重置表单验证状态
if (editFormRef.value) {
editFormRef.value.clearValidate()
}
// 打开编辑弹窗
editDialogVisible.value = true
}
// 取消编辑
const handleCancel = () => {
// 退出编辑状态
editingId.value = null
// 清空编辑表单
editForm.value = {}
}
// 保存编辑
const handleSave = async () => {
// 编辑表单提交保存方法
const handleEditSave = async () => {
try {
// 验证表单数据
if (!editForm.value.phraseName || !editForm.value.phraseContent) {
ElMessage.error('请填写完整信息')
return
}
// 名称唯一性校验(排除当前记录)
const nameValidation = validatePhraseName(editForm.value.phraseName, editingId.value)
// 先执行表单验证
const validateResult = await editFormRef.value.validate()
if (!validateResult) return
// 名称唯一性校验排除当前编辑的这条记录ID
const nameValidation = validatePhraseName(editForm.value.phraseName, editForm.value.id)
if (!nameValidation.valid) {
ElMessage.error(nameValidation.message)
return
}
// 准备更新数据
// 准备更新数据修复时间格式为ISO字符串适配后端LocalDateTime
const updateData = {
...editForm.value,
enableFlag: 1 // 确保启用状态
enableFlag: 1,
updateTime: new Date().toISOString() // 前端临时赋值,后端最终以自己的为准
}
// 调用更新接口
const response = await updateDoctorPhrase(updateData)
// 处理更新结果
if (response.code === 200) {
ElMessage.success('更新成功')
// 退出编辑状态
editingId.value = null
// 清空编辑表单
editForm.value = {}
// 重新获取数据以更新界面
editDialogVisible.value = false
// 重新拉取数据,保证列表数据最新
fetchDoctorPhraseList()
} else {
ElMessage.error('更新失败: ' + (response.msg || '未知错误'))
}
} catch (error) {
console.error('更新失败:', error)
ElMessage.error('更新操作失败: 网络请求错误')
}
}
// 组件挂载时获取数据
// 组件挂载时初始化加载数据
onMounted(() => {
fetchDoctorPhraseList()
})
@@ -577,6 +506,10 @@ onMounted(() => {
display: flex;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
/* 适配小屏幕,防止按钮换行溢出 */
gap: 10px;
/* 替换margin-left更优雅的间距 */
}
.pagination-container {
@@ -584,4 +517,9 @@ onMounted(() => {
display: flex;
justify-content: flex-end;
}
/* 新增表单样式适配 */
.add-form {
padding: 10px 0;
}
</style>

View File

@@ -59,12 +59,12 @@ const doRegistering = (row: any) => {
// })
/* 取消 */
const cancelAct = () => {
console.log('121231');
console.log('取消患者列表对话框操作');
}
/* 保存,登记 */
const handleSubmit = () => {
console.log('121231');
console.log('提交患者列表对话框操作');
}
defineExpose({})

View File

@@ -544,7 +544,7 @@ function handleDatePickerChange() {
// 清空
const onClear = () => {
console.log('1111111111');
console.log('费用明细查询条件已清空');
const today = new Date();
dateRangeValue.value = [formatDateStr(today, 'YYYY-MM-DD'), formatDateStr(today, 'YYYY-MM-DD')];

View File

@@ -44,8 +44,8 @@
>
<div class="bed-card__body">
<div>
<div class="bed-card__title" :title="item.houseName + '-' + item.bedName">
{{ item.houseName + '-' + item.bedName }}
<div class="bed-card__title" :title="(item.houseName || '-') + '-' + (item.bedName || '-')">
{{ (item.houseName || '-') + '-' + (item.bedName || '-') }}
</div>
<div class="bed-tag" :class="getBedTagClass(item)">
{{ item.bedStatus_enumText }}
@@ -130,6 +130,8 @@ const initInfoOptions = ref<InitInfoOptions>({
priorityOptions: [],
wardListOptions: [],
});
// 用于处理单击/双击冲突
let clickTimer = null;
let loadingInstance: any = undefined;
// 入院病区loading
const selectHosLoding = ref(true);
@@ -223,29 +225,38 @@ const queryParams = ref<{
bedStatus: '', // 这个字段现在只用于床位查询,不再用于患者列表查询
});
const ininData = () => {
Promise.all([
getInit().then((res) => {
initInfoOptions.value = res.data;
priorityOptions.value = res.data.priorityOptions || [];
return res;
}),
getPractitionerWard().then((res) => {
selectHosLoding.value = false;
queryParams.value.wardId = res[0].id;
initInfoOptions.value.wardListOptions = res;
return changeWardLocationId(res[0].id, true); // 传入 true 表示初始化阶段,不调用 getList
}),
]).then(() => {
const ininData = async () => {
try {
// 先获取初始化数据
const initRes = await getInit();
initInfoOptions.value = initRes.data;
priorityOptions.value = initRes.data.priorityOptions || [];
// 然后获取科室数据
const wardRes = await getPractitionerWard();
selectHosLoding.value = false;
queryParams.value.wardId = wardRes[0]?.id || '';
initInfoOptions.value.wardListOptions = wardRes;
// 获取病房数据
if (wardRes[0]?.id) {
await changeWardLocationId(wardRes[0].id, true); // 传入 true 表示初始化阶段,不调用 getList
}
// 最后获取列表数据
getList();
});
} catch (error) {
console.error('初始化数据失败:', error);
// 即使某个请求失败,也要尝试加载列表
getList();
}
};
onMounted(() => {
ininData();
});
const refreshTap = () => {
ininData();
const refreshTap = async () => {
await ininData();
};
defineExpose({ state, refreshTap });
@@ -257,23 +268,32 @@ const filteredBadList = computed(() => {
return badList.value.filter((item) => item.bedStatus == bedStatusFilter.value);
});
const getList = () => {
const getList = async () => {
loadingInstance = ElLoading.service({ fullscreen: true });
getPatientList();
// 床位查询不使用encounterStatus参数只使用基本的查询参数
const bedQueryParams = {
...queryParams.value,
encounterStatus: undefined, // 移除encounterStatus确保不影响床位列表查询
};
getBedInfo(bedQueryParams).then((res) => {
loadingInstance.close();
badList.value = res.data.records;
});
try {
// 并行获取患者列表和床位列表
const [patientData, bedRes] = await Promise.all([
getPatientList(),
getBedInfo({
...queryParams.value,
encounterStatus: undefined, // 移除encounterStatus确保不影响床位列表查询
})
]);
// 更新床位列表
badList.value = bedRes.data.records;
} catch (error) {
console.error('获取列表数据失败:', error);
} finally {
if (loadingInstance) {
loadingInstance.close();
}
}
};
// 重置查询条件
function resetQuery() {
async function resetQuery() {
// 不重置入院病区
const resetParams = {
...queryParams.value,
@@ -288,7 +308,7 @@ function resetQuery() {
bedStatus: '',
};
bedStatusFilter.value = '';
getList();
await getList();
}
// 入院病区下拉选
function changeWardLocationId(id: string | number, isInit = false) {
@@ -302,45 +322,78 @@ function changeWardLocationId(id: string | number, isInit = false) {
selectHoouseLoding.value = false;
wardLocationList.value = res;
if (!isInit) {
getList();
// 在非初始化情况下,需要同时更新患者列表和床位列表
getPatientList();
// 床位查询不使用encounterStatus参数只使用基本的查询参数
const bedQueryParams = {
...queryParams.value,
encounterStatus: undefined, // 移除encounterStatus确保不影响床位列表查询
};
getBedInfo(bedQueryParams).then((bedRes) => {
badList.value = bedRes.data.records;
});
}
return res;
});
}
// 入院病房下拉选
const onHosHouse = () => {
getList();
const onHosHouse = async () => {
await getList();
};
// 住院状态下拉选
const onHosStatus = () => {
getList();
const onHosStatus = async () => {
await getList();
};
// 获新入院患者列表
function getPatientList() {
async function getPatientList() {
// 为患者列表查询创建一个新的参数对象不包含bedStatus
const patientQueryParams = {
...queryParams.value,
bedStatus: undefined, // 移除bedStatus确保不影响患者列表查询
};
getPendingInfo(patientQueryParams).then((res) => {
try {
const res = await getPendingInfo(patientQueryParams);
loading.value = false;
patientList.value = res.data.records;
total.value = res.data.total;
});
return res;
} catch (error) {
console.error('获取患者列表失败:', error);
throw error;
}
}
const handleTransferInOk = () => {
const handleTransferInOk = async () => {
transferInDialogVisible.value = false;
getList();
await getList();
};
function handleCardClick(item: any, index: number) {}
// 单击患者卡片事件 - 直接触发入科选床界面
function handleCardClick(item: any, index: number) {
if (item.encounterStatus == 2) {
// 显示提示信息,指导用户如何分配床位
ElMessage({
message: '该患者尚未分配病床,请通过拖拽操作将患者分配到右侧床位',
type: 'warning',
grouping: true,
showClose: true,
});
} else {
pendingInfo.value = {
...item,
entranceType: 1,
};
// 双击患者卡片事件
transferInDialogVisible.value = true;
}
}
// 双击患者卡片事件 - 保持原有逻辑
function handleCardDblClick(item: any) {
if (item.encounterStatus == 2) {
// 显示提示信息,指导用户如何分配床位
ElMessage({
message: '请分配病床!',
message: '该患者尚未分配病床,请通过拖拽操作将患者分配到右侧床位',
type: 'warning',
grouping: true,
showClose: true,
@@ -367,8 +420,8 @@ function handleDragStart(event: DragEvent, item: any) {
}
}
function handleQuery() {
getList();
async function handleQuery() {
await getList();
}
// 拖拽结束事件

View File

@@ -17,7 +17,7 @@
<div class="patient-info">
<div style="display: flex; align-items: center; margin-bottom: 16px">
<div style="margin-right: 36px; font-size: 18px; font-weight: 700">
{{ props.pendingInfo.houseName + '-' + props.pendingInfo.bedName }}
{{ (props.pendingInfo.houseName || '-') + '-' + (props.pendingInfo.bedName || '-') }}
</div>
<div style="border-radius: 50px; border: 2px solid slategray; padding: 4px 12px">
{{ props.pendingInfo.contractName }}

View File

@@ -746,25 +746,42 @@ function handleGetDRMedication() {
});
}
const initData = () => {
getInit().then((res) => {
initInfoOptions.value = res.data;
const initData = async () => {
try {
// 并行获取初始化数据和科室数据
const [initRes, wardRes] = await Promise.all([
getInit(),
getPractitionerWard()
]);
// 处理初始化数据
initInfoOptions.value = initRes.data;
// 处理科室数据
queryParams.value.wardId = wardRes[0]?.id || '';
initInfoOptions.value.wardListOptions = wardRes;
// 获取病房数据
if (wardRes[0]?.id) {
changeWardLocationId(wardRes[0].id);
}
// 最后获取患者列表
getPatientList();
});
getPractitionerWard().then((res) => {
queryParams.value.wardId = res[0].id;
initInfoOptions.value.wardListOptions = res;
changeWardLocationId(res[0].id);
});
} catch (error) {
console.error('初始化数据失败:', error);
// 即使初始化失败,也要尝试加载患者列表
getPatientList();
}
};
// 初始化加载患者列表
onMounted(() => {
initData();
onMounted(async () => {
await initData();
});
const refreshTap = () => {
console.log('22222223');
initData();
const refreshTap = async () => {
console.log('刷新转科/出院页面数据');
await initData();
};
defineExpose({ refreshTap });
</script>

View File

@@ -44,16 +44,15 @@ const thirdRef = ref();
onBeforeMount(() => {});
onMounted(() => {});
defineExpose({ state });
const test = () => {
nextTick(() => {
if (activeTabName.value == 'first') {
firstRef?.value?.refreshTap();
} else if (activeTabName.value == 'second') {
secondRef?.value?.refreshTap();
} else if (activeTabName.value == 'third') {
thirdRef?.value?.refreshTap();
}
});
const test = async () => {
await nextTick();
if (activeTabName.value == 'first') {
await firstRef?.value?.refreshTap();
} else if (activeTabName.value == 'second') {
await secondRef?.value?.refreshTap();
} else if (activeTabName.value == 'third') {
await thirdRef?.value?.refreshTap();
}
};
const activeTabName = ref('first');

View File

@@ -496,7 +496,7 @@ const dateChange = () => {
};
// 计算时间
rulesFrom.value.recordTime = computed(() => {
console.log('11111111111111');
console.log('操作记录时间计算', rulesFrom.value.date + ' ' + rulesFrom.value.time);
return rulesFrom.value.date + ' ' + rulesFrom.value.time;
});

View File

@@ -274,7 +274,7 @@ function init1(data) {
* 点击患者列表行 获取患者体温单数据
*/
function viewPatient(row) {
console.log('1232312123221231');
console.log('查看患者体温单数据', row.patientName);
patientInfo.value = row;
console.log('点击患者列表行 获取患者体温单数据', row);

View File

@@ -557,7 +557,7 @@ watch(
queryParams.value.dispenseTimeETime = newQuery.occurrenceTimeETime + ' 23:59:59';
}
queryParams.value.flag = 1;
console.log('11111111111111');
console.log('药品明细查询参数已设置完成');
// 执行查询
getList();

View File

@@ -218,7 +218,7 @@ watch(
if (currentMonth < birthMonth || (currentMonth === birthMonth && currentDay < birthDay)) {
age--;
}
console.log('22222222');
console.log('计算患者年龄完成:', age);
form.value.age = age;
}

View File

@@ -1,55 +1,23 @@
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryRef"
:inline="true"
v-show="showSearch"
label-width="68px"
class="query-form"
>
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px"
class="query-form">
<el-form-item label="字典名称" prop="dictName">
<el-input
v-model="queryParams.dictName"
placeholder="请输入字典名称"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.dictName" placeholder="请输入字典名称" clearable style="width: 240px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="字典类型" prop="dictType">
<el-input
v-model="queryParams.dictType"
placeholder="请输入字典类型"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.dictType" placeholder="请输入字典类型" clearable style="width: 240px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="字典状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-select v-model="queryParams.status" placeholder="字典状态" clearable style="width: 240px">
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-date-picker v-model="dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item class="search-buttons">
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -59,76 +27,34 @@
<el-row :gutter="10" class="button-group">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['system:dict:add']"
>新增</el-button
>
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:dict:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:dict:edit']"
>修改</el-button
>
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
v-hasPermi="['system:dict:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:dict:remove']"
>删除</el-button
>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
v-hasPermi="['system:dict:remove']">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['system:dict:export']"
>导出</el-button
>
<el-button type="warning" plain icon="Download" @click="handleExport"
v-hasPermi="['system:dict:export']">导出</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Refresh"
@click="handleRefreshCache"
v-hasPermi="['system:dict:remove']"
>刷新缓存</el-button
>
<el-button type="danger" plain icon="Refresh" @click="handleRefreshCache"
v-hasPermi="['system:dict:remove']">刷新缓存</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<div class="table-wrapper">
<el-table
v-loading="loading"
:data="typeList"
@selection-change="handleSelectionChange"
>
<el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="字典编号" align="center" prop="dictId" />
<el-table-column
label="字典名称"
align="center"
prop="dictName"
:show-overflow-tooltip="true"
/>
<el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />
<el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
<template #default="scope">
<router-link :to="'/system/dict-data/index/' + scope.row.dictId" class="link-type">
<router-link :to="'/system/dict/data/' + scope.row.dictId" class="link-type">
<span>{{ scope.row.dictType }}</span>
</router-link>
</template>
@@ -144,40 +70,18 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
width="160"
class-name="small-padding fixed-width"
>
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template #default="scope">
<el-button
link
type="primary"
icon="Edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:dict:edit']"
class="action-button">修改</el-button
>
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:dict:remove']"
class="action-button">删除</el-button
>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['system:dict:edit']" class="action-button">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['system:dict:remove']" class="action-button">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="getList" />
</div>
</div>
@@ -213,7 +117,7 @@
<script setup name="Dict">
import useDictStore from '@/store/modules/dict';
import {addType, delType, getType, listType, refreshCache, updateType,} from '@/api/system/dict/type';
import { addType, delType, getType, listType, refreshCache, updateType, } from '@/api/system/dict/type';
const { proxy } = getCurrentInstance();
const { sys_normal_disable } = proxy.useDict('sys_normal_disable');
@@ -291,7 +195,7 @@ function handleAdd() {
/** 多选框选中数据 */
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.dictId);
single.value = selection.length != 1;
single.value = selection.length !== 1;
multiple.value = !selection.length;
}
/** 修改按钮操作 */
@@ -308,14 +212,14 @@ function handleUpdate(row) {
function submitForm() {
proxy.$refs['dictRef'].validate((valid) => {
if (valid) {
if (form.value.dictId != undefined) {
updateType(form.value).then((response) => {
if (form.value.dictId !== undefined) {
updateType(form.value).then(() => {
proxy.$modal.msgSuccess('修改成功');
open.value = false;
getList();
});
} else {
addType(form.value).then((response) => {
addType(form.value).then(() => {
proxy.$modal.msgSuccess('新增成功');
open.value = false;
getList();
@@ -336,7 +240,7 @@ function handleDelete(row) {
getList();
proxy.$modal.msgSuccess('删除成功');
})
.catch(() => {});
.catch(() => { });
}
/** 导出按钮操作 */
function handleExport() {

View File

@@ -0,0 +1,112 @@
<template>
<div class="app-container">
<h4 class="form-header h4">基本信息</h4>
<el-form :model="form" label-width="80px">
<el-row>
<el-col :span="8" :offset="2">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" disabled />
</el-form-item>
</el-col>
<el-col :span="8" :offset="2">
<el-form-item label="登录账号" prop="userName">
<el-input v-model="form.userName" disabled />
</el-form-item>
</el-col>
</el-row>
</el-form>
<h4 class="form-header h4">角色信息</h4>
<el-table v-loading="loading" :row-key="getRowKey" @row-click="clickRow" ref="roleRef" @selection-change="handleSelectionChange" :data="roles.slice((pageNum - 1) * pageSize, pageNum * pageSize)">
<el-table-column label="序号" width="55" type="index" align="center">
<template #default="scope">
<span>{{ (pageNum - 1) * pageSize + scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column>
<el-table-column label="角色编号" align="center" prop="roleId" />
<el-table-column label="角色名称" align="center" prop="roleName" />
<el-table-column label="权限字符" align="center" prop="roleKey" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="pageNum" v-model:limit="pageSize" />
<el-form label-width="100px">
<div style="text-align: center;margin-left:-120px;margin-top:30px;">
<el-button type="primary" @click="submitForm()">提交</el-button>
<el-button @click="close()">返回</el-button>
</div>
</el-form>
</div>
</template>
<script setup name="AuthRole">
import {getAuthRole, updateAuthRole} from "@/api/system/user copy";
const route = useRoute();
const { proxy } = getCurrentInstance();
const loading = ref(true);
const total = ref(0);
const pageNum = ref(1);
const pageSize = ref(10);
const roleIds = ref([]);
const roles = ref([]);
const form = ref({
nickName: undefined,
userName: undefined,
userId: undefined
});
/** 单击选中行数据 */
function clickRow(row) {
proxy.$refs["roleRef"].toggleRowSelection(row);
};
/** 多选框选中数据 */
function handleSelectionChange(selection) {
roleIds.value = selection.map(item => item.roleId);
};
/** 保存选中的数据编号 */
function getRowKey(row) {
return row.roleId;
};
/** 关闭按钮 */
function close() {
const obj = { path: "/system/user" };
proxy.$tab.closeOpenPage(obj);
};
/** 提交按钮 */
function submitForm() {
const userId = form.value.userId;
const rIds = roleIds.value.join(",");
updateAuthRole({ userId: userId, roleIds: rIds }).then(response => {
proxy.$modal.msgSuccess("授权成功");
close();
});
};
(() => {
const userId = route.params && route.params.userId;
if (userId) {
loading.value = true;
getAuthRole(userId).then(response => {
form.value = response.user;
roles.value = response.roles;
total.value = roles.value.length;
nextTick(() => {
roles.value.forEach(row => {
if (row.flag) {
proxy.$refs["roleRef"].toggleRowSelection(row);
}
});
});
loading.value = false;
});
}
})();
</script>

View File

@@ -0,0 +1,621 @@
<template>
<div class="app-container">
<el-row :gutter="20">
<!--部门数据-->
<el-col :span="4" :xs="24">
<div class="head-container">
<el-input
v-model="deptName"
placeholder="请输入部门名称"
clearable
prefix-icon="Search"
style="margin-bottom: 20px"
/>
</div>
<div class="head-container">
<el-tree
:data="deptOptions"
:props="{ label: 'label', children: 'children' }"
:expand-on-click-node="false"
:filter-node-method="filterNode"
ref="deptTreeRef"
node-key="id"
highlight-current
default-expand-all
@node-click="handleNodeClick"
/>
</div>
</el-col>
<!--用户数据-->
<el-col :span="20" :xs="24">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="用户状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" style="width: 308px;">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['system:user:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:user:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:user:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="Upload"
@click="handleImport"
v-hasPermi="['system:user:import']"
>导入</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['system:user:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
<el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
<el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
<el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
<template #default="scope">
<el-switch
v-model="scope.row.status"
active-value="0"
inactive-value="1"
@change="handleStatusChange(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="150" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top" v-if="scope.row.userId !== 1">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:user:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top" v-if="scope.row.userId !== 1">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']"></el-button>
</el-tooltip>
<el-tooltip content="重置密码" placement="top" v-if="scope.row.userId !== 1">
<el-button link type="primary" icon="Key" @click="handleResetPwd(scope.row)" v-hasPermi="['system:user:resetPwd']"></el-button>
</el-tooltip>
<el-tooltip content="分配角色" placement="top" v-if="scope.row.userId !== 1">
<el-button link type="primary" icon="CircleCheck" @click="handleAuthRole(scope.row)" v-hasPermi="['system:user:edit']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-col>
</el-row>
<!-- 添加或修改用户配置对话框 -->
<el-dialog :title="title" v-model="open" width="600px" append-to-body>
<el-form :model="form" :rules="rules" ref="userRef" label-width="80px">
<el-row>
<el-col :span="12">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="归属部门" prop="deptId">
<el-tree-select
v-model="form.deptId"
:data="deptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
value-key="id"
placeholder="请选择归属部门"
check-strictly
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
<el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="用户性别">
<el-select v-model="form.sex" placeholder="请选择">
<el-option
v-for="dict in sys_user_sex"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="岗位">
<el-select v-model="form.postIds" multiple placeholder="请选择">
<el-option
v-for="item in postOptions"
:key="item.postId"
:label="item.postName"
:value="item.postId"
:disabled="item.status == 1"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="角色">
<el-select v-model="form.roleIds" multiple placeholder="请选择">
<el-option
v-for="item in roleOptions"
:key="item.roleId"
:label="item.roleName"
:value="item.roleId"
:disabled="item.status == 1"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<!-- 用户导入对话框 -->
<el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
<el-upload
ref="uploadRef"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip text-center">
<div class="el-upload__tip">
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
</div>
<span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
</div>
</template>
</el-upload>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="User">
import {getToken} from "@/utils/auth";
import {
addUser,
changeUserStatus,
delUser,
deptTreeSelect,
getUser,
listUser,
resetUserPwd,
updateUser
} from "@/api/system/user copy";
const router = useRouter();
const { proxy } = getCurrentInstance();
const { sys_normal_disable, sys_user_sex } = proxy.useDict("sys_normal_disable", "sys_user_sex");
const userList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const dateRange = ref([]);
const deptName = ref("");
const deptOptions = ref(undefined);
const initPassword = ref(undefined);
const postOptions = ref([]);
const roleOptions = ref([]);
/*** 用户导入参数 */
const upload = reactive({
// 是否显示弹出层(用户导入)
open: false,
// 弹出层标题(用户导入)
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: "Bearer " + getToken() },
// 上传的地址
url: import.meta.env.VITE_APP_BASE_API + "/system/user/importData"
});
// 列显隐信息
const columns = ref([
{ key: 0, label: `用户编号`, visible: true },
{ key: 1, label: `用户名称`, visible: true },
{ key: 2, label: `用户昵称`, visible: true },
{ key: 3, label: `部门`, visible: true },
{ key: 4, label: `手机号码`, visible: true },
{ key: 5, label: `状态`, visible: true },
{ key: 6, label: `创建时间`, visible: true }
]);
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
phonenumber: undefined,
status: undefined,
deptId: undefined
},
rules: {
userName: [{ required: true, message: "用户名称不能为空", trigger: "blur" }, { min: 2, max: 20, message: "用户名称长度必须介于 2 和 20 之间", trigger: "blur" }],
nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
password: [{ required: true, message: "用户密码不能为空", trigger: "blur" }, { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" }, { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }],
email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
phonenumber: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 通过条件过滤节点 */
const filterNode = (value, data) => {
if (!value) return true;
return data.label.indexOf(value) !== -1;
};
/** 根据名称筛选部门树 */
watch(deptName, val => {
proxy.$refs["deptTreeRef"].filter(val);
});
/** 查询部门下拉树结构 */
function getDeptTree() {
deptTreeSelect().then(response => {
deptOptions.value = response.data;
});
};
/** 查询用户列表 */
function getList() {
loading.value = true;
listUser(proxy.addDateRange(queryParams.value, dateRange.value)).then(res => {
loading.value = false;
userList.value = res.rows;
total.value = res.total;
});
};
/** 节点单击事件 */
function handleNodeClick(data) {
queryParams.value.deptId = data.id;
handleQuery();
};
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
};
/** 重置按钮操作 */
function resetQuery() {
dateRange.value = [];
proxy.resetForm("queryRef");
queryParams.value.deptId = undefined;
proxy.$refs.deptTreeRef.setCurrentKey(null);
handleQuery();
};
/** 删除按钮操作 */
function handleDelete(row) {
const userIds = row.userId || ids.value;
proxy.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?').then(function () {
return delUser(userIds);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => {});
};
/** 导出按钮操作 */
function handleExport() {
proxy.download("system/user/export", {
...queryParams.value,
},`user_${new Date().getTime()}.xlsx`);
};
/** 用户状态修改 */
function handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用";
proxy.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?').then(function () {
return changeUserStatus(row.userId, row.status);
}).then(() => {
proxy.$modal.msgSuccess(text + "成功");
}).catch(function () {
row.status = row.status === "0" ? "1" : "0";
});
};
/** 更多操作 */
function handleCommand(command, row) {
switch (command) {
case "handleResetPwd":
handleResetPwd(row);
break;
case "handleAuthRole":
handleAuthRole(row);
break;
default:
break;
}
};
/** 跳转角色分配 */
function handleAuthRole(row) {
const userId = row.userId;
router.push("/system/user-auth/role/" + userId);
};
/** 重置密码按钮操作 */
function handleResetPwd(row) {
proxy.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return "不能包含非法字符:< > \" ' \\\ |"
}
},
}).then(({ value }) => {
resetUserPwd(row.userId, value).then(response => {
proxy.$modal.msgSuccess("修改成功,新密码是:" + value);
});
}).catch(() => {});
};
/** 选择条数 */
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.userId);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
/** 导入按钮操作 */
function handleImport() {
upload.title = "用户导入";
upload.open = true;
};
/** 下载模板操作 */
function importTemplate() {
proxy.download("system/user/importTemplate", {
}, `user_template_${new Date().getTime()}.xlsx`);
};
/**文件上传中处理 */
const handleFileUploadProgress = (event, file, fileList) => {
upload.isUploading = true;
};
/** 文件上传成功处理 */
const handleFileSuccess = (response, file, fileList) => {
upload.open = false;
upload.isUploading = false;
proxy.$refs["uploadRef"].handleRemove(file);
proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
getList();
};
/** 提交上传文件 */
function submitFileForm() {
proxy.$refs["uploadRef"].submit();
};
/** 重置操作表单 */
function reset() {
form.value = {
userId: undefined,
deptId: undefined,
userName: undefined,
nickName: undefined,
password: undefined,
phonenumber: undefined,
email: undefined,
sex: undefined,
status: "0",
remark: undefined,
postIds: [],
roleIds: []
};
proxy.resetForm("userRef");
};
/** 取消按钮 */
function cancel() {
open.value = false;
reset();
};
/** 新增按钮操作 */
function handleAdd() {
reset();
getUser().then(response => {
postOptions.value = response.posts;
roleOptions.value = response.roles;
open.value = true;
title.value = "添加用户";
form.value.password = initPassword.value;
});
};
/** 修改按钮操作 */
function handleUpdate(row) {
reset();
const userId = row.userId || ids.value;
getUser(userId).then(response => {
form.value = response.data;
postOptions.value = response.posts;
roleOptions.value = response.roles;
form.value.postIds = response.postIds;
form.value.roleIds = response.roleIds;
open.value = true;
title.value = "修改用户";
form.password = "";
});
};
/** 提交按钮 */
function submitForm() {
proxy.$refs["userRef"].validate(valid => {
if (valid) {
if (form.value.userId != undefined) {
updateUser(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功");
open.value = false;
getList();
});
} else {
addUser(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功");
open.value = false;
getList();
});
}
}
});
};
getDeptTree();
getList();
</script>

View File

@@ -0,0 +1,87 @@
<template>
<div class="app-container">
<el-row :gutter="20">
<el-col :span="6" :xs="24">
<el-card class="box-card">
<template v-slot:header>
<div class="clearfix">
<span>个人信息</span>
</div>
</template>
<div>
<div class="text-center">
<userAvatar />
</div>
<ul class="list-group list-group-striped">
<li class="list-group-item">
<svg-icon icon-class="user" />用户名称
<div class="pull-right">{{ state.user.userName }}</div>
</li>
<li class="list-group-item">
<svg-icon icon-class="phone" />手机号码
<div class="pull-right">{{ state.user.phonenumber }}</div>
</li>
<li class="list-group-item">
<svg-icon icon-class="email" />用户邮箱
<div class="pull-right">{{ state.user.email }}</div>
</li>
<li class="list-group-item">
<svg-icon icon-class="tree" />所属部门
<div class="pull-right" v-if="state.user.dept">{{ state.user.dept.deptName }} / {{ state.postGroup }}</div>
</li>
<li class="list-group-item">
<svg-icon icon-class="peoples" />所属角色
<div class="pull-right">{{ state.roleGroup }}</div>
</li>
<li class="list-group-item">
<svg-icon icon-class="date" />创建日期
<div class="pull-right">{{ state.user.createTime }}</div>
</li>
</ul>
</div>
</el-card>
</el-col>
<el-col :span="18" :xs="24">
<el-card>
<template v-slot:header>
<div class="clearfix">
<span>基本资料</span>
</div>
</template>
<el-tabs v-model="activeTab">
<el-tab-pane label="基本资料" name="userinfo">
<userInfo :user="state.user" />
</el-tab-pane>
<el-tab-pane label="修改密码" name="resetPwd">
<resetPwd />
</el-tab-pane>
</el-tabs>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup name="Profile">
import userAvatar from "./userAvatar";
import userInfo from "./userInfo";
import resetPwd from "./resetPwd";
import {getUserProfile} from "@/api/system/user copy";
const activeTab = ref("userinfo");
const state = reactive({
user: {},
roleGroup: {},
postGroup: {}
});
function getUser() {
getUserProfile().then(response => {
state.user = response.data;
state.roleGroup = response.roleGroup;
state.postGroup = response.postGroup;
});
};
getUser();
</script>

View File

@@ -0,0 +1,65 @@
<!--
* @Author: 徐靖博 xujb@ccjb.com.cn
* @Date: 2025-03-26 10:49:30
* @LastEditTime: 2025-03-26 13:57:02
* @LastEditors: 徐靖博 xujb@ccjb.com.cn
* @Description:
* @FilePath: \openhis-ui-vue3\src\views\system\user copy\profile\resetPwd.vue
-->
<template>
<el-form ref="pwdRef" :model="user" :rules="rules" label-width="80px">
<el-form-item label="旧密码" prop="oldPassword">
<el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password />
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password />
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submit">保存</el-button>
<el-button type="danger" @click="close">关闭</el-button>
</el-form-item>
</el-form>
</template>
<script setup>
import {updateUserPwd} from "@/api/system/user copy";
const { proxy } = getCurrentInstance();
const user = reactive({
oldPassword: undefined,
newPassword: undefined,
confirmPassword: undefined
});
const equalToPassword = (rule, value, callback) => {
if (user.newPassword !== value) {
callback(new Error("两次输入的密码不一致"));
} else {
callback();
}
};
const rules = ref({
oldPassword: [{ required: true, message: "旧密码不能为空", trigger: "blur" }],
newPassword: [{ required: true, message: "新密码不能为空", trigger: "blur" }, { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }, { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }],
confirmPassword: [{ required: true, message: "确认密码不能为空", trigger: "blur" }, { required: true, validator: equalToPassword, trigger: "blur" }]
});
/** 提交按钮 */
function submit() {
proxy.$refs.pwdRef.validate(valid => {
if (valid) {
updateUserPwd(user.oldPassword, user.newPassword).then(response => {
proxy.$modal.msgSuccess("修改成功");
});
}
});
};
/** 关闭按钮 */
function close() {
proxy.$tab.closePage();
};
</script>

View File

@@ -0,0 +1,171 @@
<template>
<div class="user-info-head" @click="editCropper()">
<img :src="options.img" title="点击上传头像" class="img-circle img-lg" />
<el-dialog :title="title" v-model="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog">
<el-row>
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
<vue-cropper
ref="cropper"
:img="options.img"
:info="true"
:autoCrop="options.autoCrop"
:autoCropWidth="options.autoCropWidth"
:autoCropHeight="options.autoCropHeight"
:fixedBox="options.fixedBox"
:outputType="options.outputType"
@realTime="realTime"
v-if="visible"
/>
</el-col>
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
<div class="avatar-upload-preview">
<img :src="options.previews.url" :style="options.previews.img" />
</div>
</el-col>
</el-row>
<br />
<el-row>
<el-col :lg="2" :md="2">
<el-upload
action="#"
:http-request="requestUpload"
:show-file-list="false"
:before-upload="beforeUpload"
>
<el-button>
选择
<el-icon class="el-icon--right"><Upload /></el-icon>
</el-button>
</el-upload>
</el-col>
<el-col :lg="{ span: 1, offset: 2 }" :md="2">
<el-button icon="Plus" @click="changeScale(1)"></el-button>
</el-col>
<el-col :lg="{ span: 1, offset: 1 }" :md="2">
<el-button icon="Minus" @click="changeScale(-1)"></el-button>
</el-col>
<el-col :lg="{ span: 1, offset: 1 }" :md="2">
<el-button icon="RefreshLeft" @click="rotateLeft()"></el-button>
</el-col>
<el-col :lg="{ span: 1, offset: 1 }" :md="2">
<el-button icon="RefreshRight" @click="rotateRight()"></el-button>
</el-col>
<el-col :lg="{ span: 2, offset: 6 }" :md="2">
<el-button type="primary" @click="uploadImg()"> </el-button>
</el-col>
</el-row>
</el-dialog>
</div>
</template>
<script setup>
import "vue-cropper/dist/index.css";
import {VueCropper} from "vue-cropper";
import {uploadAvatar} from "@/api/system/user copy";
import useUserStore from "@/store/modules/user";
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
const open = ref(false);
const visible = ref(false);
const title = ref("修改头像");
//图片裁剪数据
const options = reactive({
img: userStore.avatar, // 裁剪图片的地址
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 200, // 默认生成截图框宽度
autoCropHeight: 200, // 默认生成截图框高度
fixedBox: true, // 固定截图框大小 不允许改变
outputType: "png", // 默认生成截图为PNG格式
filename: 'avatar', // 文件名称
previews: {} //预览数据
});
/** 编辑头像 */
function editCropper() {
open.value = true;
}
/** 打开弹出层结束时的回调 */
function modalOpened() {
visible.value = true;
}
/** 覆盖默认上传行为 */
function requestUpload() {}
/** 向左旋转 */
function rotateLeft() {
proxy.$refs.cropper.rotateLeft();
}
/** 向右旋转 */
function rotateRight() {
proxy.$refs.cropper.rotateRight();
}
/** 图片缩放 */
function changeScale(num) {
num = num || 1;
proxy.$refs.cropper.changeScale(num);
}
/** 上传预处理 */
function beforeUpload(file) {
if (file.type.indexOf("image/") == -1) {
proxy.$modal.msgError("文件格式错误,请上传图片类型,如JPGPNG后缀的文件。");
} else {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
options.img = reader.result;
options.filename = file.name;
};
}
}
/** 上传图片 */
function uploadImg() {
proxy.$refs.cropper.getCropBlob(data => {
let formData = new FormData();
formData.append("avatarfile", data, options.filename);
uploadAvatar(formData).then(response => {
open.value = false;
options.img = import.meta.env.VITE_APP_BASE_API + response.imgUrl;
userStore.avatar = options.img;
proxy.$modal.msgSuccess("修改成功");
visible.value = false;
});
});
}
/** 实时预览 */
function realTime(data) {
options.previews = data;
}
/** 关闭窗口 */
function closeDialog() {
options.img = userStore.avatar;
options.visible = false;
}
</script>
<style lang='scss' scoped>
.user-info-head {
position: relative;
display: inline-block;
height: 120px;
}
.user-info-head:hover:after {
content: "+";
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
color: #eee;
background: rgba(0, 0, 0, 0.5);
font-size: 24px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
cursor: pointer;
line-height: 110px;
border-radius: 50%;
}
</style>

View File

@@ -0,0 +1,67 @@
<template>
<el-form ref="userRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" maxlength="30" />
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="form.phonenumber" maxlength="11" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" maxlength="50" />
</el-form-item>
<el-form-item label="性别">
<el-radio-group v-model="form.sex">
<el-radio label="0"></el-radio>
<el-radio label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submit">保存</el-button>
<el-button type="danger" @click="close">关闭</el-button>
</el-form-item>
</el-form>
</template>
<script setup>
import {updateUserProfile} from "@/api/system/user copy";
const props = defineProps({
user: {
type: Object
}
});
const { proxy } = getCurrentInstance();
const form = ref({});
const rules = ref({
nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
email: [{ required: true, message: "邮箱地址不能为空", trigger: "blur" }, { type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
phonenumber: [{ required: true, message: "手机号码不能为空", trigger: "blur" }, { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }],
});
/** 提交按钮 */
function submit() {
proxy.$refs.userRef.validate(valid => {
if (valid) {
updateUserProfile(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功");
props.user.phonenumber = form.value.phonenumber;
props.user.email = form.value.email;
});
}
});
};
/** 关闭按钮 */
function close() {
proxy.$tab.closePage();
};
// 回显当前登录用户信息
watch(() => props.user, user => {
if (user) {
form.value = { nickName: user.nickName, phonenumber: user.phonenumber, email: user.email, sex: user.sex };
}
},{ immediate: true });
</script>

View File

@@ -27,42 +27,49 @@ export function updateCallNumberVoiceConfig(data) {
}
// 分诊排队管理相关API
// 获取智能候选池(已签到未入队)
// 说明:直接使用门诊挂号的"当日已挂号"接口
// 获取智能候选池(使用门诊挂号当日已挂号接口)
export function getCandidatePool(params) {
return request({
url: '/triage/queue/candidatePool',
url: '/charge-manage/register/current-day-encounter',
method: 'get',
params: params,
params: {
pageNo: params?.pageNo || 1,
pageSize: params?.pageSize || 10000,
searchKey: params?.searchKey || '',
statusEnum: params?.statusEnum || -1 // -1表示排除退号记录正常挂号
},
skipErrorMsg: true // 跳过错误提示,由组件处理
}).catch(() => {
// 返回一个 rejected promise让组件可以捕获
return Promise.reject(new Error('API未实现'))
})
}
// 获取智能队列(当前队列
// 获取智能队列(使用门诊挂号当日已挂号接口
export function getQueueList(params) {
return request({
url: '/triage/queue/list',
url: '/charge-manage/register/current-day-encounter',
method: 'get',
params: params,
params: {
pageNo: params?.pageNo || 1,
pageSize: params?.pageSize || 10000,
searchKey: params?.searchKey || '',
statusEnum: params?.statusEnum || -1 // -1表示排除退号记录正常挂号
},
skipErrorMsg: true // 跳过错误提示,由组件处理
}).catch(() => {
// 返回一个 rejected promise让组件可以捕获
return Promise.reject(new Error('API未实现'))
})
}
// 获取统计信息
// 获取统计信息(使用门诊挂号当日已挂号接口统计)
export function getQueueStatistics(params) {
return request({
url: '/triage/queue/statistics',
url: '/charge-manage/register/current-day-encounter',
method: 'get',
params: params,
params: {
pageNo: 1,
pageSize: 10000,
searchKey: params?.searchKey || '',
statusEnum: params?.statusEnum || -1
},
skipErrorMsg: true // 跳过错误提示,由组件处理
}).catch(() => {
// 返回一个 rejected promise让组件可以捕获
return Promise.reject(new Error('API未实现'))
})
}
@@ -73,7 +80,26 @@ export function addToQueue(data) {
method: 'post',
data: data,
skipErrorMsg: true
}).catch(() => Promise.reject(new Error('API未实现')))
})
}
// 获取队列列表(从数据库读取)
export function getTriageQueueList(params) {
return request({
url: '/triage/queue/list',
method: 'get',
params: params,
skipErrorMsg: true
})
}
// 移出队列
export function removeFromQueue(id) {
return request({
url: `/triage/queue/remove/${id}`,
method: 'delete',
skipErrorMsg: true
})
}
// 调整队列顺序
@@ -83,7 +109,7 @@ export function adjustQueueOrder(data) {
method: 'put',
data: data,
skipErrorMsg: true
}).catch(() => Promise.reject(new Error('API未实现')))
})
}
// 叫号控制
@@ -93,7 +119,7 @@ export function callPatient(data) {
method: 'post',
data: data,
skipErrorMsg: true
}).catch(() => Promise.reject(new Error('API未实现')))
})
}
// 跳过患者
@@ -103,7 +129,7 @@ export function skipPatient(data) {
method: 'post',
data: data,
skipErrorMsg: true
}).catch(() => Promise.reject(new Error('API未实现')))
})
}
// 完成叫号
@@ -113,7 +139,7 @@ export function completeCall(data) {
method: 'post',
data: data,
skipErrorMsg: true
}).catch(() => Promise.reject(new Error('API未实现')))
})
}
// 过号重排
@@ -123,5 +149,24 @@ export function requeuePatient(data) {
method: 'post',
data: data,
skipErrorMsg: true
}).catch(() => Promise.reject(new Error('API未实现')))
})
}
// 下一患者
export function nextPatient(data) {
return request({
url: '/triage/queue/next',
method: 'post',
data: data,
skipErrorMsg: true
})
}
// 查询就诊科室列表(从门诊挂号模块复用)
export function getLocationTree(query) {
return request({
url: '/charge-manage/register/org-list',
method: 'get',
params: query
})
}

View File

@@ -0,0 +1,25 @@
// 测试util._extend是否存在
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
try {
const util = require('util');
console.log('util._extend存在吗', typeof util._extend);
if (typeof util._extend === 'function') {
console.log('util._extend是一个函数');
} else {
console.log('util._extend不是一个函数添加兼容实现');
util._extend = function(destination, source) {
for (var key in source) {
if (source.hasOwnProperty(key)) {
destination[key] = source[key];
}
}
return destination;
};
console.log('兼容实现添加成功');
}
} catch (e) {
console.error('util模块加载失败:', e);
}
} else {
console.log('不在Node.js环境中');
}