【更新】人员管理模块下增加导入导出以及该模块对应的国际化配置调整

pull/89/MERGE
小诺 2 years ago committed by 俞宝山
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">仅支持xlsxlsx格式文件</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-button>
<a-button danger @click="removeBatchUser()" v-if="hasPerm('bizUserBatchDelete')">{{
$t('common.batchRemoveButton')
}}</a-button>
</a-col>
</a-row>
</a-form>
<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 @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,28 +230,30 @@
})
}
//
bizUserApi.userOrgTreeSelector().then((res) => {
cardLoading.value = false
if (res !== null) {
treeData.value = res
// 2
treeData.value.forEach((item) => {
// 0
if (item.parentId === '0') {
defaultExpandedKeys.value.push(item.id)
// ID
if (item.children) {
item.children.forEach((items) => {
defaultExpandedKeys.value.push(items.id)
})
bizUserApi
.userOrgTreeSelector()
.then((res) => {
cardLoading.value = false
if (res !== null) {
treeData.value = res
// 2
treeData.value.forEach((item) => {
// 0
if (item.parentId === '0') {
defaultExpandedKeys.value.push(item.id)
// ID
if (item.children) {
item.children.forEach((items) => {
defaultExpandedKeys.value.push(items.id)
})
}
}
}
})
}
})
.finally(() => {
cardLoading.value = false
})
})
}
})
.finally(() => {
cardLoading.value = false
})
//
const options = {
alert: {
@ -238,19 +281,23 @@
const editStatus = (record) => {
loading.value = true
if (record.userStatus === 'ENABLE') {
bizUserApi.userDisableUser(record).then(() => {
table.value.refresh()
})
.finally(() => {
loading.value = false
})
bizUserApi
.userDisableUser(record)
.then(() => {
table.value.refresh()
})
.finally(() => {
loading.value = false
})
} else {
bizUserApi.userEnableUser(record).then(() => {
table.value.refresh()
})
.finally(() => {
loading.value = false
})
bizUserApi
.userEnableUser(record)
.then(() => {
table.value.refresh()
})
.finally(() => {
loading.value = false
})
}
}
//
@ -264,12 +311,49 @@
table.value.refresh()
})
}
//
const removeBatchUser = () => {
//
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('请选择一条或多条数据')
return
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…
Cancel
Save