sc
This commit is contained in:
@@ -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>
|
|
||||||
Reference in New Issue
Block a user