菜单管理

This commit is contained in:
sjl
2024-11-18 16:02:19 +08:00
parent 5cdbee88b4
commit a57ebbcc62
14 changed files with 355 additions and 292 deletions

View File

@@ -3,11 +3,13 @@
<el-form :model="formContent" ref='dialogFormRef' :rules='rules' >
<el-form-item label="上级菜单" prop="pid" :label-width="100">
<el-tree-select
v-model="formContent.pid"
v-model="displayPid"
:data="functionList"
check-strictly
:render-after-expand="false"
show-checkbox
check-on-click-node
node-key="id"
:props="defaultProps"
/>
</el-form-item>
@@ -20,7 +22,7 @@
<el-form-item label="图标" prop="icon" :label-width="100">
<IconSelect
:iconValue="formContent.icon"
@update:iconValue="(value) => formContent.icon = value"
@update:icon-value="iconValue => formContent.icon = iconValue"
placeholder="选择一个图标"
/>
</el-form-item>
@@ -37,8 +39,8 @@
<el-select v-model="formContent.type" clearable placeholder="请选择资源类型">
<el-option label="菜单" :value="0"></el-option>
<el-option label="按钮" :value="1"></el-option>
<el-option label="公共资源" :value="2"></el-option>
<el-option label="服务间调用资源" :value="3"></el-option>
<!-- <el-option label="公共资源" :value="2"></el-option>
<el-option label="服务间调用资源" :value="3"></el-option> -->
</el-select>
</el-form-item>
<el-form-item label="描述" prop="remark" :label-width="100">
@@ -67,8 +69,9 @@
const defaultProps = {
children: 'children',
label: 'name',
value: 'id'
};
const functionList = ref<Function.ResFunction[]>([])
const dictStore = useDictStore()
// 定义弹出组件元信息
const dialogFormRef = ref()
@@ -91,7 +94,7 @@
})
return { dialogVisible, titleType, formContent }
}
const { dialogVisible, titleType, formContent } = useMetaInfo()
// 清空formContent
const resetFormContent = () => {
@@ -136,12 +139,29 @@ const close = () => {
dialogFormRef.value?.resetFields()
}
// 计算属性,用于控制显示的 pid
const displayPid = computed({
get: () => {
return formContent.value.pid === '0' ? '' : formContent.value.pid;
},
set: (value) => {
formContent.value.pid = value;
}
});
// 保存数据
const save = () => {
try {
console.log(formContent.value)
dialogFormRef.value?.validate(async (valid: boolean) => {
console.log(formContent.value)
if (formContent.value.pid === undefined || formContent.value.pid === null || formContent.value.pid === '') {
formContent.value.pid = '0';
}
if (formContent.value.pids === undefined || formContent.value.pids === null || formContent.value.pids === '') {
formContent.value.pids = '0';
}
if (valid) {
if (formContent.value.id) {
await updateFunction(formContent.value);
@@ -152,20 +172,26 @@ const close = () => {
close()
// 刷新表格
await props.refreshTable!()
}
})
} catch (err) {
//console.error('验证过程中出现错误', err)
console.error('验证过程中出现错误', err)
}
}
const functionList = ref<Function.ResFunction[]>([])
// 打开弹窗,可能是新增,也可能是编辑
const open = async (sign: string, data: Function.ResFunction) => {
const response = await getFunctionListNoButton()
functionList.value = response.data as unknown as Function.ResFunction[]
titleType.value = sign
dialogVisible.value = true
if (formContent.value.pid ==='0') {
formContent.value.pid = '';
}
if (data.id) {
formContent.value = { ...data }
} else {

View File

@@ -28,11 +28,12 @@
import { useHandleData } from '@/hooks/useHandleData'
import type { Function } from "@/api/user/interface/function"
import ProTable from '@/components/ProTable/index.vue'
import {CirclePlus, Delete, EditPen,HomeFilled} from '@element-plus/icons-vue'
import {Back, CirclePlus, Delete, EditPen,HomeFilled} from '@element-plus/icons-vue'
import type { ColumnProps, ProTableInstance } from '@/components/ProTable/interface'
import { useDictStore } from '@/stores/modules/dict'
import ResourcePopup from './components/resourcePopup.vue'
import {deleteFunction,getFunctionList} from '@/api/user/function/index'
import * as Icons from '@element-plus/icons-vue'
const dictStore = useDictStore()
const resourcePopup = ref()
// ProTable 实例
@@ -45,6 +46,8 @@
prop: 'name',
label: '名称',
minWidth: 150,
align:'left',
headerAlign: 'center',
search: { el: 'input' },
},
{
@@ -73,7 +76,18 @@
prop: 'icon',
label: '图标',
minWidth: 100,
render: scope => {
const customIcons: { [key: string]: any } = Icons
const iconKey = scope.row.icon; //
if (!iconKey || !customIcons[iconKey]) {
// 如果 iconKey 为空或未定义,或者 customIcons 中找不到对应的图标,返回一个空的 <span> 标签
return <span></span>;
}
const icon = customIcons[iconKey]; // 如果找不到图标,使用默认图标
return (
<el-button icon={icon} />
);
},
},
{
prop: 'path',
@@ -97,6 +111,7 @@
minWidth: 70,
render: scope => {
return (
<el-tag type={scope.row.state ? 'success' : 'danger'} > {scope.row.state ? '正常' : '禁用'} </el-tag>
)
},

View File

@@ -9,8 +9,8 @@
<el-form-item label="用户名" prop='name' :label-width="100">
<el-input v-model="formContent.name" placeholder="请输入用户名" autocomplete="off" />
</el-form-item>
<el-form-item label="登录名" prop='loginName' :label-width="100">
<el-input v-model="formContent.loginName" placeholder="请输入登录名" autocomplete="off" />
<el-form-item label="登录名" prop='loginName' :label-width="100" >
<el-input v-model="formContent.loginName" placeholder="请输入登录名" autocomplete="off" :disabled="LoginNameIsShow"/>
</el-form-item>
<el-form-item label="密码" prop='password' :label-width="100" v-if="IsPasswordShow">
<el-input type="password" v-model="formContent.password" show-password placeholder="请输入密码" autocomplete="off" />
@@ -64,6 +64,7 @@
const dialogFormRef = ref()
const IsPasswordShow = ref(false)
const roleList = ref<Role.RoleBO[]>([])
const LoginNameIsShow = ref(false)
function useMetaInfo() {
const dialogVisible = ref(false)
const titleType = ref('add')
@@ -112,7 +113,7 @@
// 指定正则,此处是数字正则
{ pattern: /^[A-Za-z\u4e00-\u9fa5]{1,16}$/, message: '名称需1~16位的英文或汉字', trigger: 'blur' }],
loginName: [{ required: true, message: '登录名必填!', trigger: 'blur' },
{ pattern: /^[a-zA-Z_.]{1}[a-zA-Z0-9_.]{2,15}$/, message: '登录名需2-15位的字母数字符号', trigger: 'blur' }],
{ pattern: /^[a-zA-Z]{1}[a-zA-Z0-9]{2,15}$/, message: '格式错误需以字母开头长度为3-16位的字母数字', trigger: 'blur' }],
password: [{ required: true, message: '密码必填!', trigger: 'blur' },
{ pattern: /^(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,16}$/, message: '密码长度为8-16需包含特殊字符', trigger: 'blur' }],
})
@@ -156,9 +157,11 @@
dialogVisible.value = true
if (data.id) {
IsPasswordShow.value = false
LoginNameIsShow.value = true
formContent.value = { ...data }
} else {
IsPasswordShow.value = true
LoginNameIsShow.value = false
resetFormContent()
}
}

View File

@@ -25,7 +25,14 @@
</el-col>
<el-col :span="8">
<el-form-item label='设备模式' prop='pattern' :label-width="100">
<el-input v-model='formContent.pattern' disabled/>
<el-select v-model="formContent.pattern" clearable placeholder="请选择设备模式" disabled>
<el-option
v-for="item in dictStore.getDictData('Pattern')"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
@@ -382,12 +389,17 @@ const disabledDate = (time: Date) => {
}
}
// 打开弹窗,可能是新增,也可能是编辑
const open = (sign: string, data: Device.ResPqDev) => {
titleType.value = sign
dialogVisible.value = true
if(data.pattern ==='比对式'){
const patternItem = dictStore.getDictData('Pattern').find(item => item.id === data.pattern)
if( patternItem && patternItem.name ==='比对式'){
DevIsShow.value = false
MonIsShow.value = true
}else{

View File

@@ -41,7 +41,7 @@ import { CirclePlus, Delete, EditPen, Download, Upload } from '@element-plus/ico
import { useDictStore } from '@/stores/modules/dict'
import { getPqDevList, deletePqDev, exportPqDev, downloadTemplate, importPqDev } from '@/api/device/device/index.ts'
import { ElMessageBox } from 'element-plus'
import { reactive, ref } from 'vue'
import { computed, reactive, ref } from 'vue'
const dictStore = useDictStore()
// ProTable 实例
@@ -134,6 +134,8 @@ const openDialog = (titleType: string, row: Partial<Device.ResPqDev> = {}) => {
devicePopup.value?.open(titleType, row)
}
// 批量删除设备
const batchDelete = async (id: string[]) => {
await useHandleData(deletePqDev, id, '删除所选设备')

View File

@@ -29,24 +29,21 @@
</template>
<script setup lang='tsx' name='useRole'>
import { TestScript } from '@/api/device/interface/testScript'
import { type TestScript } from '@/api/device/interface/testScript'
import { useHandleData } from '@/hooks/useHandleData'
import { useDownload } from '@/hooks/useDownload'
import { useAuthButtons } from '@/hooks/useAuthButtons'
import ProTable from '@/components/ProTable/index.vue'
import ImportExcel from '@/components/ImportExcel/index.vue'
import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
import type{ ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
import { CirclePlus, Delete, EditPen, Share, Download, Upload, View, Refresh } from '@element-plus/icons-vue'
import testScriptDataList from '@/api/device/testScript/testScriptData'
import { useDictStore } from '@/stores/modules/dict'
import {
getTestScriptList,
} from '@/api/device/testScript/testScript'
} from '@/api/device/testScript/index'
const dictStore = useDictStore()
// const testScriptData = testScriptDataList
// ProTable 实例
const proTable = ref<ProTableInstance>()

View File

@@ -39,7 +39,7 @@
</template>
<script lang="tsx" setup>
import {dialogSmall} from "@/utils/elementBind";
import {addDictData, updateDictData} from "@/api/system/dictionary/dictData";
import {addDictData, updateDictData} from "@/api/system/dictionary/dictData/index.ts";
import {Dict} from "@/api/system/dictionary/interface";
import {ElMessage, FormItemRule} from "element-plus";
import type {Ref} from "vue";

View File

@@ -27,10 +27,10 @@
<script setup lang="tsx" name="dictData">
import {CirclePlus, Delete, Download, EditPen} from '@element-plus/icons-vue'
import {Dict} from '@/api/system/dictionary/interface'
import {type Dict} from '@/api/system/dictionary/interface'
import {ColumnProps, ProTableInstance} from '@/components/ProTable/interface'
import {useHandleData} from '@/hooks/useHandleData'
import {deleteDictData, getDictDataListByTypeId, exportDictData} from "@/api/system/dictionary/dictData";
import {deleteDictData, getDictDataListByTypeId, exportDictData} from "@/api/system/dictionary/dictData/index";
import {useDownload} from "@/hooks/useDownload";
import {exportDictType} from "@/api/system/dictionary/dictType";

View File

@@ -46,6 +46,7 @@
label: '字典名称',
align:'left',
headerAlign: 'center',
search: { el: 'input' },
},
{
prop: 'code',