标本全程监控

This commit is contained in:
wyuu 2026-02-03 17:33:25 +08:00
parent 459342d3e3
commit 31a6f3bde2
9 changed files with 646 additions and 284 deletions

View File

@ -479,5 +479,13 @@ export function refusedSaveData(query?: Object) {
data: query
})
}
// 查询申请单全程信息
export function wholeprocessList(query?: Object) {
return request({
url: '/wholeprocess/list',
method: 'get',
params: query
})
}

View File

@ -32,7 +32,7 @@ const instrOptions = ref<Array<{ yq: string; yqmc: string }>>([]);
const fields = ref(
[
{ prop: 'yq', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'yqmc', label: '名称', width: 150, enablePinyinSearch: true },
{ prop: 'yqmc', label: '名称', enablePinyinSearch: true },
]
)
const emits = defineEmits<Emits>();

View File

@ -41,7 +41,7 @@
:tooltip-config="{ appendToBody: true, zIndex: 3000 }" :show-overflow="true"
:scroll-y="{ enabled: true, rSize: 30, height: '100%' }">
<vxe-table-column v-for="field in props.fields" :field="field.prop" :title="field.label" align="center"
:width="field.width" />
:width="field.width" min-width="150" />
</vxe-table>
</div>
</div>
@ -72,7 +72,7 @@ const props = withDefaults(defineProps<Props>(), {
keyValue: false,
fields: () => [
{ prop: 'value', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'label', label: '名称', width: 150, enablePinyinSearch: true },
{ prop: 'label', label: '名称', enablePinyinSearch: true },
],
});

View File

@ -8,7 +8,7 @@
<div class="custom-header-content">
<!-- 左侧:APP产品名称 -->
<div class="app-name">
仙桃市第一人民医院检验系统 <!-- 替换为实际产品名 -->
{{ formatDict(userStore.sysLoginParam.loginYLJG || '1', 'HOS') }}
</div>
<!-- 右侧:功能按钮 + 登录信息 + 原生设置菜单 -->
@ -72,7 +72,7 @@ import useUserStore from '@/store/modules/user'
import useSettingsStore from '@/store/modules/settings'
// 引入图标和默认头像(可替换为你的默认头像)
import { CaretBottom } from '@element-plus/icons-vue'
import { formatDict, getDictData } from '@/hooks'
const appStore = useAppStore()
const userStore = useUserStore()
const settingsStore = useSettingsStore()
@ -129,6 +129,10 @@ const emits = defineEmits(['setLayout'])
function setLayout() {
emits('setLayout');
}
onMounted(() => {
getDictData('HOS')
})
</script>
<style lang='scss' scoped>

View File

@ -191,7 +191,7 @@ const printStore = usePrintStore();
const printerList = computed(() => printStore.printerList);
//@ts-ignore
import { getDicts } from '@/api/system/dict/data'
import { sum } from 'lodash';
//@ts-ignore
const { proxy } = getCurrentInstance();
const { lis_reqcx_type } = proxy.useDict("lis_reqcx_type"); //参数类别

View File

@ -19,6 +19,9 @@
<el-col :span="1.5">
<el-button type="primary" @click="setHandle" plain>设置</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" @click="clearHandle" plain>清除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" plain>打印</el-button>
</el-col>
@ -80,7 +83,7 @@
import { querybarcode, autosavebarcode, saveBarcode } from '@/api/liswork/work/LisWork';
import { paramList, updateParam } from '@/api/liswork/xtwh/ComOpt'
import { formatDict, getDictData } from '@/hooks'
import { ElMessage } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import { listUser } from '@/api/system/user.js'
import CheckUser from "@/views/liswork/work/components/CheckUser.vue";
import { checkuser } from "@/api/liswork/work/LisWork";
@ -88,7 +91,7 @@ import { classCom } from '@/utils/classCom';
const sqhRef = useTemplateRef('sqhRef');
const checkUser = useTemplateRef('checkUser');
const tableRef = useTemplateRef('tableRef');
const sqhText = ref('25082007185');
const sqhText = ref('');
const RCV_AUTOSAVE = ref('0') // 是否自动保存
const dialogVisible = ref(false);
const tableData = ref([]);
@ -192,6 +195,25 @@ const setHandle = () => {
dialogVisible.value = true
}
const clearHandle = () => {
ElMessageBox.confirm(
`确定清除 ${tableData.value.length} 条数据吗?`,
'数据清除',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
closeOnPressEscape: true,
}
).then(() => {
tableData.value = []
ElMessage.success('成功清除表格全部数据')
}).catch((reason) => {
})
}
const subHandle = () => {
let arr = JSON.parse(JSON.stringify(setList.value))
arr.forEach(e => {

View File

@ -0,0 +1,346 @@
/**
* @file index.vue 标本监控
* @author: w
* @since: 2026-02-02
*/
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" label-width="90px" inline>
<el-form-item label="病人来源:" prop="brly">
<SelectTable v-model:data="queryParams.brly" dictType='PT' placeholder="请选择病人来源" @getDataValue="handleQuery"
style="width: 12rem;" />
</el-form-item>
<el-form-item label="病人代号:" prop="brdh">
<el-input v-model="queryParams.brdh" placeholder="请输入病人代号" />
</el-form-item>
<el-form-item label="病人姓名:" prop="brxm">
<el-input v-model="queryParams.brxm" placeholder="请输入病人姓名" />
</el-form-item>
<el-form-item label="申请号:" prop="sqh">
<el-input v-model="queryParams.sqh" placeholder="请输入申请号" />
</el-form-item>
<el-form-item label="条码状态:" prop="zt">
<el-select v-model="queryParams.zt" placeholder="请选择" clearable style="width: 12rem;">
<el-option v-for="item in lis_reqzt_type" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="科室病区:" prop="ksdh">
<SelectTable v-model:data="queryParams.ksdh" dictType='DP' placeholder="请选择科室" @getDataValue="handleQuery"
style="width: 12rem;" />
</el-form-item>
<el-form-item label="申请日期:" prop="sqsj1">
<el-date-picker v-model="queryParams.sqsj1" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
style="width: 12rem;" @change="handletime" />&nbsp;-&nbsp;
<el-date-picker v-model="queryParams.sqsj2" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
@change="handletime" style="width: 12rem;" />
</el-form-item>
<el-form-item>
<el-button @click="isExpand = !isExpand" type="text">展开更多查询</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
<el-button type="default" icon="Refresh" @click="refresh">重置</el-button>
</el-form-item>
</el-form>
<el-drawer title="查询条件" v-model="isExpand" direction="rtl" size="28%" :with-header="true" :modal="false">
<el-form :model="queryParams" label-width="120px">
<el-form-item label="批准/联系人:" prop="powerman">
<el-input v-model="queryParams.powerman" placeholder="请输入批准/联系人" />
</el-form-item>
<el-form-item label="录入人:" prop="inputman">
<el-input v-model="queryParams.inputman" placeholder="请输入录入人" />
</el-form-item>
<el-form-item label="条码类别:" prop="updateBy">
</el-form-item>
<el-form-item label="单据计价:" prop="jjzt">
<el-radio-group v-model="queryParams.jjzt">
<el-radio value="">全部</el-radio>
<el-radio value="1">已计价</el-radio>
<el-radio value="2">未计价</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="明细计价:" prop="mxjjzt">
<el-radio-group v-model="queryParams.mxjjzt">
<el-radio value="">全部</el-radio>
<el-radio value="1">已计价</el-radio>
<el-radio value="2">未计价</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="类别对应仪器:" prop="yqdh">
<YQSelectTable v-model:data="queryParams.yqdh" placeholder="请选择类别对应仪器" />
</el-form-item>
<el-form-item label="仪器分组:" prop="instrGroup">
<SelectTable v-model:data="queryParams.instrGroup" :fields="instrGroupFields" :tableData="instrGroupOptions"
label="zdmc" value="zddh" objKey="zddh" :border="true" placeholder="请选择部门" />
</el-form-item>
<el-form-item label="签收人:" prop="qsr">
<el-input v-model="queryParams.qsr" placeholder="请输入批准/联系人" />
</el-form-item>
<el-form-item label="签收时间:" prop="jssj1">
<el-date-picker v-model="queryParams.jssj1" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
style="width: 46%;" @change="handletime" />&nbsp;-&nbsp;
<el-date-picker v-model="queryParams.jssj2" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
@change="handletime" style="width: 46%;" />
</el-form-item>
<el-form-item label="医疗机构:" prop="yljg">
<SelectTable v-model:data="queryParams.yljg" dictType="HOS" placeholder="请选择" @getDataValue="handleQuery" />
</el-form-item>
<el-form-item label="">
<el-checkbox v-model="queryParams.jzbz" label="急诊" true-value="1" false-value="0" />
<el-checkbox v-model="queryParams.failed1" label="患者个人信息" true-value="1" false-value="0" />
<el-checkbox v-model="queryParams.failed2" label="排除此组" true-value="1" false-value="0" />
<el-checkbox v-model="queryParams.failed3" label="TAT采样到接收超时" true-value="1" false-value="0" />
<el-checkbox v-model="queryParams.failed4" label="TAT接收到报告超时" true-value="1" false-value="0" />
<el-checkbox v-model="queryParams.failed5" label="排除科内开单" true-value="1" false-value="0" />
<el-checkbox v-model="queryParams.failed6" label="外来送检本院出报告申请单" true-value="1" false-value="0" />
<el-checkbox v-model="queryParams.failed7" label="本院申请单送外检验申请单" true-value="1" false-value="0" />
</el-form-item>
</el-form>
<template #footer>
<div class="drawer-footer">
<el-button type="primary" @click="isExpand = false"> 查询 </el-button>
<el-button @click="isExpand = false">重置</el-button>
</div>
</template>
</el-drawer>
<div class="table-container">
<CustomVxeTable :table-data="tableData" :loading="loading" :columns="columns" class="mytable-style" ref="tableRef"
:scrollYConfig="{ enabled: true, rSize: 30, height: '100%', }" :enable-column-drag="true"
@column-drag-end="handleColumnDragEnd">
<template #dy="{ row }">
<svg-icon v-if="row.zt != 1" icon-class="lvgou" />
</template>
<template #jzbz="{ row }">
<div style="color: #f00;" v-if="row.jzbz == '1'">急</div>
<div style="color: transparent;" v-else>无</div>
</template>
<template #jjzt="{ row }">
<el-checkbox :model-value="row.jjzt == '1'" readonly />
</template>
<template #mxjjzt="{ row }">
<el-checkbox :model-value="row.mxjjzt == '1'" readonly />
</template>
<template #zt="{ row }">
{{ formatDict(row.zt.trim(), 'ST') }}
</template>
<template #yljg="{ row }">
{{ formatDict(row.yljg, 'HOS') }}
</template>
</CustomVxeTable>
</div>
<div class="footer-pagination">
<div class="text-tips">
标本总人次:{{ total }} <span></span> 本页合计金额:{{ sumMoney }}
</div>
<Pagination v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total"
class="pagination" :pageSizes="[100, 200, 500, 1000]" @pagination="pagination" />
</div>
</div>
</template>
<script setup>
import { classCom } from '@/utils/classCom'
import { formatDict, getDictData } from '@/hooks'
import YQSelectTable from '@/components/SelectTable/YQSelectTable'
import dayjs from 'dayjs'
import { getComDicts } from '@/api/liswork/dict/ComDict';
import { wholeprocessList } from '@/api/liswork/work/LisWork'
import { load } from '@fingerprintjs/fingerprintjs';
const { proxy } = getCurrentInstance();
const { lis_reqzt_type } = proxy.useDict("lis_reqzt_type"); //参数类别
const isExpand = ref(false);
const queryParams = reactive({
sqsj1: '',
sqsj2: '',
brdh: '',
brxm: '',
sqh: '',
mxjjzt: '',
jjzt: '',
pageNum: 1,
pageSize: 500,
})
const sumMoney = ref(0)
const total = ref(0)
const loading = ref(false)
// 数据源
const tableData = ref([])
// 配置项
const columns = ref([
{ field: 'yljg', title: '送检医院', align: 'center', resizable: true, slotName: 'yljg', width: 150 },
{ field: 'brlyname', title: '病人来源', align: 'center', resizable: true, width: 60 },
{ field: 'ksname', title: '申请科室', resizable: true, align: 'center', width: 100 },
{ field: 'yblx', title: '标本', align: 'center', resizable: true, width: 60 },
{ field: 'ch', title: '床号', resizable: true, align: 'center', width: 40 },//sortable: true,
{ field: 'brxm', title: '姓名', align: 'center', resizable: true, width: 50 },
{ field: 'brxbname', title: '性别', align: 'center', resizable: true, width: 30 },
{ field: 'brdh', title: '病历号', align: 'center', resizable: true, width: 80 },
{ field: 'sqh', title: '申请号', align: 'center', resizable: true, width: 90 },
{ field: 'bgddhname', title: '条码类别', align: 'center', resizable: true, width: 80 },
{ field: 'jjzt', title: '计价', align: 'center', resizable: true, width: 40, slotName: 'jjzt' },
{ field: 'sqxmmc', title: '申请项目', align: 'center', resizable: true, width: 150 },
{ field: 'sl', title: '数量', align: 'center', resizable: true, width: 40 },
{ field: 'dj', title: '单价', align: 'center', resizable: true, width: 60 },
{ field: 'mxjjzt', title: '明细计价', align: 'center', resizable: true, width: 60, slotName: 'mxjjzt' },
{ field: 'jzbz', title: '急', align: 'center', resizable: true, slotName: 'jzbz', width: 30 },
{ field: 'zt', title: '当前状态', align: 'center', resizable: true, slotName: 'zt', width: 60 },
{ field: 'refused', title: '拒收标记', align: 'center', resizable: true, slotName: 'bj', width: 60 },
{ field: 'sqxmdh', title: '项目代号', align: 'center', resizable: true, width: 60 },
{ field: 'sqysname', title: '申请医生', align: 'center', resizable: true, width: 60 },
{ field: 'sqsj', title: '申请时间', align: 'center', resizable: true, width: 150 },
{ field: 'zxysname', title: '执行医生', align: 'center', resizable: true, width: 60 },
{ field: 'zxsj', title: '执行/打印时间', align: 'center', resizable: true, width: 150 },
{ field: 'cysj', title: '采样时间', align: 'center', resizable: true, width: 150 },
{ field: 'bbsjsj', title: '标本送出时间', align: 'center', resizable: true, width: 150 },
{ field: 'jssj', title: '接收时间', align: 'center', resizable: true, width: 150 },
{ field: 'sjsj', title: '上机时间', align: 'center', resizable: true, width: 150 },
{ field: 'confirmer', title: '审核人', align: 'center', resizable: true, width: 60 },
{ field: 'confirmtime', title: '审核时间', align: 'center', resizable: true, width: 150 },
{ field: 'cyrname', title: '采样人', align: 'center', resizable: true, width: 60 },
{ field: 'bbsjrname', title: '标本送出人', align: 'center', resizable: true, width: 80 },
{ field: 'jsysname', title: '接收医生', align: 'center', resizable: true, width: 60 },
{ field: 'zd', title: '诊断', align: 'center', resizable: true, width: 60 },
{ field: 'inputman', title: '录入人', align: 'center', resizable: true, width: 60 },
{ field: 'powerman', title: '批准人', align: 'center', resizable: true, width: 60 },
{ field: 'contactman', title: '联系人', align: 'center', resizable: true, width: 60 },
{ field: 'xh', title: '相关编号', align: 'center', resizable: true, width: 60 },
{ field: 'inzt', title: '是否销毁', align: 'center', resizable: true, slotName: 'inzt', width: 60 },
{ field: 'libpos', title: '存放位置', align: 'center', resizable: true, width: 60 },
{ field: 'inlibtime', title: '存放时间', align: 'center', resizable: true, width: 60 },
{ field: 'inlibman', title: '存放人', align: 'center', resizable: true, width: 60 },
{ field: 'outlibtime', title: '销毁时间', align: 'center', resizable: true, width: 60 },
{ field: 'outlibman', title: '销毁人', align: 'center', resizable: true, width: 60 },
{ field: 'yqdh', title: '上机仪器', align: 'center', resizable: true, width: 60 },
{ field: 'phone', title: '病人联系电话', align: 'center', resizable: true, width: 100 },
{ field: 'phone1', title: '家属联系电话', align: 'center', resizable: true, width: 100 },
{ field: 'sfzh', title: '身份证号', align: 'center', resizable: true, width: 60 },
{ field: 'cp_cytojs', title: '接收TAT', align: 'center', resizable: true, width: 60 },
{ field: 'cp_jstobg', title: '报告TAT', align: 'center', resizable: true, width: 60 },
{ field: 'min1', title: '接收规定TAT', align: 'center', resizable: true, width: 100 },
{ field: 'min2', title: '报告规定TAT', align: 'center', resizable: true, width: 100 },
])
const handleColumnDragEnd = (data) => {
console.log("🚀 ~ handleColumnDragEnd ~ data:", data)
columns.value = [];
nextTick(() => {
columns.value = [...data.columns];
});
}
const handletime = () => {
const dayDiff = classCom.getDayDiff(queryParams.sqsj1, queryParams.sqsj2);
if (dayDiff === -1 || dayDiff === -2) return ElMessage.warning('请选择有效的日期范围');
}
const pagination = (val) => {
queryParams.pageSize = val.limit;
queryParams.pageNum = val.page;
handleQuery();
}
const handleQuery = () => {
loading.value = true;
// 查询数据
wholeprocessList(queryParams).then((res) => {
loading.value = false;
tableData.value = res.rows;
total.value = res.total;
sumMoney.value = (res.rows.reduce((acc, cur) => acc + cur.dj * cur.sl, 0)).toFixed(2);
});
}
const refresh = () => {
queryParams = {
st: '',
et: '',
brdh: '',
brxm: '',
sqh: '',
}
handleQuery();
}
const instrGroupOptions = ref([])
const instrGroupFields = ref([
{ prop: 'zddh', label: '代号', width: 80, enablePinyinSearch: true },
{ prop: 'zdmc', label: '名称', enablePinyinSearch: true },
])
// 部门
const getinstrGroupOptions = () => {
getComDicts({ zdlb: 'GROUP' }).then((res) => {
instrGroupOptions.value = res.data
instrGroupOptions.value.push({ zddh: 'ALL', zdmc: '所有仪器' })
});
}
const timeDate = () => {
// 获取当前日期(当天)
const today = dayjs();
// 计算前6天的日期(当天 + 前6天 = 7天)
const startOfWeek = today.subtract(6, 'day');
// queryParams.sqsj1 = startOfWeek.format('YYYY-MM-DD');
// queryParams.sqsj2 = today.format('YYYY-MM-DD');
queryParams.sqsj1 = '2025-08-01';
queryParams.sqsj2 = today.format('YYYY-MM-DD');
}
onMounted(() => {
timeDate()
getinstrGroupOptions()
getDictData('HOS', 'PT', 'ST');
handleQuery()
})
</script>
<style scoped lang="scss">
.table-container {
height: calc(100% - 150px);
}
.el-form-item {
margin-bottom: 10px;
}
.footer-pagination {
display: flex;
justify-content: space-between;
align-items: center;
height: 50px;
.pagination {
margin-top: 0;
padding: 0;
}
}
.text-tips {
font-family: SourceHanSansCN, SourceHanSansCN;
font-size: 16px;
color: #409eff;
font-weight: 600;
span {
display: inline-block;
width: 100px;
}
}
</style>

View File

@ -16,6 +16,9 @@
<el-col :span="1.5">
<el-button type="primary" plain @click="saveData">保存</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" plain @click="clearData">清除</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" plain>打印</el-button>
</el-col>
@ -67,7 +70,7 @@
<script setup>
import { refusedbarcode, refusedSaveData } from '@/api/liswork/work/LisWork';
import { formatDict, getDictData } from '@/hooks'
import { ElMessage } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import { listUser } from '@/api/system/user.js'
import CheckUser from "@/views/liswork/work/components/CheckUser.vue";
import SelectUser from "./selectUser.vue";
@ -164,6 +167,25 @@ const saveData = () => {
if (!flag) return ElMessage.warning('请填写完整拒收信息!')
checkUserRef.value.open()
}
const clearData = () => {
ElMessageBox.confirm(
`确定清除 ${tableData.value.length} 条数据吗?`,
'数据清除',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
closeOnPressEscape: true,
}
).then(() => {
tableData.value = []
ElMessage.success('成功清除表格全部数据')
}).catch((reason) => {
})
}
// 校验用户
const handleCheckUserConfirm = (info) => {
checkuser({ yhdh: info.yhdh, mm: info.mm }).then(response => {

View File

@ -1,278 +1,238 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
<el-form-item label="菜单名称" prop="menuName">
<el-input
v-model="queryParams.menuName"
placeholder="请输入菜单名称"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable style="width: 200px">
<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>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
<el-form-item label="菜单名称" prop="menuName">
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable style="width: 200px"
@keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable style="width: 200px">
<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>
<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:menu:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="Sort" @click="toggleExpandAll">展开/折叠</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-if="refreshTable" v-loading="loading" :data="menuList" row-key="menuId"
:default-expand-all="isExpandAll" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
height="calc(100vh - 200px)">
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
<el-table-column prop="icon" label="图标" align="center" width="100">
<template #default="scope">
<svg-icon :icon-class="scope.row.icon" />
</template>
</el-table-column>
<el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" width="160" prop="createTime">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="210" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-hasPermi="['system:menu:edit']">修改</el-button>
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)"
v-hasPermi="['system:menu:add']">新增</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-hasPermi="['system:menu:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改菜单对话框 -->
<el-dialog :title="title" v-model="open" width="680px" append-to-body>
<el-form ref="menuRef" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="24">
<el-form-item label="上级菜单">
<el-tree-select v-model="form.parentId" :data="menuOptions"
:props="{ value: 'menuId', label: 'menuName', children: 'children' }" value-key="menuId"
placeholder="选择上级菜单" check-strictly />
</el-form-item>
</el-col>
<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-group>
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.menuType != 'F'">
<el-form-item label="菜单图标" prop="icon">
<el-popover placement="bottom-start" :width="540" trigger="click">
<template #reference>
<el-input v-model="form.icon" placeholder="点击选择图标" @blur="showSelectIcon" readonly>
<template #prefix>
<svg-icon v-if="form.icon" :icon-class="form.icon" class="el-input__icon"
style="height: 32px;width: 16px;" />
<el-icon v-else style="height: 32px;width: 16px;">
<search />
</el-icon>
</template>
</el-input>
</template>
<icon-select ref="iconSelectRef" @selected="selected" :active-icon="form.icon" />
</el-popover>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="菜单名称" prop="menuName">
<el-input v-model="form.menuName" placeholder="请输入菜单名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示排序" prop="orderNum">
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-form-item>
<template #label>
<span>
<el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>是否外链
</span>
</template>
<el-radio-group v-model="form.isFrame">
<el-radio label="0">是</el-radio>
<el-radio label="1">否</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-form-item prop="path">
<template #label>
<span>
<el-tooltip content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
路由地址
</span>
</template>
<el-input v-model="form.path" placeholder="请输入路由地址" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item prop="component">
<template #label>
<span>
<el-tooltip content="访问的组件路径,如:`system/user/index`,默认在`views`目录下" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
组件路径
</span>
</template>
<el-input v-model="form.component" placeholder="请输入组件路径" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'M'">
<el-form-item>
<el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
<template #label>
<span>
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
权限字符
</span>
</template>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item>
<el-input v-model="form.query" placeholder="请输入路由参数" maxlength="255" />
<template #label>
<span>
<el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
路由参数
</span>
</template>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item>
<template #label>
<span>
<el-tooltip content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
是否缓存
</span>
</template>
<el-radio-group v-model="form.isCache">
<el-radio label="0">缓存</el-radio>
<el-radio label="1">不缓存</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-form-item>
<template #label>
<span>
<el-tooltip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
显示状态
</span>
</template>
<el-radio-group v-model="form.visible">
<el-radio v-for="dict in sys_show_hide" :key="dict.value" :label="dict.value">{{ dict.label
}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
<span>
<el-tooltip content="选择停用则路由将不会出现在侧边栏,也不能被访问" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
菜单状态
</span>
</template>
<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-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['system:menu:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="Sort"
@click="toggleExpandAll"
>展开/折叠</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
v-if="refreshTable"
v-loading="loading"
:data="menuList"
row-key="menuId"
:default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
<el-table-column prop="icon" label="图标" align="center" width="100">
<template #default="scope">
<svg-icon :icon-class="scope.row.icon" />
</template>
</el-table-column>
<el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="status" label="状态" width="80">
<template #default="scope">
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" width="160" prop="createTime">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="210" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:menu:edit']">修改</el-button>
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['system:menu:add']">新增</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:menu:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改菜单对话框 -->
<el-dialog :title="title" v-model="open" width="680px" append-to-body>
<el-form ref="menuRef" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="24">
<el-form-item label="上级菜单">
<el-tree-select
v-model="form.parentId"
:data="menuOptions"
:props="{ value: 'menuId', label: 'menuName', children: 'children' }"
value-key="menuId"
placeholder="选择上级菜单"
check-strictly
/>
</el-form-item>
</el-col>
<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-group>
</el-form-item>
</el-col>
<el-col :span="24" v-if="form.menuType != 'F'">
<el-form-item label="菜单图标" prop="icon">
<el-popover
placement="bottom-start"
:width="540"
trigger="click"
>
<template #reference>
<el-input v-model="form.icon" placeholder="点击选择图标" @blur="showSelectIcon" readonly>
<template #prefix>
<svg-icon
v-if="form.icon"
:icon-class="form.icon"
class="el-input__icon"
style="height: 32px;width: 16px;"
/>
<el-icon v-else style="height: 32px;width: 16px;"><search /></el-icon>
</template>
</el-input>
</template>
<icon-select ref="iconSelectRef" @selected="selected" :active-icon="form.icon" />
</el-popover>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="菜单名称" prop="menuName">
<el-input v-model="form.menuName" placeholder="请输入菜单名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示排序" prop="orderNum">
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-form-item>
<template #label>
<span>
<el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>是否外链
</span>
</template>
<el-radio-group v-model="form.isFrame">
<el-radio label="0">是</el-radio>
<el-radio label="1">否</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-form-item prop="path">
<template #label>
<span>
<el-tooltip content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
路由地址
</span>
</template>
<el-input v-model="form.path" placeholder="请输入路由地址" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item prop="component">
<template #label>
<span>
<el-tooltip content="访问的组件路径,如:`system/user/index`,默认在`views`目录下" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
组件路径
</span>
</template>
<el-input v-model="form.component" placeholder="请输入组件路径" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'M'">
<el-form-item>
<el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100" />
<template #label>
<span>
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
权限字符
</span>
</template>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item>
<el-input v-model="form.query" placeholder="请输入路由参数" maxlength="255" />
<template #label>
<span>
<el-tooltip content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`' placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
路由参数
</span>
</template>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType == 'C'">
<el-form-item>
<template #label>
<span>
<el-tooltip content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
是否缓存
</span>
</template>
<el-radio-group v-model="form.isCache">
<el-radio label="0">缓存</el-radio>
<el-radio label="1">不缓存</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" v-if="form.menuType != 'F'">
<el-form-item>
<template #label>
<span>
<el-tooltip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
显示状态
</span>
</template>
<el-radio-group v-model="form.visible">
<el-radio
v-for="dict in sys_show_hide"
:key="dict.value"
:label="dict.value"
>{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
<span>
<el-tooltip content="选择停用则路由将不会出现在侧边栏,也不能被访问" placement="top">
<el-icon><question-filled /></el-icon>
</el-tooltip>
菜单状态
</span>
</template>
<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-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 #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="Menu">
@ -415,12 +375,12 @@ function submitForm() {
}
/** 删除按钮操作 */
function handleDelete(row) {
proxy.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function() {
proxy.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function () {
return delMenu(row.menuId);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => {});
}).catch(() => { });
}
getList();