mirror of https://gitee.com/xiaonuobase/snowy
【更新】人员管理模块下增加导入导出以及该模块对应的国际化配置调整
parent
87f43b5f17
commit
b51180bfbf
|
@ -69,5 +69,15 @@ export default {
|
|||
// 给人员授权角色
|
||||
grantRole(data) {
|
||||
return request('grantRole', data)
|
||||
},
|
||||
// 用户导入
|
||||
userImport(data) {
|
||||
return request('import', data)
|
||||
},
|
||||
// 用户导出
|
||||
userExport(data) {
|
||||
return request('export', data, 'get', {
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,9 @@ export default {
|
|||
batchRemoveButton: 'batch Remove',
|
||||
detailButton: 'detail',
|
||||
searchKey: 'Search Key',
|
||||
imports: 'import',
|
||||
more: 'More'
|
||||
imports: 'Import',
|
||||
more: 'More',
|
||||
export: 'Export',
|
||||
},
|
||||
model: {
|
||||
user: 'user',
|
||||
|
@ -58,5 +59,14 @@ export default {
|
|||
userStatus: 'User Status',
|
||||
resetPassword: 'Reset Password',
|
||||
role: 'Role',
|
||||
batchExportButton: 'Batch Export',
|
||||
grantRole: 'Grant Role',
|
||||
grantResource: 'Grant Resource',
|
||||
grantPermission: 'Grant Permission',
|
||||
exportUserInfo: 'Export UserInfo',
|
||||
placeholderNameAndSearchKey: 'Please enter your name or keyword',
|
||||
placeholderUserStatus: 'Please select status',
|
||||
popconfirmDeleteUser: 'Are you sure you want to delete it?',
|
||||
popconfirmResatUserPwd: 'Are you sure you want to reset?'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ export default {
|
|||
searchKey: '关键词',
|
||||
imports: '导入',
|
||||
more: '更多',
|
||||
export: '导出',
|
||||
},
|
||||
model: {
|
||||
user: '用户',
|
||||
|
@ -60,5 +61,14 @@ export default {
|
|||
userStatus: '用户状态',
|
||||
resetPassword: '重置密码',
|
||||
role: '角色',
|
||||
batchExportButton: '批量导出',
|
||||
grantRole: '授权角色',
|
||||
grantResource: '授权资源',
|
||||
grantPermission: '授权权限',
|
||||
exportUserInfo: '导出信息',
|
||||
placeholderNameAndSearchKey: '请输入姓名或关键词',
|
||||
placeholderUserStatus: '请选择状态',
|
||||
popconfirmDeleteUser: '确定要删除吗?',
|
||||
popconfirmResatUserPwd: '确定要重置吗?'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<a-drawer
|
||||
title="导入导出"
|
||||
:width="620"
|
||||
:visible="visible"
|
||||
:destroy-on-close="true"
|
||||
:footer-style="{ textAlign: 'right' }"
|
||||
@close="onClose"
|
||||
>
|
||||
<span
|
||||
>导入数据格式严格按照系统模板进行数据录入,请点击
|
||||
<a-button type="primary" size="small" @click="downloadImportUserTemplate">下载模板</a-button>
|
||||
</span>
|
||||
<a-divider dashed />
|
||||
<div>
|
||||
<a-spin :spinning="impUploadLoading">
|
||||
<a-upload-dragger :show-upload-list="false" :custom-request="customRequestLocal">
|
||||
<p class="ant-upload-drag-icon">
|
||||
<inbox-outlined></inbox-outlined>
|
||||
</p>
|
||||
<p class="ant-upload-text">单击或拖动文件到此区域进行上传</p>
|
||||
<p class="ant-upload-hint">仅支持xls、xlsx格式文件</p>
|
||||
</a-upload-dragger>
|
||||
</a-spin>
|
||||
</div>
|
||||
<a-alert v-if="impAlertStatus" type="info" :show-icon="false" banner closable @close="onImpClose" class="mt-3">
|
||||
<template #description>
|
||||
<p>导入总数:{{ impResultData.totalCount }} 条</p>
|
||||
<p>导入成功:{{ impResultData.successCount }} 条</p>
|
||||
<div v-if="impResultData.errorCount > 0">
|
||||
<p><span style="color: red">失败条数:</span>{{ impResultData.errorCount }} 条</p>
|
||||
<a-table :dataSource="impResultErrorDataSource" :columns="impErrorColumns" size="small" />
|
||||
</div>
|
||||
</template>
|
||||
</a-alert>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script setup name="bizUserImpExp">
|
||||
import userApi from '@/api/sys/userApi'
|
||||
import bizUserApi from '@/api/biz/bizUserApi'
|
||||
import downloadUtil from '@/utils/downloadUtil'
|
||||
|
||||
const impUploadLoading = ref(false)
|
||||
const impAlertStatus = ref(false)
|
||||
const impResultData = ref({})
|
||||
const impResultErrorDataSource = ref([])
|
||||
// 导入
|
||||
const customRequestLocal = (data) => {
|
||||
impUploadLoading.value = true
|
||||
const fileData = new FormData()
|
||||
fileData.append('file', data.file)
|
||||
return bizUserApi
|
||||
.userImport(fileData)
|
||||
.then((res) => {
|
||||
impAlertStatus.value = true
|
||||
impResultData.value = res
|
||||
impResultErrorDataSource.value = res.errorDetail
|
||||
})
|
||||
.finally(() => {
|
||||
impUploadLoading.value = false
|
||||
})
|
||||
}
|
||||
// 关闭导入提示
|
||||
const onImpClose = () => {
|
||||
impAlertStatus.value = false
|
||||
}
|
||||
const impErrorColumns = [
|
||||
{
|
||||
title: '索引',
|
||||
dataIndex: 'index',
|
||||
width: '80px'
|
||||
},
|
||||
{
|
||||
title: '原因',
|
||||
dataIndex: 'msg'
|
||||
}
|
||||
]
|
||||
// 定义emit事件
|
||||
const emit = defineEmits({ successful: null })
|
||||
// 默认是关闭状态
|
||||
let visible = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
|
||||
// 打开抽屉
|
||||
const onOpen = () => {
|
||||
visible.value = true
|
||||
}
|
||||
// 关闭抽屉
|
||||
const onClose = () => {
|
||||
visible.value = false
|
||||
// 关闭导入的提示
|
||||
onImpClose()
|
||||
}
|
||||
// 下载用户导入模板
|
||||
const downloadImportUserTemplate = () => {
|
||||
userApi.userDownloadImportUserTemplate().then((res) => {
|
||||
downloadUtil.resultDownload(res)
|
||||
})
|
||||
}
|
||||
// 调用这个函数将子组件的一些数据和方法暴露出去
|
||||
defineExpose({
|
||||
onOpen
|
||||
})
|
||||
</script>
|
|
@ -14,6 +14,39 @@
|
|||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="19">
|
||||
<a-card :bordered="false" style="margin-bottom: 10px">
|
||||
<a-form ref="searchFormRef" name="advanced_search" class="ant-advanced-search-form" :model="searchFormState">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="8">
|
||||
<a-form-item name="searchKey" :label="$t('common.searchKey')">
|
||||
<a-input
|
||||
v-model:value="searchFormState.searchKey"
|
||||
:placeholder="$t('user.placeholderNameAndSearchKey')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item name="userStatus" :label="$t('user.userStatus')">
|
||||
<a-select v-model:value="searchFormState.userStatus" :placeholder="$t('user.placeholderUserStatus')">
|
||||
<a-select-option v-for="item in statusData" :key="item.dictValue" :value="item.dictValue">{{
|
||||
item.name
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-button type="primary" @click="table.refresh(true)">
|
||||
<template #icon><SearchOutlined /></template>
|
||||
{{ $t('common.searchButton') }}
|
||||
</a-button>
|
||||
<a-button class="snowy-buttom-left" @click="() => searchFormRef.resetFields()">
|
||||
<template #icon><redo-outlined /></template>
|
||||
{{ $t('common.resetButton') }}
|
||||
</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
<a-card :bordered="false">
|
||||
<s-table
|
||||
ref="table"
|
||||
|
@ -26,43 +59,31 @@
|
|||
:row-selection="options.rowSelection"
|
||||
>
|
||||
<template #operator class="table-operator">
|
||||
<a-form
|
||||
ref="searchFormRef"
|
||||
name="advanced_search"
|
||||
class="ant-advanced-search-form"
|
||||
:model="searchFormState"
|
||||
>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="6">
|
||||
<a-form-item name="searchKey">
|
||||
<a-input v-model:value="searchFormState.searchKey" placeholder="请输入姓名或账号"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item name="userStatus">
|
||||
<a-select v-model:value="searchFormState.userStatus" placeholder="请选择状态">
|
||||
<a-select-option v-for="item in statusData" :key="item.dictValue" :value="item.dictValue">{{
|
||||
item.name
|
||||
}}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-button type="primary" @click="table.refresh(true)">{{ $t('common.searchButton') }}</a-button>
|
||||
<a-button class="snowy-buttom-left" @click="() => searchFormRef.resetFields()">{{
|
||||
$t('common.resetButton')
|
||||
}}</a-button>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-button type="primary" class="primaryAdd" @click="form.onOpen()" v-if="hasPerm('bizUserAdd')">
|
||||
<span>{{ $t('common.addButton') }}{{ $t('model.bizUser') }}</span>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="form.onOpen()" v-if="hasPerm('bizUserAdd')">
|
||||
<template #icon><plus-outlined /></template>
|
||||
<span>{{ $t('common.addButton') }}{{ $t('model.user') }}</span>
|
||||
</a-button>
|
||||
<a-button danger @click="removeBatchUser()" v-if="hasPerm('bizUserBatchDelete')">{{
|
||||
$t('common.batchRemoveButton')
|
||||
}}</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<a-button @click="ImpExpRef.onOpen()" v-if="hasPerm('bizUserImport')">
|
||||
<template #icon><import-outlined /></template>
|
||||
<span>{{ $t('common.imports') }}</span>
|
||||
</a-button>
|
||||
<a-button @click="exportBatchUserVerify" v-if="hasPerm('bizUserBatchExport')">
|
||||
<template #icon><delete-outlined /></template>
|
||||
{{ $t('user.batchExportButton') }}
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
title="删除此信息?"
|
||||
:visible="deleteVisible"
|
||||
@visibleChange="deleteVisibleChange"
|
||||
@confirm="deleteBatchUser"
|
||||
>
|
||||
<a-button danger v-if="hasPerm('bizUserBatchDelete')">
|
||||
<template #icon><delete-outlined /></template>
|
||||
{{ $t('common.batchRemoveButton') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'avatar'">
|
||||
|
@ -82,18 +103,35 @@
|
|||
</template>
|
||||
<template v-if="column.dataIndex === 'action'">
|
||||
<a @click="form.onOpen(record)" v-if="hasPerm('bizUserEdit')">{{ $t('common.editButton') }}</a>
|
||||
<a-divider type="vertical" v-if="hasPerm(['bizUserEdit', 'bizUserGrantRole'], 'and')" />
|
||||
<a @click="selectRole(record)" v-if="hasPerm('bizUserGrantRole')">角色</a>
|
||||
<a-divider type="vertical" v-if="hasPerm(['bizUserGrantRole', 'bizUserPwdReset'], 'and')" />
|
||||
<a-popconfirm title="确定重置此人员密码?" @confirm="resetPassword(record)">
|
||||
<a v-if="hasPerm('bizUserPwdReset')">重置密码</a>
|
||||
</a-popconfirm>
|
||||
<a-divider type="vertical" v-if="hasPerm(['bizUserPwdReset', 'bizUserDelete'], 'and')" />
|
||||
<a-popconfirm title="确定要删除此人员吗?" @confirm="removeUser(record)">
|
||||
<a-divider type="vertical" v-if="hasPerm(['bizUserEdit', 'bizUserDelete'], 'and')" />
|
||||
<a-popconfirm :title="$t('user.popconfirmDeleteUser')" @confirm="removeUser(record)">
|
||||
<a-button type="link" danger size="small" v-if="hasPerm('bizUserDelete')">{{
|
||||
$t('common.removeButton')
|
||||
}}</a-button>
|
||||
</a-popconfirm>
|
||||
<a-divider type="vertical" v-if="hasPerm(['bizUserGrantRole', 'bizUserPwdReset'], 'and')" />
|
||||
<a-dropdown v-if="hasPerm(['bizUserGrantRole', 'bizUserPwdReset'], 'and')">
|
||||
<a class="ant-dropdown-link">
|
||||
{{ $t('common.more') }}
|
||||
<DownOutlined />
|
||||
</a>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item v-if="hasPerm('bizUserPwdReset')">
|
||||
<a-popconfirm
|
||||
:title="$t('user.popconfirmResatUserPwd')"
|
||||
placement="topRight"
|
||||
@confirm="resetPassword(record)"
|
||||
>
|
||||
<a>{{ $t('user.resetPassword') }}</a>
|
||||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
<a-menu-item v-if="hasPerm('bizUserGrantRole')">
|
||||
<a @click="selectRole(record)">{{ $t('user.grantRole') }}</a>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
</template>
|
||||
</s-table>
|
||||
|
@ -108,13 +146,16 @@
|
|||
:role-global="false"
|
||||
@onBack="roleBack"
|
||||
/>
|
||||
<ImpExp ref="ImpExpRef" />
|
||||
</template>
|
||||
<script setup name="bizUser">
|
||||
import { message, Empty } from 'ant-design-vue'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import tool from '@/utils/tool'
|
||||
import downloadUtil from '@/utils/downloadUtil'
|
||||
import bizUserApi from '@/api/biz/bizUserApi'
|
||||
import roleSelectorPlus from '@/components/Selector/roleSelectorPlus.vue'
|
||||
import Form from './form.vue'
|
||||
import ImpExp from './impExp.vue'
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
@ -163,11 +204,10 @@
|
|||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
align: 'center',
|
||||
width: '240px'
|
||||
width: '220px'
|
||||
})
|
||||
}
|
||||
const { proxy } = getCurrentInstance()
|
||||
const statusData = proxy.$TOOL.dictTypeList('COMMON_STATUS')
|
||||
const statusData = tool.dictTypeList('COMMON_STATUS')
|
||||
const searchFormRef = ref()
|
||||
let defaultExpandedKeys = ref([])
|
||||
let searchFormState = reactive({})
|
||||
|
@ -181,7 +221,8 @@
|
|||
const selectedRecord = ref({})
|
||||
const loading = ref(false)
|
||||
const cardLoading = ref(true)
|
||||
|
||||
const ImpExpRef = ref()
|
||||
const deleteVisible = ref(false)
|
||||
// 表格查询 返回 Promise 对象
|
||||
const loadData = (parameter) => {
|
||||
return bizUserApi.userPage(Object.assign(parameter, searchFormState)).then((res) => {
|
||||
|
@ -189,7 +230,9 @@
|
|||
})
|
||||
}
|
||||
// 左侧树查询
|
||||
bizUserApi.userOrgTreeSelector().then((res) => {
|
||||
bizUserApi
|
||||
.userOrgTreeSelector()
|
||||
.then((res) => {
|
||||
cardLoading.value = false
|
||||
if (res !== null) {
|
||||
treeData.value = res
|
||||
|
@ -238,14 +281,18 @@
|
|||
const editStatus = (record) => {
|
||||
loading.value = true
|
||||
if (record.userStatus === 'ENABLE') {
|
||||
bizUserApi.userDisableUser(record).then(() => {
|
||||
bizUserApi
|
||||
.userDisableUser(record)
|
||||
.then(() => {
|
||||
table.value.refresh()
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
} else {
|
||||
bizUserApi.userEnableUser(record).then(() => {
|
||||
bizUserApi
|
||||
.userEnableUser(record)
|
||||
.then(() => {
|
||||
table.value.refresh()
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -264,12 +311,49 @@
|
|||
table.value.refresh()
|
||||
})
|
||||
}
|
||||
// 批量删除人员
|
||||
const removeBatchUser = () => {
|
||||
if (selectedRowKeys.value.length < 1) {
|
||||
message.warning('请选择一条或多条数据')
|
||||
// 批量导出校验并加参数
|
||||
const exportBatchUserVerify = () => {
|
||||
if ((selectedRowKeys.value.length < 1) & !searchFormState.searchKey & !searchFormState.userStatus) {
|
||||
message.warning('请输入查询条件或勾选要导出的信息')
|
||||
}
|
||||
if (selectedRowKeys.value.length > 0) {
|
||||
const params = selectedRowKeys.value.map((m) => {
|
||||
return m
|
||||
})
|
||||
exportBatchUser(params)
|
||||
return
|
||||
}
|
||||
if (searchFormState.searchKey || searchFormState.userStatus) {
|
||||
const params = {
|
||||
searchKey: searchFormState.searchKey,
|
||||
userStatus: searchFormState.userStatus
|
||||
}
|
||||
exportBatchUser(params)
|
||||
return
|
||||
}
|
||||
}
|
||||
// 批量导出
|
||||
const exportBatchUser = (params) => {
|
||||
bizUserApi.userExport(params).then((res) => {
|
||||
downloadUtil.resultDownload(res)
|
||||
})
|
||||
}
|
||||
// 批量删除校验
|
||||
const deleteVisibleChange = () => {
|
||||
if (deleteVisible.value) {
|
||||
deleteVisible.value = false
|
||||
return false
|
||||
}
|
||||
if (selectedRowKeys.value.length < 1) {
|
||||
message.warning('请选择一条或多条数据')
|
||||
deleteVisible.value = false
|
||||
return false
|
||||
} else {
|
||||
deleteVisible.value = true
|
||||
}
|
||||
}
|
||||
// 批量删除
|
||||
const deleteBatchUser = () => {
|
||||
const params = selectedRowKeys.value.map((m) => {
|
||||
return {
|
||||
id: m
|
||||
|
|
|
@ -19,12 +19,15 @@
|
|||
<a-row :gutter="24">
|
||||
<a-col :span="8">
|
||||
<a-form-item name="searchKey" :label="$t('common.searchKey')">
|
||||
<a-input v-model:value="searchFormState.searchKey" placeholder="请输入姓名或账号关键词"></a-input>
|
||||
<a-input
|
||||
v-model:value="searchFormState.searchKey"
|
||||
:placeholder="$t('user.placeholderNameAndSearchKey')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item name="userStatus" :label="$t('user.userStatus')">
|
||||
<a-select v-model:value="searchFormState.userStatus" placeholder="请选择状态">
|
||||
<a-select v-model:value="searchFormState.userStatus" :placeholder="$t('user.placeholderUserStatus')">
|
||||
<a-select-option v-for="item in statusData" :key="item.dictValue" :value="item.dictValue">{{
|
||||
item.name
|
||||
}}</a-select-option>
|
||||
|
@ -67,7 +70,7 @@
|
|||
</a-button>
|
||||
<a-button @click="exportBatchUserVerify">
|
||||
<template #icon><delete-outlined /></template>
|
||||
批量导出
|
||||
{{ $t('user.batchExportButton') }}
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
title="删除此信息?"
|
||||
|
@ -95,7 +98,7 @@
|
|||
<template v-if="column.dataIndex === 'action'">
|
||||
<a @click="form.onOpen(record)">{{ $t('common.editButton') }}</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm title="确定要删除此用户吗?" placement="topRight" @confirm="removeUser(record)">
|
||||
<a-popconfirm :title="$t('user.popconfirmDeleteUser')" placement="topRight" @confirm="removeUser(record)">
|
||||
<a-button type="link" danger size="small">
|
||||
{{ $t('common.removeButton') }}
|
||||
</a-button>
|
||||
|
@ -109,21 +112,25 @@
|
|||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>
|
||||
<a-popconfirm title="确定重置此用户密码?" placement="topRight" @confirm="resetPassword(record)">
|
||||
<a-popconfirm
|
||||
:title="$t('user.popconfirmResatUserPwd')"
|
||||
placement="topRight"
|
||||
@confirm="resetPassword(record)"
|
||||
>
|
||||
<a>{{ $t('user.resetPassword') }}</a>
|
||||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a @click="selectRole(record)">授权角色</a>
|
||||
<a @click="selectRole(record)">{{ $t('user.grantRole') }}</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a @click="grantResourceFormRef.onOpen(record)">授权资源</a>
|
||||
<a @click="grantResourceFormRef.onOpen(record)">{{ $t('user.grantResource') }}</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a @click="grantPermissionFormRef.onOpen(record)">授权权限</a>
|
||||
<a @click="grantPermissionFormRef.onOpen(record)">{{ $t('user.grantPermission') }}</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a @click="exportUserInfo(record)">导出信息</a>
|
||||
<a @click="exportUserInfo(record)">{{ $t('user.exportUserInfo') }}</a>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue