408 lines
11 KiB
Vue
408 lines
11 KiB
Vue
<script lang="ts">
|
|
export default {
|
|
name: 'AuthUser'
|
|
}
|
|
</script>
|
|
|
|
<script setup lang="ts">
|
|
import { ContentWrap } from '@/components/ContentWrap'
|
|
import { Table } from '@/components/Table'
|
|
import {
|
|
getUserListApi,
|
|
addUserListApi,
|
|
delUserListApi,
|
|
putUserListApi,
|
|
getUserApi,
|
|
postExportUserQueryListApi
|
|
} from '@/api/vadmin/auth/user'
|
|
import { useTable } from '@/hooks/web/useTable'
|
|
import { columns, searchSchema } from './components/user.data'
|
|
import { ref, unref, watch, nextTick } from 'vue'
|
|
import Write from './components/Write.vue'
|
|
import Import from './components/Import.vue'
|
|
import PasswordSendSMS from './components/PasswordSendSMS.vue'
|
|
import PasswordSendEmail from './components/PasswordSendEmail.vue'
|
|
import { Dialog } from '@/components/Dialog'
|
|
import {
|
|
ElButton,
|
|
ElMessage,
|
|
ElSwitch,
|
|
ElRow,
|
|
ElCol,
|
|
ElDropdown,
|
|
ElDropdownMenu,
|
|
ElDropdownItem,
|
|
ElIcon
|
|
} from 'element-plus'
|
|
import { useI18n } from '@/hooks/web/useI18n'
|
|
import { selectDictLabel, DictDetail } from '@/utils/dict'
|
|
import { useDictStore } from '@/store/modules/dict'
|
|
import { useAuthStoreWithOut } from '@/store/modules/auth'
|
|
import { RightToolbar } from '@/components/RightToolbar'
|
|
import { Search } from '@/components/Search'
|
|
import { useAppStore } from '@/store/modules/app'
|
|
import { useCache } from '@/hooks/web/useCache'
|
|
import { useRouter } from 'vue-router'
|
|
|
|
const { wsCache } = useCache()
|
|
const appStore = useAppStore()
|
|
|
|
const { t } = useI18n()
|
|
|
|
const authStore = useAuthStoreWithOut()
|
|
|
|
const genderOptions = ref<DictDetail[]>([])
|
|
|
|
const getOptions = async () => {
|
|
const dictStore = useDictStore()
|
|
const dictOptions = await dictStore.getDictObj(['sys_vadmin_gender'])
|
|
genderOptions.value = dictOptions.sys_vadmin_gender
|
|
}
|
|
|
|
getOptions()
|
|
|
|
const { register, elTableRef, tableObject, methods } = useTable({
|
|
getListApi: getUserListApi,
|
|
delListApi: delUserListApi,
|
|
exportQueryListApi: postExportUserQueryListApi,
|
|
response: {
|
|
data: 'data',
|
|
count: 'count'
|
|
},
|
|
defaultParams: {
|
|
is_active: true
|
|
},
|
|
props: {
|
|
columns
|
|
}
|
|
})
|
|
|
|
const dialogVisible = ref(false)
|
|
const dialogTitle = ref('')
|
|
const actionType = ref('')
|
|
const loading = ref(false)
|
|
|
|
const { getList, setSearchParams, exportQueryList } = methods
|
|
|
|
// 添加事件
|
|
const addAction = () => {
|
|
dialogTitle.value = t('exampleDemo.add')
|
|
tableObject.currentRow = null
|
|
dialogVisible.value = true
|
|
actionType.value = 'add'
|
|
}
|
|
|
|
// 编辑事件
|
|
const updateAction = async (row: any) => {
|
|
const res = await getUserApi(row.id)
|
|
if (res) {
|
|
dialogTitle.value = '编辑'
|
|
res.data.role_ids = res.data.roles.map((item: any) => item.id)
|
|
tableObject.currentRow = res.data
|
|
dialogVisible.value = true
|
|
actionType.value = 'edit'
|
|
}
|
|
}
|
|
|
|
// 删除事件
|
|
const delDatas = async (row: any) => {
|
|
const { delListApi, getSelections } = methods
|
|
const selections = ref([] as any[])
|
|
if (row) {
|
|
selections.value = [row.id]
|
|
} else {
|
|
selections.value = await getSelections()
|
|
selections.value = selections.value.map((item) => item.id)
|
|
}
|
|
await delListApi(true, selections.value)
|
|
}
|
|
|
|
const writeRef = ref<ComponentRef<typeof Write>>()
|
|
|
|
const save = async () => {
|
|
const write = unref(writeRef)
|
|
await write?.elFormRef?.validate(async (isValid) => {
|
|
if (isValid) {
|
|
loading.value = true
|
|
let data = await write?.getFormData()
|
|
if (!data) {
|
|
loading.value = false
|
|
return ElMessage.error('未获取到数据')
|
|
}
|
|
try {
|
|
const res = ref({})
|
|
if (actionType.value === 'add') {
|
|
res.value = await addUserListApi(data)
|
|
if (res.value) {
|
|
dialogVisible.value = false
|
|
getList()
|
|
}
|
|
} else if (actionType.value === 'edit') {
|
|
const user = authStore.getUser
|
|
const userId = data.id
|
|
const userTelephone = data.telephone
|
|
res.value = await putUserListApi(data)
|
|
if (res.value) {
|
|
dialogVisible.value = false
|
|
if (user.id === userId && user.telephone !== userTelephone) {
|
|
dialogVisible.value = false
|
|
authStore.logout()
|
|
return ElMessage.warning('认证已过期,请您重新登陆!')
|
|
} else {
|
|
getList()
|
|
}
|
|
}
|
|
}
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
getList()
|
|
|
|
const tableSize = ref('default')
|
|
|
|
watch(tableSize, (val) => {
|
|
tableSize.value = val
|
|
})
|
|
|
|
const route = useRouter()
|
|
const cacheTableHeadersKey = route.currentRoute.value.fullPath
|
|
|
|
watch(
|
|
columns,
|
|
async (val) => {
|
|
wsCache.set(cacheTableHeadersKey, JSON.stringify(val))
|
|
await nextTick()
|
|
elTableRef.value?.doLayout()
|
|
},
|
|
{
|
|
deep: true
|
|
}
|
|
)
|
|
|
|
const importDialogVisible = ref(false)
|
|
const importDialogTitle = ref('批量导入用户')
|
|
|
|
// 批量导入用户
|
|
const importList = () => {
|
|
importDialogVisible.value = true
|
|
}
|
|
|
|
const passwordDialogVisible = ref(false)
|
|
let passwordDialogType = 'sms'
|
|
let passwordDialogTitle = ref('重置密码并发送短信')
|
|
const selections = ref([] as any[])
|
|
|
|
// 批量发送密码至短信
|
|
const sendPasswordToSMS = async () => {
|
|
const { getSelections } = methods
|
|
selections.value = await getSelections()
|
|
if (selections.value.length > 0) {
|
|
passwordDialogVisible.value = true
|
|
passwordDialogType = 'sms'
|
|
passwordDialogTitle.value = '重置密码并发送短信'
|
|
} else {
|
|
return ElMessage.warning('请先选择数据')
|
|
}
|
|
}
|
|
|
|
// 批量发送密码至邮件
|
|
const sendPasswordToEmail = async () => {
|
|
const { getSelections } = methods
|
|
selections.value = await getSelections()
|
|
if (selections.value.length > 0) {
|
|
passwordDialogVisible.value = true
|
|
passwordDialogType = 'email'
|
|
passwordDialogTitle.value = '重置密码并发送邮件'
|
|
} else {
|
|
return ElMessage.warning('请先选择数据')
|
|
}
|
|
}
|
|
|
|
const mobile = appStore.getMobile
|
|
|
|
// 下拉菜单处理事件
|
|
const handleCommand = (command: string) => {
|
|
if (command === 'a') {
|
|
importList()
|
|
} else if (command === 'b') {
|
|
exportQueryList()
|
|
} else if (command === 'c') {
|
|
sendPasswordToSMS()
|
|
} else if (command === 'd') {
|
|
sendPasswordToEmail()
|
|
} else if (command === 'e') {
|
|
delDatas(null)
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<ContentWrap>
|
|
<Search
|
|
:model="{ is_active: true }"
|
|
:schema="searchSchema"
|
|
@search="setSearchParams"
|
|
@reset="setSearchParams"
|
|
/>
|
|
|
|
<div class="mb-8px flex justify-between">
|
|
<ElRow :gutter="10">
|
|
<ElCol :span="1.5" v-hasPermi="['auth.user.create']">
|
|
<ElButton type="primary" @click="addAction">新增用户</ElButton>
|
|
</ElCol>
|
|
<ElCol :span="1.5" v-hasPermi="['auth.user.import']" v-if="!mobile">
|
|
<ElButton @click="importList">批量导入用户</ElButton>
|
|
</ElCol>
|
|
<ElCol :span="1.5" v-hasPermi="['auth.user.export']" v-if="!mobile">
|
|
<ElButton @click="exportQueryList">导出筛选用户</ElButton>
|
|
</ElCol>
|
|
<ElCol :span="1.5" v-hasPermi="['auth.user.reset']" v-if="!mobile">
|
|
<ElButton @click="sendPasswordToSMS">重置密码通知短信</ElButton>
|
|
</ElCol>
|
|
<ElCol :span="1.5" v-hasPermi="['auth.user.reset']" v-if="!mobile">
|
|
<ElButton @click="sendPasswordToEmail">重置密码通知邮件</ElButton>
|
|
</ElCol>
|
|
<ElCol :span="1.5" v-hasPermi="['auth.user.delete']" v-if="!mobile">
|
|
<ElButton type="danger" @click="delDatas(null)">批量删除</ElButton>
|
|
</ElCol>
|
|
<ElCol :span="1.5" v-if="mobile">
|
|
<ElDropdown trigger="click" @command="handleCommand">
|
|
<ElButton>
|
|
更多
|
|
<el-icon class="el-icon--right">
|
|
<Icon icon="mdi:keyboard-arrow-down" />
|
|
</el-icon>
|
|
</ElButton>
|
|
<template #dropdown>
|
|
<ElDropdownMenu>
|
|
<ElDropdownItem command="a" v-hasPermi="['auth.user.import']"
|
|
>批量导入用户</ElDropdownItem
|
|
>
|
|
<ElDropdownItem command="b" v-hasPermi="['auth.user.export']"
|
|
>导出筛选用户</ElDropdownItem
|
|
>
|
|
<ElDropdownItem command="c" v-hasPermi="['auth.user.reset']"
|
|
>重置密码通知短信</ElDropdownItem
|
|
>
|
|
<ElDropdownItem command="d" v-hasPermi="['auth.user.reset']"
|
|
>重置密码通知邮件</ElDropdownItem
|
|
>
|
|
<ElDropdownItem command="e" v-hasPermi="['auth.user.delete']"
|
|
>批量删除</ElDropdownItem
|
|
>
|
|
</ElDropdownMenu>
|
|
</template>
|
|
</ElDropdown>
|
|
</ElCol>
|
|
</ElRow>
|
|
<RightToolbar
|
|
@get-list="getList"
|
|
v-model:table-size="tableSize"
|
|
v-model:columns="columns"
|
|
:cache-table-headers-key="cacheTableHeadersKey"
|
|
/>
|
|
</div>
|
|
|
|
<Table
|
|
v-model:limit="tableObject.limit"
|
|
v-model:page="tableObject.page"
|
|
:data="tableObject.tableData"
|
|
:loading="tableObject.loading"
|
|
:columns="columns"
|
|
:selection="true"
|
|
:size="tableSize"
|
|
:border="true"
|
|
:pagination="{
|
|
total: tableObject.count
|
|
}"
|
|
@register="register"
|
|
>
|
|
<template #action="{ row }">
|
|
<ElButton
|
|
type="primary"
|
|
v-hasPermi="['auth.user.update']"
|
|
link
|
|
size="small"
|
|
@click="updateAction(row)"
|
|
>
|
|
{{ t('exampleDemo.edit') }}
|
|
</ElButton>
|
|
<ElButton
|
|
type="danger"
|
|
v-hasPermi="['auth.user.delete']"
|
|
link
|
|
size="small"
|
|
@click="delDatas(row)"
|
|
v-if="authStore.getUser.id !== row.id && row.id !== 1"
|
|
>
|
|
{{ t('exampleDemo.del') }}
|
|
</ElButton>
|
|
</template>
|
|
|
|
<template #is_active="{ row }">
|
|
<ElSwitch :value="row.is_active" disabled />
|
|
</template>
|
|
|
|
<template #is_staff="{ row }">
|
|
<ElSwitch :value="row.is_staff" disabled />
|
|
</template>
|
|
|
|
<template #gender="{ row }">
|
|
{{ selectDictLabel(genderOptions, row.gender) }}
|
|
</template>
|
|
</Table>
|
|
|
|
<Dialog v-model="dialogVisible" :title="dialogTitle" width="700px">
|
|
<Write ref="writeRef" :current-row="tableObject.currentRow" />
|
|
|
|
<template #footer>
|
|
<ElButton type="primary" :loading="loading" @click="save">
|
|
{{ t('exampleDemo.save') }}
|
|
</ElButton>
|
|
<ElButton @click="dialogVisible = false">{{ t('dialogDemo.close') }}</ElButton>
|
|
</template>
|
|
</Dialog>
|
|
|
|
<Dialog
|
|
v-model="importDialogVisible"
|
|
:title="importDialogTitle"
|
|
width="750px"
|
|
maxHeight="550px"
|
|
>
|
|
<Import @get-list="getList" />
|
|
</Dialog>
|
|
|
|
<Dialog
|
|
v-model="passwordDialogVisible"
|
|
:title="passwordDialogTitle"
|
|
width="1000px"
|
|
maxHeight="550px"
|
|
>
|
|
<PasswordSendSMS
|
|
v-if="passwordDialogType === 'sms'"
|
|
:selections="selections"
|
|
@get-list="getList"
|
|
/>
|
|
|
|
<PasswordSendEmail
|
|
v-else-if="passwordDialogType === 'email'"
|
|
:selections="selections"
|
|
@get-list="getList"
|
|
/>
|
|
</Dialog>
|
|
</ContentWrap>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.el-dropdown-link {
|
|
cursor: pointer;
|
|
color: var(--el-color-primary);
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
</style>
|