dev-cl
parent
ef1ba0e84f
commit
461248b8da
@ -1,205 +0,0 @@ |
|||||||
<template> |
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="800px"> |
|
||||||
<el-form |
|
||||||
ref="formRef" |
|
||||||
v-loading="formLoading" |
|
||||||
:model="formData" |
|
||||||
:rules="formRules" |
|
||||||
label-width="80px" |
|
||||||
> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="12" :offset="0"> |
|
||||||
<el-form-item label="上级部门" prop="parentId"> |
|
||||||
<el-tree-select |
|
||||||
v-model="formData.parentId" |
|
||||||
:data="deptTree" |
|
||||||
:props="defaultProps" |
|
||||||
check-strictly |
|
||||||
default-expand-all |
|
||||||
placeholder="请选择上级部门" |
|
||||||
value-key="deptId" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
<el-col :span="12" :offset="0"> |
|
||||||
<el-form-item label="部门名称" prop="name"> |
|
||||||
<el-input v-model="formData.name" placeholder="请输入部门名称" /> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="12" :offset="0"> |
|
||||||
<el-form-item label="负责人" prop="leaderUserId"> |
|
||||||
<el-select |
|
||||||
v-model="formData.leaderUserId" |
|
||||||
clearable |
|
||||||
filterable |
|
||||||
placeholder="请输入负责人" |
|
||||||
> |
|
||||||
<el-option |
|
||||||
v-for="item in employeeOptions" |
|
||||||
:key="item.id" |
|
||||||
:disabled="item.status == 1" |
|
||||||
:label="item.name" |
|
||||||
:value="item.id" |
|
||||||
/> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
<el-col :span="12" :offset="0"> |
|
||||||
<el-form-item label="状态" prop="status"> |
|
||||||
<el-radio-group v-model="formData.status"> |
|
||||||
<el-radio :value="0"> 启用 </el-radio> |
|
||||||
<el-radio :value="1"> 禁用 </el-radio> |
|
||||||
</el-radio-group> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="12" :offset="0"> |
|
||||||
<el-form-item label="排序" prop="sort"> |
|
||||||
<el-input-number v-model="formData.sort" :min="0" /> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
<el-col :span="12" :offset="0"> |
|
||||||
<el-form-item label="业务系统" prop="instanceId"> |
|
||||||
<el-select |
|
||||||
v-model="formData.instanceId" |
|
||||||
placeholder="选择主业务系统" |
|
||||||
clearable |
|
||||||
filterable |
|
||||||
> |
|
||||||
<el-option |
|
||||||
v-for="item in instanceIdOptions" |
|
||||||
:key="item.instanceId" |
|
||||||
:label="item.instanceName" |
|
||||||
:disabled="item.status == 1" |
|
||||||
:value="item.instanceId" |
|
||||||
/> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="24" :offset="0"> |
|
||||||
<el-form-item label="备注" prop="remark"> |
|
||||||
<Editor v-model:modelValue="formData.remark" /> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
</el-form> |
|
||||||
<template #footer> |
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button> |
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button> |
|
||||||
</template> |
|
||||||
</Dialog> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="SystemDeptForm" setup> |
|
||||||
import { defaultProps, handleTree } from '@/utils/tree' |
|
||||||
import * as DeptApi from '@/api/system/dept' |
|
||||||
import { getEmployeeSimpleList } from '@/api/pers/employee' |
|
||||||
import { CommonStatusEnum } from '@/utils/constants' |
|
||||||
import { getSimpleAppList } from '@/api/system/app' |
|
||||||
|
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
|
|
||||||
const dialogVisible = ref(false) // 弹窗的是否展示 |
|
||||||
const dialogTitle = ref('') // 弹窗的标题 |
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
|
||||||
const formData = ref<any>({}) |
|
||||||
const formRules = reactive<any>({ |
|
||||||
parentId: [{ required: true, message: '上级部门不能为空', trigger: 'blur' }], |
|
||||||
name: [{ required: true, message: '部门名称不能为空', trigger: 'blur' }], |
|
||||||
sort: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }], |
|
||||||
email: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }], |
|
||||||
phone: [ |
|
||||||
{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' } |
|
||||||
], |
|
||||||
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }] |
|
||||||
}) |
|
||||||
const formRef = ref() // 表单 Ref |
|
||||||
const deptTree = ref() // 树形结构 |
|
||||||
const employeeOptions = ref<any>([]) // 用户列表 |
|
||||||
const instanceIdOptions = ref<any>([]) // 实例ids |
|
||||||
|
|
||||||
/** 打开弹窗 */ |
|
||||||
const open = async (type: string, id?: number) => { |
|
||||||
dialogVisible.value = true |
|
||||||
dialogTitle.value = t('action.' + type) |
|
||||||
formType.value = type |
|
||||||
resetForm() |
|
||||||
// 修改时,设置数据 |
|
||||||
if (id) { |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
formData.value = await DeptApi.getDept(id) |
|
||||||
formData.value.remark = formData.value.remark || '' |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
// 获得用户列表 |
|
||||||
getEmployeeSimpleList().then((data) => { |
|
||||||
employeeOptions.value = data |
|
||||||
}) |
|
||||||
//实例 |
|
||||||
getSimpleAppList().then((data) => { |
|
||||||
instanceIdOptions.value = data |
|
||||||
}) |
|
||||||
// 获得部门树 |
|
||||||
await getTree() |
|
||||||
} |
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
|
||||||
|
|
||||||
/** 提交表单 */ |
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
|
||||||
const submitForm = async () => { |
|
||||||
// 校验表单 |
|
||||||
if (!formRef.value) return |
|
||||||
const valid = await formRef.value.validate() |
|
||||||
if (!valid) return |
|
||||||
// 提交请求 |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
const data = formData.value as unknown as DeptApi.DeptVO |
|
||||||
if (formType.value === 'create') { |
|
||||||
await DeptApi.createDept(data) |
|
||||||
message.success(t('common.createSuccess')) |
|
||||||
} else { |
|
||||||
await DeptApi.updateDept(data) |
|
||||||
message.success(t('common.updateSuccess')) |
|
||||||
} |
|
||||||
dialogVisible.value = false |
|
||||||
// 发送操作成功的事件 |
|
||||||
emit('success') |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置表单 */ |
|
||||||
const resetForm = () => { |
|
||||||
formData.value = { |
|
||||||
id: undefined, |
|
||||||
parentId: undefined, |
|
||||||
name: undefined, |
|
||||||
sort: 1, |
|
||||||
leaderUserId: undefined, |
|
||||||
status: CommonStatusEnum.ENABLE, |
|
||||||
remark: undefined, |
|
||||||
instanceId: undefined |
|
||||||
} |
|
||||||
formRef.value?.resetFields() |
|
||||||
} |
|
||||||
|
|
||||||
/** 获得部门树 */ |
|
||||||
const getTree = async () => { |
|
||||||
deptTree.value = [] |
|
||||||
const data = await DeptApi.getSimpleDeptList({ allFlag: true }) |
|
||||||
let dept: Tree = { id: 0, name: '顶级部门', children: [] } |
|
||||||
dept.children = handleTree(data) |
|
||||||
deptTree.value.push(dept) |
|
||||||
} |
|
||||||
</script> |
|
@ -1,121 +0,0 @@ |
|||||||
<template> |
|
||||||
<!-- 搜索工作栏 --> |
|
||||||
<el-form :model="queryParams" ref="queryFormRef" inline label-width="0"> |
|
||||||
<el-form-item> |
|
||||||
<el-input |
|
||||||
v-model="queryParams.name" |
|
||||||
placeholder="请输入部门名称" |
|
||||||
clearable |
|
||||||
class="!w-240px" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item> |
|
||||||
<el-button @click="handleQuery" v-hasPermi="['basic:dept:search']"> 搜索</el-button> |
|
||||||
<el-button @click="resetQuery" v-hasPermi="['basic:dept:reset']"> 重置</el-button> |
|
||||||
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['basic:dept:add']"> |
|
||||||
新增 |
|
||||||
</el-button> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
|
|
||||||
<!-- 列表 --> |
|
||||||
<el-table v-loading="loading" :data="list" row-key="id" default-expand-all border> |
|
||||||
<el-table-column prop="name" label="部门名称" /> |
|
||||||
<el-table-column prop="leaderUserName" label="负责人" width="120" /> |
|
||||||
<el-table-column prop="instanceName" label="业务系统" width="200" /> |
|
||||||
<el-table-column prop="sort" label="排序" width="80" /> |
|
||||||
<el-table-column prop="status" label="状态" width="100"> |
|
||||||
<template #default="scope"> |
|
||||||
<el-tag :type="scope.row.status == 0 ? 'success' : 'danger'"> |
|
||||||
{{ scope.row.status == 0 ? '正常' : '停用' }} |
|
||||||
</el-tag> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
<el-table-column label="创建时间" prop="createTime" width="180" :formatter="dateFormatter" /> |
|
||||||
<el-table-column label="操作" class-name="fixed-width" width="160"> |
|
||||||
<template #default="scope"> |
|
||||||
<el-button |
|
||||||
link |
|
||||||
type="primary" |
|
||||||
@click="openForm('update', scope.row.id)" |
|
||||||
v-hasPermi="['basic:dept:update']" |
|
||||||
> |
|
||||||
修改 |
|
||||||
</el-button> |
|
||||||
<el-button |
|
||||||
link |
|
||||||
type="danger" |
|
||||||
@click="handleDelete(scope.row.id)" |
|
||||||
v-hasPermi="['basic:dept:delete']" |
|
||||||
> |
|
||||||
删除 |
|
||||||
</el-button> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
</el-table> |
|
||||||
|
|
||||||
<!-- 表单弹窗:添加/修改 --> |
|
||||||
<DeptForm ref="formRef" @success="getList" /> |
|
||||||
</template> |
|
||||||
<script setup lang="ts" name="SystemDept"> |
|
||||||
import { handleTree } from '@/utils/tree' |
|
||||||
import * as DeptApi from '@/api/system/dept' |
|
||||||
import DeptForm from './DeptForm.vue' |
|
||||||
import { dateFormatter } from '@/utils/formatTime' |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
|
|
||||||
const loading = ref(true) // 列表的加载中 |
|
||||||
const list = ref() // 列表的数据 |
|
||||||
const queryParams = reactive({ |
|
||||||
allFlag: true, |
|
||||||
name: undefined |
|
||||||
}) |
|
||||||
const queryFormRef = ref() // 搜索的表单 |
|
||||||
|
|
||||||
/** 查询部门列表 */ |
|
||||||
const getList = async () => { |
|
||||||
loading.value = true |
|
||||||
try { |
|
||||||
const data = await DeptApi.getDeptPage(queryParams) |
|
||||||
list.value = handleTree(data) |
|
||||||
} finally { |
|
||||||
loading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 搜索按钮操作 */ |
|
||||||
const handleQuery = () => { |
|
||||||
getList() |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置按钮操作 */ |
|
||||||
const resetQuery = () => { |
|
||||||
queryFormRef.value.resetFields() |
|
||||||
handleQuery() |
|
||||||
} |
|
||||||
|
|
||||||
/** 添加/修改操作 */ |
|
||||||
const formRef = ref() |
|
||||||
const openForm = (type: string, id?: number) => { |
|
||||||
formRef.value.open(type, id) |
|
||||||
} |
|
||||||
|
|
||||||
/** 删除按钮操作 */ |
|
||||||
const handleDelete = async (id: number) => { |
|
||||||
try { |
|
||||||
// 删除的二次确认 |
|
||||||
await message.delConfirm() |
|
||||||
// 发起删除 |
|
||||||
await DeptApi.deleteDept(id) |
|
||||||
message.success(t('common.delSuccess')) |
|
||||||
// 刷新列表 |
|
||||||
await getList() |
|
||||||
} catch {} |
|
||||||
} |
|
||||||
|
|
||||||
/** 初始化 **/ |
|
||||||
onMounted(async () => { |
|
||||||
await getList() |
|
||||||
}) |
|
||||||
</script> |
|
@ -1,122 +0,0 @@ |
|||||||
<template> |
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle"> |
|
||||||
<el-form |
|
||||||
ref="formRef" |
|
||||||
v-loading="formLoading" |
|
||||||
:model="formData" |
|
||||||
:rules="formRules" |
|
||||||
label-width="80px" |
|
||||||
> |
|
||||||
<el-form-item label="字典名称" prop="name"> |
|
||||||
<el-input v-model="formData.name" placeholder="请输入字典名称" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="字典类型" prop="type"> |
|
||||||
<el-input |
|
||||||
v-model="formData.type" |
|
||||||
:disabled="typeof formData.id !== 'undefined'" |
|
||||||
placeholder="请输入参数名称" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="状态" prop="status"> |
|
||||||
<el-radio-group v-model="formData.status"> |
|
||||||
<el-radio |
|
||||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
|
||||||
:key="dict.value" |
|
||||||
:label="dict.value" |
|
||||||
> |
|
||||||
{{ dict.label }} |
|
||||||
</el-radio> |
|
||||||
</el-radio-group> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="备注" prop="remark"> |
|
||||||
<el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
<template #footer> |
|
||||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button> |
|
||||||
</template> |
|
||||||
</Dialog> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="SystemDictTypeForm" setup> |
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
|
||||||
import * as DictTypeApi from '@/api/system/dict/dict.type' |
|
||||||
import { CommonStatusEnum } from '@/utils/constants' |
|
||||||
|
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
|
|
||||||
const dialogVisible = ref(false) // 弹窗的是否展示 |
|
||||||
const dialogTitle = ref('') // 弹窗的标题 |
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
|
||||||
const formData = ref({ |
|
||||||
id: undefined, |
|
||||||
name: '', |
|
||||||
type: '', |
|
||||||
status: CommonStatusEnum.ENABLE, |
|
||||||
remark: '' |
|
||||||
}) |
|
||||||
const formRules = reactive({ |
|
||||||
name: [{ required: true, message: '字典名称不能为空', trigger: 'blur' }], |
|
||||||
type: [{ required: true, message: '字典类型不能为空', trigger: 'blur' }], |
|
||||||
status: [{ required: true, message: '状态不能为空', trigger: 'change' }] |
|
||||||
}) |
|
||||||
const formRef = ref() // 表单 Ref |
|
||||||
|
|
||||||
/** 打开弹窗 */ |
|
||||||
const open = async (type: string, id?: number) => { |
|
||||||
dialogVisible.value = true |
|
||||||
dialogTitle.value = t('action.' + type) |
|
||||||
formType.value = type |
|
||||||
resetForm() |
|
||||||
// 修改时,设置数据 |
|
||||||
if (id) { |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
formData.value = await DictTypeApi.getDictType(id) |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
|
||||||
|
|
||||||
/** 提交表单 */ |
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
|
||||||
const submitForm = async () => { |
|
||||||
// 校验表单 |
|
||||||
if (!formRef.value) return |
|
||||||
const valid = await formRef.value.validate() |
|
||||||
if (!valid) return |
|
||||||
// 提交请求 |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
const data = formData.value as DictTypeApi.DictTypeVO |
|
||||||
if (formType.value === 'create') { |
|
||||||
await DictTypeApi.createDictType(data) |
|
||||||
message.success(t('common.createSuccess')) |
|
||||||
} else { |
|
||||||
await DictTypeApi.updateDictType(data) |
|
||||||
message.success(t('common.updateSuccess')) |
|
||||||
} |
|
||||||
dialogVisible.value = false |
|
||||||
// 发送操作成功的事件 |
|
||||||
emit('success') |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置表单 */ |
|
||||||
const resetForm = () => { |
|
||||||
formData.value = { |
|
||||||
id: undefined, |
|
||||||
type: '', |
|
||||||
name: '', |
|
||||||
status: CommonStatusEnum.ENABLE, |
|
||||||
remark: '' |
|
||||||
} |
|
||||||
formRef.value?.resetFields() |
|
||||||
} |
|
||||||
</script> |
|
@ -1,181 +0,0 @@ |
|||||||
<template> |
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle"> |
|
||||||
<el-form |
|
||||||
ref="formRef" |
|
||||||
v-loading="formLoading" |
|
||||||
:model="formData" |
|
||||||
:rules="formRules" |
|
||||||
label-width="80px" |
|
||||||
> |
|
||||||
<el-form-item label="字典类型" prop="type"> |
|
||||||
<el-input |
|
||||||
v-model="formData.dictType" |
|
||||||
:disabled="typeof formData.id !== 'undefined'" |
|
||||||
placeholder="请输入参数名称" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="数据标签" prop="label"> |
|
||||||
<el-input v-model="formData.label" placeholder="请输入数据标签" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="数据键值" prop="value"> |
|
||||||
<el-input v-model="formData.value" placeholder="请输入数据键值" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="显示排序" prop="sort"> |
|
||||||
<el-input-number v-model="formData.sort" :min="0" controls-position="right" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="状态" prop="status"> |
|
||||||
<el-radio-group v-model="formData.status"> |
|
||||||
<el-radio |
|
||||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
|
||||||
:key="dict.value" |
|
||||||
:label="dict.value" |
|
||||||
> |
|
||||||
{{ dict.label }} |
|
||||||
</el-radio> |
|
||||||
</el-radio-group> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="颜色类型" prop="colorType"> |
|
||||||
<el-select v-model="formData.colorType"> |
|
||||||
<el-option |
|
||||||
v-for="item in colorTypeOptions" |
|
||||||
:key="item.value" |
|
||||||
:label="item.label + '(' + item.value + ')'" |
|
||||||
:value="item.value" |
|
||||||
/> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="CSS Class" prop="cssClass"> |
|
||||||
<el-input v-model="formData.cssClass" placeholder="请输入 CSS Class" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="备注" prop="remark"> |
|
||||||
<el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
<template #footer> |
|
||||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button> |
|
||||||
</template> |
|
||||||
</Dialog> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="SystemDictDataForm" setup> |
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
|
||||||
import * as DictDataApi from '@/api/system/dict/dict.data' |
|
||||||
import { CommonStatusEnum } from '@/utils/constants' |
|
||||||
|
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
|
|
||||||
const dialogVisible = ref(false) // 弹窗的是否展示 |
|
||||||
const dialogTitle = ref('') // 弹窗的标题 |
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
|
||||||
const formData = ref({ |
|
||||||
id: undefined, |
|
||||||
sort: undefined, |
|
||||||
label: '', |
|
||||||
value: '', |
|
||||||
dictType: '', |
|
||||||
status: CommonStatusEnum.ENABLE, |
|
||||||
colorType: '', |
|
||||||
cssClass: '', |
|
||||||
remark: '' |
|
||||||
}) |
|
||||||
const formRules = reactive({ |
|
||||||
label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }], |
|
||||||
value: [{ required: true, message: '数据键值不能为空', trigger: 'blur' }], |
|
||||||
sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }], |
|
||||||
status: [{ required: true, message: '状态不能为空', trigger: 'change' }] |
|
||||||
}) |
|
||||||
const formRef = ref() // 表单 Ref |
|
||||||
|
|
||||||
// 数据标签回显样式 |
|
||||||
const colorTypeOptions = readonly([ |
|
||||||
{ |
|
||||||
value: 'default', |
|
||||||
label: '默认' |
|
||||||
}, |
|
||||||
{ |
|
||||||
value: 'primary', |
|
||||||
label: '主要' |
|
||||||
}, |
|
||||||
{ |
|
||||||
value: 'success', |
|
||||||
label: '成功' |
|
||||||
}, |
|
||||||
{ |
|
||||||
value: 'info', |
|
||||||
label: '信息' |
|
||||||
}, |
|
||||||
{ |
|
||||||
value: 'warning', |
|
||||||
label: '警告' |
|
||||||
}, |
|
||||||
{ |
|
||||||
value: 'danger', |
|
||||||
label: '危险' |
|
||||||
} |
|
||||||
]) |
|
||||||
|
|
||||||
/** 打开弹窗 */ |
|
||||||
const open = async (type: string, id?: number, dictType?: string) => { |
|
||||||
dialogVisible.value = true |
|
||||||
dialogTitle.value = t('action.' + type) |
|
||||||
formType.value = type |
|
||||||
resetForm() |
|
||||||
if (dictType) { |
|
||||||
formData.value.dictType = dictType |
|
||||||
} |
|
||||||
// 修改时,设置数据 |
|
||||||
if (id) { |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
formData.value = await DictDataApi.getDictData(id) |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
|
||||||
|
|
||||||
/** 提交表单 */ |
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
|
||||||
const submitForm = async () => { |
|
||||||
// 校验表单 |
|
||||||
if (!formRef.value) return |
|
||||||
const valid = await formRef.value.validate() |
|
||||||
if (!valid) return |
|
||||||
// 提交请求 |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
const data = formData.value as DictDataApi.DictDataVO |
|
||||||
if (formType.value === 'create') { |
|
||||||
await DictDataApi.createDictData(data) |
|
||||||
message.success(t('common.createSuccess')) |
|
||||||
} else { |
|
||||||
await DictDataApi.updateDictData(data) |
|
||||||
message.success(t('common.updateSuccess')) |
|
||||||
} |
|
||||||
dialogVisible.value = false |
|
||||||
// 发送操作成功的事件 |
|
||||||
emit('success') |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置表单 */ |
|
||||||
const resetForm = () => { |
|
||||||
formData.value = { |
|
||||||
id: undefined, |
|
||||||
sort: undefined, |
|
||||||
label: '', |
|
||||||
value: '', |
|
||||||
dictType: '', |
|
||||||
status: CommonStatusEnum.ENABLE, |
|
||||||
colorType: '', |
|
||||||
cssClass: '', |
|
||||||
remark: '' |
|
||||||
} |
|
||||||
formRef.value?.resetFields() |
|
||||||
} |
|
||||||
</script> |
|
@ -1,207 +0,0 @@ |
|||||||
<template> |
|
||||||
<ContentWrap> |
|
||||||
<el-form |
|
||||||
class="-mb-15px" |
|
||||||
:model="queryParams" |
|
||||||
ref="queryFormRef" |
|
||||||
:inline="true" |
|
||||||
label-width="68px" |
|
||||||
> |
|
||||||
<el-form-item label="字典名称" prop="dictType"> |
|
||||||
<el-select v-model="queryParams.dictType" class="!w-240px"> |
|
||||||
<el-option |
|
||||||
v-for="item in dictTypeList" |
|
||||||
:key="item.type" |
|
||||||
:label="item.name" |
|
||||||
:value="item.type" |
|
||||||
/> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="字典标签" prop="label"> |
|
||||||
<el-input |
|
||||||
v-model="queryParams.label" |
|
||||||
placeholder="请输入字典标签" |
|
||||||
clearable |
|
||||||
@keyup.enter="handleQuery" |
|
||||||
class="!w-240px" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="状态" prop="status"> |
|
||||||
<el-select v-model="queryParams.status" placeholder="数据状态" clearable class="!w-240px"> |
|
||||||
<el-option |
|
||||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
|
||||||
:key="dict.value" |
|
||||||
:label="dict.label" |
|
||||||
:value="dict.value" |
|
||||||
/> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item> |
|
||||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> |
|
||||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> |
|
||||||
<el-button |
|
||||||
type="primary" |
|
||||||
plain |
|
||||||
@click="openForm('create')" |
|
||||||
v-hasPermi="['system:dict:create']" |
|
||||||
> |
|
||||||
<Icon icon="ep:plus" class="mr-5px" /> 新增 |
|
||||||
</el-button> |
|
||||||
<el-button |
|
||||||
type="success" |
|
||||||
plain |
|
||||||
@click="handleExport" |
|
||||||
:loading="exportLoading" |
|
||||||
v-hasPermi="['system:dict:export']" |
|
||||||
> |
|
||||||
<Icon icon="ep:download" class="mr-5px" /> 导出 |
|
||||||
</el-button> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
</ContentWrap> |
|
||||||
|
|
||||||
<!-- 列表 --> |
|
||||||
<ContentWrap> |
|
||||||
<el-table v-loading="loading" :data="list"> |
|
||||||
<el-table-column label="字典编码" align="center" prop="id" /> |
|
||||||
<el-table-column label="字典标签" align="center" prop="label" /> |
|
||||||
<el-table-column label="字典键值" align="center" prop="value" /> |
|
||||||
<el-table-column label="字典排序" align="center" prop="sort" /> |
|
||||||
<el-table-column label="状态" align="center" prop="status"> |
|
||||||
<template #default="scope"> |
|
||||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
<el-table-column label="颜色类型" align="center" prop="colorType" /> |
|
||||||
<el-table-column label="CSS Class" align="center" prop="cssClass" /> |
|
||||||
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip /> |
|
||||||
<el-table-column |
|
||||||
label="创建时间" |
|
||||||
align="center" |
|
||||||
prop="createTime" |
|
||||||
width="180" |
|
||||||
:formatter="dateFormatter" |
|
||||||
/> |
|
||||||
<el-table-column label="操作" align="center"> |
|
||||||
<template #default="scope"> |
|
||||||
<el-button |
|
||||||
link |
|
||||||
type="primary" |
|
||||||
@click="openForm('update', scope.row.id)" |
|
||||||
v-hasPermi="['system:dict:update']" |
|
||||||
> |
|
||||||
修改 |
|
||||||
</el-button> |
|
||||||
<el-button |
|
||||||
link |
|
||||||
type="danger" |
|
||||||
@click="handleDelete(scope.row.id)" |
|
||||||
v-hasPermi="['system:dict:delete']" |
|
||||||
> |
|
||||||
删除 |
|
||||||
</el-button> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
</el-table> |
|
||||||
<!-- 分页 --> |
|
||||||
<Pagination |
|
||||||
:total="total" |
|
||||||
v-model:page="queryParams.pageNo" |
|
||||||
v-model:limit="queryParams.pageSize" |
|
||||||
@pagination="getList" |
|
||||||
/> |
|
||||||
</ContentWrap> |
|
||||||
|
|
||||||
<!-- 表单弹窗:添加/修改 --> |
|
||||||
<DictDataForm ref="formRef" @success="getList" /> |
|
||||||
</template> |
|
||||||
<script setup lang="ts" name="SystemDictData"> |
|
||||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' |
|
||||||
import { dateFormatter } from '@/utils/formatTime' |
|
||||||
import download from '@/utils/download' |
|
||||||
import * as DictDataApi from '@/api/system/dict/dict.data' |
|
||||||
import * as DictTypeApi from '@/api/system/dict/dict.type' |
|
||||||
import DictDataForm from './DictDataForm.vue' |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const route = useRoute() // 路由 |
|
||||||
|
|
||||||
const loading = ref(true) // 列表的加载中 |
|
||||||
const total = ref(0) // 列表的总页数 |
|
||||||
const list = ref([]) // 列表的数据 |
|
||||||
const queryParams = reactive({ |
|
||||||
pageNo: 1, |
|
||||||
pageSize: 10, |
|
||||||
label: '', |
|
||||||
status: undefined, |
|
||||||
dictType: route.params.dictType |
|
||||||
}) |
|
||||||
const queryFormRef = ref() // 搜索的表单 |
|
||||||
const exportLoading = ref(false) // 导出的加载中 |
|
||||||
const dictTypeList = ref<DictTypeApi.DictTypeVO[]>() // 字典类型的列表 |
|
||||||
|
|
||||||
/** 查询列表 */ |
|
||||||
const getList = async () => { |
|
||||||
loading.value = true |
|
||||||
try { |
|
||||||
const data = await DictDataApi.getDictDataPage(queryParams) |
|
||||||
list.value = data.list |
|
||||||
total.value = data.total |
|
||||||
} finally { |
|
||||||
loading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 搜索按钮操作 */ |
|
||||||
const handleQuery = () => { |
|
||||||
queryParams.pageNo = 1 |
|
||||||
getList() |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置按钮操作 */ |
|
||||||
const resetQuery = () => { |
|
||||||
queryFormRef.value.resetFields() |
|
||||||
handleQuery() |
|
||||||
} |
|
||||||
|
|
||||||
/** 添加/修改操作 */ |
|
||||||
const formRef = ref() |
|
||||||
const openForm = (type: string, id?: number) => { |
|
||||||
formRef.value.open(type, id, queryParams.dictType) |
|
||||||
} |
|
||||||
|
|
||||||
/** 删除按钮操作 */ |
|
||||||
const handleDelete = async (id: number) => { |
|
||||||
try { |
|
||||||
// 删除的二次确认 |
|
||||||
await message.delConfirm() |
|
||||||
// 发起删除 |
|
||||||
await DictDataApi.deleteDictData(id) |
|
||||||
message.success(t('common.delSuccess')) |
|
||||||
// 刷新列表 |
|
||||||
await getList() |
|
||||||
} catch {} |
|
||||||
} |
|
||||||
|
|
||||||
/** 导出按钮操作 */ |
|
||||||
const handleExport = async () => { |
|
||||||
try { |
|
||||||
// 导出的二次确认 |
|
||||||
await message.exportConfirm() |
|
||||||
// 发起导出 |
|
||||||
exportLoading.value = true |
|
||||||
const data = await DictDataApi.exportDictData(queryParams) |
|
||||||
download.excel(data, '字典数据.xls') |
|
||||||
} catch { |
|
||||||
} finally { |
|
||||||
exportLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 初始化 **/ |
|
||||||
onMounted(async () => { |
|
||||||
await getList() |
|
||||||
// 查询字典(精简)列表 |
|
||||||
dictTypeList.value = await DictTypeApi.getSimpleDictTypeList() |
|
||||||
}) |
|
||||||
</script> |
|
@ -1,229 +0,0 @@ |
|||||||
<template> |
|
||||||
<!-- 搜索工作栏 --> |
|
||||||
<ContentWrap> |
|
||||||
<el-form |
|
||||||
ref="queryFormRef" |
|
||||||
:inline="true" |
|
||||||
:model="queryParams" |
|
||||||
class="-mb-15px" |
|
||||||
label-width="68px" |
|
||||||
> |
|
||||||
<el-form-item label="字典名称" prop="name"> |
|
||||||
<el-input |
|
||||||
v-model="queryParams.name" |
|
||||||
class="!w-240px" |
|
||||||
clearable |
|
||||||
placeholder="请输入字典名称" |
|
||||||
@keyup.enter="handleQuery" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="字典类型" prop="type"> |
|
||||||
<el-input |
|
||||||
v-model="queryParams.type" |
|
||||||
class="!w-240px" |
|
||||||
clearable |
|
||||||
placeholder="请输入字典类型" |
|
||||||
@keyup.enter="handleQuery" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="状态" prop="status"> |
|
||||||
<el-select |
|
||||||
v-model="queryParams.status" |
|
||||||
class="!w-240px" |
|
||||||
clearable |
|
||||||
placeholder="请选择字典状态" |
|
||||||
> |
|
||||||
<el-option |
|
||||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
|
||||||
:key="dict.value" |
|
||||||
:label="dict.label" |
|
||||||
:value="dict.value" |
|
||||||
/> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="创建时间" prop="createTime"> |
|
||||||
<el-date-picker |
|
||||||
v-model="queryParams.createTime" |
|
||||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" |
|
||||||
class="!w-240px" |
|
||||||
end-placeholder="结束日期" |
|
||||||
start-placeholder="开始日期" |
|
||||||
type="daterange" |
|
||||||
value-format="yyyy-MM-dd HH:mm:ss" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item> |
|
||||||
<el-button @click="handleQuery"> |
|
||||||
<Icon class="mr-5px" icon="ep:search" /> |
|
||||||
搜索 |
|
||||||
</el-button> |
|
||||||
<el-button @click="resetQuery"> |
|
||||||
<Icon class="mr-5px" icon="ep:refresh" /> |
|
||||||
重置 |
|
||||||
</el-button> |
|
||||||
<el-button |
|
||||||
v-hasPermi="['system:dict:create']" |
|
||||||
plain |
|
||||||
type="primary" |
|
||||||
@click="openForm('create')" |
|
||||||
> |
|
||||||
<Icon class="mr-5px" icon="ep:plus" /> |
|
||||||
新增 |
|
||||||
</el-button> |
|
||||||
<el-button |
|
||||||
v-hasPermi="['system:dict:export']" |
|
||||||
:loading="exportLoading" |
|
||||||
plain |
|
||||||
type="success" |
|
||||||
@click="handleExport" |
|
||||||
> |
|
||||||
<Icon class="mr-5px" icon="ep:download" /> |
|
||||||
导出 |
|
||||||
</el-button> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
</ContentWrap> |
|
||||||
|
|
||||||
<!-- 列表 --> |
|
||||||
<ContentWrap> |
|
||||||
<el-table v-loading="loading" :data="list"> |
|
||||||
<el-table-column align="center" label="字典编号" prop="id" /> |
|
||||||
<el-table-column align="center" label="字典名称" prop="name" show-overflow-tooltip /> |
|
||||||
<el-table-column align="center" label="字典类型" prop="type" width="300" /> |
|
||||||
<el-table-column align="center" label="状态" prop="status"> |
|
||||||
<template #default="scope"> |
|
||||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
<el-table-column align="center" label="备注" prop="remark" /> |
|
||||||
<el-table-column |
|
||||||
:formatter="dateFormatter" |
|
||||||
align="center" |
|
||||||
label="创建时间" |
|
||||||
prop="createTime" |
|
||||||
width="180" |
|
||||||
/> |
|
||||||
<el-table-column align="center" label="操作"> |
|
||||||
<template #default="scope"> |
|
||||||
<el-button |
|
||||||
v-hasPermi="['system:dict:update']" |
|
||||||
link |
|
||||||
type="primary" |
|
||||||
@click="openForm('update', scope.row.id)" |
|
||||||
> |
|
||||||
修改 |
|
||||||
</el-button> |
|
||||||
<router-link :to="'/dict/type/data/' + scope.row.type"> |
|
||||||
<el-button link type="primary">数据</el-button> |
|
||||||
</router-link> |
|
||||||
<el-button |
|
||||||
v-hasPermi="['system:dict:delete']" |
|
||||||
link |
|
||||||
type="danger" |
|
||||||
@click="handleDelete(scope.row.id)" |
|
||||||
> |
|
||||||
删除 |
|
||||||
</el-button> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
</el-table> |
|
||||||
<!-- 分页 --> |
|
||||||
<Pagination |
|
||||||
v-model:limit="queryParams.pageSize" |
|
||||||
v-model:page="queryParams.pageNo" |
|
||||||
:total="total" |
|
||||||
@pagination="getList" |
|
||||||
/> |
|
||||||
</ContentWrap> |
|
||||||
|
|
||||||
<!-- 表单弹窗:添加/修改 --> |
|
||||||
<DictTypeForm ref="formRef" @success="getList" /> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script lang="ts" name="SystemDictType" setup> |
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
|
||||||
import { dateFormatter } from '@/utils/formatTime' |
|
||||||
import * as DictTypeApi from '@/api/system/dict/dict.type' |
|
||||||
import DictTypeForm from './DictTypeForm.vue' |
|
||||||
import download from '@/utils/download' |
|
||||||
|
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
|
|
||||||
const loading = ref(true) // 列表的加载中 |
|
||||||
const total = ref(0) // 列表的总页数 |
|
||||||
const list = ref([]) // 字典表格数据 |
|
||||||
const queryParams = reactive({ |
|
||||||
pageNo: 1, |
|
||||||
pageSize: 10, |
|
||||||
name: '', |
|
||||||
type: '', |
|
||||||
status: undefined, |
|
||||||
createTime: [] |
|
||||||
}) |
|
||||||
const queryFormRef = ref() // 搜索的表单 |
|
||||||
const exportLoading = ref(false) // 导出的加载中 |
|
||||||
|
|
||||||
/** 查询字典类型列表 */ |
|
||||||
const getList = async () => { |
|
||||||
loading.value = true |
|
||||||
try { |
|
||||||
const data = await DictTypeApi.getDictTypePage(queryParams) |
|
||||||
list.value = data.list |
|
||||||
total.value = data.total |
|
||||||
} finally { |
|
||||||
loading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 搜索按钮操作 */ |
|
||||||
const handleQuery = () => { |
|
||||||
queryParams.pageNo = 1 |
|
||||||
getList() |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置按钮操作 */ |
|
||||||
const resetQuery = () => { |
|
||||||
queryFormRef.value.resetFields() |
|
||||||
handleQuery() |
|
||||||
} |
|
||||||
|
|
||||||
/** 添加/修改操作 */ |
|
||||||
const formRef = ref() |
|
||||||
const openForm = (type: string, id?: number) => { |
|
||||||
formRef.value.open(type, id) |
|
||||||
} |
|
||||||
|
|
||||||
/** 删除按钮操作 */ |
|
||||||
const handleDelete = async (id: number) => { |
|
||||||
try { |
|
||||||
// 删除的二次确认 |
|
||||||
await message.delConfirm() |
|
||||||
// 发起删除 |
|
||||||
await DictTypeApi.deleteDictType(id) |
|
||||||
message.success(t('common.delSuccess')) |
|
||||||
// 刷新列表 |
|
||||||
await getList() |
|
||||||
} catch {} |
|
||||||
} |
|
||||||
|
|
||||||
/** 导出按钮操作 */ |
|
||||||
const handleExport = async () => { |
|
||||||
try { |
|
||||||
// 导出的二次确认 |
|
||||||
await message.exportConfirm() |
|
||||||
// 发起导出 |
|
||||||
exportLoading.value = true |
|
||||||
const data = await DictTypeApi.exportDictType(queryParams) |
|
||||||
download.excel(data, '字典类型.xls') |
|
||||||
} catch { |
|
||||||
} finally { |
|
||||||
exportLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 初始化 **/ |
|
||||||
onMounted(() => { |
|
||||||
getList() |
|
||||||
}) |
|
||||||
</script> |
|
@ -1,261 +0,0 @@ |
|||||||
<template> |
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="500px"> |
|
||||||
<el-form |
|
||||||
ref="formRef" |
|
||||||
v-loading="formLoading" |
|
||||||
:model="formData" |
|
||||||
:rules="formRules" |
|
||||||
label-width="100px" |
|
||||||
> |
|
||||||
<el-form-item label="服务类型" prop="serviceId"> |
|
||||||
<el-select v-model="formData.serviceId" placeholder="选择服务类型" filterable> |
|
||||||
<el-option |
|
||||||
v-for="item in props.appList" |
|
||||||
:key="item.serviceId" |
|
||||||
:label="item.serviceName" |
|
||||||
:value="item.serviceId" |
|
||||||
/> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="上级菜单"> |
|
||||||
<el-tree-select |
|
||||||
v-model="formData.parentId" |
|
||||||
:data="menuTree" |
|
||||||
:default-expanded-keys="[0]" |
|
||||||
:props="defaultProps" |
|
||||||
check-strictly |
|
||||||
node-key="id" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="菜单名称" prop="name"> |
|
||||||
<el-input v-model="formData.name" clearable placeholder="请输入菜单名称" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="菜单类型" prop="type"> |
|
||||||
<el-radio-group v-model="formData.type"> |
|
||||||
<el-radio-button :value="1"> 目录 </el-radio-button> |
|
||||||
<el-radio-button :value="2"> 菜单 </el-radio-button> |
|
||||||
<el-radio-button :value="3"> 按钮 </el-radio-button> |
|
||||||
</el-radio-group> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item v-if="formData.type !== 3" label="菜单图标"> |
|
||||||
<IconSelect v-model="formData.icon" clearable /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item v-if="formData.type !== 3" label="路由地址" prop="path"> |
|
||||||
<template #label> |
|
||||||
<Tooltip |
|
||||||
message="访问的路由地址,如:`user`。如需外网地址时,则以 `http(s)://` 开头" |
|
||||||
titel="路由地址" |
|
||||||
/> |
|
||||||
</template> |
|
||||||
<el-input v-model="formData.path" clearable placeholder="请输入路由地址" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item v-if="formData.type === 2" label="组件地址" prop="component"> |
|
||||||
<el-input v-model="formData.component" clearable placeholder="例如说:system/user/index" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item v-if="formData.type === 2" label="组件名字" prop="componentName"> |
|
||||||
<el-input v-model="formData.componentName" clearable placeholder="例如说:SystemUser" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item v-if="formData.type !== 1" label="权限标识" prop="permission"> |
|
||||||
<template #label> |
|
||||||
<Tooltip |
|
||||||
message="Controller 方法上的权限字符,如:@PreAuthorize(`@ss.hasPermission('system:user:list')`)" |
|
||||||
titel="权限标识" |
|
||||||
/> |
|
||||||
</template> |
|
||||||
<el-input v-model="formData.permission" clearable placeholder="请输入权限标识" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="显示排序" prop="sort"> |
|
||||||
<el-input-number v-model="formData.sort" :min="0" clearable controls-position="right" /> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label="菜单状态" prop="status"> |
|
||||||
<el-radio-group v-model="formData.status"> |
|
||||||
<el-radio :value="0"> 启用 </el-radio> |
|
||||||
<el-radio :value="1"> 禁用 </el-radio> |
|
||||||
</el-radio-group> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item v-if="formData.type !== 3" label="显示状态" prop="visible"> |
|
||||||
<template #label> |
|
||||||
<Tooltip message="选择隐藏时,路由将不会出现在侧边栏,但仍然可以访问" titel="显示状态" /> |
|
||||||
</template> |
|
||||||
<el-radio-group v-model="formData.visible"> |
|
||||||
<el-radio key="true" :label="true" border>显示</el-radio> |
|
||||||
<el-radio key="false" :label="false" border>隐藏</el-radio> |
|
||||||
</el-radio-group> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item v-if="formData.type !== 3" label="总是显示" prop="alwaysShow"> |
|
||||||
<template #label> |
|
||||||
<Tooltip |
|
||||||
message="选择不是时,当该菜单只有一个子菜单时,不展示自己,直接展示子菜单" |
|
||||||
titel="总是显示" |
|
||||||
/> |
|
||||||
</template> |
|
||||||
<el-radio-group v-model="formData.alwaysShow"> |
|
||||||
<el-radio key="true" :label="true" border>总是</el-radio> |
|
||||||
<el-radio key="false" :label="false" border>不是</el-radio> |
|
||||||
</el-radio-group> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item v-if="formData.type === 2" label="缓存状态" prop="keepAlive"> |
|
||||||
<template #label> |
|
||||||
<Tooltip |
|
||||||
message="选择缓存时,则会被 `keep-alive` 缓存,必须填写「组件名称」字段" |
|
||||||
titel="缓存状态" |
|
||||||
/> |
|
||||||
</template> |
|
||||||
<el-radio-group v-model="formData.keepAlive"> |
|
||||||
<el-radio key="true" :label="true" border>缓存</el-radio> |
|
||||||
<el-radio key="false" :label="false" border>不缓存</el-radio> |
|
||||||
</el-radio-group> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
<template #footer> |
|
||||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button> |
|
||||||
</template> |
|
||||||
</Dialog> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="SystemMenuForm" setup> |
|
||||||
// import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
|
||||||
import * as MenuApi from '@/api/system/menu' |
|
||||||
import { CACHE_KEY } from '@/hooks/web/useCache' |
|
||||||
import { CommonStatusEnum, SystemMenuTypeEnum } from '@/utils/constants' |
|
||||||
import { defaultProps, handleTree } from '@/utils/tree' |
|
||||||
import cache from '@/plugins/cache' |
|
||||||
|
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
|
|
||||||
const props = defineProps({ |
|
||||||
appList: Object as any |
|
||||||
}) |
|
||||||
|
|
||||||
const dialogVisible = ref(false) // 弹窗的是否展示 |
|
||||||
const dialogTitle = ref('') // 弹窗的标题 |
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
|
||||||
const formData = ref({ |
|
||||||
id: 0, |
|
||||||
name: '', |
|
||||||
permission: '', |
|
||||||
type: SystemMenuTypeEnum.DIR, |
|
||||||
sort: Number(undefined), |
|
||||||
parentId: 0, |
|
||||||
path: '', |
|
||||||
icon: '', |
|
||||||
component: '', |
|
||||||
componentName: '', |
|
||||||
status: CommonStatusEnum.ENABLE, |
|
||||||
visible: true, |
|
||||||
keepAlive: true, |
|
||||||
alwaysShow: true, |
|
||||||
serviceId: undefined |
|
||||||
}) |
|
||||||
const formRules = reactive({ |
|
||||||
name: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }], |
|
||||||
sort: [{ required: true, message: '菜单顺序不能为空', trigger: 'blur' }], |
|
||||||
path: [{ required: true, message: '路由地址不能为空', trigger: 'blur' }], |
|
||||||
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }] |
|
||||||
}) |
|
||||||
const formRef = ref() // 表单 Ref |
|
||||||
|
|
||||||
/** 打开弹窗 */ |
|
||||||
const open = async (type: string, id?: number, parentId?: number) => { |
|
||||||
dialogVisible.value = true |
|
||||||
dialogTitle.value = t('action.' + type) |
|
||||||
formType.value = type |
|
||||||
resetForm() |
|
||||||
if (parentId) { |
|
||||||
formData.value.parentId = parentId |
|
||||||
} |
|
||||||
// 修改时,设置数据 |
|
||||||
if (id) { |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
formData.value = await MenuApi.getMenu(id) |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
// 获得菜单列表 |
|
||||||
await getTree() |
|
||||||
} |
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
|
||||||
|
|
||||||
/** 提交表单 */ |
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
|
||||||
const submitForm = async () => { |
|
||||||
// 校验表单 |
|
||||||
if (!formRef.value) return |
|
||||||
const valid = await formRef.value.validate() |
|
||||||
if (!valid) return |
|
||||||
// 提交请求 |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
if ( |
|
||||||
formData.value.type === SystemMenuTypeEnum.DIR || |
|
||||||
formData.value.type === SystemMenuTypeEnum.MENU |
|
||||||
) { |
|
||||||
if (!isExternal(formData.value.path)) { |
|
||||||
if (formData.value.parentId === 0 && formData.value.path.charAt(0) !== '/') { |
|
||||||
message.error('路径必须以 / 开头') |
|
||||||
return |
|
||||||
} else if (formData.value.parentId !== 0 && formData.value.path.charAt(0) === '/') { |
|
||||||
message.error('路径不能以 / 开头') |
|
||||||
return |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
const data = formData.value as unknown as MenuApi.MenuVO |
|
||||||
if (formType.value === 'create') { |
|
||||||
await MenuApi.createMenu(data) |
|
||||||
message.success(t('common.createSuccess')) |
|
||||||
} else { |
|
||||||
await MenuApi.updateMenu(data) |
|
||||||
message.success(t('common.updateSuccess')) |
|
||||||
} |
|
||||||
dialogVisible.value = false |
|
||||||
// 发送操作成功的事件 |
|
||||||
emit('success') |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
// 清空,从而触发刷新 |
|
||||||
cache.local.delete(CACHE_KEY.ROLE_ROUTERS) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 获取下拉框[上级菜单]的数据 */ |
|
||||||
const menuTree = ref<Tree[]>([]) // 树形结构 |
|
||||||
const getTree = async () => { |
|
||||||
menuTree.value = [] |
|
||||||
const res = await MenuApi.getSimpleMenusList() |
|
||||||
let menu: Tree = { id: 0, name: '主类目', children: [] } |
|
||||||
menu.children = handleTree(res) |
|
||||||
menuTree.value.push(menu) |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置表单 */ |
|
||||||
const resetForm = () => { |
|
||||||
formData.value = { |
|
||||||
id: 0, |
|
||||||
name: '', |
|
||||||
permission: '', |
|
||||||
type: SystemMenuTypeEnum.DIR, |
|
||||||
sort: Number(undefined), |
|
||||||
parentId: 0, |
|
||||||
path: '', |
|
||||||
icon: '', |
|
||||||
component: '', |
|
||||||
componentName: '', |
|
||||||
status: CommonStatusEnum.ENABLE, |
|
||||||
visible: true, |
|
||||||
keepAlive: true, |
|
||||||
alwaysShow: true, |
|
||||||
serviceId: undefined |
|
||||||
} |
|
||||||
formRef.value?.resetFields() |
|
||||||
} |
|
||||||
|
|
||||||
/** 判断 path 是不是外部的 HTTP 等链接 */ |
|
||||||
const isExternal = (path: string) => { |
|
||||||
return /^(https?:|mailto:|tel:)/.test(path) |
|
||||||
} |
|
||||||
</script> |
|
@ -1,184 +0,0 @@ |
|||||||
<template> |
|
||||||
<!-- 搜索工作栏 --> |
|
||||||
<ContentWrap> |
|
||||||
<el-form |
|
||||||
ref="queryFormRef" |
|
||||||
:inline="true" |
|
||||||
:model="queryParams" |
|
||||||
class="-mb-15px" |
|
||||||
label-width="68px" |
|
||||||
> |
|
||||||
<el-form-item label="菜单名称" prop="name"> |
|
||||||
<el-input |
|
||||||
v-model="queryParams.name" |
|
||||||
class="!w-240px" |
|
||||||
clearable |
|
||||||
placeholder="请输入菜单名称" |
|
||||||
@keyup.enter="handleQuery" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item> |
|
||||||
<el-button @click="handleQuery"> |
|
||||||
<Icon class="mr-5px" icon="ep:search" /> |
|
||||||
搜索 |
|
||||||
</el-button> |
|
||||||
<el-button @click="resetQuery"> |
|
||||||
<Icon class="mr-5px" icon="ep:refresh" /> |
|
||||||
重置 |
|
||||||
</el-button> |
|
||||||
<el-button plain type="primary" @click="openForm('create')"> |
|
||||||
<Icon class="mr-5px" icon="ep:plus" /> |
|
||||||
新增 |
|
||||||
</el-button> |
|
||||||
<el-button plain type="danger" @click="toggleExpandAll"> |
|
||||||
<Icon class="mr-5px" icon="ep:sort" /> |
|
||||||
展开/折叠 |
|
||||||
</el-button> |
|
||||||
<el-button plain @click="refreshMenu"> |
|
||||||
<Icon class="mr-5px" icon="ep:refresh" /> |
|
||||||
刷新菜单缓存 |
|
||||||
</el-button> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
</ContentWrap> |
|
||||||
|
|
||||||
<!-- 列表 --> |
|
||||||
<ContentWrap> |
|
||||||
<el-table |
|
||||||
v-if="refreshTable" |
|
||||||
v-loading="loading" |
|
||||||
:data="list" |
|
||||||
:default-expand-all="isExpandAll" |
|
||||||
row-key="id" |
|
||||||
> |
|
||||||
<el-table-column :show-overflow-tooltip="true" label="菜单名称" prop="name" width="250" /> |
|
||||||
<el-table-column align="center" label="图标" prop="icon" width="100"> |
|
||||||
<template #default="scope"> |
|
||||||
<Icon :icon="scope.row.icon" /> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
<el-table-column label="排序" prop="sort" width="60" /> |
|
||||||
<el-table-column :show-overflow-tooltip="true" label="权限标识" prop="permission" /> |
|
||||||
<el-table-column :show-overflow-tooltip="true" label="组件路径" prop="component" /> |
|
||||||
<el-table-column :show-overflow-tooltip="true" label="组件名称" prop="componentName" /> |
|
||||||
<el-table-column label="状态" prop="status" width="80" /> |
|
||||||
<el-table-column label="服务类型" prop="" width="100"> |
|
||||||
<template #default="{ row }"> |
|
||||||
{{ getServiceName(row.serviceId) }} |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
<el-table-column align="center" label="操作"> |
|
||||||
<template #default="scope"> |
|
||||||
<el-button link type="primary" @click="openForm('update', scope.row.id)"> |
|
||||||
修改 |
|
||||||
</el-button> |
|
||||||
<el-button link type="primary" @click="openForm('create', undefined, scope.row.id)"> |
|
||||||
新增 |
|
||||||
</el-button> |
|
||||||
<el-button link type="danger" @click="handleDelete(scope.row.id)"> 删除 </el-button> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
</el-table> |
|
||||||
</ContentWrap> |
|
||||||
|
|
||||||
<!-- 表单弹窗:添加/修改 --> |
|
||||||
<MenuForm ref="formRef" :appList="appList" @success="getList" /> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="SystemMenu" setup> |
|
||||||
import { handleTree } from '@/utils/tree' |
|
||||||
import * as MenuApi from '@/api/system/menu' |
|
||||||
import MenuForm from './MenuForm.vue' |
|
||||||
import { CACHE_KEY } from '@/hooks/web/useCache' |
|
||||||
import cache from '@/plugins/cache' |
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
|
|
||||||
const loading = ref(true) // 列表的加载中 |
|
||||||
const list = ref<any>([]) // 列表的数据 |
|
||||||
const queryParams = reactive({ |
|
||||||
name: undefined, |
|
||||||
status: undefined |
|
||||||
}) |
|
||||||
const queryFormRef = ref() // 搜索的表单 |
|
||||||
const isExpandAll = ref(false) // 是否展开,默认全部折叠 |
|
||||||
const refreshTable = ref(true) // 重新渲染表格状态 |
|
||||||
|
|
||||||
/** 查询列表 */ |
|
||||||
const getList = async () => { |
|
||||||
loading.value = true |
|
||||||
try { |
|
||||||
const data = await MenuApi.getMenuList(queryParams) |
|
||||||
list.value = handleTree(data) |
|
||||||
} finally { |
|
||||||
loading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 搜索按钮操作 */ |
|
||||||
const handleQuery = () => { |
|
||||||
getList() |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置按钮操作 */ |
|
||||||
const resetQuery = () => { |
|
||||||
queryFormRef.value.resetFields() |
|
||||||
handleQuery() |
|
||||||
} |
|
||||||
|
|
||||||
/** 添加/修改操作 */ |
|
||||||
const formRef = ref() |
|
||||||
const openForm = (type: string, id?: number, parentId?: number) => { |
|
||||||
formRef.value.open(type, id, parentId) |
|
||||||
} |
|
||||||
|
|
||||||
/** 展开/折叠操作 */ |
|
||||||
const toggleExpandAll = () => { |
|
||||||
refreshTable.value = false |
|
||||||
isExpandAll.value = !isExpandAll.value |
|
||||||
nextTick(() => { |
|
||||||
refreshTable.value = true |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
/** 刷新菜单缓存按钮操作 */ |
|
||||||
const refreshMenu = async () => { |
|
||||||
try { |
|
||||||
await message.confirm('即将更新缓存刷新浏览器!', '刷新菜单缓存') |
|
||||||
// 清空,从而触发刷新 |
|
||||||
cache.local.delete(CACHE_KEY.ROLE_ROUTERS) |
|
||||||
// 刷新浏览器 |
|
||||||
location.reload() |
|
||||||
} catch {} |
|
||||||
} |
|
||||||
|
|
||||||
/** 删除按钮操作 */ |
|
||||||
const handleDelete = async (id: number) => { |
|
||||||
try { |
|
||||||
console.log(id) |
|
||||||
// 删除的二次确认 |
|
||||||
await message.delConfirm() |
|
||||||
// 发起删除 |
|
||||||
await MenuApi.deleteMenu(id) |
|
||||||
message.success(t('common.delSuccess')) |
|
||||||
// 刷新列表 |
|
||||||
await getList() |
|
||||||
} catch {} |
|
||||||
} |
|
||||||
|
|
||||||
const appList = ref([] as any) |
|
||||||
const getOptions = () => { |
|
||||||
MenuApi.getServiceAppList().then((data) => { |
|
||||||
appList.value = data |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
function getServiceName(serviceId: any) { |
|
||||||
return appList.value.find((it: any) => it.serviceId == serviceId)?.serviceName |
|
||||||
} |
|
||||||
|
|
||||||
/** 初始化 **/ |
|
||||||
onMounted(() => { |
|
||||||
getOptions() |
|
||||||
getList() |
|
||||||
}) |
|
||||||
</script> |
|
@ -1,83 +0,0 @@ |
|||||||
<template> |
|
||||||
<div> |
|
||||||
<el-table v-loading="loading" :data="tableList" border> |
|
||||||
<el-table-column type="index" width="50" /> |
|
||||||
<el-table-column |
|
||||||
v-for="col in columns" |
|
||||||
:prop="col.prop" |
|
||||||
:key="col.prop" |
|
||||||
:label="col.label" |
|
||||||
:width="col.width" |
|
||||||
/> |
|
||||||
<el-table-column label="状态" key="status"> |
|
||||||
<template #default="scope"> |
|
||||||
<el-switch |
|
||||||
v-model="scope.row.status" |
|
||||||
:active-value="0" |
|
||||||
active-text="在职" |
|
||||||
inactive-text="离职" |
|
||||||
:inactive-value="1" |
|
||||||
disabled |
|
||||||
/> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
</el-table> |
|
||||||
<Pagination |
|
||||||
v-model:limit="pageSize" |
|
||||||
v-model:page="currentPage" |
|
||||||
:total="total" |
|
||||||
@pagination="getList" |
|
||||||
/> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script setup name="RoleEmployee"> |
|
||||||
import { getRoleUsers } from '@/api/system/role' |
|
||||||
|
|
||||||
const props = defineProps({ |
|
||||||
roleId: { |
|
||||||
type: Number |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
watch( |
|
||||||
() => props.roleId, |
|
||||||
(newValue) => { |
|
||||||
getList(newValue) |
|
||||||
} |
|
||||||
) |
|
||||||
|
|
||||||
const loading = ref(false) |
|
||||||
const tableList = ref([]) |
|
||||||
const total = ref(0) |
|
||||||
const pageSize = ref(20) |
|
||||||
const currentPage = ref(1) |
|
||||||
|
|
||||||
const columns = ref([ |
|
||||||
{ prop: 'name', label: '姓名', width: '200px' }, |
|
||||||
{ prop: 'mobile', label: '手机号', width: '150px' }, |
|
||||||
{ prop: 'deptName', label: '部门' }, |
|
||||||
{ prop: 'roles', label: '角色' } |
|
||||||
]) |
|
||||||
|
|
||||||
async function getList() { |
|
||||||
loading.value = true |
|
||||||
try { |
|
||||||
const data = await getRoleUsers({ |
|
||||||
pageNo: currentPage.value, |
|
||||||
pageSize: pageSize.value, |
|
||||||
id: props.roleId |
|
||||||
}) |
|
||||||
tableList.value = data.list |
|
||||||
total.value = data.total |
|
||||||
} finally { |
|
||||||
loading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
onMounted(() => { |
|
||||||
getList() |
|
||||||
}) |
|
||||||
</script> |
|
||||||
|
|
||||||
<style lang="scss" scoped></style> |
|
@ -1,99 +0,0 @@ |
|||||||
<template> |
|
||||||
<div> |
|
||||||
<el-form ref="formRef" v-loading="formLoading" label-width="0px"> |
|
||||||
<el-form-item> |
|
||||||
<el-tree |
|
||||||
ref="treeRef" |
|
||||||
:data="menuOptions" |
|
||||||
:props="defaultProps" |
|
||||||
empty-text="加载中,请稍候" |
|
||||||
node-key="id" |
|
||||||
show-checkbox |
|
||||||
style="width: 100%" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item> |
|
||||||
<el-button |
|
||||||
:disabled="formLoading" |
|
||||||
type="primary" |
|
||||||
@click="submitForm" |
|
||||||
v-hasPermi="['basic:role:update-menu']" |
|
||||||
>保存权限</el-button |
|
||||||
> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="RoleAssignMenuForm" setup> |
|
||||||
import { defaultProps, handleTree } from '@/utils/tree' |
|
||||||
import * as MenuApi from '@/api/system/menu' |
|
||||||
import * as PermissionApi from '@/api/system/permission' |
|
||||||
|
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
|
|
||||||
const props = defineProps({ |
|
||||||
roleId: { |
|
||||||
type: Number |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
watch( |
|
||||||
() => props.roleId, |
|
||||||
(newValue) => { |
|
||||||
getCheckedMenu(newValue) |
|
||||||
} |
|
||||||
) |
|
||||||
|
|
||||||
const dialogVisible = ref(false) // 弹窗的是否展示 |
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
|
||||||
const formRef = ref() // 表单 Ref |
|
||||||
const menuOptions = ref<any[]>([]) // 菜单树形结构 |
|
||||||
const treeRef = ref() // 菜单树组件 Ref |
|
||||||
|
|
||||||
/** 提交表单 */ |
|
||||||
const submitForm = async () => { |
|
||||||
// 提交请求 |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
const data = { |
|
||||||
roleId: props.roleId, |
|
||||||
menuIds: [ |
|
||||||
...(treeRef.value.getCheckedKeys(false) as unknown as Array<number>), // 获得当前选中节点 |
|
||||||
...(treeRef.value.getHalfCheckedKeys() as unknown as Array<number>) // 获得半选中的父节点 |
|
||||||
] |
|
||||||
} |
|
||||||
await PermissionApi.assignRoleMenu(data) |
|
||||||
message.success(t('common.updateSuccess')) |
|
||||||
dialogVisible.value = false |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const checkedMenuIds = ref([]) |
|
||||||
|
|
||||||
async function init() { |
|
||||||
menuOptions.value = handleTree(await MenuApi.getSimpleMenusList()) |
|
||||||
getCheckedMenu(props.roleId) |
|
||||||
} |
|
||||||
|
|
||||||
async function getCheckedMenu(id) { |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
checkedMenuIds.value = await PermissionApi.getRoleMenuList(id) |
|
||||||
treeRef.value.setCheckedKeys([], false) |
|
||||||
// 设置选中 |
|
||||||
checkedMenuIds.value.forEach((menuId: number) => { |
|
||||||
treeRef.value.setChecked(menuId, true, false) |
|
||||||
}) |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
onMounted(() => { |
|
||||||
init() |
|
||||||
}) |
|
||||||
</script> |
|
||||||
<style lang="scss" scoped></style> |
|
@ -1,166 +0,0 @@ |
|||||||
<template> |
|
||||||
<el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px"> |
|
||||||
<el-form-item label="权限范围"> |
|
||||||
<el-select v-model="formData.dataScope"> |
|
||||||
<el-option |
|
||||||
v-for="item in dataScopeOptions" |
|
||||||
:key="item.value" |
|
||||||
:label="item.label" |
|
||||||
:value="item.value" |
|
||||||
/> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item |
|
||||||
v-if="formData.dataScope === SystemDataScopeEnum.DEPT_CUSTOM" |
|
||||||
label="权限范围" |
|
||||||
style="display: flex" |
|
||||||
> |
|
||||||
<el-card class="card" shadow="never"> |
|
||||||
<template #header> |
|
||||||
全选/全不选: |
|
||||||
<el-switch |
|
||||||
v-model="treeNodeAll" |
|
||||||
active-text="是" |
|
||||||
inactive-text="否" |
|
||||||
inline-prompt |
|
||||||
@change="handleCheckedTreeNodeAll()" |
|
||||||
/> |
|
||||||
全部展开/折叠: |
|
||||||
<el-switch |
|
||||||
v-model="deptExpand" |
|
||||||
active-text="展开" |
|
||||||
inactive-text="折叠" |
|
||||||
inline-prompt |
|
||||||
@change="handleCheckedTreeExpand" |
|
||||||
/> |
|
||||||
父子联动(选中父节点,自动选择子节点): |
|
||||||
<el-switch v-model="checkStrictly" active-text="是" inactive-text="否" inline-prompt /> |
|
||||||
</template> |
|
||||||
<el-tree |
|
||||||
ref="treeRef" |
|
||||||
:check-strictly="!checkStrictly" |
|
||||||
:data="deptOptions" |
|
||||||
:props="defaultProps" |
|
||||||
default-expand-all |
|
||||||
empty-text="加载中,请稍后" |
|
||||||
node-key="id" |
|
||||||
show-checkbox |
|
||||||
/> |
|
||||||
</el-card> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item label-width="0"> |
|
||||||
<el-button |
|
||||||
:disabled="formLoading" |
|
||||||
type="primary" |
|
||||||
@click="submitForm" |
|
||||||
v-hasPermi="['basic:role:update-data']" |
|
||||||
>保存权限</el-button |
|
||||||
> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="RoleDataPermissionForm" setup> |
|
||||||
import { defaultProps, handleTree } from '@/utils/tree' |
|
||||||
import { SystemDataScopeEnum } from '@/utils/constants' |
|
||||||
|
|
||||||
import * as DeptApi from '@/api/system/dept' |
|
||||||
import * as PermissionApi from '@/api/system/permission' |
|
||||||
import * as RoleApi from '@/api/system/role' |
|
||||||
|
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
|
|
||||||
const props = defineProps({ |
|
||||||
roleId: { |
|
||||||
type: Number |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
watch( |
|
||||||
() => props.roleId, |
|
||||||
(newValue) => { |
|
||||||
getRoleInfo(newValue) |
|
||||||
} |
|
||||||
) |
|
||||||
|
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
|
||||||
const formData = ref({ |
|
||||||
id: 0, |
|
||||||
name: '', |
|
||||||
dataScope: undefined, |
|
||||||
dataScopeDeptIds: [] |
|
||||||
}) |
|
||||||
const formRef = ref() // 表单 Ref |
|
||||||
const deptOptions = ref<any[]>([]) // 部门树形结构 |
|
||||||
const deptExpand = ref(false) // 展开/折叠 |
|
||||||
const treeRef = ref() // 菜单树组件 Ref |
|
||||||
const treeNodeAll = ref(false) // 全选/全不选 |
|
||||||
const checkStrictly = ref(true) // 是否严格模式,即父子不关联 |
|
||||||
|
|
||||||
// const dataScopeOptions = getIntDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE) |
|
||||||
const dataScopeOptions = [ |
|
||||||
{ label: '全部数据权限', value: 1 }, |
|
||||||
{ label: '指定部门数据权限', value: 2 }, |
|
||||||
{ label: '部门数据权限', value: 3 }, |
|
||||||
{ label: '部门及以下数据权限', value: 4 }, |
|
||||||
{ label: '仅本人数据权限', value: 5 } |
|
||||||
] |
|
||||||
|
|
||||||
async function getRoleInfo(id) { |
|
||||||
try { |
|
||||||
formData.value = await RoleApi.getRole(id) |
|
||||||
nextTick(() => { |
|
||||||
treeRef.value.setCheckedKeys(formData.value.dataScopeDeptIds) |
|
||||||
}) |
|
||||||
} catch (error) { |
|
||||||
console.log(error) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 提交表单 */ |
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
|
||||||
const submitForm = async () => { |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
const data = { |
|
||||||
roleId: formData.value.id, |
|
||||||
dataScope: formData.value.dataScope, |
|
||||||
dataScopeDeptIds: |
|
||||||
formData.value.dataScope !== SystemDataScopeEnum.DEPT_CUSTOM |
|
||||||
? [] |
|
||||||
: treeRef.value.getCheckedKeys(false) |
|
||||||
} |
|
||||||
await PermissionApi.assignRoleDataScope(data) |
|
||||||
message.success(t('common.updateSuccess')) |
|
||||||
// 发送操作成功的事件 |
|
||||||
emit('success') |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 全选/全不选 */ |
|
||||||
const handleCheckedTreeNodeAll = () => { |
|
||||||
treeRef.value.setCheckedNodes(treeNodeAll.value ? deptOptions.value : []) |
|
||||||
} |
|
||||||
|
|
||||||
/** 展开/折叠全部 */ |
|
||||||
const handleCheckedTreeExpand = () => { |
|
||||||
const nodes = treeRef.value?.store.nodesMap |
|
||||||
for (let node in nodes) { |
|
||||||
if (nodes[node].expanded === deptExpand.value) { |
|
||||||
continue |
|
||||||
} |
|
||||||
nodes[node].expanded = deptExpand.value |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
async function init() { |
|
||||||
getRoleInfo(props.roleId) |
|
||||||
deptOptions.value = handleTree(await DeptApi.getSimpleDeptList()) |
|
||||||
} |
|
||||||
|
|
||||||
onMounted(() => { |
|
||||||
init() |
|
||||||
}) |
|
||||||
</script> |
|
@ -1,96 +0,0 @@ |
|||||||
<template> |
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="400px"> |
|
||||||
<el-form |
|
||||||
ref="formRef" |
|
||||||
v-loading="formLoading" |
|
||||||
:model="formData" |
|
||||||
:rules="formRules" |
|
||||||
label-width="80px" |
|
||||||
> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="24" :offset="0"> |
|
||||||
<el-form-item label="角色名称" prop="name"> |
|
||||||
<el-input v-model="formData.name" placeholder="请输入角色名称" /> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
</el-form> |
|
||||||
<template #footer> |
|
||||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button> |
|
||||||
</template> |
|
||||||
</Dialog> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="SystemRoleForm" setup> |
|
||||||
// import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
|
||||||
import * as RoleApi from '@/api/system/role' |
|
||||||
|
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
|
|
||||||
const dialogVisible = ref(false) // 弹窗的是否展示 |
|
||||||
const dialogTitle = ref('') // 弹窗的标题 |
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
|
||||||
const formData = ref({ |
|
||||||
id: undefined, |
|
||||||
name: '' |
|
||||||
}) |
|
||||||
const formRules = reactive({ |
|
||||||
name: [{ required: true, message: '角色名称不能为空', trigger: 'blur' }] |
|
||||||
}) |
|
||||||
const formRef = ref() // 表单 Ref |
|
||||||
|
|
||||||
/** 打开弹窗 */ |
|
||||||
const open = async (type: string, id?: number) => { |
|
||||||
dialogVisible.value = true |
|
||||||
dialogTitle.value = t('action.' + type) |
|
||||||
formType.value = type |
|
||||||
resetForm() |
|
||||||
// 修改时,设置数据 |
|
||||||
if (id) { |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
formData.value = await RoleApi.getRole(id) |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置表单 */ |
|
||||||
const resetForm = () => { |
|
||||||
formData.value = { |
|
||||||
id: undefined, |
|
||||||
name: '' |
|
||||||
} |
|
||||||
formRef.value?.resetFields() |
|
||||||
} |
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
|
||||||
|
|
||||||
/** 提交表单 */ |
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
|
||||||
const submitForm = async () => { |
|
||||||
// 校验表单 |
|
||||||
if (!formRef.value) return |
|
||||||
const valid = await formRef.value.validate() |
|
||||||
if (!valid) return |
|
||||||
// 提交请求 |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
const data = formData.value as unknown as RoleApi.RoleVO |
|
||||||
if (formType.value === 'create') { |
|
||||||
await RoleApi.createRole(data) |
|
||||||
message.success(t('common.createSuccess')) |
|
||||||
} else { |
|
||||||
await RoleApi.updateRole(data) |
|
||||||
message.success(t('common.updateSuccess')) |
|
||||||
} |
|
||||||
dialogVisible.value = false |
|
||||||
// 发送操作成功的事件 |
|
||||||
emit('success') |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
</script> |
|
@ -1,147 +0,0 @@ |
|||||||
<template> |
|
||||||
<div class="flex"> |
|
||||||
<el-card shadow="always" :body-style="{ padding: '10px' }"> |
|
||||||
<div class="flex justify-between items-center" style="width: 300px"> |
|
||||||
<div class="text-16px font-bold">角色列表</div> |
|
||||||
<el-button |
|
||||||
type="primary" |
|
||||||
style="padding: 0px" |
|
||||||
text |
|
||||||
@click="openForm('create')" |
|
||||||
v-hasPermi="['basic:role:add']" |
|
||||||
> |
|
||||||
新增 |
|
||||||
</el-button> |
|
||||||
</div> |
|
||||||
<div class="border-top-1px mt-10px pt-10px"> |
|
||||||
<div |
|
||||||
class="flex justify-between items-center pl-10px pr-10px cursor-pointer pt-5px pb-5px" |
|
||||||
v-for="(item, index) in list" |
|
||||||
:key="index" |
|
||||||
:class="{ actived: libraryIndex == index }" |
|
||||||
@click="libraryIndex = index" |
|
||||||
> |
|
||||||
<div class="flex-1 text-14px">{{ item.name }}</div> |
|
||||||
<div class="ml-10px"> |
|
||||||
<el-button |
|
||||||
type="primary" |
|
||||||
style="padding: 0px" |
|
||||||
text |
|
||||||
v-hasPermi="['basic:role:update']" |
|
||||||
@click="openForm('update', item.id)" |
|
||||||
> |
|
||||||
修改 |
|
||||||
</el-button> |
|
||||||
<el-button |
|
||||||
type="primary" |
|
||||||
class="ml-10px" |
|
||||||
style="padding: 0px" |
|
||||||
text |
|
||||||
v-hasPermi="['basic:role:delete']" |
|
||||||
@click="handleDelete(item.id)" |
|
||||||
> |
|
||||||
删除 |
|
||||||
</el-button> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<Pagination |
|
||||||
v-model:limit="queryParams.pageSize" |
|
||||||
v-model:page="queryParams.pageNo" |
|
||||||
layout="total, prev, pager, next" |
|
||||||
small |
|
||||||
:total="total" |
|
||||||
@pagination="getList" |
|
||||||
/> |
|
||||||
</div> |
|
||||||
</el-card> |
|
||||||
<el-card class="ml-20px" style="flex: 1" shadow="always" :body-style="{ padding: '10px' }"> |
|
||||||
<el-tabs v-if="list && list.length" v-model="roleOperateIndex" type="card"> |
|
||||||
<el-tab-pane label="角色用户" :name="1"> |
|
||||||
<RoleEmployee v-if="roleOperateIndex == 1" :roleId="list[libraryIndex].id" /> |
|
||||||
</el-tab-pane> |
|
||||||
<el-tab-pane label="菜单权限" :name="2"> |
|
||||||
<RoleAssignMenuForm |
|
||||||
v-if="roleOperateIndex == 2" |
|
||||||
ref="assignMenuFormRef" |
|
||||||
:roleId="list[libraryIndex].id" |
|
||||||
@success="getList" |
|
||||||
/> |
|
||||||
</el-tab-pane> |
|
||||||
<el-tab-pane label="数据权限" :name="3"> |
|
||||||
<RoleDataPermissionForm |
|
||||||
v-if="roleOperateIndex == 3" |
|
||||||
ref="dataPermissionFormRef" |
|
||||||
:roleId="list[libraryIndex].id" |
|
||||||
@success="getList" |
|
||||||
/> |
|
||||||
</el-tab-pane> |
|
||||||
</el-tabs> |
|
||||||
</el-card> |
|
||||||
<!-- 表单弹窗:添加/修改 --> |
|
||||||
<RoleForm ref="formRef" @success="getList" /> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="SystemRole" setup> |
|
||||||
import RoleForm from './RoleForm.vue' |
|
||||||
import RoleEmployee from './Comp/RoleEmployee.vue' |
|
||||||
import RoleAssignMenuForm from './RoleAssignMenuForm.vue' |
|
||||||
import RoleDataPermissionForm from './RoleDataPermissionForm.vue' |
|
||||||
import * as RoleApi from '@/api/system/role' |
|
||||||
|
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
|
|
||||||
const total = ref(0) // 列表的总页数 |
|
||||||
const list = ref<any>([]) // 列表的数据 |
|
||||||
|
|
||||||
const libraryIndex = ref(0) |
|
||||||
const queryParams = reactive({ |
|
||||||
pageNo: 1, |
|
||||||
pageSize: 20 |
|
||||||
}) |
|
||||||
|
|
||||||
/** 查询角色列表 */ |
|
||||||
const getList = async () => { |
|
||||||
const data = await RoleApi.getRolePage(queryParams) |
|
||||||
list.value = data.list |
|
||||||
total.value = data.total |
|
||||||
} |
|
||||||
|
|
||||||
/** 添加/修改操作 */ |
|
||||||
const formRef = ref() |
|
||||||
const openForm = (type: string, id?: number) => { |
|
||||||
formRef.value.open(type, id) |
|
||||||
} |
|
||||||
|
|
||||||
/** 数据权限操作 */ |
|
||||||
const dataPermissionFormRef = ref() |
|
||||||
|
|
||||||
/** 菜单权限操作 */ |
|
||||||
const assignMenuFormRef = ref() |
|
||||||
|
|
||||||
/** 删除按钮操作 */ |
|
||||||
const handleDelete = async (id: number) => { |
|
||||||
try { |
|
||||||
// 删除的二次确认 |
|
||||||
await message.delConfirm() |
|
||||||
// 发起删除 |
|
||||||
await RoleApi.deleteRole(id) |
|
||||||
message.success(t('common.delSuccess')) |
|
||||||
// 刷新列表 |
|
||||||
await getList() |
|
||||||
} catch {} |
|
||||||
} |
|
||||||
|
|
||||||
const roleOperateIndex = ref(1) |
|
||||||
|
|
||||||
/** 初始化 **/ |
|
||||||
onMounted(() => { |
|
||||||
getList() |
|
||||||
}) |
|
||||||
</script> |
|
||||||
|
|
||||||
<style lang="scss" scoped> |
|
||||||
.actived { |
|
||||||
background-color: var(--el-color-primary-light-9); |
|
||||||
} |
|
||||||
</style> |
|
@ -1,24 +0,0 @@ |
|||||||
<template> |
|
||||||
<IFrame :src="src" /> |
|
||||||
</template> |
|
||||||
<script lang="ts" setup> |
|
||||||
import * as ConfigApi from '@/api/infra/config' |
|
||||||
|
|
||||||
defineOptions({ name: 'InfraSwagger' }) |
|
||||||
|
|
||||||
const loading = ref(true) // 是否加载中 |
|
||||||
const src = ref(import.meta.env.VITE_BASE_URL + '/doc.html') // Knife4j UI |
|
||||||
// const src = ref(import.meta.env.VITE_BASE_URL + '/swagger-ui') // Swagger UI |
|
||||||
|
|
||||||
/** 初始化 */ |
|
||||||
onMounted(async () => { |
|
||||||
try { |
|
||||||
const data = await ConfigApi.getConfigKey('url.swagger') |
|
||||||
if (data && data.length > 0) { |
|
||||||
src.value = data |
|
||||||
} |
|
||||||
} finally { |
|
||||||
loading.value = false |
|
||||||
} |
|
||||||
}) |
|
||||||
</script> |
|
@ -1,56 +0,0 @@ |
|||||||
<template> |
|
||||||
<div class="head-container"> |
|
||||||
<el-input v-model="deptName" class="mb-20px" clearable placeholder="请输入部门名称"> |
|
||||||
<template #prefix> |
|
||||||
<Icon icon="ep:search" /> |
|
||||||
</template> |
|
||||||
</el-input> |
|
||||||
</div> |
|
||||||
<div class="head-container"> |
|
||||||
<el-tree |
|
||||||
ref="treeRef" |
|
||||||
:data="deptList" |
|
||||||
:expand-on-click-node="false" |
|
||||||
:filter-node-method="filterNode" |
|
||||||
:props="defaultProps" |
|
||||||
default-expand-all |
|
||||||
highlight-current |
|
||||||
node-key="id" |
|
||||||
@node-click="handleNodeClick" |
|
||||||
/> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script lang="ts" name="SystemUserDeptTree" setup> |
|
||||||
import { ElTree } from 'element-plus' |
|
||||||
import * as DeptApi from '@/api/system/dept' |
|
||||||
import { defaultProps, handleTree } from '@/utils/tree' |
|
||||||
|
|
||||||
const deptName = ref('') |
|
||||||
const deptList = ref<Tree[]>([]) // 树形结构 |
|
||||||
const treeRef = ref<InstanceType<typeof ElTree>>() |
|
||||||
|
|
||||||
/** 获得部门树 */ |
|
||||||
const getTree = async () => { |
|
||||||
const res = await DeptApi.getSimpleDeptList() |
|
||||||
deptList.value = [] |
|
||||||
deptList.value.push(...handleTree(res)) |
|
||||||
} |
|
||||||
|
|
||||||
/** 基于名字过滤 */ |
|
||||||
const filterNode = (name: string, data: Tree) => { |
|
||||||
if (!name) return true |
|
||||||
return data.name.includes(name) |
|
||||||
} |
|
||||||
|
|
||||||
/** 处理部门被点击 */ |
|
||||||
const handleNodeClick = async (row: { [key: string]: any }) => { |
|
||||||
emits('node-click', row) |
|
||||||
} |
|
||||||
const emits = defineEmits(['node-click']) |
|
||||||
|
|
||||||
/** 初始化 */ |
|
||||||
onMounted(async () => { |
|
||||||
await getTree() |
|
||||||
}) |
|
||||||
</script> |
|
@ -1,228 +0,0 @@ |
|||||||
<template> |
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle" style="width: 800px"> |
|
||||||
<el-form |
|
||||||
ref="formRef" |
|
||||||
v-loading="formLoading" |
|
||||||
:model="formData" |
|
||||||
:rules="formRules" |
|
||||||
label-width="80px" |
|
||||||
> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="12"> |
|
||||||
<el-form-item label="用户姓名" prop="nickname"> |
|
||||||
<el-input v-model="formData.nickname" placeholder="请输入用户姓名" /> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
<!-- <el-col :span="12"> |
|
||||||
<el-form-item label="用户性别"> |
|
||||||
<el-radio-group v-model="formData.sex"> |
|
||||||
<el-radio :value="1"> 男 </el-radio> |
|
||||||
<el-radio :value="2"> 女 </el-radio> |
|
||||||
</el-radio-group> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="12"> |
|
||||||
<el-form-item label="归属部门" prop="deptId"> |
|
||||||
<el-tree-select |
|
||||||
v-model="formData.deptId" |
|
||||||
:data="deptList" |
|
||||||
:props="defaultProps" |
|
||||||
check-strictly |
|
||||||
node-key="id" |
|
||||||
placeholder="请选择归属部门" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
</el-col> --> |
|
||||||
<el-col :span="12"> |
|
||||||
<el-form-item label="角色" prop="role"> |
|
||||||
<el-select |
|
||||||
v-model="formData.roleIds" |
|
||||||
multiple |
|
||||||
collapse-tags |
|
||||||
collapse-tags-tooltip |
|
||||||
:max-collapse-tags="2" |
|
||||||
placeholder="请选择角色" |
|
||||||
> |
|
||||||
<el-option |
|
||||||
v-for="item in roleOptions" |
|
||||||
:key="item.id" |
|
||||||
:label="item.name" |
|
||||||
:value="item.id" |
|
||||||
/> |
|
||||||
</el-select> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="12"> |
|
||||||
<el-form-item label="手机号码" prop="mobile"> |
|
||||||
<el-input v-model="formData.mobile" maxlength="11" placeholder="请输入手机号码" /> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
<el-col :span="12"> |
|
||||||
<el-form-item label="邮箱" prop="email"> |
|
||||||
<el-input v-model="formData.email" maxlength="50" placeholder="请输入邮箱" /> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="12"> |
|
||||||
<el-form-item v-if="formData.id === undefined" label="登录账号" prop="username"> |
|
||||||
<el-input v-model="formData.username" placeholder="请输入登录账号" /> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
<el-col :span="12"> |
|
||||||
<el-form-item v-if="formData.id === undefined" label="用户密码" prop="password"> |
|
||||||
<el-input |
|
||||||
v-model="formData.password" |
|
||||||
placeholder="请输入用户密码" |
|
||||||
show-password |
|
||||||
type="password" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
<!-- <el-row :gutter="20"> |
|
||||||
<el-col :span="12" :offset="0"> |
|
||||||
<el-form-item label="入职日期" prop="hireDate"> |
|
||||||
<el-date-picker |
|
||||||
v-model="formData.hireDate" |
|
||||||
type="date" |
|
||||||
format="YYYY-MM-DD" |
|
||||||
value-format="YYYY-MM-DD" |
|
||||||
placeholder="选择日期时间" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> --> |
|
||||||
<el-row :gutter="20"> |
|
||||||
<el-col :span="24"> |
|
||||||
<el-form-item label="备注"> |
|
||||||
<el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" /> |
|
||||||
</el-form-item> |
|
||||||
</el-col> |
|
||||||
</el-row> |
|
||||||
</el-form> |
|
||||||
<template #footer> |
|
||||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> |
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button> |
|
||||||
</template> |
|
||||||
</Dialog> |
|
||||||
</template> |
|
||||||
<script lang="ts" name="SystemUserForm" setup> |
|
||||||
import { CommonStatusEnum } from '@/utils/constants' |
|
||||||
// import { defaultProps, handleTree } from '@/utils/tree' |
|
||||||
import { handleTree } from '@/utils/tree' |
|
||||||
import { formatDate } from '@/utils/formatTime' |
|
||||||
|
|
||||||
import * as RoleApi from '@/api/system/role' |
|
||||||
import * as DeptApi from '@/api/system/dept' |
|
||||||
import * as UserApi from '@/api/system/user' |
|
||||||
|
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
|
|
||||||
const dialogVisible = ref(false) // 弹窗的是否展示 |
|
||||||
const dialogTitle = ref('') // 弹窗的标题 |
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 |
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改 |
|
||||||
const formData = ref({ |
|
||||||
nickname: '', |
|
||||||
deptId: '', |
|
||||||
mobile: '', |
|
||||||
email: '', |
|
||||||
id: undefined, |
|
||||||
username: '', |
|
||||||
password: '', |
|
||||||
sex: 1, |
|
||||||
remark: '', |
|
||||||
status: CommonStatusEnum.ENABLE, |
|
||||||
roleIds: [], |
|
||||||
hireDate: '' |
|
||||||
}) |
|
||||||
const formRules = ref<any>({ |
|
||||||
username: [{ required: true, message: '登录账号不能为空', trigger: 'blur' }], |
|
||||||
nickname: [{ required: true, message: '用户姓名不能为空', trigger: 'blur' }], |
|
||||||
password: [{ required: true, message: '用户密码不能为空', trigger: 'blur' }], |
|
||||||
email: [ |
|
||||||
{ |
|
||||||
type: 'email', |
|
||||||
message: '请输入正确的邮箱地址', |
|
||||||
trigger: ['blur', 'change'] |
|
||||||
} |
|
||||||
], |
|
||||||
mobile: [{ required: true, message: '手机号不能为空', trigger: 'blur' }] |
|
||||||
}) |
|
||||||
const formRef = ref() // 表单 Ref |
|
||||||
const deptList = ref<Tree[]>([]) // 树形结构 |
|
||||||
const roleOptions = ref<any>([]) |
|
||||||
|
|
||||||
/** 打开弹窗 */ |
|
||||||
const open = async (type: string, id?: number) => { |
|
||||||
dialogVisible.value = true |
|
||||||
dialogTitle.value = t('action.' + type) |
|
||||||
formType.value = type |
|
||||||
resetForm() |
|
||||||
// 修改时,设置数据 |
|
||||||
if (id) { |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
formData.value = await UserApi.getUser(id) |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
// 加载部门树 |
|
||||||
deptList.value = handleTree(await DeptApi.getSimpleDeptList({ allFlag: false })) |
|
||||||
// 加载岗位列表 |
|
||||||
roleOptions.value = await RoleApi.getSimpleRoleList() |
|
||||||
} |
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
|
||||||
|
|
||||||
/** 提交表单 */ |
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
|
||||||
const submitForm = async () => { |
|
||||||
// 校验表单 |
|
||||||
if (!formRef.value) return |
|
||||||
const valid = await formRef.value.validate() |
|
||||||
if (!valid) return |
|
||||||
// 提交请求 |
|
||||||
formLoading.value = true |
|
||||||
try { |
|
||||||
const data = formData.value as unknown as UserApi.UserVO |
|
||||||
if (formType.value === 'create') { |
|
||||||
await UserApi.createUser(data) |
|
||||||
message.success(t('common.createSuccess')) |
|
||||||
} else { |
|
||||||
await UserApi.updateUser(data) |
|
||||||
message.success(t('common.updateSuccess')) |
|
||||||
} |
|
||||||
dialogVisible.value = false |
|
||||||
// 发送操作成功的事件 |
|
||||||
emit('success') |
|
||||||
} finally { |
|
||||||
formLoading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置表单 */ |
|
||||||
const resetForm = () => { |
|
||||||
formData.value = { |
|
||||||
nickname: '', |
|
||||||
deptId: '', |
|
||||||
mobile: '', |
|
||||||
email: '', |
|
||||||
id: undefined, |
|
||||||
username: '', |
|
||||||
password: '', |
|
||||||
sex: 1, |
|
||||||
remark: '', |
|
||||||
status: CommonStatusEnum.ENABLE, |
|
||||||
roleIds: [], |
|
||||||
hireDate: formatDate(new Date(), 'YYYY-MM-DD') |
|
||||||
} |
|
||||||
formRef.value?.resetFields() |
|
||||||
} |
|
||||||
</script> |
|
@ -1,209 +0,0 @@ |
|||||||
<template> |
|
||||||
<!-- <el-row :gutter="20"> --> |
|
||||||
<!-- 左侧部门树 --> |
|
||||||
<!-- <el-col :span="4" :xs="24"> |
|
||||||
<DeptTree @node-click="handleDeptNodeClick" /> |
|
||||||
</el-col> |
|
||||||
<el-col :span="20" :xs="24"> --> |
|
||||||
<!-- 搜索 --> |
|
||||||
<el-form :model="queryParams" ref="queryFormRef" inline label-width="0"> |
|
||||||
<el-form-item prop="nickname"> |
|
||||||
<el-input |
|
||||||
v-model="queryParams.nickname" |
|
||||||
placeholder="请输入姓名" |
|
||||||
clearable |
|
||||||
@keyup.enter="handleQuery" |
|
||||||
class="!w-240px" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item prop="mobile"> |
|
||||||
<el-input |
|
||||||
v-model="queryParams.mobile" |
|
||||||
placeholder="请输入手机号码" |
|
||||||
clearable |
|
||||||
@keyup.enter="handleQuery" |
|
||||||
class="!w-240px" |
|
||||||
/> |
|
||||||
</el-form-item> |
|
||||||
<el-form-item> |
|
||||||
<el-button @click="handleQuery" v-hasPermi="['basic:employee:search']">搜索</el-button> |
|
||||||
<el-button @click="resetQuery" v-hasPermi="['basic:employee:reset']">重置</el-button> |
|
||||||
<el-button |
|
||||||
type="primary" |
|
||||||
plain |
|
||||||
@click="openForm('create')" |
|
||||||
v-hasPermi="['basic:employee:add']" |
|
||||||
> |
|
||||||
新增 |
|
||||||
</el-button> |
|
||||||
</el-form-item> |
|
||||||
</el-form> |
|
||||||
<el-table v-loading="loading" :data="list"> |
|
||||||
<el-table-column label="用户编号" key="id" prop="id" /> |
|
||||||
<el-table-column label="登录账号" prop="username" /> |
|
||||||
<el-table-column label="用户姓名" prop="nickname" /> |
|
||||||
<!-- <el-table-column label="部门" key="deptName" prop="deptName" /> --> |
|
||||||
<el-table-column label="手机号码" prop="mobile" width="120" /> |
|
||||||
<el-table-column label="状态" key="status"> |
|
||||||
<template #default="scope"> |
|
||||||
<el-switch |
|
||||||
v-model="scope.row.status" |
|
||||||
:active-value="0" |
|
||||||
:inactive-value="1" |
|
||||||
active-text="在职" |
|
||||||
inactive-text="离职" |
|
||||||
v-hasPermi="['basic:employee:update']" |
|
||||||
@change="handleStatusChange(scope.row)" |
|
||||||
/> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
<el-table-column label="创建时间" prop="createTime" width="180" :formatter="dateFormatter" /> |
|
||||||
<el-table-column label="操作" width="260"> |
|
||||||
<template #default="scope"> |
|
||||||
<el-button |
|
||||||
type="primary" |
|
||||||
link |
|
||||||
@click="openForm('update', scope.row.id)" |
|
||||||
v-hasPermi="['basic:employee:update']" |
|
||||||
> |
|
||||||
修改 |
|
||||||
</el-button> |
|
||||||
<el-button |
|
||||||
type="primary" |
|
||||||
link |
|
||||||
@click="handleDelete(scope.row.id)" |
|
||||||
v-hasPermi="['basic:employee:delete']" |
|
||||||
> |
|
||||||
删除 |
|
||||||
</el-button> |
|
||||||
<el-button |
|
||||||
type="primary" |
|
||||||
link |
|
||||||
@click="handleResetPwd(scope.row)" |
|
||||||
v-hasPermi="['basic:employee:password']" |
|
||||||
> |
|
||||||
重置密码 |
|
||||||
</el-button> |
|
||||||
</template> |
|
||||||
</el-table-column> |
|
||||||
</el-table> |
|
||||||
<Pagination |
|
||||||
:total="total" |
|
||||||
v-model:page="queryParams.pageNo" |
|
||||||
v-model:limit="queryParams.pageSize" |
|
||||||
@pagination="getList" |
|
||||||
/> |
|
||||||
<!-- </el-col> --> |
|
||||||
<!-- </el-row> --> |
|
||||||
|
|
||||||
<!-- 添加或修改用户对话框 --> |
|
||||||
<UserForm ref="formRef" @success="getList" /> |
|
||||||
</template> |
|
||||||
<script setup lang="ts" name="SystemUser"> |
|
||||||
import { CommonStatusEnum } from '@/utils/constants' |
|
||||||
import { dateFormatter } from '@/utils/formatTime' |
|
||||||
import * as UserApi from '@/api/system/user' |
|
||||||
import UserForm from './UserForm.vue' |
|
||||||
// import DeptTree from './DeptTree.vue' |
|
||||||
const message = useMessage() // 消息弹窗 |
|
||||||
const { t } = useI18n() // 国际化 |
|
||||||
|
|
||||||
const loading = ref(true) // 列表的加载中 |
|
||||||
const total = ref(0) // 列表的总页数 |
|
||||||
const list = ref([]) // 列表的数 |
|
||||||
const queryParams = reactive({ |
|
||||||
pageNo: 1, |
|
||||||
pageSize: 10, |
|
||||||
username: undefined, |
|
||||||
nickname: undefined, |
|
||||||
mobile: undefined, |
|
||||||
deptId: undefined |
|
||||||
}) |
|
||||||
const queryFormRef = ref() // 搜索的表单 |
|
||||||
|
|
||||||
/** 查询列表 */ |
|
||||||
const getList = async () => { |
|
||||||
loading.value = true |
|
||||||
try { |
|
||||||
const data = await UserApi.getUserPage(queryParams) |
|
||||||
list.value = data.list |
|
||||||
total.value = data.total |
|
||||||
} finally { |
|
||||||
loading.value = false |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 搜索按钮操作 */ |
|
||||||
const handleQuery = () => { |
|
||||||
queryParams.pageNo = 1 |
|
||||||
getList() |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置按钮操作 */ |
|
||||||
const resetQuery = () => { |
|
||||||
queryFormRef.value?.resetFields() |
|
||||||
handleQuery() |
|
||||||
} |
|
||||||
|
|
||||||
// /** 处理部门被点击 */ |
|
||||||
// const handleDeptNodeClick = async (row) => { |
|
||||||
// queryParams.deptId = row.id |
|
||||||
// await getList() |
|
||||||
// } |
|
||||||
|
|
||||||
/** 添加/修改操作 */ |
|
||||||
const formRef = ref() |
|
||||||
const openForm = (type: string, id?: number) => { |
|
||||||
formRef.value.open(type, id) |
|
||||||
} |
|
||||||
|
|
||||||
/** 修改用户状态 */ |
|
||||||
const handleStatusChange = async (row: UserApi.UserVO) => { |
|
||||||
try { |
|
||||||
// 修改状态的二次确认 |
|
||||||
const text = row.status === CommonStatusEnum.ENABLE ? '启用' : '停用' |
|
||||||
await message.confirm('确认要"' + text + '""' + row.username + '"用户吗?') |
|
||||||
// 发起修改状态 |
|
||||||
await UserApi.updateUserStatus(row.id, row.status) |
|
||||||
// 刷新列表 |
|
||||||
await getList() |
|
||||||
} catch { |
|
||||||
// 取消后,进行恢复按钮 |
|
||||||
row.status = |
|
||||||
row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE : CommonStatusEnum.ENABLE |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** 删除按钮操作 */ |
|
||||||
const handleDelete = async (id: number) => { |
|
||||||
try { |
|
||||||
// 删除的二次确认 |
|
||||||
await message.delConfirm() |
|
||||||
// 发起删除 |
|
||||||
await UserApi.deleteUser(id) |
|
||||||
message.success(t('common.delSuccess')) |
|
||||||
// 刷新列表 |
|
||||||
await getList() |
|
||||||
} catch {} |
|
||||||
} |
|
||||||
|
|
||||||
/** 重置密码 */ |
|
||||||
const handleResetPwd = async (row: UserApi.UserVO) => { |
|
||||||
try { |
|
||||||
// 重置的二次确认 |
|
||||||
const result = await message.prompt( |
|
||||||
'请输入"' + row.username + '"的新密码', |
|
||||||
t('common.reminder') |
|
||||||
) |
|
||||||
const password = result.value |
|
||||||
// 发起重置 |
|
||||||
await UserApi.resetUserPwd(row.id, password) |
|
||||||
message.success('修改成功,新密码是:' + password) |
|
||||||
} catch {} |
|
||||||
} |
|
||||||
|
|
||||||
/** 初始化 */ |
|
||||||
onMounted(() => { |
|
||||||
getList() |
|
||||||
}) |
|
||||||
</script> |
|
Loading…
Reference in new issue