初始化
This commit is contained in:
280
saiadmin-artd/src/views/system/user/index.vue
Normal file
280
saiadmin-artd/src/views/system/user/index.vue
Normal file
@@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<div class="art-full-height">
|
||||
<div class="box-border flex gap-4 h-full max-md:block max-md:gap-0 max-md:h-auto">
|
||||
<div class="flex-shrink-0 w-64 h-full max-md:w-full max-md:h-auto max-md:mb-5">
|
||||
<ElCard class="tree-card art-card-xs flex flex-col h-full mt-0" shadow="never">
|
||||
<template #header>
|
||||
<b>部门列表</b>
|
||||
</template>
|
||||
<ElScrollbar>
|
||||
<ElTree
|
||||
:data="treeData"
|
||||
:props="{ children: 'children', label: 'label' }"
|
||||
node-key="id"
|
||||
default-expand-all
|
||||
highlight-current
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</ElScrollbar>
|
||||
</ElCard>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col flex-grow min-w-0">
|
||||
<!-- 搜索栏 -->
|
||||
<TableSearch v-model="searchForm" @search="handleSearch" @reset="handleReset" />
|
||||
|
||||
<ElCard class="flex flex-col flex-1 min-h-0 art-table-card" shadow="never">
|
||||
<!-- 表格头部 -->
|
||||
<ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData">
|
||||
<template #left>
|
||||
<ElSpace wrap>
|
||||
<ElButton v-permission="'core:user:save'" @click="showDialog('add')" v-ripple>
|
||||
<template #icon>
|
||||
<ArtSvgIcon icon="ri:add-fill" />
|
||||
</template>
|
||||
新增
|
||||
</ElButton>
|
||||
</ElSpace>
|
||||
</template>
|
||||
</ArtTableHeader>
|
||||
|
||||
<!-- 表格 -->
|
||||
<ArtTable
|
||||
:loading="loading"
|
||||
:data="data"
|
||||
:columns="columns"
|
||||
:pagination="pagination"
|
||||
@sort-change="handleSortChange"
|
||||
@selection-change="handleSelectionChange"
|
||||
@pagination:size-change="handleSizeChange"
|
||||
@pagination:current-change="handleCurrentChange"
|
||||
>
|
||||
<!-- 操作列 -->
|
||||
<template #operation="{ row }">
|
||||
<div class="flex gap-2" v-if="row.id !== 1 && userStore.info.id !== row.id">
|
||||
<SaButton
|
||||
v-permission="'core:user:update'"
|
||||
type="secondary"
|
||||
@click="showDialog('edit', row)"
|
||||
/>
|
||||
<SaButton
|
||||
v-permission="'core:user:destroy'"
|
||||
type="error"
|
||||
@click="deleteRow(row, api.delete, refreshData)"
|
||||
/>
|
||||
<ElDropdown>
|
||||
<ArtIconButton
|
||||
icon="ri:more-2-fill"
|
||||
class="!size-8 bg-g-200 dark:bg-g-300/45 text-sm"
|
||||
/>
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
<ElDropdownItem>
|
||||
<div
|
||||
class="flex-c gap-2"
|
||||
v-permission="'core:user:home'"
|
||||
@click="showWorkDialog('edit', row)"
|
||||
>
|
||||
<ArtSvgIcon icon="ri:home-office-line" />
|
||||
<span>设置首页</span>
|
||||
</div>
|
||||
</ElDropdownItem>
|
||||
<ElDropdownItem>
|
||||
<div
|
||||
class="flex-c gap-2"
|
||||
v-permission="'core:user:password'"
|
||||
@click="handlePassword(row)"
|
||||
>
|
||||
<ArtSvgIcon icon="ri:key-line" />
|
||||
<span>修改密码</span>
|
||||
</div>
|
||||
</ElDropdownItem>
|
||||
<ElDropdownItem>
|
||||
<div
|
||||
class="flex-c gap-2"
|
||||
v-permission="'core:user:cache'"
|
||||
@click="handleCache(row)"
|
||||
>
|
||||
<ArtSvgIcon icon="ri:eraser-line" />
|
||||
<span>清理缓存</span>
|
||||
</div>
|
||||
</ElDropdownItem>
|
||||
</ElDropdownMenu>
|
||||
</template>
|
||||
</ElDropdown>
|
||||
</div>
|
||||
</template>
|
||||
</ArtTable>
|
||||
</ElCard>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 表单弹窗 -->
|
||||
<EditDialog
|
||||
v-model="dialogVisible"
|
||||
:dialog-type="dialogType"
|
||||
:data="dialogData"
|
||||
@success="refreshData"
|
||||
/>
|
||||
<!-- 工作台弹窗 -->
|
||||
<WorkDialog
|
||||
v-model="workDialogVisible"
|
||||
:dialog-type="workDialogType"
|
||||
:data="workDialogData"
|
||||
@success="refreshData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTable } from '@/hooks/core/useTable'
|
||||
import { useSaiAdmin } from '@/composables/useSaiAdmin'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import TableSearch from './modules/table-search.vue'
|
||||
import EditDialog from './modules/edit-dialog.vue'
|
||||
import WorkDialog from './modules/work-dialog.vue'
|
||||
import api from '@/api/system/user'
|
||||
import deptApi from '@/api/system/dept'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const treeData = ref([])
|
||||
|
||||
// 编辑框
|
||||
const { dialogType, dialogVisible, dialogData, showDialog, handleSelectionChange, deleteRow } =
|
||||
useSaiAdmin()
|
||||
|
||||
const {
|
||||
dialogType: workDialogType,
|
||||
dialogVisible: workDialogVisible,
|
||||
dialogData: workDialogData,
|
||||
showDialog: showWorkDialog
|
||||
} = useSaiAdmin()
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = ref({
|
||||
username: undefined,
|
||||
phone: undefined,
|
||||
email: undefined,
|
||||
dept_id: undefined,
|
||||
status: ''
|
||||
})
|
||||
|
||||
const {
|
||||
columns,
|
||||
columnChecks,
|
||||
data,
|
||||
loading,
|
||||
pagination,
|
||||
getData,
|
||||
searchParams,
|
||||
resetSearchParams,
|
||||
handleSortChange,
|
||||
handleSizeChange,
|
||||
handleCurrentChange,
|
||||
refreshData
|
||||
} = useTable({
|
||||
core: {
|
||||
apiFn: api.list,
|
||||
apiParams: {
|
||||
...searchForm.value
|
||||
},
|
||||
columnsFactory: () => [
|
||||
{ type: 'index', width: 60, label: '序号' },
|
||||
{
|
||||
prop: 'avatar',
|
||||
label: '用户名',
|
||||
minWidth: 200,
|
||||
saiType: 'imageAndText',
|
||||
saiFirst: 'username',
|
||||
saiSecond: 'email'
|
||||
},
|
||||
{ prop: 'phone', label: '手机号', width: 120 },
|
||||
{ prop: 'depts.name', label: '部门', minWidth: 150 },
|
||||
{ prop: 'status', label: '状态', width: 80, saiType: 'dict', saiDict: 'data_status' },
|
||||
{ prop: 'dashboard', label: '首页', width: 100, saiType: 'dict', saiDict: 'dashboard' },
|
||||
{ prop: 'login_time', label: '上次登录', width: 170, sortable: true },
|
||||
{
|
||||
prop: 'operation',
|
||||
label: '操作',
|
||||
width: 140,
|
||||
fixed: 'right',
|
||||
useSlot: true
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param params
|
||||
*/
|
||||
const handleSearch = (params: Record<string, any>) => {
|
||||
Object.assign(searchParams, params)
|
||||
getData()
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
const handleReset = () => {
|
||||
searchForm.value.dept_id = undefined
|
||||
resetSearchParams()
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换部门
|
||||
* @param data
|
||||
*/
|
||||
const handleNodeClick = (data: any) => {
|
||||
searchParams.dept_id = data.id
|
||||
getData()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门数据
|
||||
*/
|
||||
const getDeptList = () => {
|
||||
deptApi.accessDept().then((data: any) => {
|
||||
treeData.value = data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param row
|
||||
*/
|
||||
const handlePassword = (row: any) => {
|
||||
ElMessageBox.prompt('请输入新密码', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputPattern: /^.{6,16}$/,
|
||||
inputErrorMessage: '密码长度在6到16之间',
|
||||
type: 'warning'
|
||||
}).then(({ value }) => {
|
||||
api.changePassword({ id: row.id, password: value }).then(() => {
|
||||
ElMessage.success('修改密码成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
* @param row
|
||||
*/
|
||||
const handleCache = (row: any) => {
|
||||
ElMessageBox.confirm('确定要清理缓存吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
api.clearCache({ id: row.id }).then(() => {
|
||||
ElMessage.success('清理缓存成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDeptList()
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user