feat(menu): 优化菜单服务性能并新增医生排班功能
- 添加菜单缓存注解以提升查询性能 - 实现菜单完整路径计算优化,解决 N+1 查询问题 - 新增 selectAllMenus 方法供路径计算使用 - 添加今日医生排班查询功能 - 重构前端图标显示逻辑,使用 SVG 图标替代 Element 图标 - 添加前端菜单数据本地缓存机制 - 更新菜单管理界面的表单组件绑定方式 - 新增预约管理、门诊管理和药房管理路由配置
This commit is contained in:
43
openhis-ui-vue3/src/api/appointmentmanage/doctorSchedule.js
Normal file
43
openhis-ui-vue3/src/api/appointmentmanage/doctorSchedule.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取今日医生排班列表
|
||||
export function getTodayDoctorScheduleList() {
|
||||
return request({
|
||||
url: '/doctor-schedule/today',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取医生排班列表
|
||||
export function getDoctorScheduleList() {
|
||||
return request({
|
||||
url: '/appointment/doctor-schedule/list',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 添加医生排班
|
||||
export function addDoctorSchedule(data) {
|
||||
return request({
|
||||
url: '/appointment/doctor-schedule',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新医生排班
|
||||
export function updateDoctorSchedule(data) {
|
||||
return request({
|
||||
url: '/appointment/doctor-schedule',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除医生排班
|
||||
export function deleteDoctorSchedule(id) {
|
||||
return request({
|
||||
url: '/appointment/doctor-schedule/delete/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询日结结算单列表
|
||||
export function listDayEndSettlement(query) {
|
||||
return request({
|
||||
url: '/medication/dayEndSettlement/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询日结结算单详细
|
||||
export function getDayEndSettlement(settlementId) {
|
||||
return request({
|
||||
url: '/medication/dayEndSettlement/' + settlementId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增日结结算单
|
||||
export function addDayEndSettlement(data) {
|
||||
return request({
|
||||
url: '/medication/dayEndSettlement',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改日结结算单
|
||||
export function updateDayEndSettlement(data) {
|
||||
return request({
|
||||
url: '/medication/dayEndSettlement',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除日结结算单
|
||||
export function delDayEndSettlement(settlementId) {
|
||||
return request({
|
||||
url: '/medication/dayEndSettlement/' + settlementId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
@@ -286,6 +286,48 @@ export const dynamicRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/appoinmentmanage',
|
||||
component: Layout,
|
||||
name: 'AppoinmentManage',
|
||||
meta: { title: '预约管理', icon: 'appointment' },
|
||||
children: [
|
||||
{
|
||||
path: 'deptManage',
|
||||
component: () => import('@/views/appoinmentmanage/deptManage/index.vue'),
|
||||
name: 'DeptManage',
|
||||
meta: { title: '科室排班管理', icon: 'calendar' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/clinicmanagement',
|
||||
component: Layout,
|
||||
name: 'ClinicManagement',
|
||||
meta: { title: '门诊管理', icon: 'operation' },
|
||||
children: [
|
||||
{
|
||||
path: 'dayEnd',
|
||||
component: () => import('@/views/clinicmanagement/dayEnd/index.vue'),
|
||||
name: 'DayEnd',
|
||||
meta: { title: '门诊日结', icon: 'document' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/medicationmanagement',
|
||||
component: Layout,
|
||||
name: 'MedicationManagement',
|
||||
meta: { title: '药房管理', icon: 'medication' },
|
||||
children: [
|
||||
{
|
||||
path: 'dayEndSettlement',
|
||||
component: () => import('@/views/medicationmanagement/dayEndSettlement/index.vue'),
|
||||
name: 'DayEndSettlement',
|
||||
meta: { title: '日结结算单管理', icon: 'document' }
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// 合并常量路由和动态路由,确保所有路由都能被访问
|
||||
|
||||
@@ -39,9 +39,7 @@
|
||||
<span class="custom-tree-node">
|
||||
<div class="tree-node-info">
|
||||
<div class="node-main">
|
||||
<el-icon :size="16" :color="getIconColor(data)">
|
||||
<component :is="getIconComponent(data.icon)" />
|
||||
</el-icon>
|
||||
<svg-icon :icon-class="data.icon" :style="{ color: getIconColor(data) }" />
|
||||
<span class="menu-label" style="margin-left: 8px;">{{ node.label }}</span>
|
||||
<el-tag v-if="data.fullPath" type="info" size="small" effect="plain" class="path-tag-inline">
|
||||
{{ data.fullPath }}
|
||||
@@ -88,9 +86,7 @@
|
||||
class="selected-function-item"
|
||||
>
|
||||
<div class="function-info">
|
||||
<el-icon :size="16" :color="getIconColor(item)">
|
||||
<component :is="getIconComponent(item.icon)" />
|
||||
</el-icon>
|
||||
<svg-icon :icon-class="item.icon" :style="{ color: getIconColor(item) }" />
|
||||
<div class="function-details">
|
||||
<span class="function-name">{{ item.menuName }}</span>
|
||||
<el-tag v-if="item.fullPath" type="info" size="small" class="function-path-below">
|
||||
@@ -193,6 +189,7 @@ import {
|
||||
SuccessFilled,
|
||||
QuestionFilled as QuestionFilledIcon
|
||||
} from '@element-plus/icons-vue'
|
||||
import SvgIcon from '@/components/SvgIcon'
|
||||
|
||||
// 添加 loading 状态
|
||||
const loading = ref(false)
|
||||
@@ -214,81 +211,6 @@ watch(filterText, (val) => {
|
||||
treeRef.value?.filter(val)
|
||||
})
|
||||
|
||||
// 图标映射
|
||||
const iconMap = {
|
||||
'menu': Menu,
|
||||
'grid': Grid,
|
||||
'folder': Folder,
|
||||
'tickets': Tickets,
|
||||
'document': Document,
|
||||
'setting': Setting,
|
||||
'user': User,
|
||||
'goods': Goods,
|
||||
'chat-dot-square': ChatDotSquare,
|
||||
'histogram': Histogram,
|
||||
'wallet': Wallet,
|
||||
'office-building': OfficeBuilding,
|
||||
'postcard': Postcard,
|
||||
'collection': Collection,
|
||||
'video-play': VideoPlay,
|
||||
'camera': Camera,
|
||||
'headset': Headset,
|
||||
'phone': Phone,
|
||||
'message': Message,
|
||||
'chat-line-square': ChatLineSquare,
|
||||
'chat-round': ChatRound,
|
||||
'guide': Guide,
|
||||
'help': Help,
|
||||
'info-filled': InfoFilled,
|
||||
'circle-check': CircleCheck,
|
||||
'circle-close': CircleClose,
|
||||
'warning': Warning,
|
||||
'question-filled': QuestionFilled,
|
||||
'star': Star,
|
||||
'link': Link,
|
||||
'position': Position,
|
||||
'picture': Picture,
|
||||
'upload': Upload,
|
||||
'download': Download,
|
||||
'caret-left': CaretLeft,
|
||||
'caret-right': CaretRight,
|
||||
'more': More,
|
||||
'close': Close,
|
||||
'check': Check,
|
||||
'arrow-up': ArrowUp,
|
||||
'arrow-down': ArrowDown,
|
||||
'arrow-left': ArrowLeft,
|
||||
'arrow-right': ArrowRight,
|
||||
'plus': Plus,
|
||||
'minus': Minus,
|
||||
'zoom-in': ZoomIn,
|
||||
'zoom-out': ZoomOut,
|
||||
'refresh': Refresh,
|
||||
'search': Search,
|
||||
'edit': Edit,
|
||||
'delete': Delete,
|
||||
'share': Share,
|
||||
'view': View,
|
||||
'switch-button': SwitchButton,
|
||||
'hide': Hide,
|
||||
'finished': Finished,
|
||||
'circle-plus': CirclePlus,
|
||||
'remove': Remove,
|
||||
'circle-check-filled': CircleCheckFilled,
|
||||
'circle-close-filled': CircleCloseFilled,
|
||||
'warning-filled': WarningFilled,
|
||||
'info-filled-icon': InfoFilledIcon,
|
||||
'success-filled': SuccessFilled,
|
||||
'question-filled-icon': QuestionFilledIcon
|
||||
}
|
||||
|
||||
// 获取图标组件
|
||||
const getIconComponent = (iconName) => {
|
||||
if (!iconName) return Document
|
||||
// 移除前缀,如 fa-, el-icon-
|
||||
const cleanIconName = iconName.replace(/^(fa-|el-icon-)/, '').toLowerCase()
|
||||
return iconMap[cleanIconName] || Document
|
||||
}
|
||||
|
||||
// 获取图标颜色
|
||||
const getIconColor = (data) => {
|
||||
@@ -302,6 +224,24 @@ const getIconColor = (data) => {
|
||||
const loadMenuData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 尝试从本地缓存获取菜单数据
|
||||
const cachedMenuData = localStorage.getItem('menuTreeCache');
|
||||
const cacheTimestamp = localStorage.getItem('menuTreeCacheTimestamp');
|
||||
|
||||
// 检查缓存是否有效(24小时内)
|
||||
if (cachedMenuData && cacheTimestamp) {
|
||||
const cacheAge = Date.now() - parseInt(cacheTimestamp);
|
||||
if (cacheAge < 24 * 60 * 60 * 1000) { // 24小时
|
||||
menuTree.value = JSON.parse(cachedMenuData);
|
||||
// 展开所有节点
|
||||
expandedKeys.value = getAllNodeIds(menuTree.value);
|
||||
// 获取已保存的配置
|
||||
await loadSavedConfig();
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const response = await listMenu({})
|
||||
if (response.code === 200) {
|
||||
// 过滤掉隐藏的菜单项、目录和按钮类型的菜单,只保留当前角色可访问的菜单项
|
||||
@@ -311,6 +251,10 @@ const loadMenuData = async () => {
|
||||
// 展开所有节点
|
||||
expandedKeys.value = getAllNodeIds(filteredMenus)
|
||||
|
||||
// 将菜单数据缓存到本地存储
|
||||
localStorage.setItem('menuTreeCache', JSON.stringify(filteredMenus));
|
||||
localStorage.setItem('menuTreeCacheTimestamp', Date.now().toString());
|
||||
|
||||
// 获取已保存的配置
|
||||
await loadSavedConfig()
|
||||
} else {
|
||||
@@ -389,7 +333,7 @@ const saveConfig = async () => {
|
||||
fullPath: fullPath,
|
||||
menuName: node.menuName,
|
||||
path: node.path,
|
||||
icon: node.icon, // 保存图标信息
|
||||
icon: node.icon, // 保存数据库中的图标类名
|
||||
menuType: node.menuType // 保存菜单类型信息
|
||||
};
|
||||
|
||||
@@ -406,7 +350,7 @@ const saveConfig = async () => {
|
||||
fullPath: node.path,
|
||||
menuName: node.menuName,
|
||||
path: node.path,
|
||||
icon: node.icon, // 保存图标信息
|
||||
icon: node.icon, // 保存数据库中的图标类名
|
||||
menuType: node.menuType // 保存菜单类型信息
|
||||
};
|
||||
console.log(`构造的菜单项对象(错误处理):`, menuItem);
|
||||
@@ -435,6 +379,9 @@ const saveConfig = async () => {
|
||||
if (saveResult.code === 200) {
|
||||
// 只有在数据库保存成功后,才保存到本地存储
|
||||
localStorage.setItem('homeFeaturesConfig', JSON.stringify(menuDataWithPaths))
|
||||
// 清除菜单树缓存,以便下次加载最新数据
|
||||
localStorage.removeItem('menuTreeCache');
|
||||
localStorage.removeItem('menuTreeCacheTimestamp');
|
||||
ElMessage.success('配置保存成功')
|
||||
// 触发全局事件,通知首页更新快捷功能
|
||||
window.dispatchEvent(new Event('homeFeaturesConfigUpdated'));
|
||||
@@ -493,6 +440,36 @@ const filterNode = (value, data) => {
|
||||
// 加载已保存的配置
|
||||
const loadSavedConfig = async () => {
|
||||
try {
|
||||
// 尝试从本地缓存获取配置
|
||||
const cachedConfig = localStorage.getItem('homeFeaturesConfigCache');
|
||||
const cacheTimestamp = localStorage.getItem('homeFeaturesConfigCacheTimestamp');
|
||||
|
||||
// 检查缓存是否有效(1小时内)
|
||||
if (cachedConfig && cacheTimestamp) {
|
||||
const cacheAge = Date.now() - parseInt(cacheTimestamp);
|
||||
if (cacheAge < 60 * 60 * 1000) { // 1小时
|
||||
const parsedConfig = JSON.parse(cachedConfig);
|
||||
// 检查数据格式,如果是包含对象的数组(新格式),提取菜单ID
|
||||
if (parsedConfig && Array.isArray(parsedConfig)) {
|
||||
if (parsedConfig.length > 0 && typeof parsedConfig[0] === 'object' && parsedConfig[0].hasOwnProperty('menuId')) {
|
||||
// 新格式:[{menuId: 1, fullPath: "...", ...}, ...]
|
||||
checkedKeys.value = parsedConfig.map(item => item.menuId);
|
||||
} else {
|
||||
// 旧格式:[1, 2, 3, ...]
|
||||
checkedKeys.value = parsedConfig;
|
||||
}
|
||||
|
||||
// 根据保存的配置初始化已选择的功能
|
||||
const allNodes = getAllNodes(menuTree.value)
|
||||
const checkedNodes = allNodes.filter(node =>
|
||||
checkedKeys.value.includes(node.menuId) && node.menuType === 'C'
|
||||
)
|
||||
selectedFunctions.value = checkedNodes
|
||||
}
|
||||
return; // 使用缓存数据,直接返回
|
||||
}
|
||||
}
|
||||
|
||||
// 优先从数据库获取已保存的配置
|
||||
const response = await getCurrentUserConfig('homeFeaturesConfig')
|
||||
let savedConfig = null;
|
||||
@@ -539,6 +516,10 @@ const loadSavedConfig = async () => {
|
||||
checkedKeys.value.includes(node.menuId) && node.menuType === 'C'
|
||||
)
|
||||
selectedFunctions.value = checkedNodes
|
||||
|
||||
// 将配置缓存到本地存储
|
||||
localStorage.setItem('homeFeaturesConfigCache', JSON.stringify(parsedConfig));
|
||||
localStorage.setItem('homeFeaturesConfigCacheTimestamp', Date.now().toString());
|
||||
} else {
|
||||
// 如果解析失败,使用默认配置
|
||||
const defaultSelections = getDefaultSelections(menuTree.value)
|
||||
|
||||
@@ -59,9 +59,7 @@
|
||||
@click="handleQuickAccess(func)"
|
||||
>
|
||||
<div class="quick-icon">
|
||||
<el-icon :size="28" :color="func.iconColor">
|
||||
<component :is="func.icon" />
|
||||
</el-icon>
|
||||
<svg-icon :icon-class="func.icon" :style="{ fontSize: '28px', color: func.iconColor }" />
|
||||
</div>
|
||||
<div class="quick-label">{{ func.label }}</div>
|
||||
</div>
|
||||
@@ -138,6 +136,7 @@ import { getHomeStatistics, getPendingEmrCount } from '@/api/home'
|
||||
import { listTodo } from '@/api/workflow/task.js'
|
||||
import { getCurrentUserConfig } from '@/api/system/userConfig'
|
||||
import { listMenu, getMenuFullPath } from '@/api/system/menu'
|
||||
import { getTodayDoctorScheduleList } from '@/api/appointmentmanage/doctorSchedule'
|
||||
import { ElDivider } from 'element-plus'
|
||||
import {
|
||||
User,
|
||||
@@ -220,6 +219,7 @@ import {
|
||||
|
||||
// 为别名单独导入
|
||||
import { InfoFilled as InfoFilledIcon, QuestionFilled as QuestionFilledIcon, SuccessFilled } from '@element-plus/icons-vue'
|
||||
import SvgIcon from '@/components/SvgIcon'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
@@ -400,8 +400,8 @@ const convertMenuIdsToQuickAccess = async (menuIds) => {
|
||||
return {
|
||||
key: menuItem.menuId,
|
||||
label: menuItem.menuName,
|
||||
icon: getIconComponent(menuItem.icon || 'Document'), // 使用菜单项的图标,如果没有则使用默认图标
|
||||
iconColor: getIconColorByMenuType(menuItem.menuType) || '#67C23A', // 使用菜单类型的颜色,如果没有则使用默认颜色
|
||||
icon: menuItem.icon || 'document', // 使用数据库中的图标类名
|
||||
iconColor: menuItem.iconColor || getIconColorByMenuType(menuItem.menuType) || '#67C23A', // 优先使用数据库中的颜色,否则使用菜单类型的颜色
|
||||
route: route
|
||||
};
|
||||
}).filter(item => item.route); // 过滤掉 route 为空的项
|
||||
@@ -436,8 +436,8 @@ const convertMenuIdsToQuickAccess = async (menuIds) => {
|
||||
return {
|
||||
key: matchedMenu.perms || matchedMenu.path || `menu_${matchedMenu.menuId}`,
|
||||
label: matchedMenu.menuName,
|
||||
icon: getIconComponent(matchedMenu.icon),
|
||||
iconColor: getIconColorByMenuType(matchedMenu.menuType),
|
||||
icon: matchedMenu.icon || 'document', // 使用数据库中的图标类名
|
||||
iconColor: matchedMenu.iconColor || getIconColorByMenuType(matchedMenu.menuType),
|
||||
route: fullPath || matchedMenu.path // 确保 route 不为空
|
||||
};
|
||||
} catch (error) {
|
||||
@@ -446,8 +446,8 @@ const convertMenuIdsToQuickAccess = async (menuIds) => {
|
||||
return {
|
||||
key: matchedMenu.perms || matchedMenu.path || `menu_${matchedMenu.menuId}`,
|
||||
label: matchedMenu.menuName,
|
||||
icon: getIconComponent(matchedMenu.icon),
|
||||
iconColor: getIconColorByMenuType(matchedMenu.menuType),
|
||||
icon: matchedMenu.icon || 'document', // 使用数据库中的图标类名
|
||||
iconColor: matchedMenu.iconColor || getIconColorByMenuType(matchedMenu.menuType),
|
||||
route: matchedMenu.path || matchedMenu.fullPath || '/' // 确保 route 不为空
|
||||
};
|
||||
}
|
||||
@@ -490,81 +490,6 @@ const flattenMenuTree = (menuTree) => {
|
||||
return result;
|
||||
};
|
||||
|
||||
// 获取图标组件
|
||||
const getIconComponent = (iconName) => {
|
||||
if (!iconName) return Document;
|
||||
// 移除前缀,如 fa-, el-icon-
|
||||
const cleanIconName = iconName.replace(/^(fa-|el-icon-)/, '').toLowerCase();
|
||||
|
||||
const iconMap = {
|
||||
'menu': markRaw(Menu),
|
||||
'grid': markRaw(Grid),
|
||||
'folder': markRaw(Folder),
|
||||
'tickets': markRaw(Tickets),
|
||||
'document': markRaw(Document),
|
||||
'setting': markRaw(Setting),
|
||||
'user': markRaw(User),
|
||||
'goods': markRaw(Goods),
|
||||
'chat-dot-square': markRaw(ChatDotSquare),
|
||||
'histogram': markRaw(Histogram),
|
||||
'wallet': markRaw(Wallet),
|
||||
'office-building': markRaw(OfficeBuilding),
|
||||
'postcard': markRaw(Postcard),
|
||||
'collection': markRaw(Collection),
|
||||
'video-play': markRaw(VideoPlay),
|
||||
'camera': markRaw(Camera),
|
||||
'headset': markRaw(Headset),
|
||||
'phone': markRaw(Phone),
|
||||
'message': markRaw(Message),
|
||||
'chat-line-square': markRaw(ChatLineSquare),
|
||||
'chat-round': markRaw(ChatRound),
|
||||
'guide': markRaw(Guide),
|
||||
'help': markRaw(Help),
|
||||
'info-filled': markRaw(InfoFilled),
|
||||
'circle-check': markRaw(CircleCheck),
|
||||
'circle-close': markRaw(CircleClose),
|
||||
'warning': markRaw(Warning),
|
||||
'question-filled': markRaw(QuestionFilled),
|
||||
'star': markRaw(Star),
|
||||
'link': markRaw(Link),
|
||||
'position': markRaw(Position),
|
||||
'picture': markRaw(Picture),
|
||||
'upload': markRaw(Upload),
|
||||
'download': markRaw(Download),
|
||||
'caret-left': markRaw(CaretLeft),
|
||||
'caret-right': markRaw(CaretRight),
|
||||
'more': markRaw(More),
|
||||
'close': markRaw(Close),
|
||||
'check': markRaw(Check),
|
||||
'arrow-up': markRaw(ArrowUp),
|
||||
'arrow-down': markRaw(ArrowDown),
|
||||
'arrow-left': markRaw(ArrowLeft),
|
||||
'arrow-right': markRaw(ArrowRight),
|
||||
'plus': markRaw(Plus),
|
||||
'minus': markRaw(Minus),
|
||||
'zoom-in': markRaw(ZoomIn),
|
||||
'zoom-out': markRaw(ZoomOut),
|
||||
'refresh': markRaw(Refresh),
|
||||
'search': markRaw(Search),
|
||||
'edit': markRaw(Edit),
|
||||
'delete': markRaw(Delete),
|
||||
'share': markRaw(Share),
|
||||
'view': markRaw(View),
|
||||
'switch-button': markRaw(SwitchButton),
|
||||
'hide': markRaw(Hide),
|
||||
'finished': markRaw(Finished),
|
||||
'circle-plus': markRaw(CirclePlus),
|
||||
'remove': markRaw(Remove),
|
||||
'circle-check-filled': markRaw(CircleCheckFilled),
|
||||
'circle-close-filled': markRaw(CircleCloseFilled),
|
||||
'warning-filled': markRaw(WarningFilled),
|
||||
'info-filled-icon': markRaw(InfoFilledIcon),
|
||||
'success-filled': markRaw(SuccessFilled),
|
||||
'question-filled-icon': markRaw(QuestionFilledIcon)
|
||||
};
|
||||
|
||||
return iconMap[cleanIconName] || markRaw(Document);
|
||||
};
|
||||
|
||||
// 根据菜单类型获取图标颜色
|
||||
const getIconColorByMenuType = (menuType) => {
|
||||
@@ -581,48 +506,48 @@ const getDefaultQuickAccessConfig = () => {
|
||||
switch (role) {
|
||||
case 'doctor':
|
||||
return [
|
||||
{ key: 'outpatient', label: '门诊接诊', icon: markRaw(ChatDotRound), iconColor: '#409eff', route: '/doctorstation' },
|
||||
{ key: 'emr', label: '病历管理', icon: markRaw(Document), iconColor: '#67c23a', route: '/doctorstation/doctorphrase' },
|
||||
{ key: 'prescription', label: '开立处方', icon: markRaw(Box), iconColor: '#e6a23c', route: '/clinicmanagement/ePrescribing' },
|
||||
{ key: 'history', label: '历史处方', icon: markRaw(Clock), iconColor: '#f56c6c', route: '/clinicmanagement/historicalPrescription' },
|
||||
{ key: 'schedule', label: '排班管理', icon: markRaw(Calendar), iconColor: '#909399', route: '/appoinmentmanage/deptManage' },
|
||||
{ key: 'inquiry', label: '患者查询', icon: markRaw(Search), iconColor: '#409eff', route: '/patientmanagement' }
|
||||
{ key: 'outpatient', label: '门诊接诊', icon: 'chat-dot-round', iconColor: '#409eff', route: '/doctorstation' },
|
||||
{ key: 'emr', label: '病历管理', icon: 'document', iconColor: '#67c23a', route: '/doctorstation/doctorphrase' },
|
||||
{ key: 'prescription', label: '开立处方', icon: 'box', iconColor: '#e6a23c', route: '/clinicmanagement/ePrescribing' },
|
||||
{ key: 'history', label: '历史处方', icon: 'clock', iconColor: '#f56c6c', route: '/clinicmanagement/historicalPrescription' },
|
||||
{ key: 'schedule', label: '排班管理', icon: 'calendar', iconColor: '#909399', route: '/appoinmentmanage/deptManage' },
|
||||
{ key: 'inquiry', label: '患者查询', icon: 'search', iconColor: '#409eff', route: '/patientmanagement' }
|
||||
];
|
||||
case 'nurse':
|
||||
return [
|
||||
{ key: 'ward', label: '病房管理', icon: markRaw(User), iconColor: '#409eff', route: '/inpatientNurse/inpatientNurseStation' },
|
||||
{ key: 'execution', label: '医嘱执行', icon: markRaw(Operation), iconColor: '#67c23a', route: '/inpatientNurse/medicalOrderExecution' },
|
||||
{ key: 'proofread', label: '医嘱核对', icon: markRaw(Document), iconColor: '#e6a23c', route: '/inpatientNurse/medicalOrderProofread' },
|
||||
{ key: 'drugCollect', label: '领药管理', icon: markRaw(Box), iconColor: '#f56c6c', route: '/inpatientNurse/medicineCollect' },
|
||||
{ key: 'tpr', label: '体温单', icon: markRaw(Monitor), iconColor: '#909399', route: '/inpatientNurse/tprsheet' },
|
||||
{ key: 'nursing', label: '护理记录', icon: markRaw(ChatDotRound), iconColor: '#409eff', route: '/inpatientNurse/nursingRecord' }
|
||||
{ key: 'ward', label: '病房管理', icon: 'user', iconColor: '#409eff', route: '/inpatientNurse/inpatientNurseStation' },
|
||||
{ key: 'execution', label: '医嘱执行', icon: 'operation', iconColor: '#67c23a', route: '/inpatientNurse/medicalOrderExecution' },
|
||||
{ key: 'proofread', label: '医嘱核对', icon: 'document', iconColor: '#e6a23c', route: '/inpatientNurse/medicalOrderProofread' },
|
||||
{ key: 'drugCollect', label: '领药管理', icon: 'box', iconColor: '#f56c6c', route: '/inpatientNurse/medicineCollect' },
|
||||
{ key: 'tpr', label: '体温单', icon: 'monitor', iconColor: '#909399', route: '/inpatientNurse/tprsheet' },
|
||||
{ key: 'nursing', label: '护理记录', icon: 'chat-dot-round', iconColor: '#409eff', route: '/inpatientNurse/nursingRecord' }
|
||||
];
|
||||
case 'pharmacist':
|
||||
return [
|
||||
{ key: 'dispensing', label: '发药管理', icon: markRaw(Box), iconColor: '#409eff', route: '/pharmacymanagement' },
|
||||
{ key: 'prescription', label: '处方审核', icon: markRaw(Document), iconColor: '#67c23a', route: '/pharmacymanagement' },
|
||||
{ key: 'inventory', label: '库存管理', icon: markRaw(Van), iconColor: '#e6a23c', route: '/medicineStorage' },
|
||||
{ key: 'purchase', label: '采购管理', icon: markRaw(ShoppingCart), iconColor: '#f56c6c', route: '/medicineStorage' },
|
||||
{ key: 'warning', label: '效期预警', icon: markRaw(Warning), iconColor: '#f56c6c', route: '/medicationmanagement/statisticalManagement/statisticalManagement' },
|
||||
{ key: 'statistics', label: '用药统计', icon: markRaw(DataLine), iconColor: '#909399', route: '/monitor' }
|
||||
{ key: 'dispensing', label: '发药管理', icon: 'box', iconColor: '#409eff', route: '/pharmacymanagement' },
|
||||
{ key: 'prescription', label: '处方审核', icon: 'document', iconColor: '#67c23a', route: '/pharmacymanagement' },
|
||||
{ key: 'inventory', label: '库存管理', icon: 'van', iconColor: '#e6a23c', route: '/medicineStorage' },
|
||||
{ key: 'purchase', label: '采购管理', icon: 'shopping-cart', iconColor: '#f56c6c', route: '/medicineStorage' },
|
||||
{ key: 'warning', label: '效期预警', icon: 'warning', iconColor: '#f56c6c', route: '/medicationmanagement/statisticalManagement/statisticalManagement' },
|
||||
{ key: 'statistics', label: '用药统计', icon: 'data-line', iconColor: '#909399', route: '/monitor' }
|
||||
];
|
||||
case 'cashier':
|
||||
return [
|
||||
{ key: 'registration', label: '挂号收费', icon: markRaw(Money), iconColor: '#409eff', route: '/charge/outpatientregistration' },
|
||||
{ key: 'clinicCharge', label: '门诊收费', icon: markRaw(Wallet), iconColor: '#67c23a', route: '/charge/cliniccharge' },
|
||||
{ key: 'refund', label: '退费管理', icon: markRaw(Document), iconColor: '#e6a23c', route: '/charge/clinicrefund' },
|
||||
{ key: 'invoice', label: '发票打印', icon: markRaw(Files), iconColor: '#f56c6c', route: '/basicmanage/InvoiceManagement' },
|
||||
{ key: 'record', label: '收费记录', icon: markRaw(Clock), iconColor: '#909399', route: '/charge/clinicRecord' },
|
||||
{ key: 'insurance', label: '医保结算', icon: markRaw(Bell), iconColor: '#409eff', route: '/ybmanagement' }
|
||||
{ key: 'registration', label: '挂号收费', icon: 'money', iconColor: '#409eff', route: '/charge/outpatientregistration' },
|
||||
{ key: 'clinicCharge', label: '门诊收费', icon: 'wallet', iconColor: '#67c23a', route: '/charge/cliniccharge' },
|
||||
{ key: 'refund', label: '退费管理', icon: 'document', iconColor: '#e6a23c', route: '/charge/clinicrefund' },
|
||||
{ key: 'invoice', label: '发票打印', icon: 'files', iconColor: '#f56c6c', route: '/basicmanage/InvoiceManagement' },
|
||||
{ key: 'record', label: '收费记录', icon: 'clock', iconColor: '#909399', route: '/charge/clinicRecord' },
|
||||
{ key: 'insurance', label: '医保结算', icon: 'bell', iconColor: '#409eff', route: '/ybmanagement' }
|
||||
];
|
||||
default: // admin
|
||||
return [
|
||||
{ key: 'patient', label: '患者管理', icon: markRaw(User), iconColor: '#409eff', route: '/patient/patientmgr' },
|
||||
{ key: 'appointment', label: '预约管理', icon: markRaw(Calendar), iconColor: '#67c23a', route: '/appoinmentmanage' },
|
||||
{ key: 'doctor', label: '医生管理', icon: markRaw(User), iconColor: '#e6a23c', route: '/doctorstation' },
|
||||
{ key: 'surgery', label: '手术管理', icon: markRaw(Operation), iconColor: '#f56c6c', route: '/surgerymanage' },
|
||||
{ key: 'drug', label: '药品管理', icon: markRaw(Box), iconColor: '#909399', route: '/pharmacymanagement' },
|
||||
{ key: 'statistic', label: '数据统计', icon: markRaw(TrendCharts), iconColor: '#409eff', route: '/monitor' }
|
||||
{ key: 'patient', label: '患者管理', icon: 'user', iconColor: '#409eff', route: '/patient/patientmgr' },
|
||||
{ key: 'appointment', label: '预约管理', icon: 'calendar', iconColor: '#67c23a', route: '/appoinmentmanage' },
|
||||
{ key: 'doctor', label: '医生管理', icon: 'user', iconColor: '#e6a23c', route: '/doctorstation' },
|
||||
{ key: 'surgery', label: '手术管理', icon: 'operation', iconColor: '#f56c6c', route: '/surgerymanage' },
|
||||
{ key: 'drug', label: '药品管理', icon: 'box', iconColor: '#909399', route: '/pharmacymanagement' },
|
||||
{ key: 'statistic', label: '数据统计', icon: 'trend-charts', iconColor: '#409eff', route: '/monitor' }
|
||||
];
|
||||
}
|
||||
};
|
||||
@@ -639,12 +564,7 @@ const updatePendingEmrTodo = () => {
|
||||
}
|
||||
|
||||
// 今日日程
|
||||
const scheduleList = ref([
|
||||
{ id: 1, time: '09:00', title: '科室晨会', location: '第一会议室', type: 'info', tag: '日常' },
|
||||
{ id: 2, time: '10:30', title: '病例讨论', location: '第二会议室', type: 'primary', tag: '会议' },
|
||||
{ id: 3, time: '14:00', title: '专家查房', location: '住院部3楼', type: 'warning', tag: '重要' },
|
||||
{ id: 4, time: '16:00', title: '新药培训', location: '培训中心', type: 'success', tag: '培训' }
|
||||
])
|
||||
const scheduleList = ref([])
|
||||
|
||||
// 获取问候语
|
||||
const getGreeting = () => {
|
||||
@@ -980,8 +900,58 @@ const getTaskIcon = (category) => {
|
||||
|
||||
// 获取日程数据(实际应用中应该从API获取)
|
||||
const fetchScheduleList = async () => {
|
||||
// TODO: 调用API获取真实数据
|
||||
console.log('Fetching schedule list...')
|
||||
try {
|
||||
console.log('Fetching schedule list...')
|
||||
const response = await getTodayDoctorScheduleList()
|
||||
if (response.code === 200) {
|
||||
// 将API返回的数据转换为前端所需的格式
|
||||
const scheduleData = response.data.map((schedule, index) => {
|
||||
// 根据排班类型设置标签类型
|
||||
let tagType = 'info'
|
||||
if (schedule.weekday) {
|
||||
tagType = schedule.weekday.toLowerCase()
|
||||
} else if (schedule.timePeriod) {
|
||||
tagType = schedule.timePeriod.toLowerCase()
|
||||
}
|
||||
|
||||
// 确定标题
|
||||
const title = schedule.doctor ? `${schedule.doctor}医生排班` : '医生排班'
|
||||
|
||||
// 确定位置
|
||||
const location = schedule.clinic || schedule.deptId || '未知科室'
|
||||
|
||||
return {
|
||||
id: schedule.id || index,
|
||||
time: schedule.startTime || '未知时间',
|
||||
title: title,
|
||||
location: location,
|
||||
type: tagType,
|
||||
tag: schedule.timePeriod || '排班'
|
||||
}
|
||||
})
|
||||
|
||||
// 更新日程列表
|
||||
scheduleList.value = scheduleData
|
||||
} else {
|
||||
console.error('获取排班信息失败:', response.msg)
|
||||
// 如果API调用失败,使用默认数据
|
||||
scheduleList.value = [
|
||||
{ id: 1, time: '09:00', title: '科室晨会', location: '第一会议室', type: 'info', tag: '日常' },
|
||||
{ id: 2, time: '10:30', title: '病例讨论', location: '第二会议室', type: 'primary', tag: '会议' },
|
||||
{ id: 3, time: '14:00', title: '专家查房', location: '住院部3楼', type: 'warning', tag: '重要' },
|
||||
{ id: 4, time: '16:00', title: '新药培训', location: '培训中心', type: 'success', tag: '培训' }
|
||||
]
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取排班信息异常:', error)
|
||||
// 如果出现异常,使用默认数据
|
||||
scheduleList.value = [
|
||||
{ id: 1, time: '09:00', title: '科室晨会', location: '第一会议室', type: 'info', tag: '日常' },
|
||||
{ id: 2, time: '10:30', title: '病例讨论', location: '第二会议室', type: 'primary', tag: '会议' },
|
||||
{ id: 3, time: '14:00', title: '专家查房', location: '住院部3楼', type: 'warning', tag: '重要' },
|
||||
{ id: 4, time: '16:00', title: '新药培训', location: '培训中心', type: 'success', tag: '培训' }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// 监听本地存储变化,以便在其他标签页或窗口中修改配置后更新当前页面
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryRef"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="90px"
|
||||
>
|
||||
<el-form-item label="查询日期:">
|
||||
<el-date-picker
|
||||
v-model="queryTime"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
style="width: 300px; margin-right: 20px"
|
||||
@change="handleQuery"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="结算类型:">
|
||||
<el-select
|
||||
v-model="queryParams.settlementType"
|
||||
placeholder="结算类型"
|
||||
clearable
|
||||
style="width: 150px; margin-right: 30px"
|
||||
>
|
||||
<el-option label="日结" value="daily" />
|
||||
<el-option label="周结" value="weekly" />
|
||||
<el-option label="月结" value="monthly" />
|
||||
</el-select>
|
||||
<el-button type="primary" plain icon="Search" @click="handleQuery">查询</el-button>
|
||||
<el-button type="primary" plain icon="Printer" @click="handlePrint">打印</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="['medication:dayEndSettlement:add']"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="Edit"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
v-hasPermi="['medication:dayEndSettlement:edit']"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['medication:dayEndSettlement:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['medication:dayEndSettlement:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="dayEndSettlementList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="结算单号" align="center" prop="settlementNo" />
|
||||
<el-table-column label="结算日期" align="center" prop="settlementDate" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.settlementDate, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结算类型" align="center" prop="settlementType" />
|
||||
<el-table-column label="结算状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总金额" align="center" prop="totalAmount" />
|
||||
<el-table-column label="操作人" align="center" prop="operator" />
|
||||
<el-table-column label="操作时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="View" @click="handleView(scope.row)" v-hasPermi="['medication:dayEndSettlement:query']">查看</el-button>
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['medication:dayEndSettlement:edit']">修改</el-button>
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['medication:dayEndSettlement:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@size-change="getList"
|
||||
@current-change="getList"
|
||||
/>
|
||||
|
||||
<!-- 添加或修改日结结算单对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="dayEndSettlementRef" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="结算单号" prop="settlementNo">
|
||||
<el-input v-model="form.settlementNo" placeholder="请输入结算单号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结算日期" prop="settlementDate">
|
||||
<el-date-picker clearable
|
||||
v-model="form.settlementDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择结算日期">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="结算类型" prop="settlementType">
|
||||
<el-select v-model="form.settlementType" placeholder="请选择结算类型">
|
||||
<el-option label="日结" value="daily" />
|
||||
<el-option label="周结" value="weekly" />
|
||||
<el-option label="月结" value="monthly" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="结算状态" prop="status">
|
||||
<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-form-item label="总金额" prop="totalAmount">
|
||||
<el-input-number v-model="form.totalAmount" placeholder="请输入总金额" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="DayEndSettlement">
|
||||
import { listDayEndSettlement, getDayEndSettlement, delDayEndSettlement, addDayEndSettlement, updateDayEndSettlement } from "@/api/medicationmanagement/dayEndSettlement";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
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 open = ref(false);
|
||||
const queryTime = ref([]);
|
||||
|
||||
const dayEndSettlementList = ref([]);
|
||||
const queryFormRef = ref();
|
||||
const dayEndSettlementRef = ref();
|
||||
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
settlementNo: null,
|
||||
settlementDate: null,
|
||||
settlementType: null,
|
||||
status: null
|
||||
});
|
||||
|
||||
const form = ref({});
|
||||
const rules = ref({
|
||||
settlementNo: [
|
||||
{ required: true, message: "结算单号不能为空", trigger: "blur" }
|
||||
],
|
||||
settlementDate: [
|
||||
{ required: true, message: "结算日期不能为空", trigger: "blur" }
|
||||
],
|
||||
settlementType: [
|
||||
{ required: true, message: "结算类型不能为空", trigger: "change" }
|
||||
],
|
||||
totalAmount: [
|
||||
{ required: true, message: "总金额不能为空", trigger: "blur" }
|
||||
]
|
||||
});
|
||||
|
||||
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
||||
|
||||
/** 查询日结结算单列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const response = await listDayEndSettlement(queryParams.value);
|
||||
dayEndSettlementList.value = response.rows;
|
||||
total.value = response.total;
|
||||
} catch (error) {
|
||||
console.error('获取日结结算单列表失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
open.value = false;
|
||||
reset();
|
||||
};
|
||||
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
form.value = {
|
||||
id: null,
|
||||
settlementNo: null,
|
||||
settlementDate: null,
|
||||
settlementType: null,
|
||||
status: "0",
|
||||
totalAmount: null,
|
||||
remark: null
|
||||
};
|
||||
proxy.resetForm("dayEndSettlementRef");
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryTime.value = [];
|
||||
proxy.resetForm("queryRef");
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
/** 多择框多选 */
|
||||
const handleSelectionChange = (selection) => {
|
||||
ids.value = selection.map(item => item.id);
|
||||
single.value = selection.length !== 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
reset();
|
||||
open.value = true;
|
||||
title.value = "添加日结结算单";
|
||||
};
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = (row) => {
|
||||
reset();
|
||||
const settlementId = row.id || ids.value[0];
|
||||
getDayEndSettlement(settlementId).then(response => {
|
||||
form.value = response.data;
|
||||
open.value = true;
|
||||
title.value = "修改日结结算单";
|
||||
});
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
proxy.$refs["dayEndSettlementRef"].validate(valid => {
|
||||
if (valid) {
|
||||
if (form.value.id != null) {
|
||||
updateDayEndSettlement(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("修改成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
} else {
|
||||
addDayEndSettlement(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("新增成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = (row) => {
|
||||
const settlementIds = row.id || ids.value;
|
||||
proxy.$modal.confirm('是否确认删除日结结算单编号为"' + settlementIds + '"的数据项?').then(function() {
|
||||
return delDayEndSettlement(settlementIds);
|
||||
}).then(() => {
|
||||
getList();
|
||||
proxy.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
proxy.download("medication/dayEndSettlement/export", {
|
||||
...queryParams.value
|
||||
}, `dayEndSettlement_${new Date().getTime()}.xlsx`);
|
||||
};
|
||||
|
||||
/** 打印按钮操作 */
|
||||
const handlePrint = () => {
|
||||
// TODO: 实现打印功能
|
||||
proxy.$modal.msgSuccess("打印功能待实现");
|
||||
};
|
||||
|
||||
/** 查看按钮操作 */
|
||||
const handleView = (row) => {
|
||||
// TODO: 实现查看功能
|
||||
proxy.$modal.msgSuccess("查看功能待实现");
|
||||
};
|
||||
|
||||
/** 初始化数据 */
|
||||
getList();
|
||||
</script>
|
||||
@@ -124,9 +124,9 @@
|
||||
<el-col :span="24">
|
||||
<el-form-item label="菜单类型" prop="menuType">
|
||||
<el-radio-group v-model="form.menuType">
|
||||
<el-radio label="M">目录</el-radio>
|
||||
<el-radio label="C">菜单</el-radio>
|
||||
<el-radio label="F">按钮</el-radio>
|
||||
<el-radio value="M">目录</el-radio>
|
||||
<el-radio value="C">菜单</el-radio>
|
||||
<el-radio value="F">按钮</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -174,8 +174,8 @@
|
||||
</span>
|
||||
</template>
|
||||
<el-radio-group v-model="form.isFrame">
|
||||
<el-radio label="0">是</el-radio>
|
||||
<el-radio label="1">否</el-radio>
|
||||
<el-radio value="0">是</el-radio>
|
||||
<el-radio value="1">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -247,8 +247,8 @@
|
||||
</span>
|
||||
</template>
|
||||
<el-radio-group v-model="form.isCache">
|
||||
<el-radio label="0">缓存</el-radio>
|
||||
<el-radio label="1">不缓存</el-radio>
|
||||
<el-radio value="0">缓存</el-radio>
|
||||
<el-radio value="1">不缓存</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -266,7 +266,7 @@
|
||||
<el-radio
|
||||
v-for="dict in sys_show_hide"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
:value="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
@@ -285,7 +285,7 @@
|
||||
<el-radio
|
||||
v-for="dict in sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
:value="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
@@ -303,7 +303,7 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Menu">
|
||||
import {addMenu, delMenu, getMenu, listMenu, updateMenu} from "@/api/system/menu";
|
||||
import {addMenu, delMenu, getMenu, listMenu, updateMenu, treeselect} from "@/api/system/menu";
|
||||
import SvgIcon from "@/components/SvgIcon";
|
||||
import IconSelect from "@/components/IconSelect";
|
||||
|
||||
@@ -351,10 +351,28 @@ async function getList() {
|
||||
/** 查询菜单下拉树结构 */
|
||||
function getTreeselect() {
|
||||
menuOptions.value = [];
|
||||
listMenu().then(response => {
|
||||
const menu = { menuId: 0, menuName: "主类目", children: [] };
|
||||
menu.children = proxy.handleTree(response.data, "menuId");
|
||||
menuOptions.value.push(menu);
|
||||
// 使用专门的treeselect API,它返回预构建的树形结构
|
||||
treeselect().then(response => {
|
||||
// TreeSelect对象使用id、label、children字段,但el-tree-select组件期望menuId、menuName、children字段
|
||||
// 需要将TreeSelect对象转换为el-tree-select组件期望的格式
|
||||
const convertTreeSelectToMenuFormat = (treeSelectList) => {
|
||||
return treeSelectList.map(item => ({
|
||||
menuId: item.id,
|
||||
menuName: item.label,
|
||||
value: item.id,
|
||||
label: item.label,
|
||||
children: item.children ? convertTreeSelectToMenuFormat(item.children) : []
|
||||
}));
|
||||
};
|
||||
|
||||
const rootNode = {
|
||||
menuId: 0,
|
||||
menuName: "主类目",
|
||||
value: 0,
|
||||
label: "主类目",
|
||||
children: convertTreeSelectToMenuFormat(response.data)
|
||||
};
|
||||
menuOptions.value.push(rootNode);
|
||||
});
|
||||
}
|
||||
/** 取消按钮 */
|
||||
@@ -426,7 +444,7 @@ async function handleUpdate(row) {
|
||||
const response = await getMenu(row.menuId);
|
||||
form.value = response.data;
|
||||
// 使用后端返回的完整路径
|
||||
form.value.fullPath = row.fullPath || row.path;
|
||||
form.value.fullPath = response.data.fullPath || response.data.path;
|
||||
open.value = true;
|
||||
title.value = "修改菜单";
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user